9418 lines
312 KiB
Plaintext
Executable File
9418 lines
312 KiB
Plaintext
Executable File
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
Version 2.00
|
||
|
||
|
||
December 21, 1993
|
||
|
||
|
||
(C) Copyright Psion PLC 1990-93
|
||
|
||
|
||
All rights reserved. This manual and the programs referred to herein are copyrighted works of Psion
|
||
PLC, London, England. Reproduction in whole or in part, including utilization in machines capable of
|
||
reproduction or retrieval, without express written permission of Psion PLC, is prohibited. Reverse
|
||
engineering is also prohibited. :
|
||
|
||
|
||
The information in this document is subject to change without notice.
|
||
|
||
|
||
Psion and the Psion logo are registered trademarks, and Psion, Psion MC, Psion HC, Psion Series 3 and
|
||
Psion Series 3a are trademarks of Psion PLC. |
|
||
|
||
|
||
TopSpeed is a registered trademark of Clarion Software Corporation. M, IBM XT and IBM AT are
|
||
registered trademarks of International Business Machines Corp. Microsoft and MS-DOS are registered
|
||
trademarks of Microsoft Corporation. Apple and Macintosh are registered trademarks of Apple Computer
|
||
Inc. VAX and VMS are registered trademarks of Digital Equipment Corporation. Brief is a registered
|
||
trademark of Underware Inc. Psion PLC acknowledges that some other/names referred to are registered
|
||
trademarks. |
|
||
|
||
|
||
)
|
||
|
||
|
||
Contents
|
||
A IVICUINK: MICDIINt;-GNG SNK vcsissscssccasncscdececeu cease ovcenveuieve css ecueedudciiessneidcrecdeewencs 1
|
||
VIGIIIIKOXG yccecuscccasasacezediwaanerew nodes seaatani oes ousescaiencannandessaaevdocancautesecseeises 1
|
||
Commands provided in MCLINK..............ceccccscccscccccscccccccscscccccsscssecccees 1
|
||
MCLINK and single floppy disk drive PCS ..............ccccccccssccsccscccscccceccess 2
|
||
Exiting the MCLINK program ............ccccccccccccccscescccsscccsccesscccessovesecccees 2
|
||
Display the version Of MCLINK ..............ccccccccsccescccvccccceccsseenccsesssceccers 2
|
||
MCLINK file-handling Commands. ............cscccccccscsccscsscsscssccscesccscscccecesccececs 2
|
||
HUIGS ON: TIEMAMES 5 suisse eevesseecoradisbicai conc ceeaiebiededanssacatesadentesescieneeeek 2
|
||
NLR cerca oc ewemiocsnt acto ance Neate saw ce dea mane naka welde ona anteducumcedsauaicecieielse ont benceaees 3
|
||
COPY aaiiadteiicatiaiencae lunes cso cs Monnens sonee arctan naneeaten age iannend awe a 3
|
||
RENAME coscinececead cs eae tenscvwvscsesuiaincadse utaeoet Solanueswaesaaneoue nae ees 4
|
||
EE iE acces itcacidio ae swetaetaontaddaenwasoeias ces cee ueanten semaalen sanubaw Mie cenGee leas eeeees 4
|
||
BVI DUR eo tessastcicoacaing eatavenadeaceu ee uncanaie suse pademnacea chan aaoneeaceeere ceed eects 4
|
||
Changing MCLINK communications SettingS..............ccccccscscscscscscccscscsecececs 4
|
||
Options for the SET Command ...............ccccscccccccsscccssccscesccccceccceccceccecs 4
|
||
Serial port and Baud rate Options ............c.cccccccsscssccscccsccscccccecccecccsececs 5
|
||
MIOGEM OPTIONS hsiscssceseshaec cant dav sencasvs cous autacadecuaevedeisantatenias eoeeeeeiedates 5
|
||
Examples of the SET command
|
||
Advanced use Of MCLINK.............c.cccscccccscceccccnccssscsescccsssseccvessecsvecevccencs 5
|
||
Running programs remotely on the MC, HC or Series 3............cccccccsecccs 5
|
||
MICLINK batch files ...............cccccccscccscsccccssccccscsssscecceccsccsssceecseccsveecess 6
|
||
MCLINK command line processing..............ccccscscsssccscsccsccccecsccscecescecess 6
|
||
Invoking MCLINK inside an MS-DOS batch file .................cccccsccecsccscceces 6
|
||
MICLINK and MOdeMS .............ccccccccccsccscscsccsccsccsceccsccecescccecescescevecesescccess 6
|
||
MCLINK as a PC file server via the phone System. ............scccccccsceccesscces 7
|
||
MCLINK and modem Baud ratesS.............cccccccccscsccsccccesccccscccesccccccssecess 7
|
||
Link on the MC/HC as a requestor via MOdEM.............sccsccsccscecscescecccces 7
|
||
Link and Modem Baud rates. ............ccesscccsscccsccscessccecceesccesceccseves ere 8
|
||
Link/MCLINK with MNP ..............cccscscscsccscsccsccssscsccsctecessescsceescscescesces 8
|
||
Examples with modems. ............cccccccccsscssecsccccccscsscsscescceccceeccecceccecsesecccecs 8
|
||
Using a Dacom QuadPlus MNP 5 compressing modem...............scecceseees 8
|
||
Using an Amstrad SM2400 moder. .............ccececessccssescesssccccscsccccecceccs 8
|
||
Using a Dowty Quattro SB2422...............cccccsccccsnccsccssccccccececcccccvecccess 9
|
||
Using a WorldPort 1200 pocket Modem. ...........ccssceccccsccecccccscccscceccccecs 9
|
||
An HC with a Psion Quad modem ..............sccscscscecccccccceccccccccccececccecees 9
|
||
An HC with the Amstrad SM2400 modem ...............ccsccsccscecccceccecceccecs 9
|
||
IVIGDEING- OXG se scecsressiacecaassewcineroiswateastcusssaousaseecate ain eeGaigontanmuceteadaventienat: 9
|
||
USING -MICPRINE vvtauisscomadccsuacrencoss sean wdasanseceeutaonuseeataedia ake coveuumeewad 9
|
||
EXITING MICPRING 25 cevscecasccancsdesctus boveareviccets eeceanuiedosstantdea ndencecatannecins 9
|
||
Printer Configuration On the MC ..............cccccccsccscscccccesccsccsccccesccscceecces 10
|
||
Printer configuration On the Series 3............ccccecsccscsccecccacsssccsccscescceaces 10
|
||
PAlAMPELOIS 5.0555 cds ccccae saeuaaenwse caw tasson sense wale dese omer ueceessc2 seven aieawed vacation suiek 10
|
||
The <prdev> parameter .............cccccsccscccsccccsccsscccceccceseccccuceececesevucess 10
|
||
The -C<poOrt> parameter .............cccccccccccscccsccsccsccnccessctsccsceccccececeucess 10
|
||
The -t<timeout> parameter.............cccccccccccccsccssccccccccccesceccceccecescceecss 11
|
||
ENG = DAFAMEER oii coescs teins acacnsicsewrvecsnssidalsceobicasctwuduesdecewesleisaesececetors 11
|
||
SHIA O XC esis ieeeend arcs oceciidastavcbated dbaeetiubaes een eoedaaceeenveuki cate weduGlasaaieadacecs 11
|
||
A RESOUCE FUCS vce oa casters csoens a dunciscnntedavauaaspuesxdaauianSnesadneswaniieasWenieapentteaewenedonecs 13
|
||
MICFOGUGTION iescesecaie awossse eects odale ices watcsaacassnsRacbensantes vecsaue usa Oeaecied aeseewenas 13
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
rr reser ssh se ress nna eremmeeee
|
||
|
||
|
||
Format of Sibo resource fileS.............cccsccecenccccccccccccs :
|
||
|
||
|
||
isiehuce na aeeecaadecusnaidmsseate 15
|
||
The format Of .rsc fil€S............cccccsseccsecessccesceeces | Sesh aeiiniaanastaesasee cia 15
|
||
Some strategies for reading .rSc fileS..............scccsseccecsscscscececscscscscsasess 15
|
||
Example of reading resource files directly............. hehe wedencuvmeuaciatewsinues 16
|
||
Using the rscfile Class in Olib..............:sccccsecccscscccscecscecccscscsceceseccscssccseeees 16
|
||
Basic services of the rscfile claSs..............cseceseees | atoatealeiactecie See teatmt aati 16
|
||
Reading compressed resource files with the rscfile Class .............ccceceeees 17
|
||
Initialising an rscfile ODjeCt.............ccccseesecsecscseees Pere ree ree 17
|
||
Which header files are needed ................cccceccecccsceccccssccsscsccscescccccsceees 18
|
||
Run-time errors with the rscfile ClaSs.............ccccccdecssceccescsessscsccsscnsceccs 18
|
||
Possible errors during initialisation ...............cccccccqcscccssccsscsecsccsaccessenccs 18
|
||
Errors during rs_read Or rs read DUf............cscsscscdscsecscecetescsscnssceseecaes 18
|
||
How rscfile errors are reported .............cscesseseeeees d eusigulee se sa beamquabeeua sears 19
|
||
Dealing with errors in rs_read or rs read Duf.............c.ccscscscssscncnceesceees 19
|
||
Advice on where to locate resource fileS ...............ccccdecescccccccccccccccssecccccecs 21
|
||
Mono-lingual applications ..............cccessccccescccvssccdescccccccccccescsccccscceececs 21
|
||
Multi-lingual applications ...............ccccccncccccccccesncsecccccccsaccecsssssccscecesess 21
|
||
Copying of applications ...............cccccccesscccssceeccess Siicatacsaronteee eres 22
|
||
General comments on multi-lingual applications..............csccccsscsssesscccscesceecs 22
|
||
The basic principle of independence of code from resource file .............. 22
|
||
Careful design of screen layout ...........cccccccessccccccercccscceccceccsccesccecsences 23
|
||
Codesize problems. ...........sscsscsscssssscsscscscscoesenees shorty Dating TectatSoeectacan: 23
|
||
Varying KEVYDOAlGS viessisciside cake tices ened ice dikcwks aidesecdeceseedoxwca veweuceieens 23
|
||
CONCIUSION aise Sec cctyatiwreestcocascsiice soi uadotessiadononeseeke UL cbaduadingniemaeeeea mannan: 23
|
||
Creating .rsc files USING FCOMP.EXE...........ccecccccsceeesecs i alerhcsaseianaieta bse alesis aia oleeecies 23
|
||
GONGFateG <fS0 THES 6s 6ciaccesieciieacetdontetsecinaieewsuseoaeesbeescaveceusuaantedanusccese 24
|
||
The syntax of the rcoMp COMMANG.............cccccccccccccvcccccsccccecccccccoeeeecs 24
|
||
Include files within a resource SCTipt ............cccceee: Dolged dee cube ee enoe ane 25
|
||
Conditional compilation in resource files ............... a Seian muueeetsaooneuaucassees 25
|
||
Contents of .rss fileS .............cccccecccccccscccevevcccccsovenece Mera oeisatnnamoe kata euaet ences 25
|
||
Declaring STRUCTS ...........cccccccccvccccccreccsscccccscees po auimataiesdeevaeeesenesses 26
|
||
Possible member types in STRUCTS............cccccsscepccsceccccccecssescccscceececs 26
|
||
Declaring RESOURCES .................ccecesccscceccecceees Wire ates mate alee fae aate etal 27
|
||
Declaring the values of sub-STRUCTSs................00 Daeiteas sreicnadiacauewtacenes 27
|
||
Leading byte and word length values..................8. : SE ET Cee eT ee 28
|
||
Arrays Within resource fileS ............cccccccccccccccccccuhecccccccccccccccccceccecececs 29
|
||
Creating SYSTEM resource fileS ...........ccccsscccseeees Dacia deals unease ausewarereasins 30
|
||
|
||
|
|
||
3 WDR Printing...............c.:ccsccecssecesccccscseocseccosesccseceeceeeeens heed entree ees: 31
|
||
INFOGUCUON i ssies ise ecatesh insets condateddanenaeseteaentee Ceessaseeees | ssp ctsalanebe reson eeeuuateniss 31
|
||
Creating .wdr files .............cccccccscccscceccccccccccesccecs oat saseauestebbess sheneetadcel 31
|
||
The WDR printing environment variables............... Det Ort heals ewan ecee coin 31
|
||
A note on reading environment variables .............. U creaepdieniiales atusenese tens 32
|
||
Overview of the contents of a .wdr file.............cccceeees Heath acta cioumaeeceubasemacas 32
|
||
Deciphering general. wr ...........cccccccccsscsccescccsesess pedessingcaciant seuveaassasaeads 33
|
||
TNE NEAGEF TESOUICE wisccva cesses scar siesensicencauisuerssssacieleuvia censuses eseevsseceuwades 33
|
||
TNE COMMANAS FESOUICE...........cccessccccscvccevccscesecs Temes aes sebecamentaa wean ens 34
|
||
Model rOSOUrCeS........cccsccvecscesscccesccccccscccccssceceeses | sia atatnensoiceaateoseee aoe 34
|
||
TYDCTACE FESOUICES ei iisteeresdobaccelodaracsekcadsSdcesesases sexhlvsneveniecericaeeene ees 35
|
||
Translates reSOUMCES ..........ceccesccccscccesccecscsesscesses ee ne rere 35
|
||
Summary of resource types in a .wdr file.............. Lacouanet aa weedeecewensveuee: 35
|
||
More details on the contents Of .wWdr fileS ............ccsccesecvccvscccecsccseccsccesenecs 36
|
||
POSSIDIC WOl-TAQS aise is sccias seas insascanciseendeadiiaeusernie facut beg cemanrovaceaseueanns 36
|
||
The notion of “printer models” ...........scssccssssesceees b wslagdaeseacuaberius seventies 36
|
||
Overview of the different Command StringS...........1....cecccsesesssseeeeecesees 36
|
||
Special characters in COMMANA StringS ...........scccecsescscsccccscscscsacscscsceees 37
|
||
The MOVE_RIGHT commands..............ccceccscseeseees omens svaptaeeneestasame nan: 37
|
||
PRIMO UNITS csciigencescoowaesteinte dexter cicie eer edeawcasuce Leiioduiitaia wou aust Sune ou sean 37
|
||
Possible model-flags ............ccecccccescccescccccccscccvecs ces aeons vas: 38
|
||
Typefaces and fonts .........cccesccccccccccccccccccccsccesecs | sac cg Ghi tieanonmecaeeuseas 38
|
||
TY DETACE NUMDELS ses ccsianvnictiacsienscetawvceGolacccssuedewns mensenaaaesabencnedseeaesenes 38
|
||
|
||
|
||
CONTENTS
|
||
|
||
|
||
Possible typeface-flags ............cccccccsceccccccccceccseccceccesescsssavescececesseereccs 39
|
||
FICIGIIES OF TONTS ot saa ssicaties sesisadd vo vawsntaidee nod dowd aca wus ceaenoens savesenensaeeeaawa gaa 39
|
||
Widths of characters in fonts.............ccccccccssccccccscccccccescccecescescsececsccees 39
|
||
Creating .wdr fileS USING WOtraN.eXe ...........cccccccsccscccccccccsscescescescesccsevecsces 40
|
||
Contents OF .Wd FileS .............cccccscccacsccsssccescecsceccccceecseccccccceeccccseseceecs 40
|
||
Acceptable syntax within a COMMANDS resource definition.................. 41
|
||
Acceptable commands within a TRANSLATES resource definition........... 41
|
||
Acceptable commands within a WIDTHS resource definition .................. 42
|
||
Acceptable commands within a TYPEFACE resource definition ............... 42
|
||
Acceptable commands within a MODEL resource definition.................... 42
|
||
Allowed typeface NUMDETS. ..............ccccesscscescscscecscscscuctacecsescceccesseceeces 43
|
||
|
||
BM: (DBP TOS iso scios dace ei obece cons dadciadeducecaataaesdocbsa scacncweGastecwawodedenecenetoledednn staal 45
|
||
IPIRFOGUCTION sae cpio sca seaticore i seubauncsacuae suatiieetacasaccacee he baSaake aa iweteekavocsesacden 45
|
||
Basic structure of DBF files................ccccscsccscecccscccccscccccceccecceccencevccnccecccece 45
|
||
The Standard header...............cccsscsccscscccsccecscecccccccceccccteccccccevccecccecccece 46
|
||
The extended header ...............cccscssssccsccsccccccsccccescecceccceccceccevcceccceccces 46
|
||
The field information reCord...........cccscsccccscecceccecsccccccecceccencecevceccecceeces 46
|
||
The format of all reCords............ccccscscscscscecessscssescccesescvcecceceusecececceccce 46
|
||
DGICTE TECOLOS ends cusacveysewascasGacaisceeuhddeeuad menses ote esboscene nn irwelndddoweunelns 47
|
||
DESCTIPTIVE FECOFS ...........cecccccnccceccscsccccsccsceccececsccecscccccececceccecceeceeces 48
|
||
More On type 1 records ...........ccecccscscccsccesccccscssecececccecescccscececscceeecece 48
|
||
The Series 3 Database ...............ccccsccscscscecccccescccceccceccccerecececccececcecccceccece 48
|
||
Field information record ...........ccccscscscsccecscsccscecsevccecsceccecccececceccececcece 48
|
||
EXtGnded NGAGel ais ceescncs daidacdasicucdastebel eis eausewseoeeieandosseuues vassceareeicieewence: 48
|
||
DESCHPUVE TECONG ixesitsscencaascnscawesecsawdsnedeedoamuccdeniebeShodeGiadooeteccaeieelcun 48
|
||
Flags options for the Series 3 Database ................cccccecscecccccceccecesecececs 50
|
||
EPYOG™ VO CONGS oanaseitten see cicsacnsssvanians dalmancwicn Suneasasleanei esa cchunetheen cect 50
|
||
Continuation Sub-fields ...............ccccecsssscscscecscascececcccecececscscecsceccccecece 50
|
||
The Series 3 Agenda ...............ccsccssscsssscsscscsscscscvscesescecsrecceuscececercececececes 50
|
||
Field information reCord ............cecscscscscscscsctecscscscccccecscececccceccocececcecccs 50
|
||
Extended Neader ..............cscsscscscscsccscscsccscscscscscoscecescccceeeececeecesecececess 50
|
||
D@SCIIPLIVE FECOIE ...4.ccceacessecvcccsnoseccvaesesdseescescsdcvecceectsechcccdececdacececcecc 51
|
||
TYPE: T GOCONOS ses iies te see neat oatsGsanesu aa chons uestncebeddadeuboudatecidocucunchichenwene 51
|
||
Calculating with AlarmTime.............ccccscsscsscscescscesscccsccccscescececececceccces 51
|
||
The text Of AN APPOINTMENT ................cccscscscscecscscecccccccececccececcccececcccee 52
|
||
TODO MOINS oes esi on sicisg shen su siaccuedet <i cs sdeundaawannedenfascensevese deaeadnueceuh cowie 52
|
||
FREDCOE ILONNS ssiciati sate tagbasdaavasens casceicdauccsedseee hws iasnes os bireaaceiaanei Beaton: 52
|
||
|
||
5 Series 3a Agenda File Format ..................cccsccossccsscoccccsscccscccscceccoccecccoccocceccess, 55
|
||
HITE OGUCTION ices pcsiredtiedccpiandews decwenineeRediediadudelaisawededivabeansheercaddduoetedacs beets coeav: 55
|
||
Basic structure of Agenda files..............cc.cccscscsveccccscoscccececececscececccccececces, 55
|
||
The standard header................cccccoccecscsscscscecscsscscececceceecececceccececececess 55
|
||
The extended header ...............cccccsscsssscscscecscscssevcccccceececcescecccccecceces 56
|
||
TMG Gata TOCONGS 3iiciassiecss secs szacceuedcossavevwsuedeasieaceedesk deaveecseoe ek sioles csevune 56
|
||
RECONG: VDES sgsts crepe iscaies ube, ease addiaaesademesanteeudsbantudenteeeairboas aabistuecutienin: 56
|
||
Type O - deleted record ..............ccsessossscrensncesccccaescscssssearsovessecescassessceecs 56
|
||
Types 1 to 4 - Entry reCOrds ..............scccsscscscscscecccccscccccececececscececcecececccces 57
|
||
NCEY GOtAIS TONG uj sicsonsisescooccsenea iewsstbuaecatese tstenciesuidusSecnetcexcxeh maceausve 57
|
||
ING THO: THONG sees cat ncrsic dames Goes da eandin ccaeonewodadeiaecidensiastemiuekeoieecodeecn 59
|
||
TEINS: ALANNA TIONG: eeserisascenenctandealtiadautwievouraa be oiasansc ees uecabieciecs ccceatamisoeaneies 60
|
||
WRNEANEMO HONG saccc essa sicessc¥salaovdevech wvpasheudands saccclnd decals @eeek hee oe 60
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
A rei ei Stns ern wnt i= acpbnets
|
||
|
||
|
||
Type 5 - repeats ............cccsccccscscscsccccscscescececcscvaveces Lace tatedueteaetadycsou 60 ~~
|
||
Type 6 - anonymous data ssteaesesseneseneanenessenessseenesnsspenessseansssseaceneneaneneaee 62
|
||
Types 7 and 8 - reServed. ............ccsccssscscscssccscsccssscscccsccecececcecevscccceseevececs 62
|
||
Type 9 - to-do list information ...........ccccsccscesccccscsaces L Bduateeeinacamnecan ie cette 62
|
||
Types 10 to 14 - descriptive records ..........ccscecscscsees | siieielaseesiwateaeneiaetnodes 62
|
||
Type 10 - styles descriptive record...........ccccssscsceceees , bee titsuayatetaecasecnentanened 63
|
||
Type 11 - to-do manager descriptive record............00. dente temalinaeGacomsueshaunesene 63
|
||
Type 12 - frequently changing data descriptive record ................cssecccceseeees 63
|
||
Type 13 - general descriptive record..............cs.cssseees de duet oasatcn Some saieninns 63
|
||
Diamond list setup field ............ccccccccccssccccsseaceecs dea aetna aeudodetescetuorses 64
|
||
Day entry defaults field ...............ccccecceseccccsccscces d Sue tenaneunnguiMemmeus ents 64
|
||
Anniversary entry defaults field ...............cccccccccccccscccscccsccccsccecscssccesens 65
|
||
General defaults field ..............ccccceccceccccccssccccesecs hte decssudoiuateecacieewauns 65
|
||
Day VIEW SEttINgS Field..............cccccesccecccccccccccccedescccceccccceusscesseescsesacs 66
|
||
Week view Settings field.................ccscccccccccscccecesccccccccsseccsssccscsscoesecs 66
|
||
Year view settings field ..............cscscecssscevcsccccececs SadalaenledreWauw cases tonsuadds 66
|
||
To-do view settings field ................cccccceccscccecceees ieaciaseaseaeeeud cas weamoutes 66
|
||
Anniversary view Settings field ..............cccccsccssscssesscsscsessccscescssssscesens 67 x
|
||
List view Settings field ..............cccccescescccsccscesceecs Lace cwentinoeuasuiosmauac seas 67 :
|
||
Type 14 - print setup descriptive record...............scsee ne wadhawieatsea eoaeawanceeeues 67
|
||
Type) 10 Weal sccucs0d scocacitenntevssdbesevasineuctieseecseest Besteip setae seta eetiaiont 67
|
||
:
|
||
6 Word Processor File Format ................cccceccecceccccccccccesceees bs siavsatcuesuedaeasutaneucncte 69
|
||
The document header............cccecceccccceccccescccccccvccscece GLa lout seedeonneecseemecie: 69
|
||
FRECOPG TV DCS ois Gees csiiss re can cheeses ane een ca maeaiw esa eeivanaad cy axcincen eden aeiaee dese onawer 70
|
||
The options data record (type 1, length 10) .......... Hatta darias tas dian ate oy heat se 70
|
||
Printer-related data record (type 2, length 58) ....... ominigdiidaguiteennamersiiedmens 70
|
||
Printer model data record (type 3, variable length)..,.............ccscecsscssceees 72
|
||
Page header record (type 4, variable length).......... Pawbawsbaeneanewa sank Gueecees 72
|
||
Page footer record (type 5, variable length)........... Dood alot aa aisoseacanecuans 72
|
||
Style data record (type 6, length 8O)............sesceses Ls aaaeecaesamicn moanoemasanues 73
|
||
Emphasis data record (type 7, length 28).............. Oats a vesnaccaananseaouetonst 74
|
||
Document text record (type 8, variable length) ...... pacbniciettadotnnenvauanamaeaeet 74
|
||
Document index record (type 9, variable length) ....,.......:sssscsssessereeseeees 75
|
||
| _
|
||
| a
|
||
7 Writing Device Drivers .............cccccscssscsscscoscescsccccsccscceccechecssccccsccecaccececcescovees 77
|
||
IATHOCUICTION ices os bicesbct casas ccevalestiensconwneeeecbesseeeesaaes Lassteascccesevesecasseeceeees 77
|
||
The location of device Grivers..........ceccrecccccsscsceees Po Salinuwncacunet smaesnaas Sonne 78
|
||
Device Driver NOMOS oxic scsccesesicnds scscoset an slekwrnseduos wsassecandesecd eds sestansnens 78
|
||
Device Driver Chantel ..............ccccccceccccscsccesccces preseeeeeneeneeeenseenerenens 78
|
||
Searcning fOr PODS 4 sscei chia cine cortsecccesGace ts ousactsesecewses cet ieisuesadeeuaudses 79
|
||
Device Driver Hierarchies And Attached Drivers...........cccsccccccccccesscseeees 79
|
||
Interrupts and Interrupt Service ROutines..............ccecescceecccesscccscsceccscescesnees 80
|
||
Device Driver 1/O Semaphore Waithandlers............; So vuladsnbaweetureteaueneaive 80
|
||
Loadable Logical Device Driver Structure...............0.66. (hates loaianeeca emieassengaes 81
|
||
Single Code SEQMent...........ceccccccecsccccerevecsscessces I aohicais omsawamaeaiagauicsece 81
|
||
WHE LIDEAT SUC TUG eid cesaccaticwasevidcweccnduadinse et ecdeaas ote sew veesineeseewmaieoseess 81
|
||
Mandatory LDD Functions. ................ccccccccccceccccncccucccscsccccccsccccssccsscecs 82
|
||
DevFuncinstall ...........ccsccceccecccccecvcccccssccseccccsececs i eokcepaley Gace easeanmawenseeae 82
|
||
De@VFUNCREMOVE .........cccsccvssccccceccceccscccccccecccececs daa Merl eeuecstnucmecdaes 83
|
||
DEV EUMCHOING vices caiisssactensncdecccueeavtusananeetaesnceaneceusonedeceedeanausbexsasisueatas 83
|
||
DOVEUNCRESUIMNG oxi icdsccaeae ecu ticsccticecenaddncc ceca canes sanaioenecaeacesseesieesaens 85
|
||
DOEVEUNCRESCE ioscsnecs ccausatenesscsecsvecsuedeuon cccauasencue. ccutes chinese veceuremsenees 85
|
||
DO VUNG OTIS sacivcr sed scrcenncrnstatscd acuaa casewabacssencae oi oneevanaw een cause sce eeuces 86
|
||
DEVFUNC ODEN sedéciiesssechsscstcecoctescstecscaavesccuwienteesss Janecasceesceescenrenenssoeses 87
|
||
DEVFUNCSIPAlLe GY oiccseicsiesccavsscsicvexcecoseia pedonweredocsdeess sees ee cues cveesescsanne’ 89
|
||
|
||
|
||
1V
|
||
|
||
|
||
CONTENTS
|
||
|
||
|
||
Loadable Physical Device Driver Structure..............ccsccecscceccscceveccccvccscccetees 90
|
||
SINGIG COGE SOOMENE sissscccasescecessc sense dedaseaedelncetessiwaeidoncedevencecansaumsaves 90
|
||
TRE LIBENt SH&UCTUTE sick odeveciasbiead vodienciindeiveeaasaantebseandeecdiaerssseawens 90
|
||
Mandatory PDD FUNCTIONS .............cccccccesnccccecccccveccsecevscccsccccosccecececccce 91
|
||
DeVFUuNCIAStallPDD ices csecescocsesca casas se cdaccees ceive vensasis bie eSnkersbowandcniadeeeck 91
|
||
DevEuncReEmovePDD & s isiccescsccencscacadis cas scccsd scene dGebdiesalesbcsvadenccccsoncsveree 92
|
||
DEVFUNCOPENPDD igi ve sds noses ieickiionsedsccdoss re seeabsiacdanenacsesesacinaseweschcakeetens 93
|
||
DEVEUNCStrategy POD sive eccsccrecheand phase ites hace ida dedoasbaneieteadeceniaceneact 93
|
||
|
||
8 Example Device Drivers ...............ccccccccccesccccsecccccccccccccccccccscccccccccssconsccccsscccess 95
|
||
|
||
An Attached Device Driver Example ...............ccccccccccccccccsccecesccsccecscscccssscees 95
|
||
"ENG GOVICE: TaDIG cincs oickis sa cciecescicadiwccunsieces cake ecudveatinaneawebenisercansarteaans 95
|
||
The lnstall: FUMCHHON wocesissickcsticecssavcbivevesndesecsiddcevel deeds deovecsenevasceesaccs cok 95
|
||
“ERG REMOVE: FUNCUION visiecdesideisStewhdiscueeedestiesin dh beaeiavecoue ence ueaaverceeeaees 95
|
||
ENG FIOM 'FUNCHON 6c.i dee oeidicitecascuwasineanceeacaecsariiedusateabiosdencanes tear Secciaoobeek 95
|
||
The RESUME FUNCtion ...........ccccccccccccccccccccccccccccsccsevcctccvecececccceccscscecce 95
|
||
UNE: RESCUE. FUNCTION sods coniwaceccusesscibactenennsaxncicsovneronsusacetuaciceiesvonutesebee 95
|
||
“EMG? URITS FURCHON ices ioiscicic cis cocceedeutinc atecediowidudeddacdansdeebecineece eowenekes 96
|
||
PNG ODEN: FUN CtOMsces seis cece cess. cdscadascemeceranecovesuslnieses aa cade ccsdelioncamiaends 96
|
||
THE Strategy FUNCHON 55sses ccs: cscseerckseweieediovesccinwcwedOinacendevennoueteeeecanedeks 96
|
||
The Wait Handler Function .............ccsecccccccsssccccsccccevcccccecccncscncucccccesecs 96
|
||
|
||
Non Interrupt Based Sound Drriver................ccccoccsccscsccsscsccsccccceseeccscsesseecce 97
|
||
NING GOVICE TaDIe ieead si cceivakenececassvecavcewsndsveasececacnesdeus seauacerin na cenaerdsaceses 97
|
||
Whe: INStalll PUM Cti OM aceesca dis oisesecrrsacowsesien tenet ucecicaieeaweaee saecowneueenePake 97
|
||
The Remove Function ..............ccccccsccoseccsccssccesecccsscccccccccececccccecccseeeccs 97
|
||
AMO IGIG FUNCUON i scs'iccccardententiwakiocdecasdansessncndetaweain 4 dole bond soaskaconeen kee 97
|
||
The Resume Function ............cccccccccccescsccscccsccccccesccccecccecssceccccveccsceeccs 98
|
||
The Reset Function ............ccccccscscscccccscccsccssccccccescsccccceeccccecccsseccseccces 98
|
||
PNG URNS FUNCTION vsscsiscsiccsnccosseeisees tb Secdeeigecionn beiieec ues hae sacs saedbaieaeecs 98
|
||
The Open Function. ...........ccccccccccccccccccscsccecvssescscsscesesccescsscesvevececsevecs 98
|
||
The Strategy Function ..............ccccccccccesscsscsccsccssccccccccecceesecccecccesccccces 98
|
||
The Wait Handler Function ...............cccecsccccsccecsccccccccccccccccccccccceececeuecs 98
|
||
EX€rciSiINg the VECtOIS .........cccccecescccsccecccccccscencsccccsasessvececscesceccscccesess 99
|
||
|
||
Interrupt Driven Sound Driver..............cccccccssccsccccccceccccccccccccccccccevecceeseveees 99
|
||
THO GOVICE TAD a cect st ca vecatiee tes vues wercancesshanecnsaheaeehcenelsossueueiedonieiesnk 99
|
||
THe Install FUNCHON sco srins ea cend iccdcdscaiea deh eacsechedaccowastchceveeoukevouesns 99
|
||
The Remove FUN ction.............cccscccccesccnsssccssccscescecceccseccccccecceseceecceveees 99
|
||
The: Old Pun CuO eseescceekirciiteatclicaseis a cncsbeieeacecasccannee hedegiawctawokeidenoeass 100
|
||
The Resume Function ..............cccccscccscccsccccccsccceccsscccscescccceccescccecccenccs 100
|
||
THE RESET FUNCTION svi sicc ds ioveseie dein avowecaddewceewdinnteulseecbosceieeesvecacleoxeucdouuns 100
|
||
EMG UNitS FUNCTION sescGcocensasideccstieatawiednnd scons vucaciuacw ded cave nee nciead a veeeghas 100
|
||
THE OPO FUN CON ii sceceic cicwiwsde vase eis cues eadsina does odes dacebedesedceeveaseniiaesie 100
|
||
The Strategy FUNCTION ..............cccceseccccccscccccccscsscccccccccceccceseeceecesceecees 100
|
||
The Wait Handler Function .................csccsccscscccccsccccscccccecccecceccecceccences 101
|
||
|
||
9 PCMCIA cards and SSDs ..............cccccceccsccscccccccccccccccvccesceccccceccecccenccccecccececece 103
|
||
Mobility and robuStness................sccscssccsscsscsscescescecccsccccsccccscccecscccseecs 103
|
||
SIZE CONSIDEFATIONS ............ccccccccsccsccacccsccccscccsceccecceeteccccsceecsecseecceece 103
|
||
Different standards for different PUrPOSES. ..............cccceccccccscceccceccceccecce 103
|
||
FIOU INSOPLION uicedees casi cocccaveceeeaend ade Seckcnesy we neatceeeok Seesaw one ees cc 104
|
||
FlaSN: THING SVStOMNS 2 ve scwcusascscusmersawsconssaadaesausseedinverenweneetdextselebeneeeeees 104
|
||
COSt GCONSIGElALIONS veiccs cssccced cncks cack buewtndaes eiancaseesesenaicevebavelsolovavaxbeeds 104
|
||
Architectural OPENNESS ............ccccccccccccsccccccecccssccsccscssncceccecccscececsecces 104
|
||
|
||
|
||
tee
|
||
|
||
7 '
|
||
|
||
ce a
|
||
|
||
s
|
||
Fe
|
||
5
|
||
a
|
||
|
||
“
|
||
|
||
.
|
||
|
||
|
||
CHAPTER 1
|
||
|
||
|
||
NMICLINK, MCPRINT, AND SLINK
|
||
|
||
|
||
The directory \sibosdk\sys contain the following programs (amongst others), all of which can be run on a
|
||
PC connected to a SIBO computer:
|
||
|
||
|
||
mcelink. exe a program allowing file transfer and remote file access between the PC and the
|
||
SIBO computer
|
||
slink. exe a "no frills" server-only version of mclink.exe, which may run on PCs or PC-
|
||
|
||
|
||
lookalikes that cannot run mclink
|
||
meprint. exe a program for printing "through" a PC to an attached printer.
|
||
|
||
|
||
Basic information on connecting a PC with either an MC computer, a Series 3 computer (see note
|
||
below), or an HC computer, is given in, respectively, the MC Operating Manual, the Series 3 User
|
||
Guide (see note below), and the Introduction chapter of the HC Programming Guide (part of this SDK).
|
||
The information in this chapter gives some more advanced details on the above three programs.
|
||
|
||
|
||
Note: throughout this chapter a reference to the Series 3 machine is taken to include both the Series 3 and
|
||
Series 3a machines unless explicitly stated otherwise.
|
||
|
||
|
||
De Aha aes Ae ah NS ee ee ee a
|
||
~ Mclink.exe
|
||
|
||
|
||
MCLINK requires MS-DOS version 3.2 or above. MCLINK is unlikely to run inside "DOS emulations"
|
||
provided by other operating systems (though it happily runs inside MS-DOS tasks inside MicroSoft
|
||
Windows).
|
||
|
||
|
||
If you experience any problems running MCLINK on your PC, you should experiment with reduced
|
||
contents of autoexec. bat and config.sys files. Serial mouse cards may be particularly prone to interfere
|
||
with the operation of MCLINK.
|
||
|
||
|
||
If all else fails, you may wish to use the alternative SLINK program, also supplied on the PC MCLINK
|
||
disks.
|
||
|
||
|
||
Note that, by default the HC and Series 3 run at 9600 Baud, the MC and Series 3a at 19200 Baud. When
|
||
a PC running MCLINK is connected to an MC, either the PC or MC end will in general have to be
|
||
changed to enable a link to be established.
|
||
|
||
Commands provided in MCLINK
|
||
|
||
|
||
When you start up the MCLINK program, the lower window contains a $ prompt. At this prompt you
|
||
can enter various commands. These commands cover:
|
||
|
||
|
||
# file-handling
|
||
|
||
= changing the communications settings
|
||
® exiting the MCLINK program
|
||
|
||
®# displaying the version of MCLINK
|
||
|
||
|
||
® running programs on the remote computer.
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION :
|
||
|
||
|
||
For all these commands:
|
||
|
||
|
||
= the command can be abbreviated, to a minimum of the first two letters, eg DE for DELETE, RE for
|
||
RENAME, CO for CoPY, and SE for SET |
|
||
|
||
|
||
= CTRL-C stops the command (though in multiple file operations, some files may already have been
|
||
copied, deleted etc, before the command is stopped).
|
||
MCLINK and single floppy disk drive PCs
|
||
|
||
|
||
If your PC has only one floppy disk drive (currently referenced as "A:"), and you mistakenly enter DIR B:
|
||
while in the MCLINK program, the program will be halted by MS-DOS, requesting you to insert a disk
|
||
into B:.
|
||
|
||
|
||
To avoid this, use the MS-DOS aAssicn command before running the MCLINK program, like this:
|
||
|
||
|
||
ASSIGN B=A :
|
||
|
||
|
||
Then DIR B: will be read as DIR A: and the program will not be halted. See your MS-DOS manual for
|
||
further details of the ASSIGN command. | :
|
||
|
||
|
||
Exiting the MCLINK program
|
||
Type EXIT to return to MS-DOS. }
|
||
|
|
||
Display the version of MCLINK :
|
||
Type VER to display the version number. |
|
||
ne ee
|
||
|
||
|
||
MCLINK file-handling commands
|
||
|
||
|
||
For file transfer operations between a PC and a SIBO computer, you would normally use the File
|
||
Manager on the MC or various file options on the Series 3. For certain| purposes, however, you might
|
||
choose to use the file-handling commands within MCLINK on the PC instead.
|
||
|
||
Rules on filenames
|
||
|
||
|
||
In order to make full use of the file-handling commands of MCLINK, various rules about filenames need
|
||
to be appreciated.
|
||
|
||
|
||
In MCLINK the syntax of full filenames on the PC, MC, HC or Series 3 is:
|
||
filing system: :device:\directory\sub-directory\file.extension |
|
||
|
||
|
||
This is very similar to MS-DOS, except for the <filing system prefix.
|
||
|
||
|
||
If you do not specify a filing system in a file specification, LOC:: is presupposed.
|
||
In MCLINK on the PC, <fiting system is
|
||
® LOC:: for files on the PC (local)
|
||
= REM:: for files on the MC, HC, Series 3 or Series 3a (remote).
|
||
|
||
|
||
On the MC, HC or Series 3 the situation is reversed, with Loc:: for files on the MC, HC, Series 3 or
|
||
Series 3a, and REM:: for files on the PC.
|
||
|
||
|
||
Note that for all MCLINK file management commands:
|
||
= if no directory is specified, the current directory is assumed
|
||
|
||
|
||
= if no device is specified, the current device is assumed
|
||
= if no filing system is specified, the PC is assumed.
|
||
|
||
|
||
When specifying a directory or sub-directory in the file-handling co ds, make sure to add a \ onto
|
||
the end of the directory name. Otherwise the directory name will be taken as a filename. So:
|
||
|
||
|
||
COPY A:\*.* REM::\LETTERS is wrong - it would try to copy the files in the root directory of A:
|
||
to the file LETTERS !
|
||
|
||
|
||
|
|
||
|
|
||
I
|
||
|
||
|
||
i
|
||
|
|
||
|
||
|
||
+)
|
||
|
||
|
||
1 MCLINK, MCPRINT, AND SLINK
|
||
|
||
|
||
COPY A:\*.* REM::\LETTERS\ is right - it would copy the files on A: to the directory LETTERS.
|
||
|
||
|
||
Syntax: DIR filespec
|
||
|
||
|
||
The directory specified may be on the remote or local filing system - eg DIR A:\LETTERS\ looks in
|
||
directory LETTERS on the disk in drive A: of the PC, DIR REM::A:\NOTES\ looks in the NOTES directory on
|
||
the SSD in drive A: of the remote machine.
|
||
|
||
|
||
Use wildcards to list only certain files - eg DIR *.TXT to list just the .TxT files in the current directory.
|
||
When you get a directory listing with the DIR command, the following file information is given:
|
||
ws file name and extension
|
||
= date and time when the file was last modified
|
||
= size of file in bytes
|
||
and a combination of these indicators as appropriate:
|
||
Mod file has been modified since last backed up
|
||
Rdo read-only file
|
||
Sys system file
|
||
Hid hidden file
|
||
Example: CLIENTS.DBF 14/01/90 09:54:23 544 Mod RdO
|
||
|
||
|
||
.
|
||
oaataleaca tates ite Cate Selesere” ea otatatateetetetetetaate! cat aeatatataetetetel
|
||
|
||
|
||
ecified dev
|
||
|
||
|
||
Syntax: COPY filespec1 filespec2
|
||
|
||
|
||
Optional flags:
|
||
-j include sub-directories: If there are any files copied from subdirectories they are placed in
|
||
directories below the current directory, to reflect the source directory structure
|
||
-m modified files only, eg COPY REM::A:\*.* -i -m copies all modified files in all directories
|
||
of the SSD in drive A: on the remote machine to the PC.
|
||
Examples:
|
||
COPY REM::M:\*.TXT \BACKUP\ would copy all the .TxT files from the internal disk of the remote
|
||
|
||
|
||
machine to the BACKUP directory on the PC
|
||
|
||
|
||
COPY \SMITH\*.DOC REM::A:\LS\ | would copy all the .p0c files from the SMITH directory on the PC
|
||
to directory LS on the SSD in drive A: of the remote machine.
|
||
|
||
|
||
If you do not supply a complete destination name, the root directory and/or default disk on the remote
|
||
machine is assumed, and the source filename is used as the destination filename. Eg
|
||
|
||
|
||
COPY \HOME\SECURE .TXT REM: :M:
|
||
would copy SECURE.TXT to the M:\ directory on the remote machine, giving the file the name SECURE.TXT.
|
||
If you do not supply a complete source name, the current device/directory is assumed. Eg
|
||
|
||
COPY *.TXT REM::M:\
|
||
agg files from the current directory on the PC to the root directory of the remote machine's internal
|
||
|
||
|
||
Note: if you are transferring a lot of small files to the Series 3, it is a good idea not to stay in the Series 3
|
||
System Screen. This could take longer than usual because the System Screen would continually update its
|
||
file lists as files arrived. In extreme cases, with lots of very small files, the file transfer could even fail.
|
||
So press an application button, such as the TIME button.
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
Syntax: RENAME filespeci filespec2 |
|
||
|
||
You can rename a file in any directory on any drive on the PC, MC, HC or Series 3. For example
|
||
RENAME DETAILS.DOC DETAILS2.DOC |
|
||
RENAME REM::M:\CLIENTS.DBF REM::M:\BUSINESS .DBF
|
||
|
||
You can rename more than one file at a time. For example
|
||
RENAME REM::M:\*.TXT REM: :M:\*.DOC |
|
||
|
||
You cannot rename a file across directories or devices. Thus
|
||
RENAME REM::M:\LETTER1.TXT REM::B8:\LETTER2.TXT
|
||
|
||
|
||
would give an error. Instead, copy the file to the new name and destination then delete the old file.
|
||
|
||
|
||
Syntax: DELETE filespec |
|
||
Optional flag:
|
||
|
||
|
||
-i delete files of the same name in sub-directories, eg DEL *.1XT -i would delete all .1xT files
|
||
in the current directory and in any sub-directories of the current directory.
|
||
|
||
|
||
You can delete files from any directory on the PC, MC, HC or Series 3,
|
||
You can delete more than one file at a time by using wildcards. |
|
||
|
||
|
||
You cannot delete directories with this command.
|
||
|
||
|
||
Syntax: MKDIR directory
|
||
|
||
|
||
Makes a subdirectory of the current directory.
|
||
You can make directories on any drive of the PC, MC, HC or Series 3.
|
||
|
||
|
||
You can make more than one subdirectory at a time - eg MKDIR \HOME\LETTERS makes the subdirectory
|
||
\HOME\LETTERS and also the intermediate subdirectory \HomE (if it does not exist).
|
||
|
||
|
||
Changing MCLINK communications settings
|
||
The SET command in MCLINK allows you to: |
|
||
|
||
= use either of the PC's serial ports :
|
||
|
||
= change the Baud rate which the PC uses |
|
||
|
||
= use a modem (see later in this chapter for more details of using MCLINK over a modem)
|
||
The SET command creates a new MCLINK.TRM in the current directory to hold the new settings. The
|
||
next time you run MCLINK from this directory, these settings will be loaded again.
|
||
Options for the SET command |
|
||
Following the SET command you can specify a variety of options. For apote
|
||
SET -p1 -b9600 selects com1, 9600 Baud :
|
||
SET -p2 -b9600 selects com2, 9600 Baud |
|
||
The full range of options for the SET command includes -p, -b, -m, -n, and -c.
|
||
|
||
|
||
These options are also available as parameters to the command line for MCLINK (see later), but in this
|
||
case, no permanent record of the options are made in any .7RM file.
|
||
|
||
|
||
|
|
||
SEES
|
||
4 |
|
||
|
||
|
||
()
|
||
|
||
|
||
1 MCLINK, MCPRINT, AND SLINK
|
||
|
||
|
||
Serial port and Baud rate options
|
||
The SET options -p1 or -p2 select COM1 or COM2.
|
||
|
||
|
||
The option -b followed by a number sets the Baud rate. You will need to set the Baud rate on the MC,
|
||
HC or Series 3 to match that on the PC.
|
||
|
||
|
||
IMPORTANT: In general you should specify both -p and -b, or neither. If you specify just one, the other
|
||
is reset to MCLINK''s internal default value. The internal default for the Baud rate is 19200. (By default
|
||
MCLINK runs at 9600 Baud since when starting up it looks for a file called MCLINK.TRM which is built
|
||
in to MCLINK.EXE. This file sets the PC to COM1 at 9600 Baud.)
|
||
|
||
Modem options
|
||
|
||
|
||
The SET options -m or -n specify that you are using a modem (as described in more detail later in this
|
||
chapter).
|
||
|
||
|
||
The option -m means wait for a call; MCLINK will establish the speed to use to the modem.
|
||
|
||
|
||
The option -n followed by a number causes MCLINK to dial the number. The modem is assumed to
|
||
conform to the Hayes command set. Here you can if you wish specify the speed for MCLINK to use,
|
||
with -b. For example: -b2400 -n314159 dials 314159 at 2400 Baud.
|
||
|
||
|
||
The option -c<string> will cause <string> to be transmitted to the modem to configure it before
|
||
|
||
waiting/dialling:
|
||
|
||
SET -cATMO turns off the modem speaker
|
||
|
||
SET -cAT\N3 sets a Dacom modem to MNP fallback mode.
|
||
|
||
Note that the AT is optional in these commands. Multiple strings can be transmitted. For example,
|
||
SET -cMO -c\NS
|
||
|
||
|
||
Examples of the SET command:
|
||
|
||
|
||
SET -b1200 1200 Baud
|
||
|
||
SET -p2 -m waits for a call using the modem in port 2 (Com2)
|
||
|
||
SET -p1 -b2400 -n314159 modem connected to port 1 dials the phone number 314159
|
||
SET -cm0 turns off the modem speaker.
|
||
|
||
|
||
Advanced use of MCLINK
|
||
|
||
|
||
Running programs remotely on the MC, HC or Series 3
|
||
The syntax
|
||
RUN <program name>, <program command line>
|
||
causes the named program to be run on the remote computer, with the specified command line.
|
||
|
||
|
||
The program is assumed to exist in the default directory of the remote machine or the root directory of
|
||
any drive on the remote machine. Otherwise the ROM of the remote machine will be searched for the
|
||
|
||
|
||
program.
|
||
The program command line is as required by the program being invoked.
|
||
For example,
|
||
|
||
RUN CLOCK.IMG
|
||
will run a copy of CLOCK.IMG on the remote machine.
|
||
|
||
|
||
As an accelerator for running a copy of the remote shell program on HC machines the '!' command is
|
||
equivalent to typing RUN SYSSSHLL.
|
||
|
||
|
||
For example:
|
||
|
||
|
||
! DIR
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
Ee get gd a eRe can SR ee cn mf eee ng ee ee ee ee eee ee oe
|
||
|
||
|
||
will run a copy of the SYS$sHLL program passing an initial command line of DIR. See the HC
|
||
Programming Guide for further information on commands available to the SYS$SHLL program.
|
||
|
||
|
||
MCLINK batch files :
|
||
MCLINK can read a text file containing multiple commands: |
|
||
= Any line in the file containing a '!' is assumed to be a comment line and is ignored.
|
||
# Any blank line is ignored.
|
||
|
||
|
||
= You may specify almost any MCLINK command, although some may be meaningless in this
|
||
environment - DIR, for example.
|
||
|
||
|
||
= The SET command should not be used.
|
||
|
||
|
||
To invoke, a batch file, type the 'a' character immediately followed by the name of the text file
|
||
containing the commands. For example, if the file SEND_ALL. TXT contains the following lines:
|
||
|
||
|
||
! Sends all text files to the remote machine after
|
||
! creating the correct directory, then exits
|
||
|
||
MKDIR REM: :M:\NOTES\
|
||
|
||
COPY *.TXT REM: :M:\NOTES\
|
||
|
||
COPY *.DOC REM::M:\NOTES\
|
||
|
||
EXIT
|
||
|
||
|
||
then entering @SEND_ALL.TXT at the '$' prompt will cause the \NOTES\ directory to be created in the internal
|
||
memory of the remote machine, all the .TxT and .poc files in the — directory to be copied to this
|
||
directory, then MCLINK to exit.
|
||
|
||
|
||
MCLINK command line processing
|
||
|
||
|
||
MCLINK understands a command line entered when running MCLINK fn the MS-DOS prompt. The
|
||
command line may take the form of the parameters to the SET command, a filename assumed to be a
|
||
configuration file, or the @ command to run a sequence of commands. |
|
||
|
|
||
Examples: |
|
||
MCLINK -p2 -b9600 will run MCLINK using port 2 at 9600 Baud. No .7RM file will
|
||
|
||
|
||
be created, unlike using the SET command, and any future running
|
||
of the MCLINK program will not use these parameters.
|
||
|
||
|
||
MCLINK S3SETUP will run MCLINK forcing it to use the file S7SETUP. TRM as the
|
||
initial configuration file. This file would typically have been
|
||
created by a previous use of the SET command within MCLINK.
|
||
|
||
|
||
MCLINK @SEND_ALL.TXT will run MCLINK and cause the initial commands to be read
|
||
from the file SEND_ALL.TXT. MCLINK will wait until a
|
||
|
||
|
||
connection to the MC, HC or pie 3 has been established before .
|
||
|
||
|
||
running any of the commands.
|
||
|
||
|
||
Invoking MCLINK inside an MS-DOS batch file
|
||
Perhaps the most convenient way to automate a regular MCLINK task iB via an MS-DOS batch file.
|
||
|
||
|
||
For example, a batch file SEND_ALL.BAT could contain the single line
|
||
MCLINK @SEND_ALL.TXT
|
||
|
||
in which case the contents of SEND _ALL. TXT would be performed — by typing
|
||
SEND_ALL
|
||
|
||
from the MS-DOS command line.
|
||
|
||
|
||
MCLINK and modems |
|
||
|
||
|
||
A PC running MCLINK can use one modem at one end of a telephone line to connect to an HC or MC
|
||
computer attached to another modem at the other end of the telephone line.
|
||
|
||
|
||
|
|
||
(est —— - etisechlenennseecetnasacinutetewsernet ive aseeineeermnascie
|
||
6
|
||
|
||
|
||
‘a
|
||
|
||
|
||
1 MCLINK, MCPRINT, AND SLINK
|
||
|
||
|
||
Modem communication of this sort is possible only for MC and HC computers. The 3 Link software for
|
||
the Series 3 does not have any built-in modem support for communicating over a telephone line to a PC
|
||
running MCLINK. (The kMD: device driver is not present in the ROM of the Series 3.) To communicate
|
||
over a modem using a Series 3, use the Script language instead (which is included with the 3 Link
|
||
software for the Series 3).
|
||
|
||
|
||
MCLINK as a PC file server via the phone system
|
||
|
||
|
||
When used as a PC file server via the phone system, MCLINK assumes that your modem follows CCITT
|
||
tules and regulations concerning the RS232 signals - ie
|
||
|
||
|
||
= The modem drives DSR when powered up, never drops DSR and does not use DSR for any sort
|
||
of handshaking. If the modem is physically removed, MCLINK detects this as the DSR signal
|
||
disappears. If DSR is not driven MCLINK will not talk to the modem as it does not think it is
|
||
there.
|
||
|
||
|
||
= The modem responds to the DTR signal in the following manner - when MCLINK drives DTR
|
||
low, (off, inactive) the modem should reset itself - ie disconnect if online etc and eventually
|
||
enter its command mode. When MCLINK is exited, it drives DTR low to disconnect any calls
|
||
currently connected. When MCLINK is started up it drives DTR low for 2 seconds to try to
|
||
force the modem into its command mode, at its default settings.
|
||
|
||
|
||
s The modem only drives DCD when it is on line to a remote modem, and drops DCD when the
|
||
connection with the remote modem is lost.
|
||
|
||
|
||
When MCLINK is asked to communicate with a modem it sends the 'AT' command string to the modem
|
||
at the following Baud rates: 300, 600, 1200, 2400, 4800 and 9600. It monitors the response to sending this
|
||
command, and sets itself to the highest speed at which an "ok" reply was received.
|
||
|
||
|
||
MCLINK then sends the following command stream to the modem to configure it:
|
||
#ATX4EOSO=1" if the modem's maximum Baud rate was 2400 Baud or above
|
||
“ATX1E0SO=1" otherwise.
|
||
|
||
|
||
MCLINK then reads the user command configuration strings passed to it and sends them to the modem.
|
||
All commands sent to the modem are checked for validity by waiting for the modem to respond to the
|
||
command sent. If the '0K' response is received the command worked, otherwise an error is reported. This
|
||
will result in MCLINK re-starting.
|
||
|
||
|
||
NOTE: If the user command stream contains any form of reset, then the auto answering of calls should
|
||
be re-enabled explicitly.
|
||
|
||
|
||
MCLINK and modem Baud rates
|
||
|
||
|
||
When MCLINK displays the status message Waiting for an Incoming Call the Baud rate displayed will be
|
||
the fastest Baud rate that MCLINK found the modem supported. Setting the Baud rate is really a
|
||
meaningless exercise since the Baud rate at which the modem connection is made is determined by the
|
||
Baud rate of the dialling modem (originator) and not the modem accepting the call. _
|
||
|
||
|
||
If MCLINK detects the fastest Baud rate its modem can handle is 2400 Baud or above, it assumes that the
|
||
modem has the ability to provide a constant speed interface - ie the modem does not change to the
|
||
originator's Baud rate as soon as a connection is established. All modems that can handle Baud rates of
|
||
2400 and above must have the constant speed interface since this is the way in which MNP throughput is
|
||
normally achieved.
|
||
|
||
|
||
If the fastest Baud rate is below 2400 Baud then MCLINK will set the connection Baud rate to that
|
||
reported by the modem when it connects - ie the modem is assumed to change to the originators Baud
|
||
rate and MCLINK will follow it. Modems in this class will not support any form of data
|
||
compression/correction since a higher Baud rate than the connection Baud rate is required to achieve data
|
||
compression.
|
||
|
||
|
||
Link on the MC/HC as a requestor via modem
|
||
|
||
|
||
(This section closely matches the corresponding section above for MCLINK.)
|
||
|
||
|
||
When used on the HC or MC as a requestor via the phone system, Link software on the HC/MC assumes
|
||
the modem follows CCITT rules and regulations concerning the RS232 signals - ie
|
||
|
||
|
||
« The modem drives DSR when powered up, never drops DSR and does not use DSR for any sort
|
||
of handshaking. If the modem is physically removed, Link detects this as the DSR signal
|
||
disappears. If DSR is not driven Link will not talk to the modem as it does not think it is there.
|
||
|
||
|
||
7
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
= The modem responds to the DTR signal in the following manner - when Link drives DTR low,
|
||
(off, inactive) the modem should reset itself - ie disconnect if online etc and eventually enter its
|
||
command mode. When Link is exited, it drives DTR low to disconnect any calls currently
|
||
connected. When Link is started up it drives DTR low for 2 seconds to try to force the modem
|
||
into its command mode, at its default settings. !
|
||
|
||
|
||
= The modem only drives DCD when it is on line to a remote modem, and drops DCD when the
|
||
connection with the remote modem is lost.
|
||
|
||
|
||
When Link is run it sends the 'AT' command string to the modem at the following Baud rates: 300, 600,
|
||
1200, 2400, 4800, and 9600. It monitors the response to sending this command, if it sees an 'OK' it assumes
|
||
the modem can be driven at that Baud rate.
|
||
|
||
|
||
Link then sends the following command stream to the modem to confi it:
|
||
"ATX4EQSO=1" if the modem's maximum Baud rate was seh Baud or above
|
||
|
||
|
||
"NATX1EOSO=1" otherwise.
|
||
|
||
|
||
Link then reads the user command configuration strings and sends the to the modem. All commands
|
||
sent to the modem are checked for validity by waiting for the modem to respond to the command sent. If
|
||
the '0K' response is received the command worked, otherwise an =a reported. This will result in
|
||
Link re-starting.
|
||
|
||
|
||
Link and modem Baud rates
|
||
|
||
|
||
Link will send the dial string to the modem at the Baud rate specified from the Link dialog, or in the case
|
||
of the HC at the Baud rate specified in the command line. If no Baud rate is specified, the fastest Baud
|
||
rate that the modem responded to (see above) is used. By sending the dial string at the specified Baud rate
|
||
the particular type of Vxx connection will be established - eg at 2400 a V22bis, at 1200 a V22, and at
|
||
300 a V21 connection. Note that a V23 (1200/75) connection cannot be) used.
|
||
|
||
|
||
Note: if you want to use your HC as the file server and the PC as the requestor, swap the above
|
||
instructions for 'MCLINK’ and ‘Link’.
|
||
|
||
|
||
|
|
||
Link/MCLINK with MNP |
|
||
|
||
|
||
If you have MNP modems do not be surprised if the data transfer rate een your PC and MC/HC is
|
||
lower. This is because of the way MNP works.
|
||
|
||
|
||
Typically it is not worth having MNP enabled. The protocol used by Link and MCLINK is based
|
||
heavily on the MNP protocol, ie it provides an error free connection hone the PC and HC.
|
||
|
||
|
||
Examples with modems
|
||
|
||
|
||
The first four examples below focus on a PC with MCLINK as a file server. The last two examples focus
|
||
on an HC with Link software. |
|
||
|
||
|
||
For more information on any of the configuration strings see the appropriate modem manuals.
|
||
|
||
|
||
|
|
||
Using a Dacom QuadPius MNP 5 compressing modem
|
||
|
||
|
||
Run MCLINK with the following command line:
|
||
MCLINK -C&F&C1&D3\N3\J1S0=1 |
|
||
Alternatively, you could set up a. 7RM file, eg QUADPLUS.TRM and type
|
||
MCLINK @QUADPLUS.TRM |
|
||
or call the .7RM file MCLINK.TRM and just type
|
||
|
||
|
||
MCLINK
|
||
|
||
|
||
Using an Amstrad SM2400 modem
|
||
|
||
Run MCLINK with the following command line:
|
||
MCLINK -m
|
||
|
||
a ————=—— ae a ——————— ae ee ee pe ee eee
|
||
|
||
8
|
||
|
||
|
||
1 MCLINK, MCPRINT, AND SLINK
|
||
|
||
|
||
Using a Dowty Quattro SB2422
|
||
Run MCLINK with the following command line:
|
||
|
||
|
||
MCLINK -m
|
||
|
||
|
||
Using a WorldPort 1200 pocket modem
|
||
Run MCLINK with the following command line:
|
||
|
||
|
||
MCLINK -m
|
||
|
||
|
||
An HC with a Psion Quad modem
|
||
Run Link with the following command line:
|
||
LINK -n<the phone number> -c\n0
|
||
This talks to all of the above PC file server configurations.
|
||
|
||
|
||
An HC with the Amstrad SM2400 modem
|
||
Run Link with the following command line:
|
||
|
||
|
||
LINK -n<the phone number>
|
||
|
||
|
||
DR Ta cP Oy CO eer A a ee ee
|
||
Micprint.exe
|
||
|
||
|
||
MCPRINT allows an MC, HC, or Series 3 (or any other serial-printing device) to print to a printer
|
||
which is connected to an IBM PC/XT/AT or compatible. The PC must have a free serial port which is
|
||
used to connect to the MC/HC/Series 3. The printer may be connected to a parallel or serial port on the
|
||
PC.
|
||
|
||
|
||
Even if you can link the MC/HC/Series 3 directly to the printer, there may be reasons why it is more
|
||
convenient to use MCPRINT:
|
||
|
||
|
||
= The printer is shared by other PCs - either using a multi-port printer buffer or a local area
|
||
network - and it would be unreasonable to connect it directly to the MC/HC/Series 3.
|
||
|
||
|
||
= You do not wish to disturb the connection between the PC and the printer.
|
||
= You have already set up the serial connection to use MCLINK for file transfer to the PC.
|
||
|
||
|
||
= When your PC is connected to more than one printer, you can select which one the
|
||
MC/HC/Series 3 will use.
|
||
|
||
|
||
Note: it is also possible to print via MCLINK to a printer attached to your PC. To do this, set your
|
||
MC/HC/Series 3 to print to a file, and give the printer device on REM:: (such as REM::LPT1) as the “file” to
|
||
use. This method may be slower than using MCPRINT - especially when printing "justified" text from
|
||
the Word Processor on either computer - and will only work reliably on version 3.0 or above of
|
||
MCLINK. However, MCLINK can correct transmission errors, whereas MCPRINT can only report
|
||
them. Such errors may occasionally be caused by PC add-ons, such as some network card drivers.
|
||
|
||
|
||
Using MCPRINT
|
||
|
||
|
||
Physically connect the MC/HC/Series 3 to the PC exactly as for MCLINK. If the printer is connected to
|
||
LPT1, and MC/HC/Series 3 is connected to COM1, you can now run MCPRINT on the PC by typing:
|
||
|
||
|
||
MCPRINT
|
||
|
||
|
||
If LPT1 and Com‘ are not the ports used, parameters are required, as described below.
|
||
|
||
|
||
Exiting MCPRINT
|
||
To exit MCPRINT, press CONTROL-C.
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
Printer configuration on the MC
|
||
|
||
|
||
On the MC, select Print Setup from the Options menu in the System <e lication to display the Printer
|
||
|
||
|
||
dialog. Set one of the configurations to output to Serial. You don't no y have to click on the SET
|
||
SERIAL... button to change any of the Serial options because MCP uses the default settings.
|
||
|
||
|
||
Once the current configuration has been set to Serial, you print as if the printer was directly connected to
|
||
the MC - by selecting the Print menu item in any application which can print. As far as the MC software
|
||
is concerned, it is printing to a Serial printer. |
|
||
|
||
Printer configuration on the Series 3
|
||
|
||
|
||
On the Series 3, select the Printer setup option from the Special menu in the System screen. In this
|
||
dialog, set the Printer device line to Serial. You don't normally have to change the Serial characteristics
|
||
(it displays a subdialog when you press TAB) because MCPRINT uses the default settings.
|
||
|
||
|
||
You can now print as if the printer was directly connected to the Series 3 - by selecting the Print option
|
||
in any application which can print - including the built-in Word r, Agenda, Database, and
|
||
Program editor. (Remember first to use the Print setup options in these|applications, to tell the Series 3
|
||
about the type of printer and the page layout desired.) As far as the Series 3 software is concerned, it is
|
||
printing to a serial printer.
|
||
Parameters
|
||
MCPRINT takes the following parameters:
|
||
|
||
<prdev> -c<port> -t<timeout> -q
|
||
all of which are optional. To be reminded of these parameters, type:
|
||
|
||
|
||
MCPRINT ?
|
||
|
||
|
||
The <prdev> parameter
|
||
|
||
|
||
<prdev> is the print device name, as for the MS-DOS PRINT command. If omitted, the default is LPT1 (the
|
||
MS-DOS name for the first parallel port).
|
||
|
||
|
||
For example, to print to LPT2, type:
|
||
MCPRINT LPT2
|
||
|
||
|
||
If the PC is a station on a local area network, LPT2, LPT3 etc may be to redirect output to remote
|
||
printers attached to the network server.
|
||
|
||
|
||
The <prdev> parameter may specify any suitable output device. If you have a printer connected to a
|
||
second serial port on the PC, you can use:
|
||
|
||
|
||
MCPRINT COM2
|
||
|
||
|
||
In this case, you should have previously used the MS-DOS ModE command to set the serial parameters to
|
||
be used between the PC and the printer.
|
||
|
||
|
||
You can also print to a file on the PC using, for example:
|
||
MCPRINT PRINT.LIS
|
||
Note that PRINT.LIS will be overwritten each time you print.
|
||
To test the connection without wasting paper, type:
|
||
MCPRINT CON
|
||
|
||
|
||
CON is the MS-DOS name for the console (screen). When you then print! from the MC/HC/Series 3, you
|
||
should see the output appear on the screen of the PC.
|
||
|
||
|
||
The -c<port> parameter
|
||
|
||
|
||
<-c> is the serial port on the PC to which the MC/HC/Series 3 is connected. If omitted, the default is
|
||
port 1, which corresponds to com1. If the MC/HC/Series 3 is connected to the PC's second serial port,
|
||
|
||
|
||
type
|
||
MCPRINT -C2
|
||
|
||
|
||
10
|
||
|
||
|
||
1 MCLINK, MCPRINT, AND SLINK
|
||
a ee
|
||
The -t<timeout> parameter
|
||
|
||
|
||
<timeout> is a number of seconds. This parameter is provided for use on local area networks where it is
|
||
necessary to close and open the print device between each print job. It is used to specify an inactivity
|
||
ee in seconds. If there is no printing for this period, the print device is automatically closed. For
|
||
example:
|
||
|
||
|
||
MCPRINT LPT2 -T5
|
||
will close the print device after 5 seconds of inactivity.
|
||
|
||
|
||
If the parameter is omitted, the print device is not automatically closed. You don't have to specify a time-
|
||
out, as you can close the print device manually by pressing any key on the PC keyboard. Exiting
|
||
MCPRINT will also close the print device.
|
||
|
||
|
||
The MC/HC/Series 3 are multi-tasking - while one application is printing, you can carry on with
|
||
something else. However, the background printing can be held up at times, depending on the processing
|
||
requirements of the work you are doing. This can fool MCPRINT's inactivity time-out into thinking that
|
||
the printing has finished, causing it to prematurely close the print device. If you experience this problem,
|
||
consider increasing the time-out, or convert to closing the printer device manually by pressing a key on
|
||
the PC keyboard.
|
||
|
||
The -q parameter
|
||
|
||
|
||
This parameter suppresses status messages (the 'q' stands for "quiet").
|
||
|
||
|
||
ure ceran e sete e F g t te N e e
|
||
Slink.exe
|
||
|
||
|
||
SLINK is a “no-frills” server-only version of MCLINK.EXE. However, it may run on “PC"s which are
|
||
less than 100% PC-compatible and cannot run MCLINK, and it may run in combination with other
|
||
software which conflicts with MCLINK.
|
||
|
||
|
||
By default, SLINK uses the com1 port, at 9600 Baud. You can specify on the command line the Baud rate
|
||
and the serial port to use. These are in the same format as in the SET command in MCLINK. For
|
||
|
||
|
||
example:
|
||
SLINK -p2 -b9600
|
||
|
||
|
||
This sets SLINK to use com2. Note that, as with the SET command in MCLINK, -b9600 is used in this
|
||
example to keep the Baud rate at 9600.
|
||
|
||
|
||
If you just type SLINK -p2 this will reset the Baud rate to the internal default of 19200.
|
||
Press Q to quit SLINK.
|
||
SLINK has no support for modems.
|
||
|
||
|
||
11
|
||
|
||
|
||
ve
|
||
4
|
||
|
||
|
||
‘
|
||
|
||
a a
|
||
(8
|
||
|
||
t
|
||
|
||
oe
|
||
caer)
|
||
+
|
||
te
|
||
|
||
|
||
CHAPTER 2
|
||
|
||
|
||
RESOURCE FILES
|
||
|
||
|
||
This chapter covers a range of related topics:
|
||
= reasons programmers might consider using resource files
|
||
= the format of Sibo .rsc resource files
|
||
= the Olib rscfile class that can be used to read resource files
|
||
= the Sibo resource compiler tool, rcomp.exe, that can be used to create resource files
|
||
= general considerations about multi-lingual applications.
|
||
|
||
|
||
Although the topics are all related, it is by no means necessary to read and understand all the sections in
|
||
this chapter, just in order to understand one of these sections.
|
||
|
||
|
||
ye Ns ee he
|
||
Introduction
|
||
There are two main reasons why a programmer may wish to use resource files:
|
||
|
||
|
||
= Having data in a resource file, rather than as part of the program itself, cuts down on the size of
|
||
the data segment required by the program, and thus makes more efficient use of RAM.
|
||
|
||
|
||
= Resource files make it easier to write applications that can run in more than one language (eg
|
||
English, French, German...).
|
||
|
||
|
||
Text strings are a simple but important example of data that can be stored in a resource file. Suppose a
|
||
program contains lines of code such as
|
||
|
||
|
||
winfoMsg("Starting calculation"):
|
||
and
|
||
|
||
|
||
wSetBusyMsg("Scanning");
|
||
|
||
|
||
D.yh
|
||
|
||
|
||
or even
|
||
P_printf("%d items found",num);
|
||
|
||
|
||
The dataspace of this program, when compiled and linked, would contain the three strings "Starting
|
||
calculation", "Scanning", and "%d items found" - a grand total of some 45 bytes (note that a terminating
|
||
zero is stored for each string). A larger program may have many times this number of data strings; up to
|
||
2k would not be uncommon. Now this data would be permanently loaded into RAM all the time the
|
||
program is running. As a result, 2k less space would be available to the ordinary data of the program -
|
||
such as cells in a spreadsheet, or text in a word processor - thus reducing the amount of such data that the
|
||
program can accept before giving an “out of memory" error. Moreover, the operating system would be
|
||
more likely to refuse to load and run the program, on account of insufficient memory being available to
|
||
start it.
|
||
|
||
|
||
Next consider how the problem worsens for a program that is to be translated into more than one
|
||
language. Either the program has to carry the data for all the different target languages, with a choice
|
||
being made at run time between the various different possibilities:
|
||
|
||
|
||
13
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
if (language==LANG_ENGLISH)
|
||
wSetBusyMsg("Scanning");
|
||
|
||
else if (language==LANG_FRENCH)
|
||
wSetBusyMsg("Parcourt") >
|
||
|
||
else if (language==LANG_ GERMAN)
|
||
wSetBusyMsg("Suche") >
|
||
|
||
|
||
or else the code will have to be recompiled each time for a new lan e. But this latter approach makes
|
||
the problem of maintaining code much harder; each different change to the code, such as a bug fix,
|
||
will have to be propagated to all the different language versions. At the same time, the job of the
|
||
translator is not helped by the text to translate being all mixed up with the rest of the code, whilst if the
|
||
translator works on a separate list of text strings, there is the risk of ription errors when the
|
||
separate lists are merged back into the code.
|
||
|
||
|
||
For reasons such as these, serious programming in any system (Sibosdk or otherwise) frequently adopts
|
||
one or other resource file approach for text strings and other data items. The strings "Starting
|
||
calculation", "Scanning", "Xd items found", and so on, are kept in a file, not as part of the
|
||
dataspace of the program, and are loaded into RAM only when they are needed.
|
||
|
||
|
||
Thus the above call
|
||
wWInfoMsg("Scanning");
|
||
|
||
would be replaced by a call such as
|
||
InfoMsg(RESOURCE_SCANNING);
|
||
|
||
|
||
where RESOURCE_SCANNING is a symbolic constant (#define) giving the inde of the text string "Scanning" in
|
||
the resource file. (The exact meaning of the index varies between different resource file schemes. See
|
||
below for the meaning in Sibo resource files.) |
|
||
|
||
|
||
The contents of the routine InfoMsg would be something like
|
||
|
||
|
||
LOCAL_C VOID InfoMsg(INT index)
|
||
{
|
||
TEXT buf [60] ;
|
||
|
||
|
||
LoadResourceString(&buf [0] , index);
|
||
wInfoMsg(&buf [0] ) >
|
||
> :
|
||
|
||
|
||
and in turn LoadResourceString would read data from the appropriate feource file.
|
||
|
||
|
||
At the initialisation of the program, the name of the appropriate resource file would be determined, once
|
||
and for all, by reference to the current language (as obtained by a call to p_get language).
|
||
|
||
|
||
Some uses of resource files on Sibo computers
|
||
|
||
|
||
Each of the built-in or bundled applications on the MC and Series3 ranges has its own resource file, in
|
||
which are kept menu and dialog data, as well as more basic text strings The dialog data can contain
|
||
numerical layout information and numerical flags customising ee within dialogs.
|
||
|
||
|
||
Since the text strings and dialogs used by these different applications often overlap, there is also a so-
|
||
called system resource file, where common items are kept. Thus an ication loads data at various
|
||
times from each of two different resource files - its own application resource file, and the system one.
|
||
|
||
|
||
The .wdr printer driver files used by the printer subsystem in form. dyl (as on the Series3 - see the WOR
|
||
Printing chapter in this manual for more details) are also resource files, ;with the data items consisting of
|
||
escape sequences, font width tables, and other printer data.
|
||
|
||
|
||
Finally, low-level error messages are defined in another file in the ROM, sys$ctry.cfo. This file also
|
||
contains the keyboard layout tables, the fold tables, and other standard text such as the names of the days
|
||
of the week. See the Config Files chapter for more details.
|
||
|
||
|
||
14 |
|
||
|
||
|
||
2 RESOURCE FILES
|
||
|
||
|
||
i ca ee SNR Re eet ge Se Se Dn gd
|
||
Format of Sibo resource files
|
||
There are in fact three kinds of Sibo resource files:
|
||
= .cfo files, which are language configuration files (sometimes just called config files), with
|
||
sys$ctry.cfo being the principle example
|
||
= .rsc files, which are standard resource files
|
||
= .rzc files, which are Huffman compressed versions of .rsc files.
|
||
|
||
|
||
Access to the data in .cfo files is via Plib functions such as p_errs, p_gettext, and p_nmmon, as described
|
||
in the Plib Reference manual.
|
||
|
||
|
||
Data in .rsc and .rzc files can be accessed using the functionality of the rscfile class in olib.dyl, as
|
||
described later in this chapter.
|
||
|
||
|
||
The. Sibo resource compiler, rcomp.exe, can be used to create instances of .rsc files from plain text input
|
||
known as resource scripts, which typically have extension .7ss. This process is also described later in
|
||
this chapter. However, the format of .rsc files (described immediately below) is so straightforward that
|
||
programmers could easily create their own tools for producing customised .rsc files.
|
||
|
||
|
||
Unless explicitly stated to the contrary below, the remainder of this chapter focuses exclusively on the
|
||
.rsc type of resource files.
|
||
|
||
|
||
The format of .rsc files
|
||
|
||
|
||
A standard resource file just containing the three strings "Starting calculation", "Scanning", and "%d
|
||
items found", has the following contents (when dumped):
|
||
|
||
|
||
0: 31 00 08 00 53 74 61 72 74 69 6e 67 20 63 61 6c 1...Star ting cal
|
||
10: 63 75 6c 61 74 69 6f 6e 00 53 63 61 6e 6e 69 be culation .Scannin
|
||
20: 67 00 25 64 20 69 74 65 6d 73 20 66 6f 75 Ge 64 g.4d ite ms found
|
||
|
||
|
||
30: 00 04 00 19 00 220031 00 = Veep MSD vs
|
||
This conforms to the pattern:
|
||
<header><resources><index table>
|
||
where:
|
||
<header> is always four bytes long, with the first word giving the file offset of the start
|
||
of the index table, and the second word giving the length (in bytes) of the
|
||
index table
|
||
<index table> is a sequence of words, the first giving the file offset of the start of the first
|
||
resource, the second giving the file offset of the start of the second resource,
|
||
and so on, up to the last word, which gives the file offset of the end of the last
|
||
resource (which is also the beginning of the index)
|
||
<resources> are a series of variable length data items, whose contents can have any form.
|
||
|
||
|
||
Some strategies for reading .rsc files
|
||
Clearly, one way to implement a routine such as LoadResource is essentially as follows:
|
||
|
||
|
||
GLDEF_C VOID LoadResource(UBYTE *pb, INT index)
|
||
|
||
|
||
{
|
||
|
||
ULONG fpos; /* file offset */
|
||
|
||
UWORD tmp[2]; /* section of index table */
|
||
|
||
fpos=ixpos+(( index-1)*2); /* position into the index table */
|
||
p_seek(fcb,P_FABS, &fpos); 7
|
||
p_read(fcb,&tmp [0] ,4); /* read two words from index table */
|
||
|
||
|
||
p_seek(fcb,P_FABS, tmp[0] );
|
||
p_read( fcb, pb, tmp[1]-tmp [0] );
|
||
>
|
||
|
||
|
||
where:
|
||
|
||
|
||
= feb is the file control block of the open resource file
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION |
|
||
|
||
|
||
= xpos is the value of the first word in the resource file (ie the be offset of the beginning of the
|
||
|
||
|
||
index table), and has been read into memory during program initialisation, for the sake of
|
||
efficiency
|
||
|
||
|
||
a Se une cere oe ee et urce, 2 for the second resource,
|
||
and so on |
|
||
|
||
|
||
= the code would need modifications to cope with possible error values returned by the p_seek or
|
||
p_read calls (further discussed below).
|
||
|
||
|
||
This strategy relies on a value of ixpos being stored in program memory. Another strategy would be to
|
||
store the entire index table in memory - and this is the reason why the length of the index table is
|
||
recorded as the second word in the resource file. However, in practice there is no observable speed
|
||
degradation on account of reading index table data from the file every time a resource has to be loaded,
|
||
and so the earlier scheme is generally to be preferred - in view of the lesser demand it places on RAM
|
||
usage.
|
||
|
||
|
||
Example of reading resource files directly |
|
||
|
||
|
||
See the file readrsc.c in \sibosdk\demo for an example of how to read ne contents of a resource file
|
||
directly (i.e. without using the services of the rscfile class).
|
||
|
||
|
||
This example code assumes that the resource file is embedded in the applicstion’s program (.app) file.
|
||
Thus, when used in an application, the name of the resource file should be specified on the second line of
|
||
the application's .a/l file.
|
||
|
||
|
||
To use the example code, you must create a resource file with its first two resources both being short text
|
||
strings. Any additional resources are not read by the supplied code.
|
||
|
||
|
||
Using the rscfile class in Olib |
|
||
|
||
|
||
|
|
||
|
||
|
||
Although it is possible, along the lines discussed above, to read .rsc resource files using ordinary Plib
|
||
function calls, there are various reasons for instead using the functionality of the rscfile class in
|
||
olib. dyl:
|
||
|
||
|
||
= Using the rscfile class avoids needing to remember any details of the format of .rsc files
|
||
|
||
|
||
= The rscfile class also contains considerable logic, hidden from the casual user, to decode .7zc
|
||
Huffman compressed resource files - so that a decision can be taken at a later stage, to use .rzc
|
||
format files instead of .rsc format, without any need to alter or recompile existing code
|
||
|
||
|
||
ws The rscfile class automatically takes care of locating resource files suitably embedded in a .img
|
||
file - see below for more details |
|
||
|
||
|
||
= The interface to the rscfile class clarifies and documents all possible error conditions that
|
||
need to be catered for
|
||
|
||
|
||
» Learning about the rscfile class is a useful step along the rou | to learning about Psion's
|
||
proprietary object-oriented programming system - since this stem makes heavy use of the
|
||
rscfile class.
|
||
|
||
|
||
Basic services of the rscfile class
|
||
|
||
|
||
Before the functionality of the rscfile class can be used in a program, an instance of this class needs to
|
||
be created and initialised. This is dealt with below.
|
||
|
||
|
||
The outcome of the initialisation is a handle, rather like a handle to a file control block or to other 1/o
|
||
device control blocks. Subsequent rscfile services are directed via this handle.
|
||
|
||
|
||
The most primitive rscfile service is to load a resource, specified by index number (starting at 1 for the
|
||
first resource), into a supplied buffer. This is the rs_read_buf service. [In this case, it is assumed that the
|
||
caller has supplied a sufficiently long buffer.
|
||
|
||
|
||
Sometimes, however, it is more appropriate for the rscfile class to all | te a cell of sufficient length, for
|
||
the resource to be loaded into. This typically applies when a resource can have variable length, and
|
||
when the resultant alloc cell will have some permanence. The rs_read service fulfils this requirement.
|
||
|
||
|
||
16
|
||
|
||
|
||
»
|
||
|
||
|
||
2 RESOURCE FILES
|
||
|
||
|
||
As an example of the rs_read_buf service, consider the following routine InfoMsg:
|
||
|
||
|
||
LOCAL_C VOID InfoMsg(INT index)
|
||
{
|
||
TEXT buf [60];
|
||
|
||
|
||
p_send4(rcb,0_RS_READ_ BUF, index, &buf [0] );
|
||
winfoMsg(&buf [0] );
|
||
>
|
||
|
||
|
||
with rcb being the handle of a suitably initialised rscfile object.
|
||
|
||
|
||
As an example of the rs_read service, consider loading some menubar data in from a resource file. For
|
||
Hwif programs, this data is (in part) in the form of an H_MENU_DATA struct. The address of this struct has
|
||
to be written to the static _mdata (of type H_MENU_DATA*) whose existence the Hwif library presupposes. In
|
||
that case, the following call might be made during the initialisation of an Hwif application:
|
||
|
||
|
||
p_send4(rcb,0_RS_READ,MENU_DATA_INDEX,& mdata);
|
||
where MENU_DATA_INDEX is a symbolic constant giving the index of the appropriate resource.
|
||
|
||
|
||
Note that although the calling interface to rs_read_buf and rs_read may look similar, they require
|
||
different types for the penultimate parameter:
|
||
|
||
|
||
= rs_read_buf requires a parameter such as a TEXT* or a UBYTE*, ie with one level of indirection
|
||
from the actual loaded data
|
||
|
||
|
||
= rs_read requires a parameter such as a TEXT** or a UBYTE**, ie with two levels of indirection from
|
||
the actual loaded data.
|
||
|
||
|
||
Barring run-time errors (discussed below), the calls rs_read_buf and rs_read both return the length of the
|
||
resource read. Note that in the case of a (zero-terminated) string, this length includes the length of the
|
||
terminating zero, since that is part of the resource too.
|
||
|
||
|
||
Reading compressed resource files with the rscfile class
|
||
|
||
|
||
If a Huffman compressed resource file, typically with extension .rzc, is substituted for a standard
|
||
resource file (typically having extension .rsc), there is no need to alter or recompile in any way
|
||
application code making use of the rscfile class. The interface remains exactly the same.
|
||
|
||
|
||
The only point possibly worth mentioning is that the lengths returned by rs_read and rs_read_buf are the
|
||
length of the resources once decompressed, and not the length of the compressed resources on file.
|
||
|
||
|
||
Initialising an rscfile object
|
||
|
||
|
||
The following code can be used to create and initialise an rscfile object providing access to a resource
|
||
file with name rscname (assumed to be a full path name):
|
||
|
||
|
||
VOID *InitRcb( TEXT *rscname)
|
||
{
|
||
HANDLE OlibCat;
|
||
VOID *rcb;
|
||
INT ret;
|
||
|
||
|
||
Pp_findtibC"OLIB.DYL",&0libCat);
|
||
reb=p_newlibh(Ol ibCat,C_RSCFILE);
|
||
if (reb)
|
||
{
|
||
ret=p_entersend3(rcb,O_RS_INIT, rscname);
|
||
If (ret<0)
|
||
p_exit(ret);
|
||
>
|
||
return(rcb);
|
||
>
|
||
|
||
|
||
For overtly object oriented programs, the lines
|
||
|
||
|
||
p_findlib("OLIB.DYL",&0libCat);
|
||
rcb=p_newl ibh(OlibCat,C_RSCFILE);
|
||
|
||
|
||
17
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
a
|
||
|
||
|
||
can be replaced by a line such as
|
||
reb=p_new(CAT_HWIF_OLIB,C_RSCFILE); |
|
||
|
||
|
||
with the category number CAT_HWIF_OL18 being replaced by the suitable pomenre to olib.dyl from the
|
||
native category.
|
||
|
||
|
||
For Hwif programs, the line
|
||
|
||
|
||
rcb=p_new(1,C_RSCFILE);
|
||
can be used instead, taking advantage of the fact that the value of the (normally hidden) symbolic
|
||
constant CAT_HWIF_OLIB is 1.
|
||
Which header files are needed
|
||
|
||
|
||
The symbolic constants C_RSCFILE, O_RS_READ, O_RS_READ_BUF, and O_RS_INIT, are defined in the object-
|
||
oriented include file appman. g.
|
||
|
||
|
||
Duplicates of these definitions are given in the special SDK file rscfile.xg.
|
||
The value of 0_DEsTROY (defined in olib.g) is 0. (See below for use of 0| DESTROY.)
|
||
|
||
|
||
Run-time errors with the rscfile class
|
||
|
||
|
||
Broadly speaking, there are five kinds of run-time error that can arise with resource files:
|
||
|
||
|
||
1 there is insufficient memory to create or initialise the rscfile object
|
||
|
||
|
||
2 the resource file cannot be found (when the program starts)
|
||
3 ‘the data in the resource file is bad
|
||
4 the SSD containing the resource file is removed or cannot be accessed
|
||
5 there is insufficient memory to load a specified resource.
|
||
|
||
|
||
Of these possibilities, the third is regarded simply as a programming error. Thus if some data in what
|
||
should be the index table part of the file effectively says that a certain resource has length 5398 bytes,
|
||
whereas the file itself is smaller than this size, the rscfile object will panic the application (with panic
|
||
number 141).
|
||
|
||
|
||
Otherwise, errors 1 and 2 can occur when initialising a rscfile object, whereas error 4 and 5 can occur
|
||
when subsequently using the object.
|
||
|
||
|
||
Possible errors during initialisation
|
||
|
||
|
||
The only reason the calls p_newl ibh or p_new in the above routine InitRcb will fail is on account of lack of
|
||
memory. Applications can choose to discount this possibility if their minimum heap is appropriately
|
||
calibrated - see below. |
|
||
|
||
|
||
The call to rs_init can fail with file-based errors on account of the filename in *rscname. The most
|
||
pertinent possibility (assuming that a well-formed name has been ) is that the specified file does
|
||
not exist. Applications could guard against this by checking on the existence of the file prior to calling
|
||
InitReb. If the file does not exist, the user can be notified, and the "T exited.
|
||
|
||
|
||
Errors during rs_read or rs_read_buf
|
||
|
||
|
||
The only errors that an application should in practice worry about, for he rs_read and rs_read_buf
|
||
services, are the fourth and fifth in the above list.
|
||
|
||
|
||
Running out of memory can occur only in the case of rs_read - when it is impossible to allocate a call
|
||
from the heap large enough to load the resource into. The implementation of rs_read_buf is guaranteed
|
||
never to fail with out of memory.
|
||
|
||
|
||
If calls to rs_read are made during program initialisation only, it may well be legitimate to ignore the
|
||
possibility of out of memory errors in this case too - provided the decl minimum heap of the
|
||
application is large enough. The point is that only memory in the dataspace of the application has to be
|
||
allocated - not any memory in another process such as the File Server (see the chapter Fundamental
|
||
Programming Guidelines in the General Programming Manual for related discussion).
|
||
|
||
|
||
However, applications calling either rs_read or rs_read_buf ought always to consider the possibility of
|
||
the user removing the SSD containing the resource file. What will happen in this case is as follows:
|
||
|
||
|
||
|
|
||
18
|
||
|
||
|
||
-
|
||
|
||
|
||
2 RESOURCE FILES
|
||
|
||
|
||
= suppose the user removes the relevant SSD, not realising (or forgetting) that the program may
|
||
wish to access data on it
|
||
|
||
|
||
= the application makes a call to rs_read or rs_read_buf
|
||
|
||
|
||
= system code, detecting that the file is missing, presents a Notifier requesting the user to replace
|
||
the SSD; this Notifier has two exit options: Retry and Fail
|
||
|
||
|
||
= the user ought to replace the SSD and select Retry; however, it is possible that the Fail option
|
||
will be selected
|
||
|
||
|
||
= in this case, an error such as E_FILE_ABORT will be generated.
|
||
|
||
|
||
How rscfile errors are reported
|
||
|
||
|
||
The rscfile services rs_read and rs_read_buf do not return any error values; instead, they internally call
|
||
p_leave.
|
||
|
||
|
||
Applications performing sophisticated error handling, using p_enter, should be sure that p_send calls to
|
||
rs_read or rs_read_buf are (ultimately) enclosed in some call to p_enter - otherwise any errors will result
|
||
in their application being panicked, with panic number 47.
|
||
|
||
|
||
Applications not wishing to use p_enter should replace the above calls to p_send with calls to
|
||
p_entersend, as follows:
|
||
|
||
|
||
ret=p_entersend4(rcb,O_RS_READ_ BUF, index, &buf [0] );
|
||
and
|
||
ret=p_entersend4(rcb,O_RS_READ,MENU_DATA_INDEX,& mdata);
|
||
Possible values of ret that can be returned are as follows:
|
||
positive value the length of the resource loaded (no error has occurred)
|
||
|
||
|
||
negative value an error has occurred: either E_GEN_NOMEMORY for out of memory, or some other
|
||
value in case the resource file could not be accessed.
|
||
|
||
|
||
Note incidentally that the complications over possible errors while reading resource files are by no means
|
||
exclusive to the .7sc format of resource files. An application could devise its own format of data file,
|
||
and its own library of routines to extract data from these files, but these routines would have to cope with
|
||
all the same error possibilities as for the rscfile routines. That is, the error possibilities stem not from
|
||
the rscfile class, but from the notion of resource files itself.
|
||
|
||
|
||
Dealing with errors in rs_read or rs_read_buf
|
||
|
||
|
||
(This section should be skipped on a first reading.)
|
||
|
||
|
||
There follows a more detailed example of how to deal with possible errors during an rs_read call. The
|
||
case for rs_read_buf is similar, albeit simpler (since there is no possibility of an out of memory error in
|
||
this case).
|
||
|
||
|
||
19
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
LOCAL_C VOID ReadResource(VOID *ppcell,INT index)
|
||
{
|
||
INT ret;
|
||
|
||
|
||
FOREVER
|
||
|
||
{
|
||
ret=p_entersend4(rcb,0_RS_READ, index, ppcell);
|
||
if (ret>=0)
|
||
|
||
return;
|
||
|
||
while (ret<0) |
|
||
|
||
{
|
||
if (ret==E_GEN_NOMEMORY)
|
||
|
||
{
|
||
|
||
*ppcel l=NULL;/* signal failure to caller */
|
||
|
||
Tel lNoMemory();
|
||
|
||
return;
|
||
|
||
>
|
||
wsAlertW(WS_ALERT_CLIENT,O,ReplaceDisk,0);
|
||
p_send2(rcb,0O_DESTROY);
|
||
FOREVER
|
||
|
||
{
|
||
|
||
rcb=p_newlibh(Ol ibCat,C_RSCFILE);
|
||
|
||
if (reb)
|
||
|
||
break;
|
||
|
||
Tel lNoMemory();
|
||
|
||
>
|
||
ret=p_entersend3(rcb,0_RS_INIT,rscname);
|
||
>
|
||
|
||
|
||
>
|
||
|
||
|
||
as follows:
|
||
|
||
|
||
One way to implement the routine Tel \NoMemory - which must never al run out of memory - would be
|
||
LOCAL_C VOID Tel lNoMemory(VOID)
|
||
{ !
|
||
TEXT buf [40];
|
||
p_errs(&buf [0] ,E_GEN_NOMEMORY ) ;
|
||
wsAlertW(WS_ALERT_CLIENT,0,&buf [0] ,0); |
|
||
>
|
||
|
||
|
||
The way ReadResource works, in cases when the user has removed the lo and has refused to replace it,
|
||
is to present another alert, wait for the user to respond (by pressing ESC), and then try to re-~make the
|
||
|
||
|
||
connection with the resource file. For this purpose, various statics are :
|
||
|
||
OlibCat The value of the category handle of olib.dyl, as returned by the earlier call to
|
||
p_findlib |
|
||
|
||
rscname The full path name of where the resource file/should be
|
||
|
||
ReplaceDisk Text that might read, in English, "Replace the application disk”.
|
||
|
||
|
||
Clearly, for multi-lingual applications, the string ReplaceDisk must itself be read from a resource file.
|
||
Since the channel to the application resource file is broken at this stage, |it may be necessary to read in
|
||
this text during program initialisation. !
|
||
|
||
|
||
Standard practice for applications on a Series3 is to bracket calls to wsAlertW with increments and
|
||
decrements to the reserved static DatLocked:
|
||
|
||
|
||
DatLocked++;
|
||
wsAlertW(...);
|
||
DatLocked--;
|
||
|
||
|
||
Incidentally, the error handling mechanism described above is implemented automatically for object
|
||
oriented programmers who use the appman class and its methods am_load|resource and am_res_buf to
|
||
|
||
data from resource files (except that the error recovery code in appman is even better, in that it caters with
|
||
the case of the SSD being removed from one drive and replaced in another).
|
||
|
||
|
||
20
|
||
|
||
|
||
2 RESOURCE FILES
|
||
|
||
|
||
orn me a ee en ag ry ee en ee ae ae ee |
|
||
Advice on where to locate resource files
|
||
|
||
|
||
Mono-lingual applications
|
||
|
||
|
||
In the case of a mono-lingual application, the safest place to locate a resource file is within the image file.
|
||
The rscfile class will find any resource file in the second of the four possible add-file slots in an image
|
||
file.
|
||
|
||
|
||
For example, if the application is called archive.app and the resource file is called archive.rsc, an add-
|
||
file list archive.afl should be created, with the following contents:
|
||
|
||
|
||
archive.pic
|
||
archive.rsc
|
||
|
||
|
||
where archive. pic will be placed in add-file slot 1, and archive.rsc in add-file slot 2.
|
||
|
||
|
||
The named files will be added to the resultant image file, whenever this is made, just by virtue of the
|
||
existence of an .ajl file with the same basic name as the image file.
|
||
|
||
|
||
In this case, the appropriate name to pass to rs_init is simply DatCommandPtr (recall that a zero-terminated
|
||
string giving the full path name of the image file is placed at this reserved static, by the operating system,
|
||
when the process is started):
|
||
|
||
|
||
p_entersend3(rcb,0_RS_INIT,DatCommandPtr);
|
||
|
||
|
||
Not only does this scheme have the advantage of simplicity, it also prevents accidents if users copy the
|
||
main image file to an SSD, but neglect to copy the associated resource file.
|
||
|
||
|
||
For a multi-lingual application, the above continues to apply in any case when a different .img file is re-
|
||
made (using the tool eremake) for each new language version. (For more details about eremake, see the
|
||
chapter Building an Application in the General Programming Manual.)
|
||
|
||
|
||
However, for multi-lingual applications in which the resource data for more than one language is shipped
|
||
together, the resource files must in general be separate from the main .img file. (There is no scope for an
|
||
indefinite number of add-files.) The documentation for the application should emphasise to users that if
|
||
the .app file (or the .img file) is copied from one SSD to another, for consolidation purposes, then
|
||
appropriate .7sc (or .rzc) files should also be copied.
|
||
|
||
|
||
Multi-lingual applications
|
||
|
||
|
||
One scheme that has much to recommend it is to rename the resource files as follows:
|
||
|
||
|
||
archivO2.rsc for a French language resource file
|
||
archiv03.rsc for a German language resource file
|
||
archiv18.rsc for a Dutch language resource file
|
||
|
||
|
||
and so on (for an application archive. app), where the numbers at the end of the filename are the language
|
||
codes of the target languages, listed in the documentation of p_get\anguage in the Plib Reference manual.
|
||
|
||
|
||
These files should be located in a sub-directory underneath the directory containing the application
|
||
program file. The name of this subdirectory should be the same as the basic name of the program file.
|
||
For example, if the full pathname of the program file is \app\archive.app, the full pathnames of the
|
||
resource files should be \app\archive\archiv??.rsc. Again, resource files used by a program with full
|
||
pathname \img\backup.img should be located as \img\backup\backup??.rsc.
|
||
|
||
|
||
Then code to determine the name of the resource file, suitable to the language of the computer at run
|
||
time, could be as follows:
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
TEXT *FindRscName(VOID)
|
||
€
|
||
LOCAL_D TEXT RscNameBuf [P_FNAMESIZE];
|
||
TEXT *RscName;
|
||
|
||
P_INFO f;
|
||
|
||
|
||
RscName=(&RscNameBuf [0] );
|
||
|
||
p_atos(RscName, "\\app\\archive\\archivz02d.rsc",p_ get Llanguage());
|
||
|
||
p_fparse(RscName,DatCommandPtr ,RscName, NULL);
|
||
|
||
if (p_finfo(RscName, &f)<0) |
|
||
p_scpy(RscName,DatCommandPtr); |
|
||
|
||
return(RscName) >;
|
||
|
||
>
|
||
|
||
|
||
Note the check on the existence of the first filename generated by this routine; in case the language as
|
||
returned by p_get language is not supported by the application, the routine defaults back to whatever
|
||
resource file is built into the application.
|
||
|
||
|
||
Copying of applications
|
||
|
||
|
||
The above recommendation for where resource files should be located conforms to the important general
|
||
rule that if users wish to copy an application \path\name. ext from one SSD to another (say from drive a:
|
||
to drive b-), all they need to do is type
|
||
|
||
|
||
copy a:\path\name.ext b:\path\name.ext |
|
||
copy a:\path\name\*.* b:\path\name\*.*
|
||
|
||
|
||
in which case (assuming the application is not copy-protected!) all the files required or presupposed by
|
||
the application will be transferred. |
|
||
|
||
|
||
General comments on multi-lingual applications
|
||
It is a common programming error to design an application too closely around the text of one language
|
||
|
||
|
||
(eg English), and to discover only at some late stage that various tions made fail when the
|
||
application is translated into another language.
|
||
|
||
|
||
For example, if the English text "weekly" is to be read into some resource, it may be tempting to write
|
||
some code as follows:
|
||
|
||
|
||
TEXT buf [8];
|
||
|
||
|
||
|
|
||
|
||
|
||
p_entersend4(rcb,O_RS_READ_BUF ,WEEKLY_INDEX, &buf [0] );
|
||
|
||
|
||
However, when the application is translated into German (say), with the entry for "Weekly" in the
|
||
resource file being changed into "Wochentlich", the new application most likely crash when the above
|
||
code is run. The reason is that the buffer of eight bytes, which was long enough to contain the text
|
||
MWeekly", is not long enough to contain "Wéchentl ich". |
|
||
|
||
|
||
Better therefore to decide in advance what a reasonable limit on the translation of this term should be,
|
||
and use that as the size of the buffer in the code (not forgetting to oe the translators what the limit
|
||
iS).
|
||
|
||
|
||
The basic principle of independence of code from resource file
|
||
|
||
|
||
One basic guideline is that the code itself should not have to be altered, just because a new translation has
|
||
been undertaken. The original code should be general enough to start with.
|
||
|
||
|
||
The main problem with allowing code to change at a later date, to simplify the task of translators, is that
|
||
it is often difficult to foresee the side-effects of such a change. In practice, the most intense testing an
|
||
application receives is just prior to its launch in the original language; if changes are made at a later date,
|
||
these may introduce bugs which slip through subsequent testing, on t of that testing being less
|
||
severe.
|
||
|
||
|
||
For this approach to work, a special test plan has to be devised, focussing on the purely language
|
||
dependent parts of the application. This test plan should include means |of loading, one by one, all the
|
||
resources from the resource file, and displaying them on the screen for validation.
|
||
|
||
|
||
22
|
||
|
||
|
||
2 RESOURCE FILES
|
||
|
||
|
||
Provided changes made in response to problems thrown up by this test plan are restricted to the resource
|
||
files themselves, there can be some confidence that the original intensive testing still holds good. But if
|
||
code has to be changed, there is the risk of regression - something that used to work now no longer
|
||
works.
|
||
|
||
|
||
Careful design of screen layout
|
||
|
||
|
||
Design of screen layout is another area where things can go unexpectedly wrong when the contents of a
|
||
resource file is changed.
|
||
|
||
|
||
In some cases, screen layouts which (just) work in one language, become untenable in another language,
|
||
because there simply is no acceptable way of translating the text on the screen and still fitting within the
|
||
allowed display area. For this reason, displays which are already cramped in the original language
|
||
should be avoided: if they are cramped in one language, they will likely become "grid locked" in some
|
||
other language, with slightly longer words.
|
||
|
||
|
||
Even if there is ample room in some screen display, care should be taken to calculate various dimensions
|
||
dynamically, ie at run-time, using the widths of the actual characters used, rather than statically (ie at
|
||
compile-time).
|
||
|
||
|
||
Codesize problems
|
||
|
||
|
||
For related reasons, an application which, together with its resource file, only just fits on an SSD of a
|
||
certain size (say 128k), will be unlikely to fit on a similarly-sized SSD when the resource file has been
|
||
translated into another language.
|
||
|
||
|
||
Of course, as with the other problems above, it is always possible to insist that a sufficiently brief
|
||
translation be found, but this can result in abbreviations the user is likely to consider ridiculous. It is far
|
||
better to include some “spare” in the original budget, to allow for some measure of growth as the
|
||
translation takes place.
|
||
|
||
|
||
Varying keyboards
|
||
|
||
|
||
As well as the text of messages varying from one language to another, it is also possible for the keyboard
|
||
layout to alter. This does not just mean changing from QWERTY to AZERTY, but changes in which characters
|
||
can be typed in combination with various modifiers.
|
||
|
||
|
||
For example, an application in one translation may define the hot-key PSION+/ as the accelerator for
|
||
some menu command. However, a foreign language keyboard may move the / key into a place where it
|
||
cannot be pressed in conjunction with the PSION modifier. Thus on the Series3 keyboard, PSION together
|
||
with some keys changes the characters delivered, into altogether different ones. Therefore, the
|
||
accelerator would have to alter to some other keypress.
|
||
|
||
|
||
Something else that may have to change, on account of the keyboard changing, is references to the
|
||
keyboard within eg Help text (or inside “Action buttons"). For example, the DELETE key may become
|
||
the EFF key in a different language variant.
|
||
|
||
Conclusion
|
||
|
||
|
||
The possible problems of multi-lingual code form another item in the list of things that need to be
|
||
constantly under background consideration as an application is written.
|
||
|
||
|
||
The discipline of separating text into a resource file is a vital step in the right direction, but by itself, it
|
||
does not guarantee that all related problems will be solved. Every time text is used in an application, the
|
||
|
||
|
||
writer must ask the question: not what is the length of this text, but what might the length of this text be
|
||
in some foreign translation - and what would the consequences of that be?
|
||
|
||
|
||
CA a 9 A npn VO ae ee enn
|
||
Creating .rsc files using rcomp.exe
|
||
|
||
|
||
The resource compiler is a tool rcomp.exe that operates on a so-called resource script, which is a text
|
||
file, to produce a resource file as output.
|
||
|
||
|
||
The process is akin to ordinary compilation:
|
||
*.c + compiler -> *.obj
|
||
*.rss + resource compiler -> *.rsc
|
||
|
||
|
||
with .7ss being the usual extension for a resource script.
|
||
|
||
|
||
23
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
As an example, suppose a file eg.7ss has the following contents:
|
||
STRUCT STRING
|
||
|
||
|
||
>
|
||
|
||
|
||
RESOURCE STRING res_start_cale {str="Starting calculation":)
|
||
RESOURCE STRING res_scanning {str="Scanning":}
|
||
|
||
|
||
{
|
||
TEXT str; /* zero terminated text string */
|
||
RESOURCE STRING res_items_found {str=""%d items found!':}
|
||
|
||
|
||
Then invoking the command line |
|
||
rcomp eg
|
||
produces as output a file eg.rsc whose contents are exactly as described in the earlier section on the
|
||
format of .rsc files.
|
||
Note: some earlier versions of rcomp. exe do not accept the syntax
|
||
|
||
RESOURCE <struct-name> <identifier> <definition> .
|
||
instead requiring the addition of the keyword GLOBAL:
|
||
|
||
|
||
GLOBAL RESOURCE <struct-name> <identifier> <definition>
|
||
|
||
|
||
Generated .rsg files
|
||
|
||
|
||
|
|
||
As well as producing a .rsc resource file, running rcomp. exe also has | effect of creating a generated
|
||
header file, with extension .rsg. :
|
||
|
||
|
||
Thus the output of typing rcomp eg is not only the file eg.rsc but also the file eg.rsg, having the
|
||
following contents:
|
||
|
||
|
||
#idefine RES_START_CALC 1
|
||
#define RES SCANNING 2
|
||
#define RES_ITEMS FOUND 3
|
||
|
||
|
||
In turn, C source files that need to specify resource indices ought to #include these generated .rsg files,
|
||
so that they can include code such as
|
||
|
||
|
||
InfoMsg(RES_ SCANNING);
|
||
|
||
|
||
The present value of RES_SCANNING is 2. Suppose however that a new resource is added at the beginning
|
||
of eg.rss. This means that the resource "Scanning" is of course no longer the second in the resultant .rsc
|
||
file, but the third. Accordingly, any calls such as
|
||
|
||
|
||
InfoMsg(2)>; |
|
||
have to change into calls such as
|
||
InfoMsg(3);
|
||
in order that they have the same effect as before. Note that having th e lines of code instead as
|
||
InfoMsg(RES_SCANNING);
|
||
and recompiling the C source files after changing the resource script automatically ensures that the
|
||
desired outcome transpires.
|
||
|
||
|
||
The syntax of the rcomp command
|
||
The syntax for invoking rcomp. exe includes:
|
||
|
||
|
||
rcomp [-s]<name> [-o<oname> -h<hname>]
|
||
|
||
|
||
where
|
||
|
||
<name> is the name of the resource script
|
||
<oname> is the name of the resource file output
|
||
<hname> is the name of the generated header file.
|
||
|
||
|
||
One possible use of the fuller syntax is to redirect the generated header . to an .. \include\ directory.
|
||
|
||
|
||
24
|
||
|
||
|
||
2 RESOURCE FILES
|
||
|
||
|
||
Include files within a resource script
|
||
|
||
|
||
A resource file can contain lines such as
|
||
#include "archive.dh"
|
||
|
||
or
|
||
#include <archive.rh>
|
||
|
||
|
||
(no particular significance should be attached to the extensions used in these examples). As would be
|
||
expected, files specified using the quote form of #include are expected to be found in the local directory.
|
||
However, files specified using the angle bracket form of #include are expected to be found in the
|
||
directory (if any) specified by the value of the DOS environment variable INCLUDE.
|
||
|
||
|
||
If required, a batch file such as follows could be used to invoke rcomp. exe:
|
||
|
||
|
||
set OINCLUDE=%INCLUDE%
|
||
set INCLUDE=..\include
|
||
\sibosdk\sys\rcomp 41
|
||
set INCLUDE=ZOINCLUDE%
|
||
set OINCLUDE=
|
||
|
||
|
||
preserving any previous value of INCLUDE for other purposes that may apply on a PC.
|
||
|
||
|
||
Conditional compilation in resource files
|
||
Note that the resource compiler supports conditional compilation such as
|
||
|
||
|
||
#ifdef BUILD_ONE
|
||
|
||
#endif
|
||
and
|
||
|
||
#ifndef BUILD_ONE
|
||
|
||
fendi f
|
||
Names (such as BUILD_ONE) may be defined when invoking the resource compiler using a -d flag as
|
||
follows:
|
||
|
||
rcomp resfile -dBUILD_ONE
|
||
This has the same effect as including the corresponding #define in the resource file, for example:
|
||
#define BUILD_ONE
|
||
|
||
|
||
i a ee |
|
||
Contents of .rss files
|
||
Resource scripts (together with other files they #include) are made up of three types of statement:
|
||
= comments (identified by C-style /* and */ delimiters)
|
||
= declarations of STRUCTs and constants
|
||
= declarations of RESOURCES, which are instances of the sTruCTs defined.
|
||
All the declarations of structs have to precede the first definition of a RESOURCE.
|
||
|
||
|
||
White space is ignored (after the first white space character), except within quoted strings. Thus the
|
||
definitions
|
||
RESOURCE STRING res_start_cale {str="Starting calculation";}
|
||
|
||
|
||
and
|
||
|
||
|
||
RESOURCE STRING res_start_calc
|
||
{
|
||
str="Starting calculation":
|
||
|
||
|
||
}
|
||
|
||
|
||
25
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
are equivalent. Any indentation of source lines in resource scripts is purely for convenience.
|
||
|
||
|
||
Declaring STRUCTs
|
||
|
||
|
||
STRUCTS are formed of a name and a series of member definitions. STRUCT names must always be given in
|
||
upper case, whereas member names are given in lower case. For example,
|
||
|
||
|
||
STRUCT STRING
|
||
|
||
{ ,
|
||
TEXT str; |
|
||
>
|
||
|
||
|
||
defines a STRUCT with name STRING and just one member, which has type TEXT and member name str.
|
||
|
||
|
||
Again, the definition
|
||
|
||
|
||
STRUCT MENU_BAR_ITEM
|
||
{
|
||
LINK menu_id;
|
||
TEXT mb_item;
|
||
>
|
||
|
||
|
||
defines a STRUCT with name MENU_BAR_ITEM and with two members, the
|
||
with type TEXT.
|
||
|
||
|
||
t with type LINK and the second
|
||
|
||
|
||
As is discussed below, member definitions can also include default initialisations.
|
||
|
||
|
||
Possible member types in STRUCTs
|
||
The set of allowed struct member types is as follows:
|
||
|
||
|
||
cluding the terminating zero
|
||
|
||
|
||
BYTE stores a numerical value in one byte
|
||
|
||
WORD stores a numerical value in two bytes
|
||
|
||
LONG stores a numerical value in four bytes
|
||
|
||
DOUBLE stores a floating point numerical value in eight bytes
|
||
TEXT stores a zero-terminated sequence of bytes, i
|
||
|
||
LINK stores a two-byte reference to another RESOURCE
|
||
STRUCT stores a sub-STRUCT in-line.
|
||
|
||
|
||
Of these types, only TEXT and struct have variable length (see below fo
|
||
WORDS are stored low byte first then high byte. Similarly, LONGs are sto
|
||
|
||
|
||
more on variable length items).
|
||
|
||
|
||
low word first, then high word.
|
||
|
||
|
||
The resource compiler accepts any value from -128 to +255 for a BYTE,|so that C programs are free to
|
||
|
||
|
||
interpret the contents as either signed or unsigned. WORD and LONG can si
|
||
signed or unsigned.
|
||
|
||
|
||
ilarly be interpreted either as
|
||
|
||
|
||
The resource compiler can undertake some limited arithmetical evaluation of data supplied in numeric
|
||
|
||
|
||
fields (eg val=4*3.18).
|
||
|
||
|
||
TEXT data can be entered as a combination of quoted strings, binary =
|
||
str="This is a string.":
|
||
|
||
or
|
||
Str=<84><104>"is a str"<0x69>"'ng""<46>; }
|
||
|
||
or even |
|
||
|
||
|
||
#tdef ine DOUBLE_QUOTE <34>
|
||
|
||
|
||
str="Missing "DOUBLE_QUOTE;
|
||
|
||
|
||
Standard C-style processing of backslashes applies within quoted strings. Thus to enter a single
|
||
backslash in a string, the backslash character has to be repeated in the input, and so on. Thus the final
|
||
|
||
|
||
example above could also be given as
|
||
|
||
|
||
str="Missing \":
|
||
|
||
|
||
26
|
||
|
||
|
||
2 RESOURCE FILES
|
||
|
||
|
||
Allowed values of LINK items are constants, symbolic constants, or (lower-case) identifiers of other
|
||
resources. In referring to another resource, both forward and backward references are possible.
|
||
Declaring RESOURCEs
|
||
A RESOURCE is declared by specifying:
|
||
|
||
= the name of the struct being instanced
|
||
|
||
= the identifier of the RESOURCE
|
||
|
||
8 initialisers: values of all the members of the STRUCT.
|
||
|
||
|
||
The name of the STRUCT must always be given in upper case, whereas the identifier of the RESOURCE must
|
||
always be given in lower case.
|
||
|
||
|
||
For example:
|
||
RESOURCE MENU_BAR_ITEM file_mbar_item
|
||
menu_id=file_menu;
|
||
|
||
|
||
mb_item="File't;
|
||
>
|
||
|
||
|
||
During resource compilation, the various identifiers encountered are assigned the values 1, 2, 3, ....
|
||
|
||
|
||
There is no requirement to list the members of the STRUCT in the same order as their definition. Nor is it
|
||
always necessary to give values for every member:
|
||
|
||
|
||
= any member omitted will be given the default value supplied for that member, in the declaration
|
||
of the struct, if any
|
||
|
||
|
||
= failing this, a “default default" value of zero will be supplied
|
||
= however, it is an error to omit altogether to give a value for a LINK member.
|
||
For example, it is possible to declare an instance of
|
||
|
||
|
||
STRUCT NCEDIT
|
||
{
|
||
WORD current;
|
||
WORD low;
|
||
WORD high=65535;
|
||
>
|
||
|
||
|
||
just by the line
|
||
RESOURCE NCEDIT nc_edit { }
|
||
|
||
|
||
in a resource script, in which case a 6-byte long resource will be created, with the three consecutive
|
||
words containing the values 0, 0, and 65535.
|
||
|
||
|
||
Again, the result of resource compiling the following:
|
||
|
||
|
||
STRUCT TEST
|
||
{
|
||
TEXT str;
|
||
BYTE byt;
|
||
STRUCT more;
|
||
>
|
||
|
||
|
||
RESOURCE STRUCT TEST empty ¢€ }
|
||
is a 2-byte long resource, with each byte being set to zero. (Note that "zero" sub-STRUCTs are omitted in
|
||
their entirety, ie taking up zero length in the resource file.)
|
||
|
||
|
||
Declaring the values of sub-STRUCTs
|
||
Whereas the way to define the value of most members of RESOuRCEs is by a statement in the form
|
||
|
||
|
||
<member-name> = <constant>;
|
||
|
||
|
||
27
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
the way to define the value of a sub-strucT member is
|
||
|
||
|
||
<member-name> = <struct-name> {<initialisations>);
|
||
|
||
|
||
|
|
||
with the form of <initialisations>, if present, matching that of the definition of a RESOURCE itself. For
|
||
|
||
|
||
example:
|
||
|
||
|
||
STRUCT NCEDIT
|
||
{
|
||
WORD current;
|
||
WORD low;
|
||
WORD high=65535;
|
||
>
|
||
|
||
|
||
STRUCT TEST
|
||
{
|
||
TEXT str;
|
||
BYTE byt;
|
||
STRUCT more;
|
||
>
|
||
|
||
|
||
RESOURCE TEST values
|
||
{
|
||
str="This is a string":
|
||
byt=42;
|
||
more=NCEDIT {(current=100;};
|
||
|
||
|
||
>
|
||
Sometimes when there is a sub-STRUCT member in a STRUCT, there will only be one intended struct to fill
|
||
this slot, but in other cases, there may be more than one possible type of sub-sTRUCT.
|
||
|
||
|
||
Leading byte and word length values .
|
||
|
||
|
||
In cases when STRUCTs contain sub-STRUCTs, it is frequently helpful to have the instance of the sub-STRUCT
|
||
preceded by a byte or word giving the length of the instance. This is achieved by amending the
|
||
definition of the sub-sTRUCT: the keyword BYTE or woRD should be included before the opening curly
|
||
bracket prior to the definitions of the members of the STRUCT.
|
||
|
||
|
||
For example, resource compiling |
|
||
|
||
|
||
STRUCT FIRST BYTE
|
||
r
|
||
BYTE one;
|
||
>
|
||
|
||
|
||
STRUCT SECOND WORD
|
||
€£
|
||
|
||
BYTE two;
|
||
|
||
>
|
||
|
||
|
||
STRUCT THIRD
|
||
{
|
||
BYTE three: |
|
||
.
|
||
|
||
|
||
STRUCT FOURTH BYTE
|
||
r
|
||
_ STRUCT a;
|
||
STRUCT b;
|
||
STRUCT c:
|
||
|
||
)
|
||
|
||
|
||
RESOURCE FOURTH test
|
||
{
|
||
a=FIRST {one=1;); |
|
||
b=SECOND {two=2;); |
|
||
=THIRD {three=3;};
|
||
>
|
||
|
||
|
||
—$ $$ $e
|
||
|
||
|
||
2 RESOURCE FILES
|
||
SSeS
|
||
|
||
|
||
results in the following 6-byte long resource:
|
||
<01><01><01><00><02><03>
|
||
|
||
|
||
in which the first byte gives the length of the following sub-resource, the third and fourth bytes together
|
||
constitute a word giving the length of the second sub-resource, and the final sub-resource has no
|
||
preceding byte- or word- length value.
|
||
|
||
|
||
Note that the resource as a whole lacks a leading byte- or word- length value, despite the presence of the
|
||
BYTE qualifier in the definition of FourRTH. These leading length values are emitted only when the instance
|
||
of the STRUCT is as a sub-resource.
|
||
|
||
|
||
Incidentally, it is common for definitions such as
|
||
|
||
|
||
STRUCT FIRST BYTE
|
||
{
|
||
BYTE one;
|
||
>
|
||
|
||
|
||
to be given instead in the equivalent form
|
||
|
||
|
||
STRUCT FIRST
|
||
BYTE ¢
|
||
BYTE one;
|
||
>
|
||
Arrays within resource files
|
||
|
||
|
||
The resource compiler is at perhaps its most powerful in dealing with arrays of resources - strictly
|
||
speaking, arrays of sub-resources.
|
||
|
||
|
||
In order to declare an array of sub-resources, a member definition in a STRUCT definition such as
|
||
<type> <member-name>;
|
||
has to be changed into one of the forms
|
||
<type> <member-name> [<array-size>];
|
||
<type> <member-name>[ };
|
||
LEN <type> <member-name>[ ];
|
||
or
|
||
LEN BYTE <type> <member-name> [ J;
|
||
For example,
|
||
|
||
|
||
STRUCT HELP_ARRAY
|
||
{
|
||
LINK topic_id=0;
|
||
TEXT topic; |
|
||
LEN BYTE STRUCT strist{];
|
||
>
|
||
|
||
|
||
in which the initial LINK and TEXT sub-resources are followed by a variable number of sub-sTrUCTs (the
|
||
number varying between different instances of HELP_ARRAY).
|
||
|
||
|
||
In all cases with arrays, the corresponding initialiser statement in a RESOURCE definition
|
||
<member-name> = <constant>;
|
||
|
||
changes into the form
|
||
<member-name> = { <constant>, <constant>, ..., <constant> );
|
||
|
||
|
||
with <constant> being replaced by <struct-name> {<initial isations>} in the case of an array of sub-
|
||
STRUCTS.
|
||
For a variable sized array, the array of sub-resources may be preceded in the resource file by a byte or
|
||
|
||
|
||
word giving the number of elements actually in the array. This count is recorded in a word if the prefix
|
||
LEN is used, and in a byte if the prefix LEN BYTE is used.
|
||
|
||
|
||
29
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
|
|
||
Evidently, the number of sub-resources that actually occur in any given instance of the STRUCT is
|
||
determined by the syntax of the intialiser, with all but the last element being preceded by a comma.
|
||
|
||
|
||
For example, resource compiling
|
||
|
||
|
||
STRUCT STRING
|
||
|
||
{
|
||
|
||
TEXT str; :
|
||
STRUCT HELP_ARRAY
|
||
|
||
{
|
||
|
||
LINK topic_id=0;
|
||
|
||
TEXT topic;
|
||
|
||
LEN BYTE STRUCT strlist{f];
|
||
|
||
>
|
||
|
||
|
||
RESOURCE HELP_ARRAY sys help print
|
||
|
||
{
|
||
|
||
topic="How to print":
|
||
|
||
strist=
|
||
{
|
||
STRING {str="Set Printer Model with ‘Print setup'":),
|
||
STRING {str="in Word/Agenda/Data, then use 'Print'";} |
|
||
);
|
||
|
||
|
||
>
|
||
produces a single resource in which: |
|
||
s the first word is zero (the supplied default value for the topic id member)
|
||
s then there follows the sub-resource "How to print"
|
||
= next comes a byte containing the value 2, being the count of the items in the following array
|
||
|
||
|
||
= finally the strings “Set Printer ..." and "...Print'™ are —
|
||
|
||
|
||
Creating SYSTEM resource files i
|
||
|
||
|
||
For completeness, it should be mentioned that the resource compiler hie a special mode if the first line
|
||
|
||
|
||
of a resource script is found to consist of precisely the single word |
|
||
|
||
SYSTEM
|
||
In this mode, all LINK references are automatically resolved with the naganve of the correct value.
|
||
Thus whereas the resource script |
|
||
|
||
|
||
STRUCT STRING {TEXT str;}
|
||
STRUCT TEST {LINK lLnk;>
|
||
|
||
|
||
RESOURCE STRING alpha {str="Xyz";) |
|
||
RESOURCE TEST beta (lnk=alpha;}
|
||
lin i
|
||
|
||
|
||
results in the second resource consisting of the word 1, inserting a
|
||
SYSTEM
|
||
|
||
|
||
at the beginning of the resource script changes the value of this reso | to -1.
|
||
|
||
|
||
The rationale of this behaviour is connected with the facility offered to object-oriented programmers by
|
||
the appman class in olib.dyl, to load in resources from the so-called system resource file instead of from an
|
||
application-specific resource file, if the resource identifiers passed are negative. See the documentation
|
||
On appman for more details. P
|
||
|
||
|
||
CHAPTER 3
|
||
|
||
|
||
WDR PRINTING
|
||
|
||
|
||
i ee ne Se ee ee
|
||
Introduction
|
||
|
||
|
||
SIBO computers which contain form.dyl in their ROM (or on an SSD) support a wide range of services
|
||
connected with so-called WDR printing. These services include the interpretation of printer driver files
|
||
in the Psion-proprietary .wdr format, and the generation of suitable printer command sequences to effect
|
||
printing operations requested by applications. One key idea is that applications do not need to know
|
||
which particular printer driver has been selected by the user; system software takes care of converting
|
||
requests made by applications into command sequences suited to the current printer.
|
||
|
||
|
||
Another service which code in form.dyl can provide is opening the correct printer device - whether that
|
||
be the parallel port, the serial port, or a file. Once again the idea is that users can specify the printer
|
||
device, and have their choice picked up by system software, without any conscious intervention to this
|
||
effect by individual applications.
|
||
|
||
|
||
All versions of the Series3 have form.dyl in their ROM, as do suitably reprogrammed versions of the
|
||
HC.
|
||
|
||
|
||
Whilst the full power of the WDR printing system can be utilised only by object-oriented programmers,
|
||
applications that are not themselves object-oriented may still be able to make considerable use of these
|
||
services:
|
||
= picking up the choices made by the user as regards the printer device (these choices are stored in
|
||
environment variables)
|
||
= reading the contents of .wdr files directly (by themselves)
|
||
= reading the contents of .wdr files using services of the wdr class in form. dyl.
|
||
|
||
|
||
In addition, the Hwif library contains routines hPrintSetupDialog, hPrinterSetupDialog, hPrint,
|
||
hPrintSetS!I, hPrintSensePageWidth, and hPrintSenseBufWidth, which layer over WDR printing services to
|
||
achieve impressive results adequate for many purposes - without requiring any explicit use of object-
|
||
oriented techniques (nor any explicit reference to the contents of .wdr files). See the Hwif Manual for
|
||
more details.
|
||
|
||
|
||
Creating .wdr files
|
||
|
||
|
||
The creation of .wdr files is a quite separate process from their use, once created. Psion can supply a set
|
||
of .wdr files covering some common printers, and other .wdr files may be available from third parties.
|
||
However, it may prove desirable to produce a .wdr file for another printer not presently supported - or to
|
||
enhance the .wdr file for a new version of a given printer.
|
||
|
||
|
||
Note that whatever the origin of the .wdr file, the file name must not begin with fax. Such filenames are
|
||
reserved for fax driver files and are automatically interpreted as such.
|
||
|
||
|
||
One way to create .wdr files is by using the Sibo printer driver translator, wdtran. exe, which creates .wdr
|
||
files from plain text input known as printer scripts typically having extension .wd.
|
||
|
||
|
||
The operation of wdtran. exe is described later in this chapter.
|
||
|
||
|
||
31
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
The WDR printing environment variables
|
||
|
||
|
||
WDR printing software may at various times attempt to read or write the four environment variables ps0,
|
||
PSS, PSF, and PSM:
|
||
|
||
|
||
PSD is one byte long, having the value '0' to denote that the has chosen to print using the
|
||
|
||
|
||
parallel port, '1' to denote the choice of the serial port, | d '2' to denote printing to file
|
||
|
||
|
||
P$s is twelve bytes long, being a copy of the P_SRCHAR struct matching the choices last made by
|
||
the user in any serial port and handshaking dialog(s)
|
||
|
||
|
||
PSF can be up to P_FNAMESIZE (128) bytes long, being a copy of the filename last chosen by the
|
||
user as the recipient of any data printed to file
|
||
|
||
|
||
:
|
||
PSM can be up to P_FNAMESIZE+1 (129) bytes long, the first byte recording the printer model
|
||
number (see below), and the remainder giving the full path name of the last .wdr file chosen
|
||
by the user.
|
||
|
||
|
||
Any software that attempts to read these environment variables should in mind that these variables
|
||
do not always exist. Ordinarily, they are created only when the user makes an explicit choice via a
|
||
- dialog box. In the absence of one of the environment variables, the following defaults are assumed to
|
||
apply:
|
||
|
||
PSD effectively has the value '0', meaning that printing should be via the parallel port
|
||
|
||
|
||
PSS see below :
|
||
PSF any printing to file is to the file p. lis )
|
||
|
||
|
||
PSM the printer model number is 0 and the printer driver file rom::bj.wdr should be used.
|
||
The default values of the P_SRCHAR struct are as follows:
|
||
|
||
|
||
P_SRCHAR ser;
|
||
|
||
|
||
ser. tbaud=P_BAUD_9600;
|
||
ser .rbaud=P_BAUD_ 9600;
|
||
ser. frame=P_DATA_8;
|
||
ser .parity=0;
|
||
ser.hand=P_OBEY_XOFF|P_OBEY_DSR|P_IGN_CTS;
|
||
ser .xoff=0x13;
|
||
ser .xon=0x11;
|
||
ser. flags=0;
|
||
ser. tmask=0;
|
||
For more details on the P_SRCHAR struct, see the Serial Port chapter in the I/O Devices Reference manual.
|
||
|
||
|
||
The essential point is that the contents of the P_SRCHAR struct should be|used to P_FSET the serial port after
|
||
opening it.
|
||
|
||
For convenience, the printer model number is stored in printable form, with the value of '0' being added
|
||
to its numerical value. Thus to use the second model in a . wdr file - > that the printer model number
|
||
would be 1 - the first byte in PSM should be 1+'0', ie '1'. |
|
||
|
||
A note on reading environment variables LL
|
||
|
||
See the discussion on p_getenviron and p_getenv in the Plib Reference ual
|
||
|
||
|
||
Note that it is also possible to read and modify environment variables (eg for experimental purposes) by
|
||
using the SIBO Debugger. |
|
||
|
||
|
||
Overview of the contents of a .wdr file
|
||
|
||
|
||
This section provides an overview of the contents of a . wdr file. More details are provided in later
|
||
sections.
|
||
|
||
|
||
32
|
||
|
||
|
||
3 WDR PRINTING
|
||
|
||
|
||
ee
|
||
|
||
|
||
Just about the simplest possible . wdr file would have the following contents, when dumped:
|
||
|
||
|
||
0:
|
||
10:
|
||
20:
|
||
30:
|
||
40:
|
||
|
||
|
||
89 00 Oc 00 57 44 52 30
|
||
|
||
47 65 6e 65 72 61 6c 00
|
||
|
||
00 00 00 00 00 00 00 00
|
||
0
|
||
|
||
|
||
35 00 00 00 01 00 05 00
|
||
00 00 00 00 00 00 00 00
|
||
17 00 00 00 00 00 00 00
|
||
Oc 01 Od 02 2a Oa 00 02
|
||
01 00 02 05 23 4d 6f 6e
|
||
00 00 00 CO CO 00 00 00
|
||
|
||
|
||
50:
|
||
|
||
H 03 00 01
|
||
70: 00 00 01 00 01 00 01 00
|
||
80: 00 00 00 00 00 01 00 04
|
||
90: 00 7b 00 89 00
|
||
|
||
|
||
This conforms to the pattern
|
||
|
||
|
||
<header><resources><index table>
|
||
of Sibo standard .rsc resource files, as discussed in the Resource Files chapter in this manual.
|
||
|
||
|
||
Indeed, . war files are but examples of .rsc files, with the extension changed to denote the particular
|
||
purpose of being a wdr printer driver file.
|
||
|
||
|
||
In fact, .wdr files come in two types - compressed and uncompressed (standard), corresponding to the
|
||
-'zc and .rsc forms of resource file. Uncompressed files can be read by a variety of methods, as
|
||
discussed in the Resource Files chapter. However, in order to read compressed .wdr files, it is more or
|
||
less necessary to use some of the functionality of object-oriented classes in the ROM, using either:
|
||
|
||
|
||
# the rscfile class in olib.dyl
|
||
ws the wdr class in form.dyl
|
||
|
||
|
||
with the preference being for the latter, since it contains more explicit knowledge of the particular
|
||
contents of . wdr files.
|
||
|
||
|
||
Various services provided by the wdr class are described later in this chapter.
|
||
|
||
|
||
Deciphering general.wdr
|
||
|
||
|
||
The above dump is in fact that produced from an (uncompressed) version of the file general. wdr that is
|
||
part of the Series3 ROM. This file describes the most basic kind of printer possible, possessing only one
|
||
font, which is monospaced, and assumed to be 12 point (ie six lines per inch - one point corresponding to
|
||
1/72 of an inch) and 10 cpi (characters per inch). For this printer, the only way to position the print
|
||
head horizontally is by emitting space characters or carriage returns, and the only way to position the
|
||
print head vertically is by emitting line feeds or form feeds.
|
||
|
||
The index table for the file starts at file offset 0x89 (as contained in the first word in the file). Reading
|
||
successive words from this index indicates that the individual resources in the file are to be found at file
|
||
offsets 0x04, 0x28, 0x48, Ox4d, and 0x7b.
|
||
|
||
|
||
The header resource
|
||
|
||
The first resource in any .wdr file is always the header resource, having the following structure:
|
||
= the first six bytes give a signature, which must always be "wor05" for a valid .wdr file
|
||
= the next word gives the so-called wdr-flags for the file - evidently 0 in this case
|
||
|
||
|
||
= the word after that gives the number of different printer models in the file - in this case, there is
|
||
only one in the file
|
||
|
||
|
||
= finally there is an array of WOR_MODEL_INDEX structs, one struct for each printer model in the file
|
||
|
||
|
||
= each WOR_MODEL_INDEX starts with a word giving the resource identifier for the model resource
|
||
(see later) giving more information about the printer model - this identifier has value 5 in this
|
||
case
|
||
|
||
|
||
= the WOR_MODEL_INDEX struct concludes with up to 24 bytes giving the public name of the model, in
|
||
a zero-terminated string - "General" in this case.
|
||
|
||
|
||
For general. wdr, the total size of the first resource is evidently 6+2+2+1*(2+24), ie 0x24. For other .war
|
||
files which contain more than one printer model, the first resource will be larger.
|
||
|
||
|
||
33
|
||
|
||
|
||
| re
|
||
(77) 06x0 xutul
|
||
|
||
|
||
‘SMOT]OJ SB APUOPLAS oJe SoNEA SNOLBA OU} JO SonfeA oN} ‘“upm ‘yv19Ua8 10,q
|
||
|
||
|
||
"saomMOsal sovjodA3 Jo slayHuep! Jo Joqumnu poyrtoods om jo Lee ue Aq pemo]fo] SIs a
|
||
|
||
|
||
SJoyUSpr wy arnfediy SULMOT[OJ JO JoquInu oy) SUIAIZ PIOM B SOUIOD jxoUsg
|
||
|
||
|
||
Jopou seyunid om
|
||
Joy ssppf-japou pue ‘Kdrys ‘xdrys “kuru ‘curs poyyed-Os 9t} JO SanTea oq} AIS SpIOM SAY SI OT on
|
||
|
|
||
|
||
|
||
SSMO[[OJ SB SI SOMOSEI [POUL B JO SIN|ONIs OY]
|
||
|
||
"(L 38 JIBS SIO_HUSp! soNOsar yey) [TEdOI) A/xO Jos]JO ofYy ye SyES SoINOseI sTy
|
||
|
||
Je} SOPBOIPUT OT Ot JO; oIqQu) Xopur o~ SuUNMsUCD “s JoLyHUEpr sey “pM -yo4auas UI soMoser Jspour ATO
|
||
oY) “SAO PeUOHUSM sy ‘soIMOSal JopEoy OY} Ul poysl] oe SoomMOsel JOPOUT [[e JO SJoyHUSp! soMosal ou],
|
||
soounosei japo-=
|
||
|
||
|
||
! “MO[Oq Pessnosip
|
||
‘saoinosat arnfadds Kq pocualejal ase pue ‘s}UOJ SNOLIVA 32S 0} Pasn oq WED SSULYS PUEWIMIOS [BUOHIPpy
|
||
|
||
|
||
wadVOISGNYVIa O02
|
||
aXId4dNS LHDIY 3AOW 61
|
||
nlHSIY 3AOWu St
|
||
wX1d3ud LHOIY 3AOWKH ZL
|
||
|
||
|
||
nuNMOG 3AOQNn SL
|
||
wNUNL3Y SOWIAVIn SL
|
||
a39Vd MAIN = YL
|
||
|
||
|
||
| uddO IdI¥ISENSH EL
|
||
uNO LdIBISENSn 21
|
||
nddO LdIYOSHSdNSH LL
|
||
wNO LdIddSkadNSe OL
|
||
uddO DIWIIn 66
|
||
wNO OJITVLIn
|
||
u4JO O108n = Z
|
||
wWO O108n 9
|
||
0440 SNITEZONNG 86S
|
||
wNO ANITYSQNNn 9
|
||
na IGWVLSOds ¢
|
||
old ISHVSUdn yA
|
||
nHIONAT WUOdn =
|
||
wLl3S3ue 0
|
||
|
||
|
||
:(Ja;8] Woes sazif pm:
|
||
JO SIUITUOZ BES) S]If pm’ Ul Sp 0S Seq} TIM poyeroosse 3x9} SANdLIOSep oy) SUTAIS Aq SUIS} o[dunts
|
||
UI poqiiosep 1Soq ‘SSUTUBOU PSAJOSOI SALT YOO]G PUBUIWIOS 94} UI SSULNS PUBITMIOD OY) JO [Z ISIN CULL
|
||
|
||
|
||
O2X0 1: ONTBA Og} Seq YOM SI Suis
|
||
|
||
G0XO i: ONTBA 9} SB YOM Q[ suis
|
||
|
||
POxO SNyBA O47 Set] YOrM GT SuLys
|
||
|
||
20X0 ON{VA oq} Seq WOM pI suLys
|
||
:(O19Z
|
||
|
||
|
||
ye SuUNOS SuTjIE3s) Joy Jdaoxa ‘OJOZ OB SSUTS PUBUTTIOS €7 Oy} [TB “ApH ‘WDiauas Joy ‘USES 0q TED SY
|
||
|
||
|
||
*(solez pappaquia uteyn00 [eloued UI UBD SSULIS PUBTMIOD 94} 3eU} UOAIS ‘oyetdodde st se)
|
||
olez Sueur; Aue ynogM pup ‘UNOS o74q SuIpEo & WIM WAIT SI SMOTIO} JeE) Sus puwUUOS Youy
|
||
|
||
|
||
| "€2 OI ‘ZLX0 SI 934q JUNO 94} JO ONTBA OG} ‘BAOGB AM “7D19uas UT
|
||
“uoIsuedxo omny JO} poAsosel St Suruveul csoym pJom Surrey} w Aq pemoyfoy =
|
||
(aomMosel oY} Ul 334q ISIIY 94) 334q yUNOD & Aq popecold =n
|
||
s8u1ags pupunuoo JO kee wen
|
||
:JO S}SISUOO sca ‘Q24NOSAL Spuduiuios sm) SXemye St 4pm’ AUB UI GOINOSAI PUOSES OU],
|
||
9D1NOS9! SPUBWIWIOS ou
|
||
|
||
|
||
!
|
||
|
|
||
NOLLVWHOANI WA.LSAS TVNOLLIGGY
|
||
|
||
|
||
3 WDR PRINTING
|
||
a
|
||
|
||
|
||
miny Oxf0 (240)
|
||
skipx and skipy both zero
|
||
model-flags zero
|
||
|
||
|
||
and there is just one reference to a typeface resource, this having resource identifier 4 (whence it can be
|
||
found at file offset 0x4d).
|
||
Typeface resources
|
||
The structure of a typeface resource is as follows:
|
||
= the first 20 bytes give the public name of the typeface, as a zero-terminated string
|
||
= the next word gives the typeface number of the typeface
|
||
= the word following contains typeface-flags
|
||
|
||
|
||
= next comes a word which, if non-zero, contains the identifier of a translates resource to be used
|
||
by the typeface
|
||
|
||
|
||
= the word following that gives a count of the number of different sizes (or fonts) that the typeface
|
||
comes in
|
||
|
||
|
||
. asi a iS an array of WOR_FONT structs, one struct for each font size supported by the
|
||
type
|
||
|
||
|
||
= the WOR_FONT struct consists of nine words: height, height_max, height_delta, width_scale,
|
||
width_normal, width_italic, width_bold, width_italic, width_bold_italic, and concluding with
|
||
the number of the command string, in the commands resource, of the associated printer
|
||
instruction to set this particular font.
|
||
|
||
|
||
The difference between a “typeface” and a "font" is discussed in more detail below.
|
||
|
||
|
||
In general.wdr, the public name of the only typeface in the file is "Mono", the typeface number and the
|
||
typeface flags are both zero, the translates resource with identifier 3 is to be used, and there 1s only 1
|
||
WOR_FONT struct following in-line.
|
||
|
||
|
||
In a WOR_FONT struct:
|
||
s The fields height_max and height_delta are only relevant for so-called scalable typefaces
|
||
= The field width_scale is only relevant for proportional typefaces
|
||
|
||
|
||
= For monospaced typefaces, the values of the four fields width_normal through width_bold_italic
|
||
are to be interpreted as real numbers; for proportional typefaces, in which the widths of the
|
||
characters vary from character to character, these values are identifiers of font width table
|
||
resources.
|
||
|
||
|
||
There are no font width table resources in general.wdr. Incidentally, font width tables are stored in
|
||
difference form in .wdr files - see later for more details.
|
||
|
||
|
||
Translates resources |
|
||
The first word in a translate resource gives the number of translates that follow in-line.
|
||
|
||
|
||
Each translate starts off with a byte giving the length of the remainder of the translate. The next byte is
|
||
the Ascii value of the character to be translated, and that is followed by a sequence of bytes into which
|
||
the character is to be translated.
|
||
|
||
|
||
In general. wdr, there is only one translates resource, which in turn only contains one translate, whose
|
||
effect is to convert every character with Ascii value 0x05 into one with value 0x23. This results in
|
||
telephone symbols (recorded internally on the Series3 as 0x05's) being printed as hash signs.
|
||
|
||
|
||
Summary of resource types in a .wdr file
|
||
|
||
|
||
The above survey contains one example of every possible type of resource in a .wdr file, except for font
|
||
width table resources.
|
||
|
||
|
||
In summary, the possible resource types are:
|
||
|
||
|
||
header (always the first resource in the .wdr file) containing an index of all the printer
|
||
models supported by the file, as well as some important wdr-flags
|
||
|
||
|
||
i
|
||
|
||
|
||
35
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
commands (always the second resource in the .wdr file) patting the character command
|
||
sequences for resetting the printer, controlling the text format, moving the
|
||
print head position, selecting specified ont and so on
|
||
|
||
|
||
translates used to map the printer's character set onto that used by the SIBO computer
|
||
(which is based on IBM code page 850)
|
||
|
||
|
||
font width tables defining the widths of all the characters in p eoleuaan typefaces
|
||
|
||
|
||
models giving essential data governing the capabilities of a printer, and listing the
|
||
typefaces supported by the printer
|
||
typefaces describing the typefaces supported by a printer model, including the various
|
||
|
||
|
||
"font sizes” available for that typeface.
|
||
|
||
|
||
More details on the contents of .wdr files
|
||
|
||
|
||
Possible wdr-fiags
|
||
|
||
|
||
The only wdr-flag of any general significance is WR_DYL_LOAD, with a 0x01. If set (in the header
|
||
resource), this means that the contents of the .wdr file are insufficient, [by themselves, to describe the
|
||
behaviour of the printer fully, and that the wdr printing system software should load a suitable external
|
||
dyl to additionally customise the print behaviour. |
|
||
|
||
|
||
Examples of . wdr files with the woR_DYL_LOAD flag set are the printer % files for postscript printers.
|
||
Further discussion of loading additional printer dyls is beyond the scope of this document.
|
||
Other bits set in the wdr-flags may have special significance for code : the extra print dyls.
|
||
|
||
|
||
The notion of "printer models"
|
||
The notion of a printer model is essentially a device to cover more one printer using the same data.
|
||
|
||
|
||
Different printer models can be described in the same .war file, even if they support different sets of
|
||
typefaces or have other differing characteristics, so long as they have the same basic set of printer
|
||
command strings (and the same wdr-flags). |
|
||
|
||
The public name of a printer model is what is presented to the user in y dialog offering a list of
|
||
“printer models” for selection. i
|
||
|
||
|
||
Overview of the different command strings
|
||
|
||
|
||
As well as the command strings to select various fonts, a .wdr file con commands to have the printer
|
||
perform other functions. These commands are by and large clearly in the listing given earlier, eg
|
||
"ITALIC_ON" and "ITALIC_OFF", "BOLD_ON" and “BOLD_OFF", and “SUPERSC IPT_ON" and “SUPERSCRIPT_OFF".
|
||
|
||
|
||
If a printer cannot support a given feature, the corresponding comman string would generally be left
|
||
null (“"). One possible exception is italic which, if not supported, co Id be implemented as an underline.
|
||
(Note incidentally that it is possible for a printer which supports italic in one font not to support it in
|
||
another a and so on. Again, a printer may support both italic and superscript, but not both at the
|
||
same time. :
|
||
|
||
|
||
The "LANDSCAPE" command, if non-null, is the command to cause the pie to enter landscape mode (as
|
||
opposed to portrait mode).
|
||
|
||
|
||
The string of commands sent to the printer when printing starts are ambng the most important, as regards
|
||
influencing the printed outcome. The very first command the software sends the printer is the "RESET"
|
||
command. Then it sends a “FORM_LENGTH" command, and then the "PREAMBLE" command, before starting to
|
||
print the document proper (together with headers and footers, etc). At/the very end, a "POSTAMBLE"
|
||
command is sent.
|
||
|
||
|
||
The "POSTAMBLE" command may be needed to flush the printer buffer, and to restore the printer to its
|
||
default settings. |
|
||
|
||
|
||
The "PREAMBLE" Command may have such drastic consequences as choosing the basic configuration of the
|
||
printer (possibly overriding defaults set via dip switches). In any case of doubt, the documentation for a
|
||
particular printer should be consulted carefully.
|
||
|
||
|
||
a |
|
||
36 :
|
||
|
||
|
||
)
|
||
|
||
|
||
+
|
||
|
||
|
||
3 WDR PRINTING
|
||
|
||
|
||
Special characters in command strings
|
||
|
||
|
||
The commands "MOVE_RIGHT", “MOVE_DOWN", and "FORM_LENGTH" are each used in conjunction with a value
|
||
passed by the printer subsystem software. For example, the commands are to set the form length to a
|
||
given value, or to move the printer position right by a given amount. This value may either end up in the
|
||
command string by a process of substitution, or it may result in the command being repeated as required:
|
||
|
||
|
||
= if any of these commands is defined as starting off with an asterisk character ('*'), what is
|
||
actually sent to the printer is the remainder of the command string (ie minus the initial asterisk)
|
||
repeated the specified number of times
|
||
|
||
|
||
e if the string "%d" is contained within the command string, the specified value is converted into
|
||
decimal representation and is substituted for the "%d" (like printf in C)
|
||
|
||
|
||
s likewise the string “%c" means to substitute the specified value as a single byte (character), and
|
||
"Xw" means to substitute it as a pair of bytes (low byte first).
|
||
|
||
|
||
For example, in some printer drivers "MOVE_DOWN" is defined as "*<10>", so that "MOVE_DOWN n* will be sent
|
||
to the printer as n line feed characters (line feed is Ascii 10).
|
||
|
||
|
||
Again, in the HP Laserjet III printer driver, "“ovE_DOwN" is defined as "<27>&a+%dv", so that "MOVE_DOWN 6"
|
||
(say) will be sent to the printer as "<27>&a+6v".
|
||
|
||
|
||
This kind of substitution can also take place in the command strings to select a specific size of a so-called
|
||
scalable font - see below.
|
||
|
||
|
||
The MOVE_RIGHT commands
|
||
For some printers, the command to move right by a certain amount is of the general form
|
||
<prefix><repeated body><suffix>
|
||
|
||
|
||
with the central part being repeated as many times as required, depending on the amount by which the
|
||
print position is to be adjusted.
|
||
|
||
|
||
It is to cope with this case (as well as ones even more complicated) that the commands
|
||
"MOVE_RIGHT_PREFIX" and "MOVE_RIGHT_SUFFIX" are provided. These will be left null for most printers.
|
||
|
||
|
||
Printer units
|
||
|
||
|
||
The units for the "FORM_LENGTH" command are always 1/6 of an inch. Thus if the print software wishes,
|
||
as part of initialising a printer, to set the form length to 12 inches, the command
|
||
|
||
|
||
“FORM_LENGTH 72"
|
||
should always be sent.
|
||
|
||
|
||
However, the units used in many other features of printer driver files varies from printer to printer. The
|
||
key quantities are the values of minx and miny, as specified in the model resource for a printer.
|
||
|
||
|
||
Minx and miny are themselves standardly given in so-called twips, where twenty twips make a point (so
|
||
that 1440 twips make an inch). For example, in the file general. wdr discussed above, minx has the value
|
||
144 twips, ie 1/10 of an inch, and miny has the value 240 twips, ie 1/6 of an inch. This matches the
|
||
basic assumptions made in general.wdr that the font printed is 12 point and 10 cpi (see earlier).
|
||
|
||
|
||
The fundamental significance of minx is that this is the smallest amount by which the print position can
|
||
be adjusted horizontally. Similarly, miny is the smallest amount by which the print position can be
|
||
adjusted vertically. Clearly, the smaller minx and miny are, the higher the resolution of the printer.
|
||
|
||
|
||
The above values make sense for general. wdr since the only way the print position can be adjusted
|
||
horizontally is by emitting a space character (or by emitting a carriage return, which resets the horizontal
|
||
position), and the only way the print position can be adjusted vertically is by emitting a linefeed character
|
||
(or by emitting a formfeed character, which effectively resets the vertical position).
|
||
|
||
|
||
A command such as "MOVE_RIGHT n" actually means to move the print position right by n times minx, and
|
||
similarly a command such as "MOVE_DOWN m" means to move the print position down by m times miny.
|
||
|
||
|
||
The value of skipx for a printer model is subtracted from the first "MOVE_RIGHT" command in each line of
|
||
text, to compensate for the fact that many printers cannot print at the left edge of the paper. The value of
|
||
skipy is likewise subtracted from the first "MovE_DowN" command in each page, to compensate for the fact
|
||
that many printers cannot print at the very top of the paper.
|
||
|
||
|
||
37
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
!
|
||
|
||
|
||
The values of skipx and skipy are themselves expressed in terms of mae and miny, respectively. Thus if
|
||
skipy is given as 36 whereas miny is given as 20, this translates to an tual height of some 20*36 twips,
|
||
ie half an inch, at the top of the paper which is inaccessible to the printer.
|
||
|
||
|
||
Possible model-flags
|
||
There are two bits that can be set in the model-flags in a model resource:
|
||
@ WOR_MODEL_LANDSCAPE_AVAILABLE (0x01) has to be set if the model supports being put into
|
||
|
||
|
||
landscape mode
|
||
|
||
|
||
™ WOR_MODEL_MINX_IS_DOTS_PER_INCH (0x04) should be set if the value of minx is expressed, not in
|
||
twips (as standard), but in reciprocal inches (so that a minx of|300 would correspond to 1/300 of
|
||
an inch - which is not expressible as an exact number of twips).
|
||
|
||
|
||
Note that even if WR_MODEL_MINX_IS_DOTS_PER_INCH is set, the value of miny is always expressed in twips.
|
||
|
||
|
||
Typefaces and fonts
|
||
|
||
|
||
A typeface is considered to be a set of characters in a particular style, whereas a font is a particular size
|
||
of a typeface.
|
||
|
||
|
||
The public name of a typeface is what is presented to the user in any dialog offering a list of "fonts"
|
||
(actually typefaces) for selection. The various different fonts within a chosen typeface will be selected
|
||
via a secondary choice list, keyed by the notional height of the fonts. |
|
||
|
||
|
||
There can be considerable scope for authors of .wdr files in deciding how to represent the different fonts
|
||
supported by a printer (especially dot matrix printers). For example, many dot matrix printers support a
|
||
condensed font: this may be represented as a typeface called "Pica condensed" (say) or as a smaller font
|
||
of the "Pica" typeface. It is generally more useful for the user to have a number of size variants (fonts)
|
||
of one typeface rather than a number of typefaces each having only one size. For this reason the second
|
||
of the above approaches is the recommended one. It also has the advantage that the typeface names will
|
||
then (generally) be language independent, whereas the addition of a phrase such as “double width" or
|
||
"condensed" immediately makes the .wdr file language dependent. |
|
||
|
||
|
||
A dot matrix printer may support a number of variants of a font including: condensed, double height,
|
||
double width, condensed double width etc. For a twelve point base font it is recommended to map these
|
||
to the following heights: |
|
||
|
||
|
||
condensed 7 point (140 twips)
|
||
normal 12 point (240 twips) |
|
||
condensed double width 13 point (260 twips) !
|
||
double width 16 point (320 twips)
|
||
double height 22 point (440 twips)
|
||
double height double width 24 point (480 twips)
|
||
|
||
|
||
Note that a taller font must have a larger size than a shorter font, in particular the point sizes of all the
|
||
double height fonts must be larger than all the single height fonts.
|
||
|
||
|
||
If a dot matrix printer supports a large number of variations on a base font, it may turn out that two
|
||
different variations would be mapped onto the same point size. In this|case it would be perfectly
|
||
acceptable to just omit one of the fonts: if there are already 12,13,14,15 and 16 point fonts available then
|
||
omitting (say) a second 14 point is not really a hardship to the user. Alternatively, the font could be
|
||
incorporated in another typeface. In case it is decided to omit a font, in mind that double height
|
||
fonts generally look much better than double width fonts, so given a choice it 1s better to omit the latter.
|
||
|
||
|
||
Typeface numbers
|
||
|
||
|
||
The main significance of the typeface number of a typeface is when a | set up for one printer is
|
||
subsequently printed on another printer. Font “substitutions” have to be made - and these are done
|
||
according to the values set for the typeface number.
|
||
|
||
|
||
Thus if a document is prepared for one printer model, and some text is|to be printed in a typeface having
|
||
typeface number 2, say, and then the user changes the printer model setting for the document to another
|
||
printer, that text, when printed, will be printed in the first typeface found in the new printer model,
|
||
having the same typeface number.
|
||
|
||
|
||
\)
|
||
|
||
|
||
3 WDR PRINTING
|
||
eee
|
||
|
||
|
||
In case no exact match in typeface number is possible, the first typeface defined in the new printer model
|
||
is used instead.
|
||
|
||
There are a large number of allowed typeface numbers, listed later in this chapter. Note that typeface
|
||
numbers are completely independent of the public names of typefaces.
|
||
|
||
|
||
Typeface numbers may also be used in some forms of RTF file conversion.
|
||
|
||
|
||
Possible typeface-flags
|
||
There are three bits that can be set in the typeface-flags in a typeface resource:
|
||
|
||
|
||
= WOR_TYPF_PROPROTIONAL (0x01) set if the widths of the characters in a font in this typeface can vary
|
||
among themselves (the alternative is that the fonts are monospaced)
|
||
|
||
|
||
= WOR_TYPF_SCALED (0x02) set if the fonts supported by the typeface are all generated by the printer
|
||
as being different scaled versions of one common pattern
|
||
|
||
|
||
= WOR_TYPF_SERIF (0x04) set if the typeface is serif.
|
||
The WOR_TYPE_SERIF flag has significance only in certain types of RTF file transfer.
|
||
|
||
|
||
Note that scalable monospaced typefaces are not supported, so that scalable fonts always have to be
|
||
regarded as proportional, even if the widths of their characters do not vary in fact.
|
||
|
||
|
||
For scalable typefaces, there is only one woR_FONT struct per typeface, with all required information for
|
||
differently sized fonts being generated from this by arithmetical scaling.
|
||
|
||
|
||
Heights of fonts
|
||
|
||
|
||
The command string of a scalable typeface must include some kind of parameter (eg "%d") for the
|
||
particular size required to be specified when setting the font. This parameter will be filled in by system
|
||
software giving the height of the required font in point units.
|
||
|
||
|
||
However, heights of fonts in .wdr files are always given in twips (thus 240 for a 12 point font).
|
||
|
||
|
||
For non-scalable fonts, the height_max and height delta fields in a woR_FONT struct are meaningless. For
|
||
scalable fonts, the set of supported font sizes is obtained by repeatedly incrementing by height-delta,
|
||
from the value of height to the value of height _max (so that the "height" field actually plays the role of a
|
||
“height _min" field).
|
||
|
||
|
||
In general, 4 points (80 twips) is a sensible minimum height for a font, whereas the maximum allowed
|
||
height is determined by the fact that the widths of characters must at all times remain less than 255.
|
||
Widths of characters in fonts
|
||
|
||
Widths of characters in fonts in .wdr files are expressed - as are all horizontal measurements in .wdr files
|
||
- in units of minx.
|
||
|
||
|
||
The wdr system allows for widths of characters altering as they are italicised or bolded, and again when
|
||
they are simultaneously italicised and bolded. In case there is no such variation, the values of the fields
|
||
width_normal, width_bold, width_italic, and width_bold_italic, will merely duplicate each other.
|
||
|
||
|
||
For proportional fonts, these four fields each refer to font width tables. These are stored in difference
|
||
form in .wdr files. Thus if the array of stored widths is stored[:
|
||
|
||
|
||
= width of character 0 = stored([0]
|
||
|
||
® width of character 1 = width of character 0 + stored[1]
|
||
= width of character 2 = width of character 1 + stored{[2]
|
||
= width of character 3 = width of character 2 + stored{[3]
|
||
|
||
|
||
and so on. The rationale for this is that the differences are frequently zero, so that the font width table is
|
||
stored as an array, many of whose values are zero. In turn, this compresses much more markedly (for
|
||
compressed versions of . wdr files) than tables containing many different values - with the result that
|
||
smaller .wdr files get produced (bear in mind that font width tables potentially make up large parts of
|
||
these files).
|
||
|
||
|
||
The values obtained from a font width table should all be multiplied by the width_scale value for the
|
||
font. This mechanism avoids needless duplication of data in which two font width tables would
|
||
otherwise both be present in a .wdr file, even though one is merely a scaled version of the other.
|
||
|
||
|
||
39
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION |
|
||
|
||
|
||
For scalable fonts themselves, the values in the font width table (once multiplied by any width_scale
|
||
value for the font) are what would apply to a fifty point high version of the font. These have to be
|
||
further scaled, in general, to match the chosen height of the font.
|
||
|
||
|
||
Note that in all cases, widths of characters cannot exceed 255.
|
||
|
||
|
||
Creating .wdr files using wdtran.exe
|
||
|
||
|
||
The printer driver translator is a tool wdtran. exe that operates on a so-called printer script, which is a
|
||
text file, to produce a printer driver file as output.
|
||
|
||
|
||
The process is akin to ordinary compilation:
|
||
|
||
*.c + compiler -> *.obj
|
||
|
||
*.wd + printer driver translator -> *.wdr
|
||
with .wd being the usual extension for a printer script.
|
||
Some sample .wd files are distributed as part of the optional component of the Sibosdk.
|
||
To produce eg general.wdr from general.wd, simply type
|
||
|
||
|
||
wdtran general |
|
||
|
||
|
||
Contents of .wd files |
|
||
The basic contents of .wd files correspond to the different resources in|. wdr files (see earlier in this
|
||
|
||
|
||
chapter).
|
||
|
||
|
||
A .wd file consists of a number of resource definitions, of which therejare five types: COMMANDS,
|
||
TRANSLATES, WIDTHS, TYPEFACE, and MODEL.
|
||
|
||
|
||
There must be one and only one COMMANDS resource in a .wd file. There must be at least one MODEL
|
||
resource and at least one TYPEFACE resource, though there can be more ie each. There can be any number
|
||
(including zero) of WIDTHS and TRANSLATES resources.
|
||
|
||
|
||
Note that there are no definitions in a .wd file directly corresponding to the header resource in a .wdr
|
||
file. The header resource is specially created by wdtran. exe.
|
||
|
||
|
||
Each resource definition consists of a header, a number of commands, and then a footer. The header is
|
||
of the form
|
||
|
||
|
||
<RESOURCE> [identifier]
|
||
|
||
|
||
with the identifier being required only if the resource is to be referenced by another resource (it may be
|
||
the name of a width table, for example).
|
||
|
||
|
||
The resource footer is of the form:
|
||
|
||
|
||
END_<RESOURCE>
|
||
Each intervening command is of the form:
|
||
|
||
keyword [parameter]
|
||
For example, the definition of a TYPEFACE resource looks like
|
||
|
||
|
||
TYPEFACE pica
|
||
|
||
|
||
|
|
||
END_TYPEFACE
|
||
|
||
|
||
Iv
|
||
|
||
|
||
<33Aq> = <3 Aq>
|
||
WO} oy} SAKY PloYs suOHE]sUBI} [ENPLAIPU]
|
||
|
||
|
||
-gonds oy1GM Aq Jojo Yous Wo poyeredes ZuIeq out] uO Aue UO sUONEISUBI) JBo0e[pE
|
||
WWM ‘suoiyjsuv4t eJOUl JO suo JO dn opeUl oq PfNoYs Yoo[g SILVISNVAL B JO UOHIUYsp of} UII oul] Youy
|
||
|
||
|
||
UOIIUAP 394N0S94 SJLWISNVEL © UluIM SpueWWOd ajqe}deo0y
|
||
|
||
|
||
“‘SOUBSIJTUSIS PEOLIO\sty Ayomnd Jo 3TGILVdWOD 19d dH
|
||
SOMOS Jopeoy o4} UT SSeTJ-IPM SY} 03 <s6e}4> UI LO 0} <s68)}> SOV14
|
||
oy _
|
||
dpm’ 94} JOF SoINOseI Jopesy OY} Ul SseYJ-IJpM OY} UI S¥[J GYOT TAC AGH 9} 30S 0} 7Ad 3sn
|
||
|
||
|
||
2018 DONTUYSp SoINOsal SGNWRWOD B UTI Ind90 Aud yeq) xe7UAS JoTIO
|
||
|
||
|
||
*<J2> se polpioods st (17 ONn]BA [BUTIOSp) Opodo [037000 Is3 OW) ofduTExe
|
||
|
||
Joq °*(,<, pus ,>,) SjexowIG o[Sue Ur onyeA [eUTISep sy SuIs¥Td Aq porytoeds st epoo joxuOS yW “uONnTUYep
|
||
UOJ B JO PIOMASY ANVHNOD OU} UI JO ‘UONTUSp SoINOSEI SGNYHWOD OY) UI popeou oq AvUI sapod [OWUOD
|
||
‘uOHTUYSp somMosol
|
||
|
||
JIVIIdAL JUVADTOI 9Y} UIGIIM USAIS 9G P[NOYS SJUOJ [ENPIAIPUL Jos 0} Posn SSULIYS PUBTATIOS ‘ISAOMOF]
|
||
“IDALS OQ TED SOT] APM’ Ul SAOINOSSI PUBUIUIOD UO UOT}SeS JolpJee ot} Ul Poyst] SpuvUIMOS oy) Jo AUY
|
||
|
||
|
||
UOIIUIJEaP 99JNOS31 SGNVININOD 2 uluM xe}UAS ajqe}de00Y7
|
||
|
||
|
||
“ATMO SOUSTUSAOD JO}J SI SOT PM" plepuyYjs Ul SUIS|OS UOTVEJUSpUT YOo]G ol,
|
||
|
||
|
||
“poJOUsI osye ose Soul] YULT_ *(SuLNs poyonb & UI st j oy} ssofuN)
|
||
OUI] B JO pus oY} pUe j IEW UONME[OXe UB Usemjog SIojoRIEyO Aue SoJOUSI JOje[SUBI} JOAUIp JoyULId oa],
|
||
|
||
|
||
-(mozeq
|
||
90S) SJa}OeIBYS [01JU0 UTE} ABU SuLIs Oy) ‘(NO A108 30) UOHOUN oIyIOeds
|
||
B WJOJJod 0} JajULId 94} 03 3USS SI 3eq} Soj}OND UT SJo}ONIEYO Jo souNbes B SULIYS Pozong
|
||
eomosel peyroeds
|
||
JoTjoue souasJejos 0} puvuM0S & Aq pesn ‘suLys pozonbun esd Jomo] B JoynuUsp]
|
||
(VOI]TUIJop SoINOSEI JDv4adAL B UT
|
||
adAL Aq ATWO pesn) onyea oLouINU & se poyordJazUI SI YOryM SuLys pojonbun ue jue}suoZ
|
||
(TPM jo; & 3S) ONTBA B SB PoJoICIJOzUI SI YOM JOQUINU [eUIOSp B SLOUNN
|
||
sodA} oy Jo oq APU UONTUYSp somMosel B opIsUI splomASY 0} sJoj}OUTeIEg
|
||
SQNVWNOD GNI
|
||
n<fl>n NUNLIA JOVINYVI
|
||
n<ZL>u 3OVd MN
|
||
us XIddNS LHI 3AOW
|
||
u<ZE>au 1HOIY 3AON
|
||
wa = X143Nd LHOTY SAN
|
||
0<OL>a0 NMOG 3AQW
|
||
|
||
|
||
ces 440 1d1¥ISYIdNS
|
||
ro8e NO ldlydS¥adNs
|
||
ne 440 LdIYOSENS
|
||
rn NO 1d1¥ISENs
|
||
tae 430 3NI7Y30NN
|
||
nn NO 3NI1Y3qNN
|
||
an 440 DITWALI
|
||
ne NO JIIWLI
|
||
8 440 108
|
||
nts NO Q108
|
||
108 JISWVLSOd
|
||
rote J 1sWV3ed
|
||
ne HLONIT W8Od
|
||
sn6e 13S3u
|
||
SANVWHOD
|
||
|
||
|
||
*(pM ‘[oLaUas BY OY} OJ GOMNOSEI SONVWHOD OY} SI STO}) O¥1] SYOO] CoINOSEI SGNVWHOD B JO UONTUYSp oy) puB
|
||
|
||
|
||
ONLINTad YM £
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
or else
|
||
<byte>:<string>
|
||
For example:
|
||
5:35
|
||
156:"<27>R<3><35><27>R<0>"
|
||
Note that any width table for a font which uses translates must contain the correct width for each
|
||
character after it is translated. The printer driver translator does not check this.
|
||
Acceptable commands within a WIDTHS resource definition
|
||
|
||
|
||
Each line within the definition of a wiDTHS block should be made up of one or more character widths,
|
||
with adjacent character width definitions on any one line being separated from each other by white space.
|
||
|
||
|
||
Individual character width definitions should have the form
|
||
<byte>:<width>
|
||
|
||
|
||
Note that in contrast to .wdr files, which store font width tables in differenced form (see earlier in this
|
||
chapter), . wd files should define the widths of all characters in absolute terms. The differencing is
|
||
performed by wdtran. exe (just as the converse integration is performed by the wdr class in form. dyl
|
||
without the conscious intervention of any application software).
|
||
|
||
|
||
The printer driver translator will give an error if the widths of the non-breaking hyphen, potential
|
||
hyphen, and standard hyphen (character codes 7, 14, and 45) are not all the same.
|
||
|
||
|
||
Likewise, the widths given for the non-breaking space, the standard space, and the tab (character codes
|
||
15, 32, and 9) also all have to agree.
|
||
|
||
|
||
Acceptable commands within a TYPEFACE resource definition
|
||
|
||
|
||
The following commands may be present within the definition of a TYPEFACE resource:
|
||
|
||
|
||
PROPORTIONAL to set WOR_TYPF_PROPORTIONAL in the typeface-flags
|
||
SCALED to set WOR_TYPF_SCALED in the typeface-flags
|
||
|
||
SERIF to set WOR_TYPF_SERIF in the sal ese,
|
||
MULTIPLE_FONT_WIDTH_TABLES of purely historical interest
|
||
|
||
NAME <name> to give the public name of the face
|
||
|
||
TYPE <type> to give the typeface number of the typeface
|
||
TRANSLATE <identifier> to specify a TRANSLATES reso to be used
|
||
|
||
FONT to commence the definition of a FONT sub-resource.
|
||
|
||
|
||
|
|
||
|
||
|
||
The Font keyword must appear at least once in each TYPEFACE definition, and can appear more than once.
|
||
The other keywords should only appear once, at the most.
|
||
|
||
|
||
Each FONT sub-resource definition follows the same general pattern as the other resources:
|
||
|
||
|
||
FONT
|
||
<keywords>
|
||
|
||
|
||
END_FONT |
|
||
Possible keywords in the body of a FONT resource definition are HEIGHT,| HEIGHT _MAX, HEIGHT_DELTA,
|
||
WIDTH_SCALE, WIDTH, WIDTH_BOLD, WIDTH_ITALIC, WIDTH_BOLD_ ITALIC, and C p - each having the
|
||
straightforward meaning of specifying a corresponding field within the|woR_FONT structure for that font
|
||
(see earlier in this chapter). |
|
||
Acceptable commands within a MODEL resource definition
|
||
The following commands may be present within the definition of a MODEL resource:
|
||
LANDSCAPE_AVAILABLE to set WOR_MODEL_LANDSCAPE_AVAIILABLE in the model-flags
|
||
|
||
|
||
MIN_X_IS DOTS _PER_INCH to set WOR_MODEL_MINX_IS_DOTS_PER_INCH in the model-flags
|
||
|
|
||
|
||
|
||
42
|
||
|
||
|
||
3 WDR PRINTING
|
||
eee
|
||
NAME <name> | to give a public name for the printer model
|
||
TYPEFACE <identifier> to specify a TYPEFACE resource supported by the printer model.
|
||
|
||
|
||
Additionally, the keywords MIN_X, MIN_Y, SKIP_X, and SKIP_Y straightforwardly specify the minx, miny,
|
||
skipx, and skipy values for the printer model.
|
||
|
||
|
||
In contrast to the case for TYPEFACE resources, which can only have one public name each, MODEL resources
|
||
can have more than one public name each. This avoids needless duplication in a .wd file, if it turns out
|
||
that two MODEL blocks would otherwise be identical. Note that one MODEL resource having two public
|
||
names is not in general the same thing as there being two different MODEL resources in the same .wd file
|
||
(though in each case, there will be two distinct entries in the Printer Model choice list).
|
||
|
||
|
||
Allowed typeface numbers
|
||
TYPE may take any of the values:
|
||
|
||
|
||
COURIER OPTIONAL_SB RUSSIAN
|
||
|
||
PICA OPTIONAL_SC OPTIONAL_B
|
||
ELITE TIMES_ROMAN OPTIONAL_C
|
||
PRESTIGE CENTURY OPTIONAL_D
|
||
LETTER_GOTHIC PALATINO NARRATOR
|
||
GOTHIC SOUVENIR EMPHASIS
|
||
CUBIC GARAMOND ZAPF_CHANCERY
|
||
LINEPRINTER CALEDONIA OPTIONAL_DA
|
||
HELVETICA BODONI OLD_ENGLISH
|
||
AVANT_GARDE UNIVERSITY OPTIONAL_DB
|
||
SPARTAN SCRIPT OPTIONAL_DC
|
||
METRO SCRIPT_PS COOPER_BLACK
|
||
PRESENTATION OPTIONAL_SCA SYMBOL
|
||
|
||
APL OPTIONAL_SCB LINE_DRAW
|
||
OCR_A COMMERCIAL_SCRIPT MATH_7
|
||
|
||
OCR_B PARK_AVENUE MATH 8
|
||
STANDARD_ROMAN CORONET DINGBATS
|
||
EMPEROR OPTIONAL_SCC EAN
|
||
MADELEINE GREEK PC_LINE
|
||
ZAPF_HUMANIST KANA OPTIONAL_SYA
|
||
CLASSIC HEBREW
|
||
|
||
OPTIONAL_SA OPTIONAL_A
|
||
|
||
|
||
Suppose, for example, a user has a document written when the Apple Laserwriter printer driver was
|
||
selected, and the document uses two typefaces, Times Roman and Palatino. The user then changes to a
|
||
HP Laserjet II printer driver. Times Roman on the Laserwriter and CGTimes on the HP III both have a
|
||
TYPE Of TIMES_ROMAN and so the Zimes Roman typeface would be mapped to CGTimes. The HP III driver
|
||
has no typeface with a TYPE of PALATINO and so the Palatino font would be mapped to Courier.
|
||
|
||
|
||
The following rules are useful for guidance:
|
||
|
||
One of the printers monospaced typeface should be assigned a TYPE of COURIER: this should be the typeface
|
||
described as Courier or perhaps Pica in the printer's manual. The typeface's NAME should be as in the
|
||
manual (eg "Pica").
|
||
|
||
If a printer supports only one proportional typeface it should be assigned a TYPE of TIMES_ROMAN, although
|
||
it may be given a different NAME (eg "Proportional").
|
||
|
||
If a printer supports more than one proportional font then the one with serifs (if available) should be
|
||
|
||
|
||
assigned a TYPE of TIMES_ROMAN and the one without serifs should be assigned a TYPE of HELVETICA; their
|
||
NAMES should, however, be those used in the printer's manual, eg CGTimes and Univers for the HP
|
||
|
||
|
||
Laserjet III.
|
||
|
||
|
||
43
|
||
|
||
|
||
. : ' ,
|
||
7 + : - a as : 2
|
||
+ ‘ f - Z 5 ‘. 7 A t i"
|
||
? t * + ean ; :
|
||
+ .
|
||
. : 2 a i .
|
||
ve Z : . % . a e
|
||
5 . . depet ae ae
|
||
7 : ne BN
|
||
. '
|
||
le a
|
||
- _ on . .
|
||
. a . 1
|
||
7 1
|
||
‘ .
|
||
.
|
||
. ”
|
||
Saye, “ite . 2
|
||
ae ; : .
|
||
bag ‘ ah ae
|
||
RTE yi . S
|
||
‘ ¢ . ‘, a
|
||
+
|
||
‘ : =
|
||
4 a * ¥ ie te . fara
|
||
ha > : - i : * . 31 4 .
|
||
3 s -
|
||
, i s Sy or : ‘ see , ree OS ae ye
|
||
* ’ oF eat teed,
|
||
-- : . nee : , ‘ ae 2 :
|
||
: ' is . * A * ae aS Z ,
|
||
' : : Bac FE :
|
||
‘ : ‘ . a . : : ee ‘ ae . .
|
||
. i oot : ‘ 7 f
|
||
A 1 . : > j . ar . :
|
||
. 1
|
||
‘ i : 8 ” ; :
|
||
5 ‘ é i Bee z s a eo .
|
||
a =: . * ,
|
||
2 a oe ae s Croan ae at Hv 2 8 4 + = A ot
|
||
: toe ~ Fs se grils erate ane aces ree > : ; ; i 2
|
||
— Pk ‘
|
||
' 2
|
||
’
|
||
.
|
||
|
||
|
||
CHAPTER 4
|
||
|
||
|
||
DBF FILES
|
||
|
||
|
||
a Te ee a i ee ee oe, se ee |
|
||
Introduction
|
||
|
||
|
||
Database files (DBF files) are binary files containing typed, variable length records. Many SIBO
|
||
applications (for example, the MC Diary and the Series 3 Database) store their data in DBF files. The
|
||
data files created and manipulated by Opl are also examples of DBF files.
|
||
|
||
|
||
Database files are designed to be Flash-friendly, that is, they may be stored and manipulated in Flash
|
||
SSDs (or any other EPROM medium). A DBF file stored on such a medium may be modified by
|
||
appending, deleting, or replacing records without having to make a new copy of the entire file.
|
||
|
||
|
||
The chapter Database Files in the Plib Reference manual describes DBF files from the point of view of
|
||
reading and writing them using Plib function calls such as DbfOpen, DbfAppend, DbfFindRead, and
|
||
DbfNextRead. The JSAM Manual discusses more advanced techniques for using DBF files, in conjunction
|
||
with independent keyed index files. The present chapter focuses instead upon a description allowing
|
||
access to DBF files independently of these specialised Plib and ISAM functions.
|
||
|
||
|
||
First, the basic structure of a general DBF file is reviewed, and then particular examples are given of
|
||
how various SIBO applications use DBF files. This information should assist the creation of file format
|
||
conversion programs such as might run on another computer, for example converting between Series 3
|
||
Agenda files and files that can be read directly by PC-based PIMs (Personal Information Managers).
|
||
|
||
|
||
a a a Ny on ea i fs
|
||
Basic structure of DBF files
|
||
|
||
|
||
The following discussion is based around a DBF file created by a simple Op! program. It is not necessary
|
||
to be familiar with Opl to follow the discussion, since the contents of the DBF file are described
|
||
independently of the Opl program. It just happens that Opl is a convenient way to create DBF files
|
||
quickly, so that experimentation is easier.
|
||
|
||
|
||
The Opl program creating the file is as follows:
|
||
|
||
|
||
PROC writedbf:
|
||
if exist("test.dbf") sdelete "test.dbf" :endif
|
||
create "test.dbf",a,f1$, f2$, f3%, f4
|
||
a. f1$="Hel lo"
|
||
a. f2S="2"
|
||
a. f3%=3
|
||
a.f4=4
|
||
append
|
||
a. f1$="World"™
|
||
append
|
||
close
|
||
beep 5,300
|
||
ENDP
|
||
|
||
|
||
The create statement creates a DBF file with the name test.dbf, by default in the lopd\ top-level
|
||
directory on the default drive. This file is assigned the logical handle a inside the program. Each record
|
||
in the file is to have four fields (called f1$, f2$, f3%, and 4 inside the program). Standard Opl naming
|
||
conventions mean that these fields have types string, string, integer, and double, respectively.
|
||
|
||
|
||
45
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
ee ne eee ee ey ee ee
|
||
|
||
|
||
The two append statements mean that two records are written to the file, before it is closed.
|
||
|
||
|
||
Dumping the resulting file yields the following:
|
||
|
||
|
||
O: 4f 50 4c 44 61 74 61 62 61 73 65 46 69 6c 65 00 OPLDatab aseFile.
|
||
10: Of 11 16 00 Of 11 04 20 03 03 00 02 12 1005 48s... b ete ese H
|
||
20: 65 6c 6c 6f 01 32 03 00 00 00 00 00 00 00 10 40 ello.2! 0 eccncee a
|
||
30: 12 10 05 57 6f 72 6c 64 01 32 03 00 00 00 00 00 oo World .2...00-
|
||
40: 00 00 10 40 000d
|
||
|
||
|
||
This conforms to the standard DBF format of
|
||
|
||
|
||
<standard header><extended header><field information ances records>
|
||
|
||
|
||
where
|
||
<standard header> always has length 22 bytes.
|
||
<extended header> can have variable length and is frequently of zero length (as
|
||
here).
|
||
<field information record> gives the structure of all type J records following.
|
||
<other records> are the main body of the DBF file.
|
||
|
||
|
||
The standard header
|
||
|
||
|
||
The first sixteen bytes of all standard DBF files are the zero-termi | string "“OPLDatabasefile". This
|
||
string is used by all SIBO applications. Applications are allowed to use alternative strings although such
|
||
DBF files can not be read by Opl.
|
||
|
||
|
||
The two bytes at file offset 0x10 will in practice always contain the b
|
||
the bytes at file offset 0x14.
|
||
|
||
|
||
The two bytes at file offset 0x12 contain the file offset for the start of the field information record. Thus
|
||
in the absence of an extended header they would contain <16><00> and for an extended header of length
|
||
256 bytes they would contain <16><01>.
|
||
|
||
|
||
2s <0f><11>. The same applies to
|
||
|
||
|
||
The extended header
|
||
|
||
A DBF file has an extended header only if an application calls the Plib|function DbfExtHeaderwrite. At
|
||
the time of writing SIBO applications neither make this call nor make use of the extended header.
|
||
|
||
The field information record
|
||
|
||
The field information record is a type 2 record.
|
||
|
||
|
||
The first byte contains the number of fields defined for each type I rd (see below for an explanation
|
||
of type I records). In the above example four fields were defined. The number of fields defined must be
|
||
an integer between 1 and 32 inclusive
|
||
|
||
|
||
The second byte always contains <20> (see below for an explanation).
|
||
|
||
|
||
The remaining bytes contains the field types. The first byte contains the type of the first field, the second
|
||
byte contains the type of the second field and so on. The following types are allowed:
|
||
|
||
|
||
= a type of 0 means that the field is an integer: a numeric value stored in two bytes, low byte first.
|
||
= a type of 1 means that the field is a Jong: a numeric value stored in 4 bytes.
|
||
|
||
|
||
= a type of 2 means that the field is a double: a floating point value stored in 8 bytes in standard
|
||
IEEE format.
|
||
|
||
|
||
= a type of 3 means that the field is a string: a sequence of up to 255 bytes preceded by a byte
|
||
giving the length of the sequence.
|
||
|
||
|
||
The format of all records
|
||
|
||
|
||
All ae contain a two byte header followed by a sequence of bytes constituting the body of the
|
||
record. :
|
||
|
||
|
||
The highest nibble of the header word contains the record's type. The lowest three nibbles contain the
|
||
length of the record body (a nibble is four bits, thus each byte consists|of two nibbles). This explains
|
||
why the second byte in the header of the field information record is always <20>.
|
||
|
||
|
||
|
|
||
.
|
||
|
||
|
||
4 DBF FILES
|
||
a i
|
||
|
||
|
||
In the example DBF file (see above) the record immediately following the field informati
|
||
<12><10> as its header and is thus a type 1 record, with a mee of length paobyies eee
|
||
|
||
|
||
Counting past another 0x12 bytes leads to the header of the following record, which is also <12><10>.
|
||
Counting along yet another 0x12 bytes leads precisely to the end of the file.
|
||
|
||
|
||
Since each of these records are type J] they must all conform to the internal structure specified in the field
|
||
information record:
|
||
|
||
|
||
= a leading byte-counted string, for the first string field.
|
||
= asecond leading byte-counted string.
|
||
|
||
= two bytes for the integer field.
|
||
|
||
= eight bytes for the double field.
|
||
|
||
|
||
Looking more closely at the above dump, it can now be appreciated how the details of the file contents
|
||
match the earlier Opl program.
|
||
|
||
|
||
Generally speaking, the only types of record that will be found in any DBF file produced by a SIBO
|
||
application are:
|
||
|
||
|
||
type 1 standard record.
|
||
|
||
type 2 field information record.
|
||
type 3 descriptive record.
|
||
|
||
type 0 deleted record.
|
||
|
||
|
||
Deleted records
|
||
Consider the following Opl program, which differs from the earlier one in only one line:
|
||
|
||
|
||
PROC writedbf:
|
||
if exist("test.dbf") sdelete "test.dbf" :endif
|
||
create “test.dbf",a, f1$, f2$, f3%, £4
|
||
a. f1$="Hel Lo"
|
||
a. f2$="2"
|
||
a. f3%=3
|
||
a. f4=4
|
||
append
|
||
a. f1$="Wor td"
|
||
update
|
||
close
|
||
beep 5,300
|
||
ENDP
|
||
|
||
|
||
The change is that the second append instruction has become an update instruction, so that the end result
|
||
is that the file has only one record.
|
||
|
||
|
||
Dumping the DBF file output by this second program gives (provided the file is created on a Flash SSD):
|
||
O: 4f 50 4c 44 61 74 61 62 61 73 65 46 69 6c 65 00 OPLDatab aseFile.
|
||
|
||
|
||
10: Of 11 16 00 Of 11 04 20 03 03 00 02 12 00 05 48 — wane ne wa ween H
|
||
20: 65 6c 6c 6f 01 32 03 00 00 00 00 00 00 00 10 40 ello.2.. wcceees a
|
||
30: 12 10 05 57 6f 72 6c 64 01 32 03 00 00 00 00 00 oe World .2...00.
|
||
40: 00 00 10 40 |
|
||
|
||
|
||
This differs from the earlier dump only with regard to one nibble which gives the record type for the first
|
||
record in the file. The two bytes <12><10> at file offset 0x1c have changed into <12><00>, indicating that
|
||
while the same length of data remains on the file, the first record is no longer type 1 but type 0, i.e. it
|
||
has been deleted.
|
||
|
||
|
||
Erased records remain in a DBF file until such time as the file is written out again, say in response to a
|
||
"Save As" menu command, or until the file is compressed (say in response to a "Compress" menu
|
||
command). (In fact, Opl programs automatically attempt to compress their DBF files whenever they are
|
||
closed, which explains why the above example gives different results unless the file is created on Flash.)
|
||
|
||
|
||
Although erased records may remain part of a DBF file long after the application has "deleted" or
|
||
"updated" them, they are inaccessible to normal software (eg to the Plib Dbfxxx calls and the Opl database
|
||
functions such as find and count).
|
||
|
||
|
||
i S
|
||
|
||
|
||
47
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
For more discussion about the mechanism of deleting records, see the Database Files chapter in the Plib
|
||
Reference manual.
|
||
|
||
|
||
The remaining examples of DBF files in this chapter all assume that any deleted records have been
|
||
removed.
|
||
|
||
|
||
Descriptive records
|
||
|
||
|
||
From most points of view, records of type 3 and upwards are all potentially "singular" records without
|
||
the usual software support. Operations such as "Find" do not usually find text within such records as
|
||
these record types are not used by standard SIBO applications (with one important exception, discussed
|
||
below). See the Database Files chapter in the Plib Reference manual for more details of these record
|
||
|
||
|
||
types
|
||
|
||
|
||
The exception is with a record of type 3, which is a so-called "descriptive" record. See later in this
|
||
chapter for examples of data that may be stored in a descriptive record.
|
||
|
||
|
||
There is usually at most one record of type 3 in any one DBF file.
|
||
|
||
|
||
By convention, a descriptive record's data is composed of a number of'typed fields, with the types having
|
||
variable meaning depending on the application. Given that different versions of an application may define
|
||
different types of field within the descriptive record, it is good practice for applications that encounter
|
||
fields in a descriptive record that they do not understand, to preserve these fields and to write them out
|
||
|
||
|
||
again whenever the descriptive record needs to be changed.
|
||
|
||
|
||
More on type 1 records
|
||
|
||
|
||
It is not always necessary for a type 1 record to have entries for each fi ld defined in the field information
|
||
record. Depending on the application, any trailing omitted fields will usually be assumed to be zero or
|
||
null.
|
||
|
||
|
||
It is also possible for a record to have more than 32 fields. This is allowed in the case where the
|
||
descriptive record explicitly defines 32 fields. In this case, any extra data in a record, beyond the 32nd
|
||
field, is interpreted as a sequence of additional string fields.
|
||
|
||
|
||
The Series 3 Database
|
||
|
||
|
||
In this section reference to the Series 3 Database is taken to include the Series 3a Database except where
|
||
explicitly stated otherwise.
|
||
|
||
|
||
The Series 3 Database stores its files in the DBF file format, as described in general terms at the
|
||
|
||
beginning of this chapter. By convention, the Series 3 Database uses file with extension . dbf.
|
||
|
||
Field information record
|
||
|
||
The field information record of a Series 3 Database file is always as follows:
|
||
<20><20><03><03><03> ... <03><03><03>
|
||
|
||
there being 32 <03>'s in all. As mentioned above, this actually means that any type I record in the file
|
||
|
||
consists of a variable arbitrary number of string fields (where this number can exceed or fall short of 32).
|
||
|
||
Extended header
|
||
|
||
There are no extended headers on any Series 3 Database files.
|
||
|
||
|
||
Descriptive record
|
||
|
||
|
||
For an example of a descriptive record (type 3) consider the following dump of a default newly-created
|
||
and exited Series 3 Database .dbf file (see below for a Series 3a example):
|
||
|
||
|
||
2: 4f 50 4c 44 61 74 61 62
|
||
|
||
|
||
Of 10 16 00 Of 10 20 20
|
||
|
||
|
||
61 73 65 46 69 6c 65 00
|
||
03 03 03 03 03 03 03 03
|
||
|
||
|
||
OPLDatab aseFile.
|
||
|
||
|
||
20: 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03) cena eehe cece eens
|
||
30: 03 03 03 03 03 03 03 03 31 30 02 10 04 000250 __—=........ - 10..... P
|
||
40: 05 00 27 40 05 4e 61 6d 65 3a 07 05 20 48 6f 6d --'@.Nam e:.. Hom
|
||
50: 65 3a 07 05 20 57 6f 72 6b 3a 08 41 64 64 72 65 e:.. Wor k:.Addre
|
||
|
||
|
||
60: 73 73 3a 00 06 4e 6f 74 65 73 3a sS:..Not es:
|
||
48
|
||
|
||
|
||
4 DBF FILES
|
||
|
||
|
||
—— eee
|
||
The header of the first record after the field information record is <31><30>. This indicates that the record
|
||
|
||
|
||
has type 3 and body length 0x31 bytes and therefore extends to the end of the file.
|
||
|
||
|
||
Series 3a Database files are longer as the descriptive records contain more fields. Here is a newly-created
|
||
|
||
|
||
and exited Series 3a Database .dbf file.
|
||
|
||
|
||
O: 4f 50 4c 44 61 74 61 62 61 73 65 46 69 6c 65 00 OPLDatab aseFile.
|
||
|
||
10: Of 10 16 00 OF 10 20 20 03 03 03 03 03 03 03 03) cae ee cece eee
|
||
20: 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 ssa nee wees
|
||
30: 03 03 03 03 03 03 03 03 aa 30 02 10 04 000250 —s.=......... O..-.. P
|
||
40: 14 00 3a 60 82 2e c6 41 08 07 08 07 72 20 bé6 33 ood cesA woe 23
|
||
30: dO 02 dO 02 00 00 00 00 01 00 ff ff 000000 00~—......... 1.2.0...
|
||
60: f0 00 00 00 00 00 00 00 f0 00 02 00 0000 0000... ........
|
||
70: 00 00 CO 00 00 00 f0 00 00 00 00 00 00 00 0d 70.12... 6. cee eeee
|
||
|
||
80: 00 52 4f 4d 3a 3a 42 4a 2e 57 44 52 00 Oc 80 00 eROM::BJ .WOR....
|
||
90: 00 00 25 50 00 82 2e c6 41 08 07 Oc 90 25 50 00 0eMPecee Ave eeMP.
|
||
a0: 82 2e c6 41 08 07 08 07 72 03 a0 01 00 01 04 bd eoeAhesee Pocccces
|
||
bO: 00 00 ff ff 2e 40 05 4e 61 6d 65 3a 07 05 2048 ~—COti«iw..... @.N ame H
|
||
cO: 6f 6d 65 3a 07 05 20 57 6f 72 6b 3a 06 05 20 46 ome:.. Woork:.. F
|
||
dO: 61 78 3a 08 41 64 72 65 73 73 3a 00 06 4e 6f ax:.Addr ess:..No
|
||
|
||
|
||
tess
|
||
|
||
|
||
The header of the first record after the field information record is <aa><30>. This indicates that the record
|
||
has type 3 and body length Oxaa bytes and therefore extends to the end of the file.
|
||
|
||
|
||
The body of a Series 3 Database descriptive record contains:
|
||
® a field of type 1 and length 2.
|
||
= a field of type 5 and length 2.
|
||
= a field of type 4 and length 0x27.
|
||
|
||
|
||
The body of a Series 3a Database descriptive record contains the above three fields and adds the
|
||
following additional fields:
|
||
|
||
|
||
= a field of type 6 and length 58.
|
||
® a field of type 7 and variable length.
|
||
= a field of type 8 and variable length.
|
||
8 aa field of type 9 and variable length.
|
||
® aa field of type 10 and length 3.
|
||
= a field of type 11 and length 4.
|
||
|
||
The above field types are as follows:
|
||
|
||
|
||
type 1 width of a tab in columns.
|
||
|
||
type 5 general flags options.
|
||
|
||
type 4 template data.
|
||
|
||
type 6 printer setup information.
|
||
|
||
type 7 printer model: a zero terminated string that starts with the model number and
|
||
continues with the path for the printer driver file.
|
||
|
||
type 8 text for header: a zero terminated string.
|
||
|
||
type 9 text for footer: a zero terminated string.
|
||
|
||
type 10 diamond bar settings: bytes zero, one or two are set to Oxff if 'Find",'Change'
|
||
or 'Add' are included in the diamond bar respectively.
|
||
|
||
type 11 current search field: the first two bytes specify the start field with 0x00
|
||
|
||
|
||
meaning search in all fields, the second two bytes specify the end field with
|
||
Oxff meaning search from start field to last field in record. Thus values of 0x10
|
||
and 0x20 would imply a search from field sixteen to field thirty two inclusive.
|
||
|
||
|
||
Other types may be used by other versions of the Database application (eg types 2 and 3 are used by the
|
||
_MC Database) and should be preserved intact when encountered.
|
||
|
||
|
||
49
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
: third
|
||
In the above example it can be seen that the width of the tab is equal to)4 columns as given by the
|
||
and fourth bytes of the type 1 field which starts at offset Ox3b (remember that the first two bytes are the
|
||
record header). The value of the flags options is 0x05, and the contents of the labels can easily be read as
|
||
|
||
|
||
a sequence of leading byte-counted strings.
|
||
|
||
|
||
be e e h
|
||
Note that the first character in a template field name can be a telephone symbol (0x05) in which case eac
|
||
part-paragraph in the field matching the template entry can be used for automated dialling.
|
||
|
||
|
||
Flags options for the Series 3 Database
|
||
The meanings of possible bits in the flags options are as follows:
|
||
|
||
|
||
0x01 the permanent status window is on
|
||
0x02 entries are word-wrapped
|
||
0x04 a template should be displayed.
|
||
|
||
|
||
Type 1 records
|
||
|
||
' Entries in the Database are stored as single type J records in the corresponding .dbf file.
|
||
|
||
The following special (non-text) characters may occur within any string in a type 1 record in a .dbf file,
|
||
with these meanings:
|
||
|
||
|
||
0x15 forced line feed (with the two part-paragraphs on either ide of the forced line break just
|
||
counting as one paragraph for the purposes of the template, even though each part word-
|
||
wraps separately)
|
||
|
||
|
||
0x05 prefixes a diallable telephone number (over and above any indication of diallability given in
|
||
the template text) :
|
||
|
||
|
||
0x14 if this occurs as the first character in a string, it means this field should in fact be joined
|
||
together with the preceding one, as discussed in the following section.
|
||
Continuation sub-fields
|
||
|
||
|
||
The Series 3 Database uses a special mechanism in order to store fields of text exceeding 255 characters
|
||
in length. Any such fields are broken down into sub-fields with at most 255 characters of text:
|
||
|
||
|
||
= the first 255 characters form the first sub-field
|
||
|
||
|
||
= up to the next 254 characters form the second sub-field, with the special character 0x14 being
|
||
placed at the beginning of the string (and included in the p ing byte count)
|
||
|
||
|
||
= additional continuation sub-fields of up to 254 characters are
|
||
being preceded by the 0x14 character.
|
||
|
||
|
||
The continuation sub-field prefix character was in fact specially cho
|
||
on the MC, should the .dbf file be read into the MC Database appli
|
||
|
||
|
||
as required, in each case again
|
||
|
||
|
||
so as to give a suggestive display
|
||
on.
|
||
|
||
|
||
The Series 3 Agenda ;
|
||
This section describes only the Series 3 Agenda. The Series 3a Agenda is described in a separate chapter.
|
||
|
||
|
||
The Series 3 Agenda stores its files in the DBF file format, as described in general terms at the beginning
|
||
of this chapter. By convention, the Series 3 Agenda uses files with extension .agn.
|
||
|
||
|
||
Field information record
|
||
The field information record of a Series 3 Agenda file is always as follows:
|
||
<05><20><00><00><00><00><03>
|
||
|
||
|
||
indicating that each type 1 record in a .agn file consists of four integer fields followed by one string
|
||
field. More details of these fields are given below.
|
||
|
||
|
||
Extended header
|
||
There are no extended headers on any Series 3 Agenda files.
|
||
|
||
|
||
50
|
||
|
||
|
||
4 DBF FILES
|
||
|
||
|
||
Descriptive record
|
||
|
||
|
||
For an example of a descriptive record, consider the following, which is a d of a default newly-
|
||
created (and exited) Series 3 .agn file: ‘ a aia
|
||
|
||
|
||
0: 4f 50 4c 44 61 74 61 62 61 73 65 46 69 6c 65 00 OPLDatab aseFile.
|
||
10: Of 10 16 00 Of 10 05 20 00 00 00 00 03 0e 30 0c ........ wee 0.
|
||
20: f0 a4 01 3c 00 01 00 Of O00 1c 02 2e 00 er ee
|
||
|
||
|
||
The header of the first record after the field information record is <0e><30>. This means that the record
|
||
has type 3 and body length 0x0e bytes. Evidently, this record extends to the end of the file.
|
||
|
||
|
||
The body of this descriptive record is made up of a single field of type 15 and length 0x0c. The body of
|
||
this single field consists of 6 integers, with the following meanings:
|
||
|
||
|
||
= the time (in minutes since midnight) for the first appointment slot of the day
|
||
|
||
# the default length of an appointment (in minutes)
|
||
|
||
® whether or not alarms are on by default
|
||
|
||
= the default advance time (in minutes) before a timed appointment for an alarm
|
||
|
||
= the default time (in minutes since midnight) for the alarm for an untimed appointment
|
||
|
||
« the character (low byte only - the high byte is ignored) to be used as the time separator.
|
||
Evidently, these sub-fields match the various lines in the Settings dialog within the Agenda application.
|
||
|
||
|
||
Type 1 records
|
||
|
||
Entries in an Agenda are stored as single type 1 records in the corresponding .agn file.
|
||
Individual ToDo items and Repeated items are also stored as single type 1 records.
|
||
The five fields in Agenda type 1 records are
|
||
|
||
|
||
integer: DayNumber
|
||
integer: Duration
|
||
integer: Time
|
||
integer: AlarmTime
|
||
string: Text
|
||
|
||
|
||
DayNumber is the number of days since 1/1/1900 (which is day zero). As far as the Series 3 Agenda is
|
||
concerned, the first legal day is 1/1/1980, and the last legal day is 31/12/2049.
|
||
|
||
|
||
Duration, Time, and AlarmTime are all stored in minutes (ignoring for the moment the fact that some
|
||
calculations with these values have to be performed in places - as described below).
|
||
|
||
|
||
The MSB (most significant bit) of Time is a flag that indicates whether the item is timed or untimed. If
|
||
the MSB is set then the item is untimed. Accordingly, to extract the time from the Time field this value
|
||
must be anded with 0x7fff to remove the MSB
|
||
|
||
|
||
The LSB (least significant bit) of Duration is a flag that indicates whether the item has an alarm attached.
|
||
If the LSB is set then no alarm is attached. Accordingly, to extract the duration from the Duration field,
|
||
divide this value by 2 (thus removing the LSB and shifting down the duration).
|
||
|
||
|
||
If the item is untimed then the Time field contains the day note slot number and its MSB must be set (ie
|
||
or in 0x8000). In this case, the Duration field simply equals 0 if an alarm is attached or 0x01 if no alarm
|
||
is attached.
|
||
|
||
|
||
Note that the end time of a timed item (obtained by adding its start time and its duration) must always be
|
||
less than 1440 (ie midnight).
|
||
Calculating with AlarmTime
|
||
|
||
|
||
For internal efficiency reasons, the way in which the alarm pre-time (as defined by the user) is stored in
|
||
the .agn file is somewhat counter-intuitive.
|
||
|
||
|
||
To recover the pre-time of the alarm for a timed appointment, the values of Time and AlarmTime for the
|
||
entry should be added, and then the value (23*60+59) subtracted from this result.
|
||
|
||
|
||
ae
|
||
|
||
|
||
51
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
|
|
||
|
||
|
||
For example, if the value of Time is 0x3fc and the value of AlarmTime iis 0x1b2, the actual alarm pre-time
|
||
is
|
||
|
||
Ox3fc + Oxib2 - (235*60 + 59)
|
||
ie 15 minutes (for an appointment actually at 5pm in the afternoon).
|
||
|
||
|
||
In the case of untimed appointments, the integer value obtained when : larmTime is divided by 24*60
|
||
gives the number of days previous to the appointment when the alarm is due. The time of day when the
|
||
alarm is due is obtained by subtracting the remainder when AlarmTime is divided by 24*60, from
|
||
23*60+59. |
|
||
|
||
|
||
For example, if the value of Time is 0x8000 and the value of AlarmTime is 0xe87, note that
|
||
Oxe87 = 2*(24+60) + 839
|
||
so that the alarm is due two days in advance of the appointment, at 10am (since 23*60+59-839=600).
|
||
|
||
|
||
If required, appropriate values of AlarmTime to ensure given alarm pre-times can easily be calculated by
|
||
reversing the above formulae.
|
||
|
||
|
||
Finally, note that if an appointment does not have an alarm set for it, the value of AlarmTime should be
|
||
set to Oxf fff. |
|
||
|
||
|
||
The text of an appointment
|
||
The text for an appointment is contained within the Text field of the record.
|
||
|
||
|
||
In all but the cases of repeated entries, the text is simply the entire content of the field. For repeated
|
||
|
||
|
||
items, the final six bytes of the Text field have a special meaning, as ss below.
|
||
|
||
|
||
In all cases, the length of the actual text for an appointment cannot ex 63 characters.
|
||
|
||
ToDo items /
|
||
|
||
ToDo items have a DayNumber of Oxffff, and must be stored as timed] items (and so the MSB of the
|
||
Time field must be clear).
|
||
|
||
|
||
The Time field contains the item priority, that is a value from 1 to 9.
|
||
The Duration field contains a secondary integer key, which orders the ToDo items within a given
|
||
priority.
|
||
|
||
ToDo items cannot have alarms attached.
|
||
|
||
|
||
Repeat items
|
||
|
||
|
||
Timed and untimed repeat items are stored in the same general way as
|
||
except that they have a DayNumber of Oxfffe.
|
||
|
||
|
||
es specific repeat details are stored in the six bytes at the end of the Text field and have the following
|
||
ormat:
|
||
|
||
|
||
ormal timed and untimed items,
|
||
|
||
|
||
52
|
||
|
||
|
||
Byte: Type
|
||
|
||
Byte: Interval
|
||
|
||
Integer: StartDayNumber
|
||
|
||
Integer: EndDayNumber
|
||
The Type field can take the following values: |
|
||
|
||
0 Repeat yearly |
|
||
|
||
1 Repeat monthly by date
|
||
|
||
2 Repeat monthly by day
|
||
|
||
3 Repeat weekly
|
||
|
||
4 Repeat daily
|
||
|
||
5 Repeat workdays.
|
||
|
||
|
||
4 DBF FILES
|
||
|
||
|
||
StartDayNumber and EndDayNumber are stored as the number of days since 1/1/1900 (which is day 0).
|
||
Setting EndDayNumber to zero means the item repeats "forever".
|
||
|
||
|
||
53
|
||
|
||
|
||
CHAPTER 5
|
||
|
||
|
||
SERIES 3A AGENDA FILE FORMAT
|
||
|
||
|
||
i ae ee ee ee
|
||
Introduction
|
||
|
||
|
||
Series 3a Agenda files are binary files containing typed variable length records. They use the same basic
|
||
file and record structure as DBF files, but the file signature and internal record structure are NOT the
|
||
same.
|
||
|
||
|
||
In contrast, Series 3 Agenda files are DBF files and are described separately, in the DBF Files chapter.
|
||
|
||
|
||
a Ne ee a |
|
||
Basic structure of Agenda files
|
||
The basic file structure for Agenda files is as follows:
|
||
|
||
|
||
<standard header> Used to identify the file type and the version of the file structure.
|
||
<extended header> For future use, currently omitted.
|
||
<data records> The main body of the file, containing entries and preferences.
|
||
|
||
|
||
The standard header
|
||
The standard header is present at the start of all Agenda files and is always 32 bytes long.
|
||
|
||
|
||
AGD_SIG SIZE 16
|
||
AGD_SPARE_SIZE 12
|
||
|
||
|
||
typedef struct
|
||
{
|
||
UBYTE sig fAGO_SIG_SIZE};
|
||
UWORD version;
|
||
UWORD hSize;
|
||
UBYTE spare [AGD_SPARE_SIZE];
|
||
> AGD_FILE_HEADER;
|
||
|
||
|
||
The first 16 bytes of the file are always the zero terminated string AgendaF i leType*. This is used to
|
||
identify the file as an Agenda file.
|
||
|
||
|
||
The two byte parameter version at file offset 0x100f should be interpreted as a hexadecimal word that
|
||
gives the version of the file format. This is currently always Ox100F. The most significant nibble (the
|
||
version number is in the format described in the General System Services chapter of the Plib Reference
|
||
manual) is the major version number and any change in this indicates that the file format may not be
|
||
backwards compatible.
|
||
|
||
|
||
The two byte parameter hSize gives the combined size of the standard and extended header. This
|
||
effectively gives the file offset of the first data record within the file. Currently this is always 0x0020.
|
||
|
||
|
||
The array spare should not be used and is reserved for future use.
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
The extended header
|
||
At present this is never used and is reserved for future expansion.
|
||
|
||
|
||
The data records
|
||
|
||
|
||
As in DBF files all data is stored as variable length, typed records, a the type and length combined
|
||
into a single word (two bytes). The most significant nibble of the word) gives the record type. The type
|
||
determines how the contents of the record are to be interpreted. The remainder of the word gives the
|
||
length of the data that follows. This file structure is designed to be flash friendly in that deleted records
|
||
are not normally removed from the file but are marked with record type 0 which can be done in place.
|
||
|
||
|
||
This structure allows 16 record types 0x0 to Oxf, each of which are allowed to be up to Oxffe (4094) bytes
|
||
long. Although a record length of Oxfff is not explicitly illegal it is ” used.
|
||
|
||
|
||
|
|
||
a Nh Ait ee ee
|
||
Record Types
|
||
|
||
|
||
There are sixteen record types as follows.
|
||
|
||
|
||
Type Record
|
||
0 Deleted
|
||
1 Appointments (timed day entries)
|
||
|
||
2 Day notes (un-timed day entries)
|
||
|
||
3 Anniversaries
|
||
|
||
4 To-do entries
|
||
|
||
5 Repeat records |
|
||
6 Anonymous data
|
||
7 Reserved |
|
||
8 Reserved
|
||
9 To-do list information :
|
||
10 Descriptive records 1
|
||
11 Descriptive records 2 |
|
||
12 Descriptive records 3
|
||
13 Descriptive records 4
|
||
|
||
14 Descriptive records 5
|
||
15 Illegal (used to mark write failure) |
|
||
|
||
|
||
Currently record types 6, 7 & 8 are never generated by the Series 3a Agenda.
|
||
|
||
|
||
A number of the records contain day numbers and times. Unless stated] otherwise all dates are given as a
|
||
daynum. A daynum is the number of days from 1 Jan. 1970. For technical reasons dates before 1 Jan.
|
||
1980 (daynum 3652) or after 31 Dec. 2049 (daynum 29219) are ignored by the Agenda and where
|
||
appropriate will be 'clipped' to one or other of these dates (for example a repeating entry that starts on 10
|
||
June 1970 will have its start date ‘clipped’ to 1 Jan. 1980).
|
||
|
||
|
||
a ea OR Ae A A TT EE TE
|
||
Type O - deleted record |
|
||
|
||
|
||
As for DBF files, deleted records are not normally removed from the file but have their record type
|
||
changed to type 0. As any of the above record types may be converted to a type O record, there is nothing
|
||
that can usefully be said about the contents of such a record (indeed the record may not even have been a
|
||
valid Agenda record before it was deleted). Records of this type should be ignored except to calculate the
|
||
amount of space that would be freed by compressing the file.
|
||
|
||
|
||
56
|
||
|
|
||
|
||
|
||
5 SERIES 3A AGENDA FILE FORMAT
|
||
|
||
|
||
There may be any number of such records in the file.
|
||
|
||
|
||
Sa a Mes aa a I eT ae
|
||
Types 1 to 4 - entry records
|
||
|
||
|
||
Records of type 1 to 4 contain details of individual Agenda entries. Each has the same conceptual
|
||
structure as follows:
|
||
|
||
|
||
<Entry details field This is dependent on the entry type.
|
||
|
||
<Title field> Obligatory, variable length field containing the text of the entry.
|
||
<Alarm field> Optional, fixed length field containing alarm time and sound.
|
||
<Memo field> Optional variable length field containing any memo for the entry.
|
||
|
||
|
||
The record type is used to determine the length and meaning of the first field. Although these have some
|
||
similarities all four are individually described in details below.
|
||
|
||
|
||
Type 1 (timed day entry/appointment)
|
||
|
||
|
||
A type 1 record stores details of entries that occur at a specific time on a specific day. In the Series 3a
|
||
Agenda these are called timed day entries.
|
||
|
||
|
||
The details field for a timed day entry consists of eight bytes structured as follows:
|
||
|
||
|
||
UWORD day;
|
||
UWORD time;
|
||
UBYTE attr;
|
||
UBYTE code;
|
||
UWORD dur;
|
||
day is the daynum of the day on which the entry appears.
|
||
time is the time of the start of the appointment in minutes from midnight.
|
||
attr is a byte containing flags for attributes the entry may or may not have (see
|
||
below).
|
||
code is the ASCII character code for the symbol that is to be associated with the
|
||
entry when it is visible in the Year view. Values less than 32 are ignored and
|
||
treated as if the entry should not appear in the Year view.
|
||
dur is the duration of the appointment measured in minutes. It is constrained such
|
||
|
||
|
||
that the appointment cannot end after 11:59 PM. i.e. this field is between 0
|
||
and 1439 - time (inclusive).
|
||
Type 2 (untimed day entry/note)
|
||
|
||
|
||
A type 2 record stores details of entries that appear on a specific day but do not have a time associated
|
||
with them. In the Series 3a Agenda these are called untimed day entries.
|
||
|
||
|
||
The details field for an untimed day entry consists of six bytes structured as follows:
|
||
|
||
|
||
UWORD day;
|
||
UWORD slot;
|
||
UBYTE attr;
|
||
UBYTE code;
|
||
day is the daynum of the day on which the entry appears.
|
||
slot is the time slot (in minutes from midnight) in which the entry will appear in
|
||
|
||
|
||
the Day and Week views. For example a slot value of 780 would show the
|
||
entry at the start of the 1pm slot. If this is Oxffff then the entry will appear in
|
||
the default slot.
|
||
|
||
|
||
57
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
attr is the attributes byte (see below).
|
||
|
||
|
||
ode is the ASCII character code for the symbol \. is to be associated with the
|
||
° entry when it is visible in the Year view. Values less than 32 are ignored and
|
||
|
||
|
||
treated as if the entry should not appear in the Year view.
|
||
|
||
|
||
Type 3 details (anniversaries)
|
||
|
||
|
||
A type 3 record stores details of anniversaries (entries which appear in| the Anniversary view). Although
|
||
these are usually repeated there are cases where a single anniversary entry will exist. For details of
|
||
repeated entries see type 5 records below.
|
||
|
||
|
||
The details field for an anniversary record consists of nine bytes struc as follows:
|
||
|
||
|
||
UWORD day;
|
||
UWORD slot;
|
||
UBYTE attr;
|
||
UBYTE code;
|
||
UWORD baseYear;
|
||
UBYTE displayAs;
|
||
|
||
|
||
day is the daynum for the day the anniversary entry will appear on.
|
||
|
||
|
||
slot is the time slot (in minutes from midnight) in which the entry will appear in
|
||
the Day and Week views. For example a slot value of 780 would show the
|
||
entry at the start of the lpm slot. If this is Oxff#f then the anniversary will
|
||
|
||
|
||
appear in the default slot.
|
||
attr is the attributes byte (see below).
|
||
code is the ASCII code for the character to display when the entry is visible in the
|
||
|
||
|
||
Year view. Values less than 32 are illegal and cause the entry not to appear in
|
||
|
||
|
||
the Year view.
|
||
|
||
|
||
baseYear is the year of the event that the anniversary commemorates. Positive values
|
||
indicate AD years e.g. 55 means 55 AD i negative values indicate BC e.g.
|
||
-5 means 5 BC. A value of zero indicates that there is no baseYear. The
|
||
allowed range is from 30000 BC to 2049
|
||
|
||
|
||
displayAs contains flags detailing how the entry is to be displayed. The flags are as
|
||
follows: 0x01 for baseYear displayed, 0x02 for elapsed years displayed, 0x03
|
||
for both of the preceding options and 0x00 for none of them.
|
||
|
||
|
||
Type 4 details (To-do)
|
||
A type 4 record holds details of to-do entries.
|
||
|
||
|
||
These are entries which usually have an associated due date and a display from date. They appear in the
|
||
corresponding to-do list, and depending on the preference settings will appear in the Day view from the
|
||
displayFrom date until they are crossed out or deleted.
|
||
|
||
|
||
The details field for a to-do entry consists of 14 bytes structured as follows:
|
||
|
||
|
||
UWORD displayFrom;
|
||
|
||
UWORD slot;
|
||
|
||
UBYTE attr;
|
||
|
||
UBYTE code;
|
||
|
||
UWORD dueDate;
|
||
|
||
UBYTE ListNo;
|
||
|
||
UBYTE priDisp;
|
||
|
||
ULONG order;
|
||
|
||
|
||
displayFrom is the daynum of the day on which the entry first appears in the Day/Week
|
||
views of the Agenda. This must normally be the same or less than the dueDate
|
||
value.
|
||
|
||
|
||
If the entry is crossed out (see the description of the attr byte below) this is
|
||
the daynum of the day on which the entry was crossed out. In this case, and
|
||
only in this case, the displayfrom can be later than the dueDate.
|
||
|
||
If the displayFrom daynum is Oxffff, then this is an un-dated to-do i.e. one that
|
||
always appears on today. In this case the dugDate will also be Oxffff.
|
||
|
||
|
||
58
|
||
|
||
|
||
5 SERIES 3A AGENDA FILE FORMAT
|
||
|
||
|
||
slot is the time slot (in minutes from midnight) in which the entry will a in
|
||
the Day and Week views. If this is oxfff¢ then the entry will appear inthe
|
||
default slot of the appropriate to-do list.
|
||
|
||
|
||
attr is the attributes byte (see below).
|
||
|
||
|
||
code is the ASCII code for the character to display when the entry is visible in the
|
||
Year view. Values less than 32 are illegal and cause the entry not to appear in
|
||
the Year view.
|
||
|
||
|
||
dueDate is the daynum of the day the to-do should be done by. If this value is oxffff
|
||
the record is an undated to-do (i.e. one which always appears on today when it
|
||
appears in the Day/Week views).
|
||
|
||
ListNo is the internal number (0-255) of the to-do list on which the entry will appear.
|
||
|
||
|
||
Note that a value of zero does not necessarily mean that the entry appears on
|
||
the first to-do list in the To-do view. See type 9 records for further details of
|
||
the meaning of this byte.
|
||
|
||
|
||
priDisp this byte consists of two nibbles that give the priority and the method of
|
||
displaying the to-do.
|
||
The least significant nibble (bottom four bits) has a value one less than the
|
||
priority of the to-do. Thus a priority one to-do has value zero, priority two has
|
||
value one etc. This will currently always be in the range zero to eight inclusive
|
||
and all other values are illegal.
|
||
The most significant nibble (top four bits), determines how the due date should
|
||
be displayed there are currently four legal values:
|
||
O - automatic, shown as date until within a week then shown as e.g. Next wed.
|
||
1 - Always shown as date.
|
||
2 - Shown as number of days until due date.
|
||
3 - Due date never shown.
|
||
|
||
|
||
order this determines the position of the entry in its to-do list when the list is
|
||
displayed in manual order. This field is not assigned consecutively. Thus a
|
||
value of 3 for example in this field does not necessarily mean that the entry
|
||
appears third (or fourth) on the to-do list.
|
||
|
||
|
||
The attributes byte ‘aétr'.
|
||
|
||
|
||
The above record types (1 to 4) contain an attributes byte as the fifth byte within the record data. This
|
||
byte contains flags which indicate which of the two optional fields are present in the record, whether or
|
||
not the entry is repeated etc. The following flags are currently defined for the attributes byte (all other
|
||
bits should be 0).
|
||
|
||
|
||
Bit Meaning
|
||
00000001 Once only: if this bit is set the entry appears only once in the Agenda. If it is
|
||
|
||
|
||
clear the entry is repeating and there will be an associated type 5 repeat record
|
||
elsewhere in the file.
|
||
|
||
|
||
00000010 Pending: this bit is set if the entry has not been crossed out. If it is clear the
|
||
entry has been crossed out. In the case of to-do entries this alters the meaning
|
||
of the displayFrom field of the details.
|
||
|
||
|
||
00000100 Display code: if this bit is set the entry should be displayed in the Year view
|
||
(providing it has a legal code field): if it is clear the entry should not appear in
|
||
the Year view, regardless of the value of the code field.
|
||
|
||
|
||
00001000 No alarm: this bit is set if the entry does not have an associated alarm in which
|
||
case there will be no alarm field at the end of the record. If it is clear there is
|
||
an alarm field immediately after the title field.
|
||
|
||
|
||
00010000 No memo: this bit is set if there is no memo associated with the entry, in
|
||
which case there will be no memo field at the end of the record.
|
||
|
||
|
||
The title field must be present for entry records of all four types. This field follows immediately after th
|
||
details field and contains the text for the entry as well as flag for how that text should be displayed e.g.
|
||
bold, italic etc.
|
||
|
||
|
||
59
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
The format of the title field is: C)
|
||
UBYTE style;
|
||
UBYTE len;
|
||
title text.
|
||
style contains flags indicating how the text should] appear. The flags are as follows:
|
||
0x01 for bold, 0x02 for underline, 0x20 for italic.
|
||
len is the length of the text comprising the title, and the number of bytes
|
||
following. This may take any value from 0 -|254.
|
||
title text is Len bytes of the title. Note that this text is/mot zero terminated.
|
||
This fixed length field is only present if the attributes byte does not ave bit 3 (0x08) set, i.e. there is an
|
||
alarm set for the entry. |
|
||
When present this entry immediately follows the title field and has the following format:
|
||
UWORD preTime;
|
||
UBYTE Len; |
|
||
UBYTE sound[8] ; -
|
||
preTime is the time at which the alarm should occur given in minutes before 11.59 on
|
||
the day the entry appears on. (In the case ofa type-4 to-do record this is the
|
||
due date). This field can be between 0 and 46079 (midnight before, 31 days
|
||
before the entry).
|
||
len this gives the length of the text in the sound element.
|
||
sound is always eight bytes long the first len of which contain the name of the WVE
|
||
file for the alarm. A number of WVE files having names of the form
|
||
SYS$ALnn are built-in to the ROM. In addition name can be set to an ASCII
|
||
character with value between 1 and 16 inclusive: currently only “\0x01",
|
||
"\0x02" and "\0x10" are used corresponding to the rings, chimes and silent
|
||
alarms. If the name of the file is less than eight bytes long, all remaining bytes
|
||
should be zero.
|
||
When present this field comes at the end of the record immediately after the alarm field if there is one, ~~)
|
||
|
||
|
||
and after the title field if there is not. The field has the following format:
|
||
|
||
|
||
UWORD dataLength;
|
||
UBYTE data[];
|
||
|
||
|
||
dataLength is the length (in bytes) of the data in the memo field. This can be between 0
|
||
and 3600 (inclusive).
|
||
data is a block of data consisting of dataLength bytes containing the memo - details
|
||
|
||
|
||
of the memo are beyond the scope of this manual.
|
||
|
||
|
||
Type 5 - repeats
|
||
|
||
|
||
When an entry is set to repeat in the Agenda, a second record is written to the file in addition to the type
|
||
1 - 4 entry record. This record contains the date to repeat until, the days to repeat on and a list of those
|
||
dates for which the repeat should be suppressed.
|
||
|
||
|
||
Repeat records are always paired with an entry record which has bit 0 (0x01) of the attributes byte clear.
|
||
Because of the way the Series3a Agenda writes the file a type 5 repeat fecord will always occur after the
|
||
associated entry record, but this is not necessary and there is no reason! why it should not occur earlier in a
|
||
the file. If a repeat record is missing its associated entry record or if a repeated entry record exists for
|
||
which there is no associated repeat record, then the record in the file will be ignored.
|
||
|
||
|
||
60
|
||
|
||
|
||
5 SERIES 3A AGENDA FILE FORMAT
|
||
|
||
|
||
eee
|
||
|
||
|
||
The repeat record is structured as follows:
|
||
|
||
|
||
alg
|
||
|
||
|
||
ival
|
||
|
||
|
||
endDate
|
||
|
||
|
||
type
|
||
|
||
|
||
tags
|
||
|
||
|
||
filePos
|
||
|
||
|
||
exceptions [] ;
|
||
|
||
|
||
is the repeat algorithm and various flags. The bottom three bits of this byte
|
||
may take one of the following values: 0 - repeat daily, 1 - repeat weekly, 2 -
|
||
monthly by date, 3 - monthly by days, 4 - repeat annually.
|
||
|
||
If bit 3 (0x08), of this byte is set, the repeat should only appear once in the
|
||
dated views on the first occurrence after today. Otherwise all valid occurrences
|
||
are shown. All other bits in this byte should be 0.
|
||
|
||
|
||
is the daily repeat interval. This is zero if the entry repeats daily, 1 if the entry
|
||
repeats every other day etc. A value of 255 is not valid.
|
||
|
||
|
||
this is the daynum of the last day on which the entry can repeat. This is not
|
||
necessarily the last day on which it will appear. The start date is taken from
|
||
the day value at the start of the details field in the entry record. In the case of a
|
||
repeating to-do this is the displayFrom field that is normally used to give the
|
||
date from which to display the entry. Here it is used to determine the start date
|
||
of the repeat algorithm and hence determine which due dates will be associated
|
||
with the todos. To work out the display from dates for each instance of the
|
||
repeated to-do use the dueDate-displayFrom in the entry record to determine the
|
||
number of days warning for each instance of the repeat.
|
||
|
||
|
||
is the type (1-4) of the associated entry record. This information is actually
|
||
redundant since it can be determined by reading it directly once the associated
|
||
record has been found but is a useful optimisation internally to the Agenda.
|
||
|
||
|
||
is n bytes that determine which days occur in the repeat sequence. The number
|
||
of bytes n and their meaning is determined by the repeat algorithm. For repeat
|
||
daily/annually there are no tag bytes since the start date and ival determine
|
||
which dates to repeat over.
|
||
|
||
For weekly repeats there are two tag bytes. The first has a bit set for each day
|
||
of the week on which the repeat occurs. Bit 0 for Monday, bit 1 for Tuesday
|
||
etc. Bit 8 is not used and should always be 0. The second byte determines
|
||
which is the first day of the week, 0 for Monday, 1 for Tuesday etc. This is
|
||
significant when the repeat does not occur every week. A repeat which occurs
|
||
on say, Tuesday and Thursday of every other week, occurs on different dates if
|
||
the week starts on Monday than it does if the week starts on Wednesday.
|
||
|
||
For monthly by date repeats there are four tag bytes. Each bit in these bytes
|
||
represents a different day of the month. Bit 0 in the first byte is the ist of the
|
||
month, bit 1 the second and bit 7 the eighth of the month. Bit 0 of the second
|
||
tag byte is set if the repeat occurs on the 9th and so on. Bit 7 of the fourth byte
|
||
is not used and should be 0.
|
||
|
||
Monthly by days repeats have five tag bytes. Bytes 0 to 3 correspond to the
|
||
first, second, third and fourth occurrences of each day, for example bit 1 of
|
||
byte 2 is set if the algorithm repeats on the 3rd Tuesday of each month. The
|
||
last tag byte contains bits set if the repeat should occur on the last Monday,
|
||
say, of the month.
|
||
|
||
|
||
is the offset from the start of the file at which the corresponding entry record
|
||
can be found. This is given in bytes from the start of the file (not the start of
|
||
the data records), and gives the position of the type length word at the start of
|
||
the record. Note that this mechanism of associating repeat records with the
|
||
underlying entry relies on the deleted entries not being removed from the file:
|
||
they are just marked with the deleted record type. Removing such records
|
||
would require all FilePos fields to be recalculated.
|
||
|
||
|
||
61
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
exceptions The remainder of the record consists of words, each of which is the daynum of
|
||
a day on which the repeat should be suppressed. The number of exceptions 1s
|
||
determined by the length of the record. pepsi the Series 3a Agenda
|
||
currently always writes these exceptions in strictly increasing order, there is no
|
||
guarantee that this will always be the case. Any illegal values (either outside
|
||
the valid range for the Agenda or on a day which is not normally a repeat
|
||
instance) should be ignored but preserved.
|
||
|
||
|
||
Type 6 - anonymous data
|
||
|
||
|
||
This record type is currently not used and is set aside for storing aclu text carried with the
|
||
Agenda. It is intended that this information will be used by, say, conversion programs that convert other
|
||
Agenda file formats to that of the Series 3a. This allows the file to be converted back without losing
|
||
information from the original file. These records are ignored by the series 3a engine except when a
|
||
merging files. In this case incoming anonymous data records are ito the file into which data is being
|
||
merged.
|
||
|
||
|
||
Types 7 and 8 - reserved
|
||
|
||
|
||
These record types are reserved for future expansion and should not
|
||
|
||
|
||
Type 9 - to-do list information
|
||
|
||
|
||
There is one record of this type for each to-do list in the Agenda. Each contains the setting for the to-do
|
||
list and the to-do list number (as in type 4 to-do records) that corresponds to the list.
|
||
|
||
|
||
The format for these records is as follows:
|
||
|
||
|
||
UBYTE sig;
|
||
UBYTE data[]
|
||
sig a signature byte which determines the format of the rest of the record.
|
||
Currently the only legal value is Oxff.
|
||
data is data for the to-do list: the details of the data are beyond the scope of this
|
||
manual.
|
||
|
||
|
||
a hg i Eg ee
|
||
Types 10 to 14 - descriptive records
|
||
|
||
|
||
Type 10 to 14 records contain the preferences settings for the Agenda (these may be set via the
|
||
preferences dialog). Only one record of each type is allowed per Agenda file. If there is more than one
|
||
record of any type, only the last record is significant.
|
||
|
||
|
||
A descriptive record consists of the usual header word followed by the/record body. The record body
|
||
contains either simple data or a set of type/length/value (TLV) fields. A TLV field consists of a one word
|
||
header followed by the field body. The top four bits of the field heade ' contain the field type. The
|
||
bottom 12 bits contain the length of the field body. No more than one of each of the specified fields can
|
||
be present in a given record.
|
||
|
||
|
||
The structure of these records should not be extended (extra 7LV fields should not added even though
|
||
these would be ignored).
|
||
|
||
|
||
Type 10 to 14 records are described in greater detail below.
|
||
|
||
|
||
62
|
||
|
||
|
||
5 SERIES 3A AGENDA FILE FORMAT
|
||
ee ee
|
||
a a a gee OS ee eee]
|
||
Type 10 - styles descriptive record
|
||
|
||
|
||
The styles record contains the Memo editor preferences and its styles and emphases.
|
||
|
||
|
||
The styles record gets written after a memo has been created for the first ti d
|
||
ateiconten fins changed. e first time, and thereafter whenever
|
||
|
||
|
||
The details of this record are beyond the scope of this manual.
|
||
|
||
|
||
I eT Eg ee ge ee
|
||
Type 11 - to-do manager descriptive record
|
||
|
||
|
||
This record is written on creation of a new Agenda and so is always present. It gets rewritten whenever
|
||
changes have been made.
|
||
|
||
|
||
This record contains the information that the Agenda needs to determine which position each to-do list
|
||
ag the To-do view. The record consists of a header word followed by a body of three bytes structured
|
||
as follows:
|
||
|
||
|
||
UBYTE sig;
|
||
UBYTE ncats;
|
||
UBYTE catid[ncats]
|
||
|
||
|
||
sig is the signature and is always 0xéc.
|
||
ncats is the number of categories.
|
||
catid{ncats] contains ids for each category (i.e. to-do list) in the display order. Thus
|
||
|
||
|
||
catid(0) holds the id of the first displayed category, catid{1] the id of the
|
||
second, and so on up to a maximum of catid(98]. These are used to identify
|
||
each record as coming from a given category in a record.
|
||
|
||
|
||
Ea a ae a aw a Ug ea ee ON Te
|
||
Type 12 - frequently changing data descriptive record
|
||
|
||
|
||
This record is written on creation of a new Agenda and so is always present. However, as it contains data
|
||
that changes frequently, it is only rewritten when the file is closed.
|
||
|
||
|
||
This record contains zoom, wrap and status window settings for each view. It consists of a header word
|
||
followed by six VIEW_SCREEN_CFG structures for the Day, Week, Year, To-do, Anniversary and List views
|
||
respectively. A VIEW_SCREEN_CFG structure consists of three bytes and is structured as follows:
|
||
|
||
|
||
UBYTE statmode;
|
||
UBYTE wrapmode;
|
||
|
||
|
||
UBYTE zoom;
|
||
statmode this field is a flag for the status window. It is 0 if a status window is not
|
||
visible, 1 if the small status window is visible and 2 if the large status window
|
||
is visible. This flag applies to all views.
|
||
wrapmode in all views except the Year view the wrapmode field is 1 if wrap is on, and is
|
||
|
||
|
||
otherwise 0. In the Year view (which does not use wrapping) the wrapmode field
|
||
contains the index of the month that is displayed in the first row of the planner
|
||
(O = January, 11 = December).
|
||
|
||
|
||
zoom this field takes the value 0 to 3 corresponding to Roman fonts of height 8, 11,
|
||
13 and 16 respectively. It is relevant for the Day, Week, To-do, Anniversary
|
||
and List views. The zoom field is unused in the Year view entry and is set to 0.
|
||
|
||
|
||
aa aa rr a et rT
|
||
Type 13 - general descriptive record
|
||
|
||
|
||
This record is written on creation of a new Agenda and so is always present. It stores data shown in the
|
||
dialogs under the Preferences menu. It gets written whenever the values shown in one of these dialogs are
|
||
changed.
|
||
|
||
|
||
an a
|
||
63
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
is record contains entry defaults and all individual view preferences (to-do entry defaults are stored in
|
||
en list records). heck record has the normal Agenda type/length header followed by one or more 7LV
|
||
fields. There are sixteen possible type fields only some of which are currently used: the rest are reserved
|
||
for future use. If a field is not found the Agenda will use the corresponding default values. The fields can
|
||
be in any order.
|
||
|
||
|
||
Type Field
|
||
4 Diamond list setup |
|
||
5 Day entry defaults
|
||
6 Anniversary defaults
|
||
|
||
7 General defaults
|
||
9 Day view settings
|
||
|
||
10 Week view settings
|
||
|
||
11 Year view settings
|
||
|
||
12 To-do view settings
|
||
|
||
13 Anniversary view settings
|
||
|
||
14 List view settings
|
||
|
||
|
||
six bytes structured as follows:
|
||
|
||
|
||
UBYTE fnbar [6];
|
||
|
||
|
||
fnbar contains six bytes corresponding to the Day, Week, Year, To-do, List and
|
||
Anniversary views respectively. Each byte is either TRUE or FALSE depending on
|
||
whether or not the view is to be included in|the diamond list.
|
||
|
||
|
||
bytes structured as follows:
|
||
|
||
|
||
UWORD DefUnt imedEntViewT ime;
|
||
|
||
UWORD DefT imedEntT ime;
|
||
|
||
UWORD DefTimedentDuration;
|
||
|
||
UBYTE DefTimedByDefault;
|
||
UBYTE DefYearSym;
|
||
|
||
AGPREF_ALARM UntimedAlarmefs;
|
||
|
||
AGPREF_ALARM TimedAlarmDefs;
|
||
|
||
UBYTE style;
|
||
|
||
UBYTE spare;
|
||
|
||
|
||
DefUntimedEntViewTime is the default display time for untimed entries in minutes since 00:00.
|
||
|
||
|
||
DefT imedEntT ime is the default display time for timed entries in minutes since 00:00.
|
||
|
||
DefT imedEntDuration is the default duration for a timed entry in minutes.
|
||
|
||
DefT imedByDefault is 1 if entries are timed by default, ae it is O.
|
||
|
||
DefYearSym is the character code for the default year sy bol.
|
||
|
||
Unt imedA LarmDefs contains details of the default alarm for unti entries (see below for a
|
||
description of the AGPREF_ALARM structure).
|
||
|
||
TimedA Larmefs contains details of the default alarm for timed entries (see below for a
|
||
description of the AGPREF_ALARM structure).
|
||
|
||
style is the style of the font used for the entry. It should be a suitable ored
|
||
|
||
|
||
combination of the Wserv G_STY_Xxx flags: 0x00 for normal, 0x01 for bold, 0x02
|
||
for underline and 0x20 for italics. |
|
||
|
||
|
||
.
|
||
|
||
|
||
5 SERIES 3A AGENDA FILE FORMAT
|
||
—_—_—_—_—_—_—_—nknre eg»
|
||
|
||
|
||
spare is reserved and is set to 0.
|
||
|
||
|
||
An AGPREF_ALARM structure contains default alarm details. It consists of 14 bytes structured as follows:
|
||
|
||
|
||
UBYTE on;
|
||
UBYTE ndays;
|
||
UWORD minutes;
|
||
|
||
|
||
SE_SND snd;
|
||
|
||
on is 1 if an entry has an alarm by default and 0 otherwise.
|
||
|
||
minutes for timed entries minutes is the time interval in minutes between the alarm
|
||
going off and the start of the entry. For untimed entries minutes is the default
|
||
alarm time in minutes from midnight.
|
||
|
||
ndays for timed entries ndays is unused but should be set to 0. For untimed entries
|
||
ndays is the default number of days between the alarm going off and the start
|
||
of the entry.
|
||
|
||
snd contains details of the default alarm sound (see below for a description of the
|
||
|
||
|
||
SE_SND structure).
|
||
|
||
|
||
hes SE_SND structure contains details of the default alarm sound. It consists of ten bytes structured as
|
||
ollows:
|
||
|
||
|
||
UBYTE Len;
|
||
TEXT name [8] ;
|
||
UBYTE zero_term;
|
||
|
||
|
||
Len is the length of the name of the alarm.
|
||
|
||
|
||
name contains the name of the alarm stored as a sequence of ten characters. When
|
||
Len is less than eight the first unused byte contains a NULL character. Any
|
||
remaining unused bytes can take any value.
|
||
|
||
|
||
zero_term contains the NULL character.
|
||
|
||
|
||
aaa
|
||
|
||
|
||
0,2 0,0,0,0,9,0,0,6,0,9, FMM eM sMaMaMeMeMeMaMareeMeMetaotetatateeMetabetaelaMatetetetetetetaMeteletatetatatetatel, CRD
|
||
O OHO) PI I IK PO I RD eta ORD
|
||
s tasatetatotetatatat acetareteratetetatonst et atatanetaratnatotetasecateranstsrorerere srg srs ROR RR RD oneege,
|
||
be ee Od
|
||
6
|
||
|
||
o ' 4 5 ee
|
||
LR aac wth xn ain ot ae aH eS
|
||
|
||
wogecesorototececestses cece se, NH,
|
||
|
||
|
||
An anniversary entry defaults field contains the defaults for entries in the Anniversary view. It consists o
|
||
20 bytes structured as follows:
|
||
|
||
|
||
UWORD DefEntViewT ime;
|
||
UBYTE AutoApplyYearSym;
|
||
UBYTE DefYearSym;
|
||
AGPREF_ALARM AlarnmDefs;
|
||
UBYTE style;
|
||
|
||
UBYTE spare;
|
||
|
||
|
||
DefEntViewT ime is the default display time for anniversaries in minutes since midnight.
|
||
|
||
AutoApplyYearSym is 1 if the year symbol is on by default, otherwise it is 0.
|
||
|
||
DefYearSym is the character code of the default year symbol.
|
||
|
||
Alarnefs contains the default alarm details for timed and untimed entries (see the Day
|
||
entry defaults field for details of the AGPREF_ALARM structure).
|
||
|
||
style is the style of the font used for the entry. It should be a suitable cored
|
||
|
||
|
||
combination of the Wserv G_STY_Xxx flags: 0x00 for normal, 0x01 for bold 0x02
|
||
for underline and 0x20 for italics.
|
||
|
||
|
||
spare is reserved and is set to 0.
|
||
|
||
|
||
UBYTE p_psion_enter;
|
||
UBYTE timesep;
|
||
|
||
|
||
p_psion_enter is set to TRUE if PSION+-ENTER is used to complete an entry without going into
|
||
the Entry details dialog. Otherwise p_psion_enter is FALSE.
|
||
timesep is the character code for the Agenda time separator character.
|
||
|
||
|
||
65
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
O88 0,90 00,8 Mah eM Ms 0 050,00 ,8 8,8, F Mahe ramaaMseMstatamerareMeMeMetetaMetaretsr sea teteterersteratetanerenatann ests gan etate enare tans’
|
||
aren ogh senha eat aces eileterarcassecenorenenceccereresonesotetsteapl ces
|
||
|
||
|
||
UWORD agnv_flags;
|
||
ADENTVU_PREF left;
|
||
ADENTVU_PREF right;
|
||
|
||
|
||
agnv_flags this field contains both general view flags and Day view flags (all bits not used
|
||
are reserved). The general view flags are as follows:
|
||
0x01 for show appointment duration (Day, List, Week and Year views),
|
||
0x02 for show appointment end time (Day; List, Week and Year views only),
|
||
0x100 for show untimed day notes (Day, List and Week views only),
|
||
0x200 for show anniversaries (Day, List and Week views only),
|
||
0x400 for show to-dos (Day, List and Week views only) and
|
||
0x800 for show timed day notes (Day, List and Week views only).
|
||
The Day view flags are as follows:
|
||
0x04 for title to go on right hand side,
|
||
0x08 for slot compression off,
|
||
0x10 for duration arrows off and
|
||
0x20 for show overlap bars off.
|
||
|
||
|
||
left contains the preferences for the left hand side of the Day view (see below for a
|
||
description of the ADENTVU_PREF structure).
|
||
|
||
|
||
right contains the preferences for the right hand side of the Day view (see below for
|
||
a description of the ADENTVU_PREF structure).
|
||
|
||
|
||
An ADENTVU_PREF structure consists of 12 bytes structured as follows:
|
||
|
||
|
||
UWORD flags;
|
||
UWORD begint ime;
|
||
UWORD beginvis;
|
||
|
||
|
||
flags contains a combination of the slot lines on |. (0x01) and the slot times on flag
|
||
|
||
|
||
UWORD endvis;
|
||
|
||
UWORD endtime;
|
||
|
||
UWORD slotdur;
|
||
|
||
(0x02). |
|
||
|
||
begintime is O for the left hand side and beginvis for the right hand side.
|
||
beginvis is the start time of the first slot in minutes from midnight.
|
||
endvis is the start time of the last slot in minutes from midnight.
|
||
endt ime is right.beginvis for the left hand side and 1440 for the right hand side.
|
||
slotdur is the slot duration in minutes.
|
||
|
||
|
||
UWORD pref_flags;
|
||
|
||
|
||
pref_flags contains both general view flags (see above under the Day view settings field),
|
||
and Week view flags. Currently there is only one Week view flag: 0x4 for
|
||
show title on right hand side.
|
||
|
||
|
||
Wetetatstatetetetetetntatea*ete e%ete'ee%ee"
|
||
|
||
|
||
> AS
|
||
eter’ Ce te ee
|
||
|
||
|
||
s field consists of two bytes as follows:
|
||
|
||
|
||
UWORD pref_flags;
|
||
|
||
|
||
pref_flags contains a combination of the general flags (see under the Day view settings
|
||
field above) for showing appointment duration and/or end time or neither.
|
||
|
||
|
||
ws 0+ 01,0,050,000
|
||
nessrcesesececece me cateresetatotaSotote aie etetatenatetetetaraetatetstatetetetesatenatatePatatsesPatetatateteReSatatetalits ata atate tits tate teMatats tat
|
||
ee ceeears
|
||
|
||
|
||
field consists of two bytes structured as follows:
|
||
|
||
|
||
5 SERIES 3A AGENDA FILE FORMAT
|
||
|
||
|
||
UWORD ncols;
|
||
|
||
|
||
ncols contains the number of columns to be shown in the To-do view. The value of
|
||
ncols should not be more than the number of existing categories.
|
||
|
||
|
||
Wa%ePe%e"ateeMeMeeMe%e tote sZatatnteMa%a%e"a"s"ohoatat
|
||
I CO
|
||
ESO RIK RR oni etn Ke ie
|
||
=e an... re. ese
|
||
S enero, io
|
||
. oon 8 jones
|
||
onene %
|
||
e' Seen bet ot
|
||
eee, Oyama at » one,
|
||
OO) ostetotetate”s OOO
|
||
|
||
|
||
settings field consists of two bytes structured as follows:
|
||
|
||
|
||
UWORD ncols;
|
||
|
||
|
||
ncols contains the number of columns to be shown in the Anniversary view (1 to 4).
|
||
|
||
|
||
wsostacatatotateretstatetetefotatePata'etstatetatetetetetatetete’stutetet .
|
||
Re SRN ST ONY RUNNER RAKE REST USOR
|
||
Be SRD EF atte oe
|
||
RS SR at a Ee
|
||
|
||
5S
|
||
seeatataratanerateetetatSeetatetaSeoeioatetatteneenesenstenetetenescueconmronsiiearetate
|
||
|
||
|
||
The List view settings field consists of two bytes structured as follows:
|
||
UWORD pref_flags;
|
||
|
||
|
||
pref_flags contains a combination of general view and Day view flags (see under the Day
|
||
view settings field above) and the show-repeats-once flag (0x04).
|
||
|
||
|
||
eee et
|
||
Type 14 - print setup descriptive record
|
||
|
||
|
||
This record does not initially exist. It is created/rewritten to contain a new copy of the data for the
|
||
Agenda print setup after using the Agenda Print setup dialog. It is also created/rewritten after a memo
|
||
has been created or edited and Print setup data has been changed. Hence it is possible that the record will
|
||
only contain Agenda Print setup data or Memo Print setup data.
|
||
|
||
|
||
The record consists of a one word header followed by a series of 7LV fields.
|
||
|
||
Field types 0 to 3 and 6 to 9 are allowed. Field types 0 to 3 are used for the main Agenda print setup.
|
||
Field types 6 to 9 are identical to field types 0 to 3 and are used for the memo print setup.
|
||
|
||
Field type O and 6
|
||
|
||
Contains printer parameters in a PRINTER_PARAMS structure as returned by the PR_GET_PARAMS method of the
|
||
printer active object of the FORM dyl.
|
||
|
||
Field types 1 and 7
|
||
|
||
Contain printer model data from the PR_SENSE_MODEL method of the printer active object. The first byte is
|
||
the model number as returned by PR_SENSE_MODEL, followed by the name, up to and including the NULL.
|
||
Field types 2 and 8
|
||
|
||
Contain printer header text from the PR_GET_HD method of the printer active object including the
|
||
terminating NULL.
|
||
|
||
Field types 3 and 9
|
||
|
||
|
||
Contain printer footer text from the PR_GET_HD method of the printer active object including the
|
||
terminating NULL.
|
||
|
||
|
||
RR a er mr ee pe ea
|
||
Type 15 - illegal
|
||
|
||
|
||
This record type is illegal and is used to protect the Agenda against write failures on a flash SSD.
|
||
Writing to a flash SSD can fail at any time due to, say, a low battery. To protect as much as possible
|
||
against this the Agenda will write the whole of the rest of the record before ‘blowing down’ the byte
|
||
containing the record type to its correct value. This means that any file which contains a record with type
|
||
15 (Oxf) has suffered a write failure and data beyond this point cannot be trusted.
|
||
|
||
|
||
67
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
This record type is probably best thought of as an End Of File record, a any program finding a file
|
||
|
||
|
||
with a type 15 record should start by setting the end of the file to the start
|
||
|
||
|
||
record.
|
||
|
||
|
||
(the type length word) of the
|
||
|
||
|
||
CHAPTER 6
|
||
|
||
|
||
WORD PROCESSOR FILE FORMAT
|
||
|
||
|
||
This document describes the structure of a Psion word processor document to a degree which allows
|
||
external software to read and write non-password-protected documents.
|
||
|
||
|
||
Psion word processor document files contain a file header, followed by a number of type-length-value
|
||
records, from the following list:
|
||
|
||
|
||
= options data
|
||
= printer-related data
|
||
® printer model data
|
||
|
||
|
||
= page header
|
||
|
||
= page footer
|
||
|
||
= style data
|
||
|
||
=" emphasis data
|
||
|
||
|
||
= document text
|
||
= document index
|
||
|
||
|
||
eee files created by the word processor will contain records in the order listed above. Each record
|
||
consists of:
|
||
|
||
|
||
= atwo-byte record type
|
||
s atwo-byte record length, ten
|
||
# len bytes of data
|
||
Unless stated otherwise, all dimensions are stored in twips (1/1440 inch).
|
||
|
||
|
||
Reserved locations
|
||
All locations reserved for future use contain a value of zero.
|
||
|
||
|
||
aa a ag at ee ee ee ae
|
||
The document header
|
||
|
||
|
||
The document header is 40 bytes long. It starts with the 16-byte zero terminated file signature
|
||
"PSIONWPDATAFILE" followed by a two byte file version number.
|
||
|
||
|
||
Following this is a 20-byte struct, containing password data. For a non-password-protected document
|
||
there are two bytes of zero followed by eighteen bytes, each containing OxEA.
|
||
|
||
|
||
The remaining two bytes of the header are reserved for future use.
|
||
|
||
|
||
69
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
Record types
|
||
|
||
|
||
UWORD cpos
|
||
UBYTE symbols
|
||
|
||
|
||
UBYTE backup
|
||
|
||
|
||
UBYTE statzoom
|
||
|
||
|
||
UBYTE style
|
||
UBYTE mono
|
||
UBYTE outlevel
|
||
UBYTE spare
|
||
|
||
|
||
UWORD spare2
|
||
|
||
|
||
saved cursor position
|
||
|
||
|
||
show screen symbols
|
||
|
||
|
||
TRUE to keep backups (this item is used on the MC only: it is not used on
|
||
Series3 machines)
|
||
|
||
|
||
top four bits indicate the current zoom state (0x22 by default), lowest four bits
|
||
indicate the status window size: 0, 1 or 2 forjoff, small or big respectively
|
||
(this item is used by the Series3a only)
|
||
|
||
|
||
TRUE to show style bar
|
||
|
||
TRUE to load text by line, else by paragraph
|
||
lowest outline level to display
|
||
reserved for future use
|
||
|
||
|
||
reserved for future use
|
||
|
||
|
||
Displayed screen symbols are determined by any combination of the following bit fields in symbols:
|
||
|
||
|
||
0x01
|
||
0x02
|
||
|
||
|
||
show tabs
|
||
|
||
show spaces
|
||
|
||
show paragraph end markers
|
||
show hyphens
|
||
|
||
show forced line breaks
|
||
|
||
|
||
printing process. It includes, amongst other items, descriptions of the page size and margins, the page
|
||
numbering style, header and footer position and alignment.
|
||
|
||
|
||
This record consists of a structure that is used to control the display and WDR printing of formatted text
|
||
in all applications that require such services. It therefore contains some fields that are not relevant to the
|
||
|
||
|
||
word processor.
|
||
|
||
|
||
The following description is in terms of the P_EXTENT, SCRLAY_FONT and
|
||
|
||
|
||
typedef struct
|
||
{
|
||
|
||
|
||
> P_POINT;
|
||
typedef struct
|
||
{
|
||
|
||
|
||
P_POINT tl;
|
||
WORD width;
|
||
WORD height;
|
||
) P_EXTENT;
|
||
|
||
|
||
typedef struct
|
||
{
|
||
|
||
|
||
UWORD fid;
|
||
UWORD style;
|
||
UWORD height;
|
||
> SCRLAY_FONT;
|
||
|
||
|
||
PAGES_HEADER structs, defined as:
|
||
|
||
|
||
/* typeface number */ (1)
|
||
/* font style */ (2)
|
||
/* height of font in twips */
|
||
|
||
|
||
70
|
||
|
||
|
||
typedef struct
|
||
{
|
||
SCRLAY_FONT f;
|
||
UBYTE align;
|
||
|
||
|
||
UBYTE first_page;
|
||
|
||
|
||
> PAGES _HEADER;
|
||
|
||
|
||
/* font data */
|
||
/* header alignment */ (3)
|
||
|
||
|
||
In these terms, the content of the printer-related record is:
|
||
|
||
|
||
PAGE DATA
|
||
|
||
|
||
WORD width
|
||
WORD height
|
||
P_EXTENT body
|
||
WORD hdtop
|
||
WORD hdbot
|
||
WORD pdrflags
|
||
WORD docflags
|
||
|
||
|
||
UWORD pgbeg
|
||
UWORD pgend
|
||
|
||
|
||
RUNNING PAGE HEADERS
|
||
|
||
|
||
PAGES HEADER top
|
||
PAGES HEADER bot
|
||
|
||
|
||
PAGE NUMBERING
|
||
|
||
|
||
WORD offset
|
||
WORD last
|
||
WORD style
|
||
|
||
|
||
MISCELLANEOUS
|
||
|
||
|
||
SCRLAY_FONT f
|
||
UBYTE size_choice
|
||
UBYTE wo_control
|
||
UWORD spare
|
||
UWORD spare2
|
||
|
||
|
||
Notes
|
||
|
||
|
||
page width
|
||
page height
|
||
|
||
|
||
/* TRUE to emit on first page */
|
||
|
||
|
||
6 WORD PROCESSOR FILE FORMAT
|
||
|
||
|
||
body print region, with respect to top left of page (4)
|
||
|
||
|
||
page header position (5)
|
||
|
||
page footer position (6)
|
||
|
||
O for portrait, 1 for landscape
|
||
always 3 for word processor
|
||
|
||
|
||
page number to start printing (first page is 1)
|
||
|
||
|
||
last page number to print (7)
|
||
|
||
|
||
page header
|
||
page footer
|
||
|
||
|
||
page numbering offset
|
||
|
||
|
||
page count, for %m (always reset by pagination)
|
||
|
||
|
||
page number style (8)
|
||
|
||
|
||
base font for body print region (9)
|
||
paper size index (10)
|
||
|
||
|
||
TRUE to disable widow and orphan control
|
||
|
||
|
||
reserved for future use
|
||
reserved for future use
|
||
|
||
|
||
(1) Typeface numbers are defined in the following list:
|
||
|
||
|
||
0 COURIER 22 OPTIONAL_SB
|
||
1 PICA 23 OPTIONAL_SC
|
||
2 ELITE 24 TIMES ROMAN
|
||
3 PRESTIGE 25 CENTURY
|
||
|
||
4 LETTER_GOTHIC 26 PALATINO
|
||
|
||
5 GOTHIC 27 SOUVENIR
|
||
|
||
6 CUBIC 28 GARAMOND
|
||
|
||
7 LINEPRINTER 29 CALEDONIA
|
||
|
||
8 HELVETICA 30 BODONI
|
||
|
||
9 AVANT_GARDE 31 UNIVERSITY
|
||
10 SPARTAN 32 SCRIPT
|
||
|
||
11 METRO 33 SCRIPT_PS
|
||
|
||
12 PRESENTATION 34 OPTIONAL_SCA
|
||
13 APL 35 OPTIONAL_SCB
|
||
14 OCR_A 36 COMMERCIAL_SCRIPT
|
||
15 OCR_B 37 PARK_AVENUE
|
||
16 STANDARD_ROMAN 38 CORONET
|
||
|
||
17 EMPEROR 39 OPTIONAL_SCC
|
||
18 MADELEINE 40 GREEK
|
||
|
||
19 ZAPF_HUMANIST 41 KANA
|
||
|
||
20 CLASSIC 42 HEBREW
|
||
|
||
21 OPTIONAL_SA 43 OPTIONAL_A
|
||
|
||
|
||
44 RUSSIAN
|
||
|
||
45 OPTIONAL_B
|
||
46 OPTIONAL_C
|
||
47 OPTIONAL_D
|
||
48 NARRATOR
|
||
|
||
49 EMPHASIS
|
||
|
||
50 ZAPF_CHANCERY
|
||
51 OPTIONAL_DA
|
||
52 OLD_ENGLISH
|
||
53 OPTIONAL_DB
|
||
54 OPTIONAL_DC
|
||
55 COOPER_BLACK
|
||
56 SYMBOL
|
||
|
||
57 LINE_DRAW
|
||
58 MATH 7
|
||
|
||
59 MATH_8
|
||
|
||
60 DINGBATS
|
||
|
||
61 EAN
|
||
|
||
62 PC_LINE
|
||
|
||
63 OPTIONAL_SYA
|
||
|
||
|
||
A typeface that is not supported by the current printer will be mapped to a supported typeface.
|
||
(2) The font style may be zero, or any sensible combination of the following attributes:
|
||
|
||
|
||
71
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
0x01 underline
|
||
0x02 bold
|
||
|
||
0x04 italic
|
||
|
||
0x08 superscript
|
||
0x10 subscript
|
||
|
||
|
||
(3) The running page header alignment may be any one of:
|
||
left aligned
|
||
|
||
|
||
Styles or style combinations that are not supported by the current pri “y are ignored.
|
||
|
||
|
||
0
|
||
|
||
1 right aligned
|
||
2 centred
|
||
|
||
4 2-column
|
||
|
||
5
|
||
|
||
|
||
3-column i
|
||
(4) In terms of the body struct and the page width and height, the page margins are:
|
||
|
||
|
||
left body. tl.x
|
||
|
||
top body.tl.y
|
||
|
||
right width-body.tl.x-body.width
|
||
bottom height-body.tl.y-body. height
|
||
|
||
|
||
(5) The page header position measures the vertical distance between th the bottom of the header text and the
|
||
top edge of the page body print region.
|
||
|
||
|
||
(6) The page footer position measures the vertical distance between the, bottom of the footer text and the
|
||
bottom edge of the page body print region.
|
||
|
||
|
||
(7) To print all pages, the last page number should be set to Oxffff.
|
||
(8) The page number style is one of:
|
||
|
||
|
||
0 Arabic
|
||
1 Roman, upper case
|
||
2 Roman, lower case.
|
||
|
||
|
||
(9) The body area base font data is not used by word processor documents. It should always specify the
|
||
default font, with font number 0 (Courier) a style of 0 (normal) and a size of 240 (12 points).
|
||
|
||
|
||
(10) The page size choice should correspond with the earlier page width and height. The following
|
||
(English) page sizes are recognised:
|
||
|
||
|
||
Choice fed type Width Height
|
||
|
||
|
||
0 11906 16838
|
||
1 Esai
|
||
|
||
2 Executive 10440 15 120
|
||
3 Legal 12240 20160
|
||
4 Letter 12240 15840
|
||
5 Monarch 5580 10800
|
||
6 DL 6236 12472
|
||
|
||
|
||
Note that items 2 to 6 may be different in non-English versions of the software.
|
||
|
||
|
||
The record consists of a zero terminated string, containing the full path name of the current printer driver
|
||
file, preceded by a one byte index to the printer model within the file.
|
||
|
||
|
||
The default value is:
|
||
|
||
|
||
i)
|
||
MROM: :\BJ .WOR"
|
||
|
||
|
||
The record contains a5 page ieadnen text as a zero ae ae oie string may not exceed 80 bytes.
|
||
|
||
|
||
ocese
|
||
eeeceseeeateee
|
||
|
||
|
||
Then ey contains the page ne text as a zero a tepitndied ring: e. The string may not seed 80 0 bytes.
|
||
|
||
|
||
72
|
||
|
||
|
||
|
|
||
|
||
|
||
6 WORD PROCESSOR FILE FORMAT
|
||
|
||
|
||
Style data record (type 6. length 80
|
||
The file may contain up
|
||
|
||
|
||
The following description is in terms of the SCRLAY_FONT struct (described above) and the SCRLAY_ MARGINS,
|
||
SCRLAY_SPACING and SCRLAY_TABSTOP structs, defined as: 7
|
||
|
||
|
||
typedef struct
|
||
{
|
||
UWORD left; /* left margin */ (1)
|
||
UWORD right; /* right margin */
|
||
UWORD indent; /* left margin for first line of a paragraph */
|
||
UWORD align; /* alignment */ (2)
|
||
} SCRLAY_MARGINS;
|
||
typedef struct
|
||
{
|
||
UWORD Line; /* space between lines in a paragraph */
|
||
UWORD above; /* space above paragraph */
|
||
UWORD below; /* space below paragraph */
|
||
UWORD flags; /* keep together/next and new page */ (3)
|
||
} SCRLAY_SPACING;
|
||
typedef struct
|
||
{
|
||
UWORD x; /* tab position */
|
||
UWORD type; /* tab type */ (4)
|
||
|
||
|
||
} SCRLAY_TABSTOP;
|
||
|
||
|
||
In these terms, the content of the style data record is:
|
||
|
||
|
||
TEXT sc[2] two-letter short code
|
||
TEXT tag(16] style tag name
|
||
|
||
UWORD sflags style control flags (5)
|
||
SCRLAY_FONT f paragraph base font (6)
|
||
UWORD inherit inherited attributes (7)
|
||
|
||
|
||
SCRLAY_MARGINS marg margin positions
|
||
|
||
SCRLAY_SPACING spc paragraph vertical spacing
|
||
|
||
UWORD olevel outliner level
|
||
|
||
UWORD ntabs number of tabstops in following table
|
||
SCRLAY_TABSTOP tab[8] up to 8 tabstops, in ascending position order
|
||
|
||
|
||
Notes
|
||
(1) Paragraph margins are relative to the page margins (the left and right edges of the body print region).
|
||
|
||
|
||
(2) The paragraph alignment may be one of:
|
||
|
||
|
||
0 left aligned
|
||
|
||
1 right aligned
|
||
|
||
2 centred
|
||
|
||
3 justified
|
||
|
||
(3) The spacing flags may be any combination of:
|
||
|
||
0x01 keep on same page as following paragraph
|
||
0x02 keep whole paragraph on one page
|
||
0x04 paragraph starts a new page
|
||
|
||
(4) The tab type may be any one of the following:
|
||
|
||
0 left tab
|
||
|
||
1 right tab
|
||
|
||
2 centred tab
|
||
|
||
(5) The style control flags may contain any combination of:
|
||
0x02 undeletable
|
||
|
||
0x04 default
|
||
|
||
|
||
There must be one default style and at least one undeletable style in every document (in all Psion
|
||
documents they are the same - style BT). It does not make sense for the default style to be deletable.
|
||
|
||
|
||
ee ae ee Se ee
|
||
73
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
(6) In addition to the typeface numbers listed earlier, a typeface canted of -1 is used to signify that the
|
||
|
||
|
||
typeface and font size are to be inherited from the default style. In such|a case the font size is
|
||
conventionally set to zero.
|
||
|
||
|
||
(7) The inherited attributes field may contain any combination of:
|
||
|
||
|
||
0x01 underline
|
||
0x02 bold
|
||
0x04 italic
|
||
|
||
|
||
For each bit that is set, the corresponding bit in the style field of the SCRLAY_FONT struct must be clear.
|
||
Inherited attributes are taken from the default style.
|
||
|
||
|
||
The file may contain
|
||
|
||
|
||
gle emphasis.
|
||
|
||
|
||
The following description is in terms of the SCRLAY_FONT struct (described above). In these terms, the
|
||
content of the emphasis data record is:
|
||
|
||
|
||
TEXT sc[2] two-letter short code
|
||
|
||
TEXT tag({16} emphasis tag name
|
||
|
||
UWORD sflags emphasis control flags (1)
|
||
|
||
SCRLAY_FONT f emphasis font (2)
|
||
|
||
UWORD inherit inherited attributes (3)
|
||
|
||
Notes
|
||
|
||
(1) The emphasis control flags must contain the value 0x01, together with any combination of:
|
||
0x02 undeletable
|
||
|
||
0x04 default
|
||
|
||
|
||
There must be one default emphasis and at least one undeletable emphasis in every document (in all Psion
|
||
documents they are the same - emphasis NN). It does not make sense for the default emphasis to be
|
||
deletable.
|
||
|
||
|
||
(2) In addition to the typeface numbers listed earlier, a typeface n of -1 is used to signify that the
|
||
typeface and font size are to be inherited from the enclosing paragraph|style (which may itself inherit
|
||
from the default style). In such a case the font size is conventionally set to zero. i
|
||
|
||
|
||
(3) The inherited attributes field may contain any sensible combination of:
|
||
|
||
|
||
0x01 underline
|
||
0x02 bold
|
||
|
||
0x04 italic
|
||
|
||
0x08 superscript
|
||
0x10 subscript
|
||
|
||
|
||
For each bit that is set, the corresponding bit in the style field of the s RLAY_FONT struct must be clear.
|
||
|
||
|
||
Inherited attributes are taken from the enclosing paragraph style (which may itself inherit from the
|
||
default style).
|
||
|
||
|
||
sdawa noeeces a aes cocschoscoceaiuid einige nea. V8.6 8m. nineaa hoe N RA gas Leads aie Chae ebigs Lh bape eat beese case sneusnmneesalsacaeaes
|
||
natstorsretatotecetatonenswoteteteegtotete stotetocerer gus tetecotereceretetetatetetatetetstntatststate Bl totcte Mm cosets tstscatesrerensnsceets scentte, JRO RRR, OOO FOS SR COSTE Ske ecto
|
||
Seca tatatiican ee Ee RR ee % OE BO cB dad Salen SO aS Sxeere
|
||
settetescecersrebotce mac mes Pe%e"e’a'e' cx "e’e er erares re PN NN I A IK,
|
||
|
||
|
||
ere ete a earn e ene" e poe a ase" earn es
|
||
|
||
|
||
This record contains the entire text of the document. Each paragraph, ee for the final one, is
|
||
terminated by a zero. 1
|
||
|
||
|
||
The content conforms with the IBM Code Page 850 symbol set, togetiee with the following additional
|
||
symbols:
|
||
|
||
|
||
HARD_HYPHEN 7 unbreakable hyphen, not a word delimiter
|
||
SOFT_HYPHEN 14 optional, or potential, hyphen
|
||
|
||
|
||
—__—_—eeeeeeeeeee
|
||
|
||
|
||
HARD_SPACE 15 unbreakable space, not a word delimiter
|
||
74 |
|
||
|
||
|
||
6 WORD PROCESSOR FILE FORMAT
|
||
|
||
|
||
® a length (word)
|
||
|
||
= = the two character short code of a style
|
||
|
||
= the two character short code of an emphasis
|
||
The entries conform to the following rules:
|
||
|
||
|
||
= the sum of their lengths is one more than the length of the document text record (i.e. the
|
||
document size, including the final paragraph terminator).
|
||
|
||
|
||
= there is at least one entry per paragraph
|
||
= the final entry for each paragraph includes the zero that terminates the paragraph
|
||
|
||
|
||
= the short codes must correspond with styles and emphases contained in the earlier style data and
|
||
emphasis data records
|
||
|
||
|
||
75
|
||
|
||
|
||
CHAPTER 7
|
||
|
||
|
||
WRITING DEVICE DRIVERS
|
||
|
||
|
||
SN a ee, de ae ee
|
||
Introduction
|
||
|
||
|
||
This chapter is aimed at the programmer who wishes to write an installable device driver and anyone who
|
||
wishes to improve their general device driver background. The details of communicating with device
|
||
drivers can be found in the J/O System chapter of the PLIB Reference manual. Details of the resident
|
||
device drivers can be found in the appropriate chapters of the I/O Devices manual and the PLIB Reference
|
||
manual. The Borland Turbo assembler was used throughout. See also the following Example Device
|
||
Drivers chapter.
|
||
|
||
|
||
Psion SIBO machines are supplied with a set of resident device drivers built in to the ROM each of which
|
||
can be replaced with an installable device driver having the same name. Installable device drivers can
|
||
also be added to increase the number of available device drivers. Installing a device driver is carried out
|
||
dynamically without resetting the machine (this is not the case with many operating systems).
|
||
|
||
|
||
The device driver performs the logical processing required to translate low level hardware instructions
|
||
into high level services suitable for an application. Conventionally, device drivers are divided into a
|
||
logical layer riding astride a physical layer. The physical device driver (PDD) contains the code required
|
||
for talking directly with the hardware device and provides a set of low level hardware specific services.
|
||
The logical device driver (LDD) performs the logical processing that transforms these low level services
|
||
into the high level services used by an application.
|
||
|
||
|
||
The following example illustrates the two layer nature of device drivers. An application using the serial
|
||
driver decides that it requires RTS/CTS handshaking. It calls an LDD which decides whether or not a
|
||
line should be driven. If the answer is yes the LDD calls the appropriate PDD and asks for a specific line
|
||
to be driven to a specific state. The PDD duly carries out the requested service.
|
||
|
||
|
||
In the above example the LDD could have talked directly with the hardware. However Psion SIBO
|
||
machines will often use the same LDD with a PDD written specifically for each version of the hardware
|
||
device. Splitting the device driver is thus highly desirable.
|
||
|
||
|
||
An LDD must provide eight functions for use by the operating system. The functions are passed to the
|
||
operating system via a table of function offsets (sometimes called the vector function table). These
|
||
functions are mandatory. Similarly a PDD must provide two functions for use by the operating system
|
||
and may provide a further two if required.
|
||
|
||
|
||
An LDD will usually provide further services/functions for use by an application. The form that these
|
||
take is dependent on the LDD requirements and the functions supplied by the associated PDD(s). It is
|
||
advisable to adopt the predefined system defines for these services as this allows the LDD to receive I/O
|
||
requests via the usual route (p_read, p_write etc).
|
||
|
||
|
||
A PDD will usually define further services specifically for use by LDDs or (less frequently)
|
||
applications. ~
|
||
|
||
|
||
The operating system will send device drivers system events not sent to other applications. Examples are
|
||
events generated by the machine being switched on or off, memory segments being moved about and the
|
||
owning application being panicked.
|
||
|
||
|
||
Any device driver configuration that has associated hardware interrupts must contain at least an LDD.
|
||
|
||
|
||
The EPOC operating system can handle a maximum of 32 device drivers on a Series3 machine and 48 on
|
||
other machines.
|
||
|
||
|
||
77
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
The location of device drivers
|
||
|
||
|
||
Resident device drivers are built into the operating system, with the code residing in the ROM.
|
||
|
||
|
||
Installable device drivers are loaded into a device memory segment from the file in which they exist. The
|
||
device memory segments are created, owned and managed by the SYS$FSRV process.
|
||
|
||
|
||
Under no circumstances should any application or device driver attempt to create, delete or change the
|
||
size of a device memory segment.
|
||
|
||
|
||
Device Driver Names
|
||
Device drivers are known to the EPOC operating system by their names.
|
||
|
||
|
||
A logical device driver name always has three characters followed by a}colon. For example:
|
||
= Try: is the serial LDD
|
||
= TIM: is the timer LDD
|
||
= SND: is the sound LDD
|
||
|
||
|
||
A physical device driver name always has three characters followed by|a period, a further three
|
||
characters and a colon. For example:
|
||
|
||
|
||
@ TTY.UAR: is the 16450 UART driver
|
||
= TTY.AS5: is the ASICS driver
|
||
|
||
|
||
The first three characters of a PDD name are the name of the LDD to which the PDD belongs. The
|
||
second set of three characters uniquely identify the PDD. In the above examples both PDDs belong to the
|
||
Try: LDD.
|
||
|
||
|
||
The name of the device driver is the mechanism by which an application can obtain a ‘channel’ to the
|
||
device driver.
|
||
Device Driver Channels
|
||
|
||
|
||
To obtain a channel to an LDD, an application should call the 100pen operating system service. A channel
|
||
can be opened by calling the PLIB library function p_open. For example:
|
||
|
||
|
||
» p_open(&chan,"SND:", -1)
|
||
» p_open(&chan, "TIM:",-1) |
|
||
To obtain a channel to a PDD, an application should call the DevOpenPDD operating system service.
|
||
Ll pe LDDs open PDDs. The p_open library function can be used to open a PDD indirectly as
|
||
escri ow. |
|
||
|
||
|
||
For a device driver configuration consisting of an LDD and a PDD the application will usually open a
|
||
channel to the LDD only: the LDD as part of its initialisation would open a channel to the required
|
||
PDD. A channel can be opened by calling the PLIB library function p open. For example:
|
||
|
||
|
||
= p_open(&chan, "TTY .UAR:", -1)
|
||
|
||
|
||
2 p _open(&chan, "TTY.AS5:", -1)
|
||
|
||
|
||
If the LDD requires a PDD and none is specified, it is up to the LDD to either fail the open request or
|
||
hunt for a loaded PDD that it can use. The tty: device hunts for an ee PDD.
|
||
|
||
|
||
A device driver may be capable of supporting more than one open channel at a time. In order to
|
||
distinguish the channels, a qualifier can be added to the open request as part of the device name. It is up
|
||
to the device driver to specify the format of the qualifier. By convention channels are allocated a single
|
||
character sequentially from the character 'A'. For example, the parallel driver can support two open
|
||
eae 'A' and 'B'. The LDD requires one of these qualifiers in order to open a parallel driver
|
||
channel.
|
||
|
||
|
||
*® p_open(&chan,"PAR:A", -1)
|
||
= p_open(&chan, "PAR:B", -1)
|
||
|
||
|
||
LDDs have been designed to be accessed via the I/O system. I/O requests on the opened channel will
|
||
reach the ‘strategy vector’ of the device driver.
|
||
|
||
|
||
78
|
||
|
||
|
||
7 WRITING DEVICE DRIVERS
|
||
eee
|
||
|
||
|
||
ase have been designed to be accessed by an LDD either via far calls or the Dewector operating system
|
||
on.
|
||
|
||
|
||
Searching for PDDs
|
||
|
||
|
||
In the case that an LDD requires a PDD to provide some hardware specific functionality and the open
|
||
LDD request does not specify a PDD, the LDD should search for a PDD to use. In this case either there
|
||
is only one PDD for that machine (but is different across machines) or the PDDs are capable of
|
||
determining whether it can drive the specified channel.
|
||
|
||
|
||
For example the serial LDD requires a PDD. However there is currently only one serial PDD on each
|
||
machine (each machine has a different PDD though). By searching for the appropriate serial PDD, the
|
||
serial LDD can be the same on all machines.
|
||
|
||
|
||
On the other hand there are several filing system PDDs each of which is capable of reading an ID byte
|
||
from a SIBO pack. The PDD can then determine if it is the correct PDD for that hardware or not.
|
||
|
||
|
||
To search for a PDD, an LDD should use the DevF ind service. For example the Fsy: LDD would search
|
||
for all Fsy.* PDDs. As each PDD is found, it can be requested to open the appropriate channel by using
|
||
the DevOpenPpD operating system service.
|
||
|
||
|
||
Device Driver Hierarchies And Attached Drivers
|
||
LDDs are classified as either root or attached drivers.
|
||
|
||
|
||
Device drivers exist in a hierarchy the first of which is termed the root driver. The other drivers in the
|
||
hierarchy are termed attached drivers. In the language of object oriented programming, an attached driver
|
||
subclasses the root driver. In this document, the driver to which another driver is attached is referred to
|
||
as the underlying driver.
|
||
|
||
|
||
An attached device driver requires the underlying driver to provide a specified set of functions. How
|
||
these are implemented is of no concern to an attached driver. For example, the Xmodem device driver is
|
||
an attached driver which can, for example, attach to the serial driver which happens to be a root device
|
||
driver. The Xmodem driver requires the underlying driver to support the serial sense, serial set, read,
|
||
write and close functions. The power of attached drivers comes from the fact that the Xmodem driver
|
||
does not need to know anything about the physical transmission medium, and can run on either serial
|
||
port quite happily. In fact the Xmodem driver could run over any physical medium e.g. telephone,
|
||
parallel, radio, infra-red etc as long as the underlying driver supported the small set of functions
|
||
required.
|
||
|
||
|
||
Additional power comes from the fact that a driver does not have to be attached to the root driver
|
||
directly: other attached drivers may exist in the hierarchy. For example an Xmodem driver can be
|
||
attached to a modem driver that provides modem configuration and dialling functions. This can in turn be
|
||
attached to the resident serial driver.
|
||
|
||
|
||
Notice that the Xmodem driver neither knows nor cares about the driver hierarchy.
|
||
There is no limit to the number of drivers that exist in a device driver hierarchy.
|
||
|
||
|
||
When the operating system routes an I/O request to a device driver, it follows this hierarchy and calls the
|
||
strategy vector of the device driver at the top of the hierarchy. The device driver at the top of the
|
||
hierarchy is the last opened device driver on that I/O channel.
|
||
|
||
|
||
The routing mechanism is best explained by an example of an application that wishes to use the parallel
|
||
driver with a timeout facility. In its raw form, the parallel driver does not allow for timeouts. Although
|
||
the application could handle this, a neater solution (in terms of application code) is to use an attached
|
||
driver. The application opens the parallel driver in the normal way and then opens the attached driver
|
||
(written as part of the application) passing the currently opened parallel device channel handle to the open
|
||
vector. The attached driver will open a timer channel for itself and use the IoFuncAttach I/O service on
|
||
the passed opened channel. This request will go to the parallel driver since it is the next down the _
|
||
hierarchy. The parallel driver, not supporting this function, passes it on to the operating system (using
|
||
the IoRoot service) to perform the attach service. The parallel drivers open channel handle is returned by
|
||
the attached driver to the caller of the 100pen service. From this point on all I/O requests made on the
|
||
parallel drivers I/O channel handle will be directed to the strategy vector of the attached driver first
|
||
which can then process it and pass on any requests it feels necessary. For example, the loFuncWrite
|
||
request would go to the attached drivers strategy vector. It would queue a timer for an appropriate length
|
||
of time and then pass on the !ofuncWrite request to the parallel driver. If the timer expired before the
|
||
write completed, the attached driver would cancel the outstanding write request on the parallel driver and
|
||
inform the application that the timer expired. |
|
||
|
||
|
||
79
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
In the above example the same attached driver could in fact attach itself to any device driver that requires
|
||
a timeout on the IoFuncWrite request. |
|
||
|
||
|
||
An attached driver is written in exactly the same way as any other driv r. However, if the driver does not
|
||
support a requested function, the strategy vector of an attached driver calls the 1oSuper operating system
|
||
service rather than the 1oRoot system service.
|
||
|
||
|
||
Sa ee eC
|
||
Interrupts and Interrupt Service Routines
|
||
|
||
|
||
Device drivers that talk to hardware tend to have interrupt service routines associated with them,
|
||
especially if they are receiving data from an external source.
|
||
|
||
The EPOC operating system provides a framework within which an interrupt service routine can be
|
||
written relatively easily.
|
||
|
||
|
||
The SIBO architecture allows for eight independent hardware interrupt sources, some of which are pre-
|
||
allocated to system components (see the ASIC1 section of the Hardware Reference manual for details).
|
||
|
||
|
||
The operating system provides the GenSetRevector service to allow a device driver to install an interrupt
|
||
service routine for any of the eight hardware interrupt sources.
|
||
|
||
|
||
A device driver should use this system service and not poke directly into the 8086 interrupt vector table.
|
||
The address passed to the GenSetRevector service is not written into the interrupt vector table but to an
|
||
internal table.
|
||
|
||
|
||
When an interrupt occurs, the operating system builds the mandatory operating system call frame,
|
||
preserving all registers on route. The interrupt service routine is then called as a FAR routine. Since the
|
||
operating system preserves all registers the interrupt service routine is free to use any register.
|
||
|
||
|
||
To remove the interrupt service routine address, the operating system service GenResetRevector should be
|
||
used. This will reset the internal table entry to the default held in the ROM.
|
||
|
||
|
||
As with all interrupt service routines various rules apply:
|
||
|
||
|
||
= Interrupt service routines should execute as fast as possible. Operating system interrupt service
|
||
routines are tuned to last no longer than one millisecond. |
|
||
|
||
|
||
= Typically, interrupt service routines do not enable interrupts unless the routine can handle
|
||
reentrancy.
|
||
|
||
|
||
= Interrupt service routines run in the context of whatever pr 3 is running at the time of the
|
||
interrupt. An interrupt service routine should not attempt to obtain admissibility to the process
|
||
that opened the channel but access the internal driver space only which in general is its own code
|
||
space.
|
||
|
||
|
||
® An interrupt service routine must not directly cause a reschedule as this would significantly
|
||
delay its completion. It must use the IoSignalByP idNoReSched system service in order to indicate
|
||
that an event has occurred to the owning process. The handler|function of the device driver must
|
||
pick up the event and inform the owning process.
|
||
|
||
|
||
= An interrupt service routine should return with the carry flag clear if it requires a reschedule to
|
||
occur (it has called 1oSignalBy? idNoReSched) otherwise return with the carry flag set. This will
|
||
cause the operating system to reschedule if the internal state allows such an action otherwise the
|
||
reschedule request is effectively queued until such time that the operating system can reschedule.
|
||
|
||
|
||
Device Driver I/O Semaphore Waithandlers
|
||
|
||
|
||
An LDD may nominate one of its functions to be called by the operating system every time the I/O
|
||
semaphore of the process that opened the channel is signalled. The nominated function will only be called
|
||
if the application is waiting for an outstanding I/O request to complete, For well written applications this
|
||
is practically all the time. ac
|
||
|
||
|
||
By convention the vector table entry after the mandatory vectors contains the handler vector.
|
||
|
||
|
||
A handler routine is similar to an interrupt service routine in that it appears to run ‘from nowhere’.
|
||
Comparing handlers and interrupt services routines shows that:
|
||
|
||
|
||
80 |
|
||
|
||
|
||
7 WRITING DEVICE DRIVERS
|
||
eee
|
||
|
||
|
||
* A handler will always run in the context of the process that has opened a channel. An interrupt
|
||
ceca routine will run in the context of whatever process happens to be running at the time of
|
||
é interrupt.
|
||
|
||
|
||
2 A handler can access the data space of the process that opened the channel. The interrupt service
|
||
routine must not. An interrupt service routine should only access the data space in the driver
|
||
which is usually its own CS space.
|
||
|
||
|
||
= A handler can cause a reschedule. An interrupt service routine must not cause a reschedule. If it
|
||
did, the interrupt would not be fully serviced (the rest of the interrupt service routine would not
|
||
be executed until a reschedule back to the process running at the time of the interrupt, which
|
||
may not happen for a significant length of time). The interrupt service routine must only use the
|
||
loSignalByPidNoReSched to signal the channel owner.
|
||
|
||
|
||
The handler is the mechanism by which hardware interrupt events can be filtered through to the process
|
||
using the I/O channel.
|
||
|
||
|
||
ee
|
||
Loadable Logical Device Driver Structure
|
||
A loadable LDD must obey the following rules:
|
||
|
||
= The must be a single code segment and no data segments.
|
||
|
||
s The code segment must start with a Libent structure.
|
||
|
||
= There must be at least eight supported functions.
|
||
|
||
|
||
Single Code Segment
|
||
|
||
|
||
An LDD must be written to contain any internal variables within its own code segment. In general these
|
||
variables are only concerned with unit allocation and the hardware state.
|
||
|
||
|
||
Data space for a particular open channel can be allocated in the heap space of the process that opens the
|
||
device. This data space will however disappear if the process terminates. Therefore any variables
|
||
required for 'freeing' the hardware after a process terminates must exist in the code space of the device
|
||
driver.
|
||
The LibEnt Structure
|
||
A Lib€nt structure has the following format:
|
||
|
||
= two byte signature
|
||
|
||
8 eight byte name
|
||
|
||
s two byte vector count
|
||
|
||
» A vector table
|
||
The two byte signature should contain the 'LoDSignature’ define.
|
||
|
||
|
||
The eight byte name contains the name of the device driver stored as a zero terminated string. Note that
|
||
the trailing colon is omitted.
|
||
|
||
|
||
The two byte vector count contains the number of vectors that follow immediately after the count. This
|
||
should be equal to at least eight.
|
||
|
||
|
||
For example:
|
||
|
||
|
||
$1
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
dw LDDSignature s Its an LOD
|
||
|
||
db ‘pvr! ,0,0,0,0,0 s Name of the driiver
|
||
|
||
dw (VectorEnd-Vector )/2 : Number of vectors
|
||
Vector:
|
||
|
||
dw Dvrinstall : Install vector
|
||
|
||
dw DvrRemove s Remove vector
|
||
|
||
dw DvrHold 3; Hold vector
|
||
|
||
dw DvrResume s Resume vector
|
||
|
||
dw DvrReset 3; Reset Vector
|
||
|
||
dw DvrUnits > Units Vector
|
||
|
||
dw DvrOpen 3 Open Vector
|
||
|
||
dw DvrStrategy : Strategy vecto
|
||
VectorEnd:
|
||
|
||
|
||
The vector table contains the offsets within the device drivers code se: t for the functions required by
|
||
|
||
|
||
the EPOC operating system. Throughout this document the terms vector and function are used
|
||
interchangeably. The vector table must have the entries in the order shown in the example.
|
||
|
||
|
||
Mandatory LDD Functions
|
||
All LDDs must support the following eight functions:
|
||
= DevFuncinstall called on device installation.
|
||
S DevFuncRemove called on device removal.
|
||
= DevFuncHold called to temporarily disable the driver.
|
||
= DevFuncResume called to enable the driver after it has been temporarily disabled.
|
||
= DevFuncReset called when an application terminates without closing the channel.
|
||
® DevFuncUnits called to query the number of supported units (i.e. channels).
|
||
= DevFuncOpen _callled to open a channel to an LDD. |
|
||
® DevFuncStrategy called to access the device drivers functio ny from the I/O system.
|
||
|
||
|
||
All of the routines pointed at by the function vector table will be called FAR by the operating system and
|
||
should consequently use a FAR return machine code instruction to we back to the operating system.
|
||
|
||
|
||
Since the FAR return address is to the operating system it does not matter if the operating system moves
|
||
memory whilst code in the LDD is being executed: the operating system cannot move its own code.
|
||
|
||
|
||
PoPateaMeteretareMete Pete PeMetetetsetate tet tet Meh ee9,
|
||
*.] Prete rate one” Fat, eesese
|
||
7 voters:
|
||
6 o 6 jegeeee
|
||
ke < ogeeee
|
||
5 e Dc aso
|
||
ERS
|
||
|
||
|
||
internal variables. It can not be called directly by an application p :
|
||
|
||
|
||
The Devinstall operating system service will cause this function to be ais Applications should not call
|
||
this service directly and should call instead the DevLoadLDD service.
|
||
|
||
|
||
An installable device driver may have the same name as a resident device driver and when loaded is
|
||
placed at the end of the device driver table. When the operating system wishes to establish a channel with
|
||
a device driver, it searches for the device driver starting at the end of the table. It will thus find the most
|
||
recently loaded device driver having the required name. By this mechanism an installable device driver
|
||
can replace a resident device driver of the same name.
|
||
|
||
|
||
An installable device driver may have the same name as a resident device driver. When the operating
|
||
system loads a device driver, it places it at the end of the device driver table. The operating system will
|
||
search this table for the appropriate device driver when it wishes to establish a channel. The search starts
|
||
at the end and thus will locate the most recently installed device driver (if any) or if not, the resident
|
||
driver. By this mechanism an installable driver can replace any resident driver.
|
||
|
||
|
||
When called, the DS and ES segment registers are in an unknown state| The device driver should take
|
||
whatever steps necessary to obtain direct addressability to its data. For|loadable device drivers this
|
||
involves setting the DS and ES registers to the CS register.
|
||
|
||
|
||
The operating system will not move memory whilst in this function, thus the normal rules governing DS
|
||
and ES may be ignored.
|
||
|
||
|
||
All operating system services may be called, except those concerning file or device access.
|
||
|
||
|
||
—=—_—_
|
||
|
||
|
||
|
|
||
|
||
|
||
called by the operating system when the device driver i loaded in order to initialise any
|
||
|
||
|
||
7 WRITING DEVICE DRIVERS
|
||
a
|
||
|
||
|
||
PASSED
|
||
No values are passed to the install vector.
|
||
|
||
|
||
RETURN
|
||
If the installation was successful, return with the carry flag clear.
|
||
If the installation failed, return with the carry flag set and the error number in the AL register.
|
||
|
||
|
||
PANIC
|
||
The install vector must not panic: it will cause an operating system kernel fault if it does.
|
||
|
||
|
||
PRESERVE
|
||
The SS, SP and BP registers must be preserved by the install function.
|
||
|
||
|
||
It can not be called directly by an application process.
|
||
|
||
|
||
The DevRemove operating system service will cause this function to be called. Applications should not call
|
||
this directly, they should use the DewDelete service.
|
||
|
||
|
||
Before the remove function is requested, the device driver will have received a hold request. Thus
|
||
devices will only ever be removed when in a held state.
|
||
|
||
|
||
If the device driver is currently busy serving a client, the remove request should return an error.
|
||
|
||
|
||
All resident device drivers will return an error since there is no mechanism by which they can be re-
|
||
installed.
|
||
|
||
|
||
When called, the DS and ES segment registers are in an unknown state; the device driver should take
|
||
whatever steps necessary to obtain direct addressability to its data. For loadable device drivers this
|
||
involves setting the DS and ES registers to the CS register.
|
||
|
||
|
||
The operating system will not move memory whilst in this function, thus the normal rules governing DS
|
||
and ES may be ignored.
|
||
|
||
|
||
All operating system services may be called, except those concerning file or device access.
|
||
|
||
|
||
PASSED
|
||
No values are passed to the remove vector.
|
||
|
||
|
||
RETURN
|
||
If the remove was successful, return with the carry flag clear.
|
||
If the remove failed, return with the carry flag set and the error number in the AL register.
|
||
|
||
|
||
PANIC
|
||
|
||
|
||
The remove vector must not panic: it will cause an operating system kernel fault if it does.
|
||
|
||
|
||
PRESERVE
|
||
The SS, SP and BP registers must be preserved by the remove vector.
|
||
|
||
|
||
.
|
||
atetstetatatenenatotateter
|
||
|
||
|
||
2,2 ,0.0,8,8,
|
||
|
||
|
||
; NOSOS ase
|
||
|
||
OVE
|
||
5 a OR Sate
|
||
|
||
Saretetetetoconeneteterenoresetetesesesey
|
||
|
||
|
||
This vector will be called by the operating system when the device driver is requested to be held. The
|
||
hold vector is called in the context of the operating system.
|
||
|
||
|
||
The Deviold operating system service will cause this vector to be called. Applications should not call this
|
||
service.
|
||
|
||
|
||
The operating system will call the hold vector under three conditions:
|
||
=» Device memory segments are about to be moved.
|
||
|
||
|
||
83
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
s The machine is about to switch off due to the auto switch off timeout or user request, it enters
|
||
the standby state.
|
||
|
||
|
||
s The machine is about to switch off due to the power source being removed.
|
||
|
||
|
||
In all cases the device driver must respond to the request as quickly as possible. It must also ensure that
|
||
ALL interrupts from the hardware device that it is driving are disabled!
|
||
|
||
|
||
Device memory segments can only be moved if an installable device iver is being installed or removed.
|
||
If the LDD uses an attached PDD and uses the faster FAR call mechanism to call the PDD strategy
|
||
vector, the PDD strategy vector address will potentially move, thus the FAR address will be wrong. This
|
||
address can be resolved in the resume vector. The LDD must not call the PDD between a hold and
|
||
resume. Typically, the device driver only needs to disable its interrupts. When a resume occurs, the
|
||
device driver should continue as though nothing had happened.
|
||
|
||
|
||
If the machine is about to switch off due to the auto switch off or user request mechanisms (enter the
|
||
standby state), the device driver should make an orderly shut down of the device such that the state
|
||
before the shut down can be recovered when the system powers up again. The device driver should also
|
||
attempt to ensure that no data is lost. For example, in the serial driver the current state of the hardware
|
||
handshaking lines should be noted so that each state can be restored on power up. For this type of power
|
||
down the hold vector is allowed to take a significant length of time to shut down a device. For example
|
||
in a serial driver the hold vector should wait until the remote end stops transmitting data after any
|
||
hardware handshaking has been applied. Of course, the time taken should be kept to a minimum: in the
|
||
case of the serial driver above the time is roughly equivalent to 3 character transmission times. When a
|
||
resume occurs the device driver should continue as though nothing had happened.
|
||
|
||
|
||
If the machine is about to switch off due to the power source being removed, the device driver should
|
||
reset the device in the minimum possible time: no attempt should be made to perform an orderly shut-
|
||
down. The device driver is not expected to be able to recover the hardware state. When a resume occurs,
|
||
the device driver would typically fail any outstanding application requests. If the hold vector takes too
|
||
long the voltage will fall below the threshold to hold the state of the internal RAM. If this occurs the
|
||
machine will perform a warm re-boot when powering up, all data in the internal memory of the machine
|
||
bebe be lost including the device driver code! On power fail there is about 2ms available to power down
|
||
devices.
|
||
|
||
|
||
On a power failure hold, the operating system will already have sent a |reset' to all the SIBO serial
|
||
channels. Any device drivers using these channels need only record the hold reason for the resume
|
||
vector. Any other peripherals should be designed to allow a power faill mechanism with the minimum
|
||
amount of code.
|
||
|
||
|
||
It must be noted that the power fail type hold can occur whilst the device driver is in the memory move
|
||
hold state. In this case, the device driver will receive two hold requests before seeing a resume request. A
|
||
device driver must be capable of handling this. In this case, the device |driver will also receive two
|
||
resume requests. A device driver will not get a power fail hold whilst in power down hold.
|
||
|
||
|
||
A call to the hold vector will always be followed by a call to the e vector (except when a device is
|
||
requested to be removed).
|
||
|
||
|
||
When called, the DS and ES segment registers are in an unknown state: the device driver should take
|
||
whatever steps necessary to obtain direct addressability to its data. For|loadable device drivers this
|
||
involves setting the DS and ES registers to the CS register.
|
||
|
||
|
||
The device driver should not call any operating system services due to the time taken, especially on
|
||
power failure.
|
||
|
||
|
||
PASSED
|
||
The AH register takes one of the following
|
||
= DevioldNormal Device memory is about to be moved
|
||
= DevioldPowerDown The system is about to enter the eas State.
|
||
= DevHoldPowerFail The system has lost its power supply.
|
||
RETURN
|
||
None.
|
||
PANIC
|
||
|
||
|
||
The hold vector must not panic: it will cause an operating system it fault if it does.
|
||
|
||
|
||
84
|
||
|
||
|
||
7 WRITING DEVICE DRIVERS
|
||
|
||
|
||
PRESERVE
|
||
The SS, SP and BP registers must be preserved by the hold vector.
|
||
|
||
|
||
The DevResune operating system service will cause this vector to be called. Applications should not call
|
||
this service.
|
||
|
||
|
||
The resume vector will be called either when memory has finished being moved or when the machine
|
||
powers back up. In both cases the hold vector will have been called before this vector is called.
|
||
|
||
|
||
The device driver is expected to recover from the previous hold request (except power fail) and resume
|
||
any I/O that was suspended.
|
||
|
||
|
||
If the device driver has an interrupt service routine, it should reset the interrupt service routine's address
|
||
since the device driver may have moved in memory; its absolute segment address will be different.
|
||
|
||
|
||
If the hold was a device memory segment move type hold, interrupts should be re-enabled. If the LDD
|
||
uses an attached PDD and uses the FAR call mechanism to access the PDD strategy vector, the address of
|
||
the PDD should be reset by using the DevGetPDDAddress operating system service before enabling
|
||
interrupts. Typically, the PDD will have a call back to the LDD and it needs to be informed of the
|
||
change of address of the LDD call back function; the LDD-PDD interface definition should allow such a
|
||
function request.
|
||
|
||
|
||
If the hold was a power down type hold, the resume vector needs to power up the peripheral and set it to
|
||
the state that it was in before the power down occurred. If this is not possible or data has been lost, the
|
||
device driver should inform any outstanding requests of this fact.
|
||
|
||
|
||
It is also possible that the hardware device that the driver is associated with has been removed. The
|
||
driver should be able to handle this properly.
|
||
|
||
|
||
If the device driver is expected to generate events due to an external state change, the driver should check
|
||
the external state and generate appropriate events. For example, the serial driver may be requested to
|
||
inform an application when the DTR line changes state. The remote end may have changed the state of
|
||
DTR whilst the driver is held.
|
||
|
||
|
||
If the hold was a power failure type hold, the resume vector should power up the peripheral and put it
|
||
into a known state, preferably the state that the application software thinks that the device is in and fail
|
||
any outstanding requests as data is quite likely to have been lost.
|
||
|
||
|
||
When called, the DS and ES segment registers are in an unknown state. The device driver should take
|
||
whatever steps necessary to obtain direct addressability to its data. For loadable device drivers this
|
||
involves setting the DS and ES registers to the CS register.
|
||
|
||
|
||
All operating system services may be called, except those concerning file or device access.
|
||
|
||
|
||
PASSED
|
||
|
||
|
||
None
|
||
|
||
|
||
RETURN
|
||
|
||
|
||
None.
|
||
|
||
|
||
PANIC
|
||
The resume vector must not panic, it will cause an operating system kernel fault if it does.
|
||
|
||
|
||
PRESERVE
|
||
The SS, SP and BP registers must be preserved by the resume vector.
|
||
|
||
|
||
channel. The reset function is called in the context of the operating system.
|
||
|
||
|
||
85
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
1
|
||
I
|
||
|
||
|
||
The device driver must request that the operating system call the reset function. This is achieved by C)
|
||
calling the IoRequestReset system service, usually in the open vector. To cancel this request, the device |
|
||
driver should call the 1oRequestResetCancel system service. The cancel |service is usually called as part of
|
||
|
||
the close functionality in the strategy vector.
|
||
|
||
|
||
The reset vector will be called when the operating system is tidying up) resources owned by a process that
|
||
has terminated. If a process terminated before it closed the device driver channel and no reset service is
|
||
requested, that channel would remain allocated; no process will ever close the channel. The reset vector
|
||
allows a device driver to reset itself and allow the channel to be opened again.
|
||
|
||
|
||
|
|
||
|
||
|
||
Any data required to perform the reset must be stored in the device driver. The data space belonging to
|
||
the process that originally opened the channel has been returned to the joperating system memory pool
|
||
and is no longer valid.
|
||
|
||
|
||
If a device driver can handle multiple channels then the data passed to the IoRequestReset system service
|
||
should identify the channel. This data will be passed in the CX register to the reset vector.
|
||
|
||
|
||
The device driver should only have a reset request outstanding with the operating system while a process
|
||
has a channel open.
|
||
|
||
|
||
When called, the DS and ES segment registers are in an unknown state; the device driver should take
|
||
whatever steps necessary to obtain direct addressability to its data. For loadable device drivers this
|
||
involves setting the DS and ES registers to the CS register.
|
||
|
||
|
||
All operating system services may be called, except those concerning file or device access.
|
||
|
||
|
||
PASSED
|
||
This function is passed data in the CX register that the device driver requested it be sent to determine
|
||
which channel should be reset.
|
||
|
||
|
||
RETURN
|
||
|
||
|
||
None.
|
||
|
||
|
||
PANIC
|
||
|
||
|
||
The reset vector must not panic; it will cause an operating system kernel fault if it does.
|
||
|
||
|
||
PRESERVE
|
||
The SS, SP and BP registers must be preserved by the reset vector.
|
||
|
||
|
||
The operating system places no significance on the number of channels a device driver can support. It is
|
||
primarily used for informational purposes.
|
||
|
||
|
||
fa application may use the number of units to attempt to open any re channel on that device
|
||
ver.
|
||
|
||
|
||
When called, the DS and ES segment registers are in an unknown state; the device driver should take
|
||
whatever steps necessary to obtain direct addressability to its data. For loadable device drivers this
|
||
involves setting the DS and ES registers to the CS register.
|
||
|
||
|
||
All operating system services may be called, except those concerning file or device access.
|
||
|
||
|
||
PASSED
|
||
|
||
|
||
None.
|
||
|
||
|
||
RETURN
|
||
|
||
|
||
The AX register should contain the number of channels supported. If a device driver can support multiple
|
||
|
||
channels (limited only by memory constraints) then the driver may return -1. A serial device driver, for a
|
||
example, might only support two channels (TTY:A and TTY:8) whereas the file device driver can open an
|
||
unlimited number of files.
|
||
|
||
|
||
86
|
||
|
||
|
||
7 WRITING DEVICE DRIVERS
|
||
—— eee
|
||
|
||
|
||
PANIC
|
||
|
||
|
||
The channels units vector must not panic; it will cause an operating system kernel fault if it does.
|
||
|
||
|
||
PRESERVE
|
||
The SS, SP and BP registers must be preserved by the units vector.
|
||
|
||
|
||
The device driver is passed two parameters, its device handle and a pointer to an Open€nt structure.
|
||
|
||
|
||
The device handle is the entry in the system device table of this device driver. The device driver is
|
||
required to place this handle in the Chant ibandle field of the Chan€nt structure which must be allocated in
|
||
the user's data space. The operating system uses the device handle to route any I/O requests on the
|
||
opened channel to the correct device driver.
|
||
|
||
|
||
The OpenEnt structure contains three fields, OpenNamePtr, OpenMode and Openchan.
|
||
|
||
|
||
The OpenNamePtr field contains a pointer to the character that exists after the device name as passed to the
|
||
IoOpen system service. For example, if the 1o0pen service was passed a name of PAR:A, the OpenNamePtr
|
||
field would point to the colon. If the 1o0pen service was passed a name of TTY.AS5:8 the OpenNameptr field
|
||
would point to the full stop. The device driver should process the name appropriately, opening the
|
||
correct PDD as required.
|
||
|
||
|
||
The OpenMode field contains the mode for opening the device driver. The available modes are specified by
|
||
the device driver writers. For example, a combined Xmodem and Ymodem device driver could use the
|
||
mode to specify whether the Xmodem or the Ymodem protocol is to be used.
|
||
|
||
|
||
The Openchan field contains the I/O channel handle of the device that this driver is required to ‘attach’ to.
|
||
Attached device drivers are dealt with later in the chapter.
|
||
|
||
|
||
The code in a device driver open vector tends to follow a very similar pattern. This is demonstrated by
|
||
the following code fragments and associated comments.
|
||
|
||
|
||
The first stage is to allocate some data space in the calling process’ heap space. This will contain the I/O
|
||
channel control block:
|
||
|
||
|
||
mov cx, (size DeviceEnt)
|
||
|
||
HeapAl LocateCel |
|
||
|
||
jc noMemory
|
||
|
||
mov bx, ax 3; cell handle
|
||
|
||
|
||
If the device driver requires a WaitHandler (described later):
|
||
|
||
|
||
mov al, (VectorHandler-Vector)/2
|
||
IoAddHandler
|
||
|
||
jc endFreeMemory
|
||
|
||
mov [bx] .DriverHandler, ax
|
||
|
||
|
||
If the device driver's DevFuncReset vector is required to be called:
|
||
|
||
|
||
push bx
|
||
|
||
mov cx, Channel Indicator 3 unique per channel
|
||
mov bx, dx s the device handle
|
||
ToRequestReset
|
||
|
||
pop bx ; restore alloc cell
|
||
|
||
|
||
The ChanEnt field of the DriverEnt structure must be initialised:
|
||
|
||
|
||
mov [bx] .Driverlo.ChanNext, bx
|
||
mov [bx] .Driverlo.ChanSignature, IoChanSignature
|
||
mov [bx] .Driverlo.ChanLibHandle, dx
|
||
|
||
|
||
The ChanNext field is used by attached drivers and will usually be set to be the allocated cell handle of the
|
||
device driver being opened. The IoFuncAttach and loFuncDetach functions manipulate these fields. The
|
||
I/O system uses this field to direct the I/O request to the correct driver.
|
||
|
||
|
||
87
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION |
|
||
|
||
|
||
The ChanSignature field is checked by the operating system during any ” requests for the value
|
||
IoChanSignature. If it does not contain that value, the process calling the I/O service will be panicked for
|
||
having passed an invalid I/O channel handle.
|
||
|
||
|
||
The ChanLibHandle field is used by the operating system to route an application's I/O request to this
|
||
device. The I/O request will call the DevFuncStrategy vector of the device driver.
|
||
|
||
|
||
If the driver is an attached driver the following is required:
|
||
|
||
|
||
mov cx, bx : allocated channel
|
||
mov bx, [si] .OpenChan * channel attaching to
|
||
mov al, lIoFuncAttach s return in BX the
|
||
ToWwithwWait s channel attached to
|
||
|
||
|
||
Finally, if the channel has been successfully opened:
|
||
|
||
|
||
cle ; Opened Ok
|
||
ret s return BX and DX
|
||
|
||
|
||
The error recover code typically follows the following pattern:
|
||
|
||
|
||
endF reeReset:
|
||
push ax
|
||
push bx
|
||
mov cx, Channel Indicator
|
||
mov bx, dx
|
||
ToRequestResetCancel
|
||
pop bx
|
||
pop ax
|
||
endF reeHandlter:
|
||
push ax
|
||
push bx
|
||
mov bx, [bx] .DriverHandler
|
||
ToRemovelandler
|
||
pop bx
|
||
pop ax
|
||
endF reeMemory:
|
||
push ax
|
||
HeapFreeCel l
|
||
pop ax
|
||
stc
|
||
noMemory:
|
||
ret
|
||
|
||
|
||
If a device driver supports a fixed number of channels, it typically contains static control blocks. In order
|
||
to determine if a requested channel is currently open, a field should be interrogated. The device driver
|
||
should ensure that interrupts are disabled during this sort of check since a context switch could occur and
|
||
another process request the opening of the same channel. This is the classic 'test and set' problem
|
||
encountered in multi-tasking environments.
|
||
|
||
|
||
When called, the DS and ES segment registers point to the data segment of the application process
|
||
attempting to open a device channel. The application should ensure the DS and ES segment registers
|
||
do in fact point to its data segment. The device driver must obey the normal rules concerning segment
|
||
register manipulation. The DS and ES segment registers can be reloaded if required from the Intent
|
||
structure pointed at by the BP register.
|
||
|
||
|
||
All operating system services may be called. |
|
||
PASSED
|
||
|
||
DX contains the device handle of the device driver.
|
||
|
||
SI is a pointer to the OpenEnt structure
|
||
|
||
BP is a pointer to the IntEnt structure.
|
||
|
||
|
||
RETURN
|
||
|
||
|
||
If the channel open was successful, return with the carry flag clear and the BX register containing the
|
||
open channel.
|
||
|
||
|
||
If the open failed, return with the carry flag set and the error number in the AL register.
|
||
|
||
|
||
88
|
||
|
||
|
||
7 WRITING DEVICE DRIVERS
|
||
|
||
|
||
PANIC
|
||
|
||
|
||
The open vector can panic; it will cause the process requesting the device open to terminate. It is
|
||
however more usual to return an error to the calling process.
|
||
|
||
|
||
PRESERVE
|
||
The DS, ES, SS, SP, BP and DX registers must be preserved by the open vector.
|
||
|
||
|
||
not have to support any particular function, as it is a matter of design between a device driver writer and
|
||
application writer as to what functions and associated parameters are provided.
|
||
|
||
|
||
To obtain the power of attached device drivers, it is recommended that the device driver use the system
|
||
defines with their appropriate functionality, for example, the loFuncWrite function number should always
|
||
be associated with writing data.
|
||
|
||
The strategy function is passed the channel handle as allocated in the open vector in the BX register. This
|
||
typically contains control information concerning the current state of the I/O channel.
|
||
|
||
|
||
The SI register contains a pointer to a RqEnt structure. This structure contains four fields, RqFunction,
|
||
RqgStatusPtr, RoA1Ptr and RaA2Ptr.
|
||
|
||
|
||
The RqFunction field contains the function number as passed to the IoWithWait (or loAsynchronous) I/O
|
||
request by the application. If a device driver does not support the specified function, it should pass the
|
||
request on to its ‘parent’ device driver.
|
||
|
||
|
||
The RqStatus pointer contains a pointer to a memory location in the application process's data space that
|
||
receives the I/O requests completion status. The device driver must set this memory location to the value
|
||
PendingErr whilst the I/O request is outstanding and a completion code when the I/O request completes.
|
||
An I/O request may complete within the strategy vector or it may complete some time in the future,
|
||
presumably from some interrupt.
|
||
|
||
|
||
The RqA1Ptr and RqA2Ptr fields contain the argument 1 and 2 parameters as passed to the IoWithwait (or
|
||
IoAsynchronous) system services. The device driver is free to specify what these parameters are (if any).
|
||
|
||
|
||
The operating system defines a set of common function numbers used by device drivers referred to as the
|
||
loFuncxxx set of defines. By convention, a device driver should select from this list, particularly if some
|
||
of the more advanced features of the I/O system are to be used, such as attached device drivers. The more
|
||
common defines are:
|
||
|
||
|
||
= loFuncRead ; read from the device.
|
||
|
||
® IlofuncWrite ; write to the device.
|
||
|
||
@ toFuncClose ; Close device channel.
|
||
|
||
® oFuncCancel ; cancel an I/O request.
|
||
|
||
® loFuncSet ; set driver characteristics
|
||
|
||
= loFuncSense ; sense driver characteristics.
|
||
® oFuncF lush ; flush any buffers.
|
||
|
||
|
||
The PLIB library functions p_read, p_ write and p_close will call the device driver with the 1oFuncRead,
|
||
loFuncWrite and IoFuncClose function numbers. Thus, if the device driver choses an alternative function
|
||
number set, an application will not be able to use the supplied library functions.
|
||
|
||
|
||
All resident device drivers obey the following conventions:
|
||
= Acancel request will cancel any outstanding requests. A cancel request will not return any error.
|
||
|
||
|
||
=» Aclose request will ensure that any outstanding requests are completed before closing the
|
||
channel. A close request will not return any error.
|
||
|
||
|
||
= Only one request of a particular type can be outstanding at any one time. If a second request is
|
||
made the device driver will panic the calling application.
|
||
|
||
|
||
89
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION |
|
||
|
||
|
||
Any functions that the strategy function does not support should be sasbed on to the next driver down the
|
||
driver hierarchy. If the driver is a root driver (attached driver), this is achieved using the 1oRoot
|
||
(I1oSuper)system service. If the requested function is not supported by any driver, the operating system
|
||
will return a NotSupported error.
|
||
|
||
When called, the DS and ES segment registers point to the data segment of the application process
|
||
making the I/O function request. The application should ensure that the DS and ES segment registers do
|
||
in fact point to its data segment. The device driver must obey the normal rules concerning segment
|
||
register manipulation. The DS and ES segment registers can be reloaded if required from the Intent
|
||
structure pointed at by the BP register.
|
||
|
||
|
||
All operating system services may be called.
|
||
|
||
|
||
PASSED
|
||
|
||
BX contains the allocated channel control block.
|
||
DX contains the device handle of the device driver.
|
||
SI is a pointer to the RgEnt structure.
|
||
|
||
BP is a pointer to the IntEnt structure.
|
||
|
||
|
||
RETURN
|
||
|
||
|
||
If the function request is successful, the strategy vector should return with carry clear. A request
|
||
typically causes some I/O. If the I/O is completed by the strategy vector (eg the close function), the
|
||
completion status should be written back to the RqStatusPtr location and the I/O semaphore signalled
|
||
(using the IoSignal system service). If the request has not yet completed, the RqStatusPtr location should
|
||
contain the value PendingErr and the I/O semaphore should not be signalled.
|
||
|
||
|
||
If the function request failed the strategy vector should return with set and the error code in AL.
|
||
Typically no I/O requests will be completed.
|
||
|
||
|
||
PANIC
|
||
|
||
|
||
The strategy vector can panic; it will cause the process making the I/O request to terminate. In most cases
|
||
it is usual to return an error to the calling process. A major exception to this is if the calling process
|
||
makes an I/O request of the same type as one that is currently outstanding and the device driver only
|
||
supports one I/O request of a particular type at a time; by convention the device driver should panic the
|
||
calling process with the PanicloPending panic code. |
|
||
|
||
|
||
PRESERVE
|
||
The DS, ES, SS, SP and BP registers must be preserved by the strategy vector.
|
||
|
||
|
||
Loadable Physical Device Driver Structure
|
||
A loadable PDD must obey the following rules:
|
||
= There must be a single code segment and no data segments.
|
||
« The code segment must start with a LibEnt structure.
|
||
= There must be at least two supported functions, with typically|a further two defined.
|
||
|
||
|
||
Single Code Segment
|
||
|
||
|
||
A PDD must be written to contain any internal variables within its own code segment. Typically, these
|
||
variables are only concerned with unit (i.e. channel) allocation and hardware state.
|
||
|
||
|
||
Data space for a particular open channel can be allocated in the heap ig of the process that opens the
|
||
device. This data space will however disappear if the process terminates, thus any variables required for
|
||
‘freeing’ the hardware after a process terminates must exist in the code/space of the device driver.
|
||
|
||
|
||
The LibEnt Structure
|
||
A LibEnt structure has the following format:
|
||
|
||
|
||
90
|
||
|
||
|
||
7 WRITING DEVICE DRIVERS
|
||
|
||
|
||
—— eee
|
||
2 A two byte signature
|
||
= An eight byte name
|
||
= A two byte vector count
|
||
# A vector table
|
||
The two byte signature should contain the "PDDSignature' define.
|
||
|
||
|
||
The eight byte name contains a zero terminated name, being that of the device driver. Note that there is
|
||
no trailing colon.
|
||
|
||
|
||
The two byte vector count contains the number of vectors that follow immediately after the count. There
|
||
should be at least two.
|
||
|
||
|
||
For example:
|
||
dw PDDSignature ; Its an PDD driver
|
||
db "DVR .HW1' 0 ; Name of the driver
|
||
dw (VectorEnd-Vector )/2 ; Number of vectors
|
||
Vector:
|
||
dw Dvrinstalt ; Install vector
|
||
dw DvrRemove ; Remove vector
|
||
VectorEnd:
|
||
Most PDDs also define a further two vectors:
|
||
dw DvrOpen : Open Vector
|
||
dw DvrStrategy : Strategy vector
|
||
|
||
|
||
The table of vectors is a table of offsets within the device drivers code segment of the routines that
|
||
implement the required functionality. The vector table must have the entries in the order shown in the
|
||
|
||
|
||
example.
|
||
|
||
|
||
Mandatory PDD functions
|
||
All PDDs must support the following two functions:
|
||
|
||
|
||
® DevFuncinstal LPDD called on device installation.
|
||
S DevFuncRemovePDD called on device removal.
|
||
Most PDDs will support the following two additional functions:
|
||
® DevFuncOpenPDD called to open a PDD
|
||
= DevFuncStrategyPDD called to provide PDD functionality
|
||
|
||
|
||
All of the routines pointed at by the function vector table will be called FAR by the operating system and
|
||
should consequently use a FAR return machine code instruction to return back to the operating system.
|
||
|
||
|
||
Since the FAR return address is to the operating system, it does not matter if the operating system moves
|
||
memory whilst code in the LDD is being executed; the operating system cannot move.
|
||
|
||
|
||
by the operating system when the device driver is loaded to initialise any of its
|
||
internal variables. The install vector is called in the context of the operating system and not the process
|
||
that is loading the device driver.
|
||
|
||
|
||
The Devinstall operating system service will cause this vector to be called. Applications should not call
|
||
this directly, they should use the DevLoadPpD service.
|
||
|
||
|
||
An installable device driver may have the same name as a currently installed device driver. When
|
||
installed, the driver is added to the end of the device driver table. When a channel to a device driver is
|
||
being established by the operating system, it searches the device table from the end first, thus the latest
|
||
installed device driver with the required name will be asked first for a channel. By this mechanism,
|
||
installable device drivers can replace any of the resident drivers.
|
||
|
||
|
||
When called, the DS and ES segment registers are in an unknown state. The device driver should take
|
||
whatever steps necessary to obtain direct addressability to its data. For loadable device drivers this
|
||
involves setting the DS and ES registers to the CS register.
|
||
|
||
|
||
91
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
|
|
||
The operating system will not move memory whilst in this function, as the normal rules governing DS
|
||
and ES may be ignored.
|
||
|
||
|
||
All operating system services may be called except those concerning file or device access.
|
||
|
||
|
||
PASSED
|
||
No values are passed to the install vector.
|
||
|
||
|
||
RETURN
|
||
If the installation was successful, return with the carry flag clear.
|
||
|
||
|
||
If the installation failed, return with the carry flag set and the error —" in the AL register.
|
||
|
||
|
||
el fault if it does.
|
||
|
||
|
||
PANIC |
|
||
The install vector must not panic; it will cause an operating system |
|
||
|
||
|
||
PRESERVE
|
||
The SS, SP and BP registers must be preserved by the install vector. |
|
||
|
|
||
|
||
|
||
driver is requested to be unloaded.
|
||
The remove vector is called in the context of the operating system and not the process that requests the
|
||
unload.
|
||
|
||
|
||
The DevRemove operating system service will cause this vector to be called. Applications should not call
|
||
this service directly; instead, they should call the DevwDelete service.
|
||
|
||
|
||
Before the remove function is requested, the operating system will send a DevFuncHold request to all
|
||
LDDs. The LDD is responsible for ensuring that no activity will occur during the remove. Note that any
|
||
device driver that handles hardware interrupts must contain an LDD since only LDDs receive a hold
|
||
request.
|
||
|
||
|
||
If the device driver is currently busy serving a client, the remove request should return an error.
|
||
|
||
|
||
All resident device drivers will return an error since there is no mechanism by which they can be re-
|
||
installed.
|
||
|
||
|
||
When called, the DS and ES segment registers are in an unknown state; the device driver should take
|
||
whatever steps necessary to obtain direct addressability to its data. For loadable device drivers this
|
||
involves setting the DS and ES registers to the CS register.
|
||
|
||
|
||
The operating system will not move memory whilst in this function, thus the normal rules governing DS |
|
||
and ES may be ignored.
|
||
|
||
|
||
All operating system services may be called except those concerning file or device access.
|
||
|
||
|
||
PASSED
|
||
No values are passed to the remove vector.
|
||
|
||
|
||
RETURN
|
||
If the remove was successful, return with the carry flag clear.
|
||
If the remove failed, return with the carry flag set and the error number in the AL register.
|
||
|
||
|
||
|
|
||
PANIC
|
||
|
||
|
||
The remove vector must not panic; it will cause an operating system ~~ fault if it does.
|
||
|
||
|
||
PRESERVE
|
||
The SS, SP and BP registers must be preserved by the remove vector.
|
||
|
||
|
||
92
|
||
|
||
|
||
7 WRITING DEVICE DRIVERS
|
||
|
||
|
||
When an application opens a channel to an LDD, it normally uses the 1o0pen system service. If the name
|
||
specifies, or the LDD requires, a PDD then it needs to open a channel to a PDD. The Devopenppp system
|
||
service will call this PDD vector to establish a channel. The LDD now has a choice of calling a PDD
|
||
vector using the Dewector system service or calling the fourth vector in the vector table directly. The
|
||
fourth vector is assumed to be a strategy vector to which any parameters as required by the LDD-PDD
|
||
interface can be passed. The FAR address of the strategy vector is returned by the DevGetPpDAddress.
|
||
When an LDD receives a DevFuncResume it should call DevGetPDDAddress again to ensure that if the PDD
|
||
has moved the LDD still has its correct address.
|
||
|
||
|
||
As a design, a PDD could provide many vectors, one for each required function. The LDD would then
|
||
use the Dewector system service to access each of these functions. The DevGetPpDAddress will only return
|
||
the FAR address of the fourth vector.
|
||
|
||
|
||
When called, the DS and ES segment registers point to the data segment of the application process
|
||
making the open function request. The application should ensure that this is indeed the case. The device
|
||
driver must obey the normal rules concerning segment register manipulation.
|
||
|
||
|
||
All operating system services may be called.
|
||
|
||
|
||
PASSED
|
||
|
||
|
||
The BX register contains a pointer to the PDD unit name. The pointer passed to the DevOpenPpD service is
|
||
used to find the PDD device to open. The BX register is loaded with a pointer to the trailing colon (if
|
||
any) in the PDD unit name. For example if the name TTY.AS5:A was passed to the DevOpenpDD service, BX
|
||
would contain a pointer to :A upon calling the open vector.
|
||
|
||
RETURN
|
||
|
||
If the open was successful, return with the carry flag clear.
|
||
|
||
|
||
If the open failed, return with the carry flag set and the error number in the AL register.
|
||
|
||
|
||
PANIC
|
||
The open vector can panic; it will cause the process requesting the device open to terminate. It is
|
||
however more usual to return an error to the calling process.
|
||
|
||
|
||
PRESERVE
|
||
The SS, SP and BP registers must be preserved by the open vector.
|
||
|
||
|
||
Typically, all application function requests are routed through the strategy vector. To speed the calling
|
||
interface, the DevGetPDDAddress operating system function will return a FAR address of this vector.
|
||
|
||
|
||
The device driver writer defines all the functions and return values as required.
|
||
|
||
|
||
When called, the DS and ES segment registers point to the data segment of the application process
|
||
making the function request. The application should ensure that the DS and ES segment registers do in
|
||
fact point to its data segment. The device driver must obey the normal rules concerning segment register
|
||
manipulation.
|
||
|
||
|
||
All operating system services may be called.
|
||
|
||
|
||
PASSED
|
||
The parameters passed are defined by the device driver write.
|
||
|
||
|
||
RETURN
|
||
All returns are defined by the device driver writer.
|
||
|
||
|
||
93
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
PANIC
|
||
|
||
|
||
The strategy vector can panic; it will cause the process requesting the function to terminate. It is however
|
||
more usual to return an error to the calling process.
|
||
{
|
||
|
||
|
||
PRESERVE
|
||
Which registers are preserved is defined by the device driver writer.
|
||
|
||
|
||
94
|
||
|
||
|
||
CHAPTER 8
|
||
|
||
|
||
EXAMPLE DEVICE DRIVERS
|
||
|
||
|
||
This chapter contains explanatory notes for the example device drivers supplied with the Psion C SDK.
|
||
aad ae code for these examples can be found in \sibosdk\ldd. The Borland Turbo assembler is used
|
||
ugnout.
|
||
|
||
|
||
See also the preceding Writing Device Drivers chapter and the appropriate chapters in the I/O Devices
|
||
Reference manual.
|
||
|
||
|
||
ee ee
|
||
An Attached Device Driver Example
|
||
|
||
|
||
The code in atimdvr.asm contains an example of an attached device driver. Attached drivers add
|
||
functionality to, or replace, a service provided by an underlying device driver. The example is a generic
|
||
timeout device driver that adds a timeout facility to the underlying device driver's P_FREAD requests. The
|
||
example driver may be attached to either the serial or the parallel drivers.
|
||
|
||
|
||
The example code in ¢_atim.c shows how the device driver is loaded and attached to a serial driver. It
|
||
also ponte tl the additional functionality becomes transparent to the application once the driver has
|
||
been attached.
|
||
|
||
|
||
The device table
|
||
|
||
|
||
The start of the file consists of the device driver header. The name of the driver is specified to be ATM.
|
||
The driver is an LDD type driver consisting of nine callable functions, the first eight of which are
|
||
mandatory. The ninth function (a wait handler) is required by the device driver to function correctly.
|
||
|
||
|
||
Note that the following notes apply specifically to the functions as used in the example driver.
|
||
|
||
|
||
The Install Function
|
||
|
||
|
||
The install function does not have to perform any actions apart from report that it has completed
|
||
successfully.
|
||
|
||
|
||
The Remove Function
|
||
|
||
|
||
The remove function does not have to perform any actions apart from reporting that it has completed
|
||
successfully. This makes the reasonable assumption that the user of the device driver will not attempt to
|
||
remove it if it is associated with any open channels.
|
||
|
||
|
||
The Hold Function
|
||
The hold function is not required to do anything since it does not access or use hardware directly.
|
||
|
||
|
||
The Resume Function
|
||
|
||
|
||
Since the hold function does not do anything that needs to be undone, the resume function is not required
|
||
to do anything (otherwise it might have performed tasks such as stopping interrupts, shutting down
|
||
hardware etc).
|
||
|
||
|
||
The Reset Function
|
||
|
||
|
||
The reset function is not required to do anything: it can never be called since the driver does not ask the
|
||
operating system to call this function if its client terminates without closing an open channel. The timer
|
||
|
||
|
||
95
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION |
|
||
|
||
|
||
!
|
||
|
||
|
||
device driver and the driver attached to are responsible for releasing system resources if a client
|
||
terminates. Thus this driver can leave it up to those drivers to tidy up. |
|
||
|
||
|
||
The Units Function
|
||
|
||
|
||
The driver can support an unlimited number of open requests subject ; system memory and timer
|
||
channel availability. |
|
||
|
||
|
||
The Open Function
|
||
|
||
|
||
The open function is called by the operating system when an applicatioy uses the IoOpen system service to
|
||
open the ATM: device. This is usually done via the PLIB library function p_open.
|
||
|
||
|
||
The open function runs in the context of the process that makes the open request. Thus resource
|
||
allocation (e.g. memory allocation requests) will be associated with process.
|
||
|
||
|
||
The open function allocates enough memory to hold all of the required |internal variables and if itialises
|
||
the memory to zero. It then makes function nine in the device table a wait handler function by jusing the
|
||
loAddHandler system service. This installs the function in the linked list of wait handler functions. The
|
||
wait handler by default is not callable, and should, for performance reasons, only be made callable when
|
||
it has some processing to do. 7
|
||
|
||
|
||
A channel to a timer device is opened, the name TIM: is generated on T. run time stack.
|
||
|
||
|
||
The I/O system channel header is set up, the I/O system requires that
|
||
structure as the first item in the allocated cell.
|
||
|
||
|
||
Finally, if all has gone well, our driver attaches itself to the underlying driver whose already open handle
|
||
was passed to the open function.
|
||
|
||
If any errors occur, the device driver is responsible for tidying up all of the currently allocated resources.
|
||
It may be noted that any I/O requests made by the device driver on its own channel (as allocated) after
|
||
the attach request has been made will be routed to the underlying driver rather than starting from the top
|
||
|
||
|
||
of the driver chain. Thus for example in the CancelRead procedure the loFuncCancel request ill be routed
|
||
to the strategy function of the ‘attached to' driver and not to the strategy function of our attached driver.
|
||
|
||
|
||
device driver has a ChanEnt
|
||
|
||
|
||
The Strategy Function
|
||
|
||
|
||
Once opened, the strategy function will be called when an application makes an I/O request. All I/O
|
||
requests on the open channel will be routed to our example driver which must decide how they are to be
|
||
handled. Some I/O requests are not recognised by the example driver and should be passed to the
|
||
underlying driver. This may be done using the 1oSuper system service (note that a root device driver
|
||
would make an IoRoot system service request to pass on any meaningless I/O requests).
|
||
|
||
|
||
Some requests may be redefined; the example driver redefines the meaning of the lofuncSet and
|
||
loFuncSense (P_FSET and P_FSENSE) services to allow an application to set and sense the timeout| values to
|
||
use. The application that attaches the example driver to the serial driver must be careful when ing these
|
||
services, since they produce different results depending on whether the time out driver has been attached
|
||
or sash ns one case they set and sense the serial characteristics and in T other they set and sense a time
|
||
out value).
|
||
|
||
|
||
Some requests may be modified to enhance them; this driver enhances the IoFuncRead (P_FREAD) service
|
||
and, as a side effect, the loFuncCancel (P_FCANCEL) service causing the read request to time out./ This type
|
||
of modification is transparent to an application. It may use the IoFuncRead service identically regardless of
|
||
whether this time out driver has been attached (the IoFuncRead service will of course not time dut if this
|
||
driver has not been attached).
|
||
|
||
|
||
“Because the 1oFunckead service effectively runs two I/O requests, that i the lower driver's loFUncRead and
|
||
a timer channel's loFuncRead, both requests must be cancelled by the example driver if the application
|
||
wishes to cancel the original request. Thus the example driver is required to add functionality to the
|
||
|
||
|
||
loFuncCancel service.
|
||
|
||
|
||
It should be noted that an loFuncClose (P_FCLOSE) request should only detach itself from the lower driver
|
||
and release any resources allocated by this drivers open function. It should not attempt to pass| on the
|
||
IoFuncClose request to the lower level driver (after a detach the I/O system will no longer be able to route
|
||
any I/O requests to a lower driver).
|
||
|
||
|
||
The Wait Handler Function
|
||
|
||
|
||
When an application makes an 1oFuncRead request, the example driver makes two asynchronous I/O
|
||
requests, one on the timer and one on the lower driver. In order for the device driver to gain some
|
||
|
||
|
||
|
|
||
96
|
||
|
||
|
||
8 EXAMPLE DEVICE DRIVERS
|
||
|
||
|
||
processing time, so as to find out what happened to these requests, it needs to enable the already installed
|
||
wait handler routine. When the I/O semaphore is signalled, the wait handler function will be called by
|
||
the operating system (only if the application is currently waiting for an I/O request to complete) so it can
|
||
check to see if either of the two asynchronous requests that it made have completed.
|
||
|
||
|
||
It is possible that neither of the outstanding requests has completed in which case the wait handler
|
||
function should return with the carry flag clear.
|
||
|
||
|
||
If either of the outstanding requests has completed, this driver cancels the other request using up the
|
||
signal generated by cancelling. The wait handler should return with the carry flag set and the AL register
|
||
set to zero since there is no more processing to do at this time.
|
||
|
||
|
||
Although synchronous I/O requests are used within the wait handler (in cancelling and using up signals)
|
||
the wait handler will not be called, i.e. it is not called re-entrantly by the operating system.
|
||
|
||
|
||
Non Interrupt Based Sound Driver |
|
||
|
||
|
||
The code in snddvr.asm contains an example of a root device driver that does not require interrupt
|
||
service routines.
|
||
|
||
|
||
The driver accesses the sound chip within the Series3 and can play notes passed to it from an application.
|
||
|
||
|
||
The sound system within a Series3 can only be accessed by a single process at a time. The operating © -
|
||
system has some state variables that can be used (via system services) as mutual exclusion semaphores.
|
||
|
||
|
||
When the channel to the sound driver is opened, it requests exclusive use of the sound system. When the
|
||
channel is closed it releases this resource. The hardware sound device is switched on only when sound i is
|
||
to be played. 7 cs
|
||
|
||
|
||
The example device driver times the duration of the notes using a system timer. This limits the device :
|
||
driver to ten notes per second as the system timer can not go beyond a resolution of one of. a
|
||
second. This is not a particularly high resolution for the note duration. pe a
|
||
|
||
|
||
As well as the system timer, the device driver makes use of a wait handler function in order aie the “:
|
||
notes. as
|
||
|
||
|
||
The example code in t_mus.c shows how the device driver is loaded and the functions provide a are used
|
||
to generate sound. ;
|
||
|
||
The device table s
|
||
|
||
The start of the file contains the device driver header. The name of the driver is specified to be mus:. The
|
||
driver is an LDD type driver consisting of nine callable functions, the first eight of which are mandatory.
|
||
The ninth function (nominated to be a wait handler function) is required by the device driver to function
|
||
|
||
correctly.
|
||
|
||
|
||
Note that the following notes apply specifically to the functions as used in the example driver.
|
||
WANE!
|
||
|
||
|
||
The Install Function
|
||
|
||
|
||
The install function should indicate that the device driver has no channel open on it yet. This variable. (in
|
||
the device driver space) is required to know how to handle the remove, hold and resume Pare 7
|
||
|
||
|
||
The Remove Function
|
||
|
||
|
||
If the device driver currently owns the sound channel, the remove function will stop the playing of —
|
||
and release to the operating system the sound channel resource. ee
|
||
|
||
|
||
In the normal course of events, the remove function would not be called when an eppiicaiiba has an open
|
||
channel to the device driver. It is however quite possible for this to occur and a device driver should —
|
||
accommodate such a possibility. The StopSound routine and HwFreeCombo operating system service should
|
||
only be called if the driver owns the sound channel otherwise any sound and ownership from other device
|
||
drivers (e.g. alarms) will be ecversey affected when this driver is removed. _ oe
|
||
|
||
|
||
ae ie
|
||
|
||
|
||
The Hold Function
|
||
|
||
|
||
The hold function will stop any sound that is currently being made if this driver currently owns the
|
||
systems sound resource. This device driver does not attempt to determine how far through the current _
|
||
note (duration) it has got. When the resume function is called, the following note (if any) will be played.
|
||
|
||
|
||
97
|
||
|
||
|
||
_ ADDITIONAL SYSTEM INFORMATION |
|
||
|
||
|
||
The Resume Function
|
||
|
||
|
||
The resume function will, if the driver currently owns the systems sound resource, simply switch back on
|
||
the hardware sound device. No note is played at this point. Because the driver uses the services of the
|
||
timer device driver, any outstanding timeout will eventually complete causing the device driver's wait
|
||
handler routine to be run. This in turn determines whether or not more notes are to be played.
|
||
|
||
|
||
The Reset Function | |
|
||
Since the reset function can only be called when there is an open channel, the device driver does not have
|
||
|
||
|
||
. to check that it owns the systems sound resource. The reset function simply stops any current sound,
|
||
|
||
|
||
~~
|
||
|
||
|
||
“nt
|
||
|
||
|
||
powers down the sound system and marks the channel as closed.
|
||
|
||
|
||
The Units Function
|
||
|
||
|
||
The sound system can support no more than one user; thus the device driver supports no more] than one
|
||
open channel at any given time. Note that the device driver will report|that it supports one sound channel
|
||
whether or not that one channel is available.
|
||
|
||
|
||
The Open Function
|
||
|
||
|
||
The open function is called by the operating system when an application wishes to obtain a channel to a
|
||
device called mus: (the example device driver's name). The open function attempts to obtain exclusive use
|
||
‘of the sound resource by calling the HwGetCombo operating system service. It returns with the carry flag
|
||
clear if the driver has successfully obtained the sound resource.
|
||
|
||
|
||
The open function then allocates the I/O control block, adds function i e as a wait handler function and
|
||
obtains.a channel to a timer device. If any of these requests fail, the driver tidies up after itself.
|
||
|
||
|
||
It finally requests that the operating system call the reset function if the client terminates without closing
|
||
|
||
|
||
<4 the’I/O channel. Once successfully opened, the internal variable is set to indicate this.
|
||
|
||
|
||
Yk
|
||
|
||
|
||
4
|
||
|
||
|
||
Sie.
|
||
ee
|
||
|
||
|
||
. 98 |
|
||
|
||
|
||
completion status.
|
||
ay cre on eee?
|
||
|
||
|
||
-
|
||
|
||
|
||
The Strategy Function |
|
||
|
||
|
||
The example device driver supports three functions: playing sound, cancelling the playing and closing the
|
||
channel. This implementation uses the 1oFuncWrite (P_FWRITE) service to play sound, the !oFun¢Cancel
|
||
(P_FCANCEL) service to cancel playing and the-IoFuncClose (P_FCLOSE) service to close the channel.
|
||
|
||
|
||
|
|
||
|
||
|
||
The playing of a sound is achieved by writing the user specified note at the required volume to the sound
|
||
generation chip. The specified timeout is used to queue a timeout request on the timer channelj opened by
|
||
this device driver. When the timeout occurs, the timer device driver will write the completion|status
|
||
word and signal the I/O semaphore. Providing the application is waiting for an I/O request to complete,
|
||
the device driver's wait handler will be called. The wait handler writes the next note into the sound chip
|
||
thus playing the required tune.
|
||
|
||
Here lies a fundamental difference between wait handlers and interrupt service routines. Not on y does an
|
||
application have to be waiting for an I/O request to complete but it must also be able to obtair processing
|
||
‘time in which to run the wait handler code. If a higher priority process is using all of the CPU (even if
|
||
only for a short period of time), the sound application will not get a chance to run the wait handler
|
||
function. Thus applications using this device driver will find that notes sometimes play for a lot longer
|
||
than originally intended.
|
||
|
||
|
||
This effect can be observed by running the example program and switching to the system task |(by
|
||
pressing the System button on the Series3 machine for example ) forcing the system to update the lists.
|
||
|
||
|
||
The lofuncCancel service simply cancels any outstanding write request |by cancelling the outstanding
|
||
‘timer request, waiting for its completion and then completing the write request with the E_FILE_CANCEL
|
||
completion status. The wait handler is also disabled, primarily for system performance reasons.
|
||
|
||
|
||
The lofuncClose request will cancel any outstanding write close the ‘a channel, cancel the reset
|
||
‘Tequest and release the sound resource back to the operating system. | 3
|
||
The Wait Handler Function -_ |
|
||
|
||
|
||
This function should check whether the outstanding timer request has completed and, if so, start playing
|
||
‘the next note. If there are no more notes to play, the original write request is completed with zero
|
||
|
||
|
||
* N
|
||
|
||
+ rs ~
|
||
|
||
" ae . + -
|
||
ae a a
|
||
|
||
|
||
.8 EXAMPLE DEVICE DRIVERS
|
||
|
||
|
||
Exercising the vectors
|
||
|
||
|
||
The hold and resume vectors can be exercised simply by switching the machine off and then back on
|
||
again. The sound should stop when switched off and resume when switched back on.
|
||
|
||
|
||
The reset function can be exercised by running the example program, switching to the system task and
|
||
terminating the example program. If the example program can be re-run and generate sound and/or the
|
||
alarms still work then the driver has tidied up any system resources it needed to.
|
||
|
||
|
||
oy
|
||
|
||
|
||
Interrupt Driven Sound Driver we
|
||
|
||
|
||
The code in sndfrc.asm contains an example of a root device driver that uses the FRC as annang:
|
||
counter) as an interrupt source to drive a sound system. _
|
||
|
||
|
||
eve
|
||
ref
|
||
|
||
|
||
The driver accesses the sound chip within the Series3 and has the ability to play the notes pied to it’
|
||
from an application.
|
||
|
||
|
||
The sound system within a Series3 should only be accessed by a single process at a time. The operating
|
||
system has some state variables that can be used (via system aking, as mutual exclusion semaphores,
|
||
|
||
|
||
Similarly the FRC should only be accessed by a single-process at a time. Ifa: second process grabs. the;
|
||
FRC without the first knowing then the first will a never receive. e another FRC eas and hence
|
||
|
||
|
||
appear to hang. a ay de
|
||
|
||
|
||
When the channel to the sound driver is opened, iceauceie: exclusive use of the:sound system and the;
|
||
FRC; when the channel is closed it releases these resources. It is only when some.sound is tq be: made,
|
||
that the hardware is switched on and the notes played.
|
||
|
||
|
||
Ta
|
||
|
||
|
||
This device driver uses the FRC as a timer to time the duration. of cote. The FRGo can be programmed to
|
||
run at either 32Hz or 512kHz, thus allowing a much greater resolution than the system timer device
|
||
driver that can only provide 1/ 10th of a second resolution. This version allows for a minimum duration
|
||
of 10ms, allowing notes of shorter duration and hence increasing the frequency with which the interrupt
|
||
service routine is called causing avery high percentage of the cae bandwidth: ‘to: Pe used:i.s3 S07
|
||
|
||
|
||
For this driver an eight bit number is used to specify. the, duration of a note and hence) the ‘nexinon a
|
||
duration is 2.56 seconds.
|
||
|
||
|
||
Since the notes are ‘changed i in the interrupt service youtine which i is independent off ‘most other F system,
|
||
activity, a high level of accuracy of note duration can be obtained. . ea eee a 7
|
||
|
||
|
||
The example code 1 in t musfre.c Shows how thé device driver i is 5 loaded and the fuictiong pov are,
|
||
used to generate sound: ore saree
|
||
|
||
|
||
The device table ~--..:: Gp Re ae ye Att Fe Oy ck BAP: te Loe tee ae
|
||
|
||
|
||
The start of the. file contains the device driver header. The name of the driver is specified | to Bé MUS:? : The
|
||
driver is an LDD consisting of nine callable functions, the first eight of which are mandatory. The ninth
|
||
function (nominated to be a wait handler, function) is required by the device driver i in. order to * ieee
|
||
|
||
|
||
correctly. gon Ree pe pas
|
||
|
||
|
||
Note that the sie ta as notes apply ores to the functions as used in the cxample driver.. sue
|
||
|
||
|
||
“ . ; yo ty ty gs
|
||
“ape eee PRE the Q ’ pone a sath elk Se agen ax
|
||
|
||
|
||
The instal Function _
|
||
|
||
|
||
The install function should set the fact that the device driver has.n no o channel open. on ‘it yet. This ‘Variable
|
||
(in the device driver space) is required to know how, to handle the remove, hold and resume Tequests. -
|
||
|
||
|
||
The Remove Function = _ “> ea ae oh 3 a a
|
||
|
||
|
||
The remove function will, if the driver currently owns s the systems sound resource, stop any sound being
|
||
made, stop the FRC from generating interrupts, remove the FRC interrupt service routine address and.
|
||
free the sound channel.
|
||
|
||
|
||
In the normal course of events, the remove function: would not be called when an application ‘has’ an open
|
||
channel to the device driver. It is however quite possible for this to occur and a device driver. should.
|
||
accommodate such a possibility. The stopSound routine and HwFreeCombo operating system service should
|
||
only be called if the driver owns the sound channel, otherwise any sound and ownership from other
|
||
device drivers (eg alarms) will be adversely affected when this driver is removed.
|
||
|
||
|
||
‘ ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
The.Hold Function ._.
|
||
|
||
|
||
The hold function will, if the driver currently owns the systems sound meat stop any sound that is
|
||
currently being made and stop the FRC from generating interrupts. , |
|
||
|
||
|
||
The device driver does not attempt to determine how far through the c
|
||
|
||
|
||
t note (duration) it has got;
|
||
when the resume function is called the following note (if any) will be p :
|
||
|
||
|
||
layed.
|
||
|
||
|
||
‘The ‘Resume Function. «© :. -:
|
||
|
||
|
||
The resume function will, if the driver currently owns the systems sound resource, reset the FRC
|
||
interrupt service routine address held by the operating system to point to the drivers interrupt service
|
||
routine code. The device driver may have moved in memory and thus the absolute CS. address will be
|
||
|
||
wrong. If a write request is currently queued (i.e. a hold request was made while the driver was playing
|
||
some sounds), the sound hardware and FRC interrupts are re-enabled. eee 3
|
||
|
||
|
||
After a power down type hold:the FRC is reset and hence needs to be re-programmed to generate
|
||
interrupts at the required frequency. With a memory move type hold the FRC will continue its
|
||
countdown and, if the count reaches zero, generate the next interrupt. This will be ignored by this device
|
||
driver since the FRC is re-programmed in the reset function. 2) |
|
||
|
||
|
||
The Reset Function: §° °°: © 0iu"’
|
||
|
||
|
||
Since the reset function can only be called when there is an open channel the device driver does not have
|
||
to check that it owns the systems sound resource. The reset function s PS any current sound, powers
|
||
down the sound system, disables FRC interrupts, resets the FRC interrupt address back to the default
|
||
address and marks the channel as closed.
|
||
|
||
|
||
The Units Function
|
||
|
||
|
||
The sound system will support no more than one user and hence the device driver supports only one open
|
||
channel at any given time. Note that the device driver does not guarantee that a channel is avai able by
|
||
reporting that it supports one channel; another system component may own the sound resource|when the
|
||
open request is made. |
|
||
|
||
|
||
The Open Function
|
||
|
||
|
||
The open function is called by the operating system when an application wishes to obtain a channel to a
|
||
device called mus: (our device driver name). The open function attempts to obtain exclusive use of the
|
||
sound resource by calling the HwGetCombo operating system service. If this returns with the carry flag clear
|
||
then the driver has successfully obtained the sound resource.
|
||
|
||
|
||
The open function then attempts to obtain exclusive use of the FRC resource by calling HwGetChannel with
|
||
the interrupt channel number as the hardware resource required. If this returns with the carry flag clear
|
||
then the driver has successfully obtained the FRC resource.
|
||
|
||
|
||
The open function then allocates the I/O control block, adds function nine as a wait handler function, and
|
||
requests that the operating system call the reset function if the client terminates without closing the I/O
|
||
channel. |
|
||
|
||
|
|
||
|
||
|
||
Once successfully opened, the SoundChan.Pid internal variable is set to the process id of the client process
|
||
(required by the interrupt service routine) and the SoundChan.OpenfreChan is set to indicate the channel has
|
||
been opened (as required by the hold, resume and remove vectors).
|
||
|
||
|
||
The Strategy Function |
|
||
|
||
|
||
This device driver supports three functions: playing sound, cancelling he playing and closing the
|
||
channel. This implementation chose to use the IoFuncWrite (P_FWRITE) service to mean play sound, the
|
||
|
||
|
||
IoFunecCancel (P_FCANCEL) service to cancel playing and the loFuncClose (P_FCLOSE) service to clase the
|
||
channel.
|
||
|
||
|
||
The playing of a sound is achieved by writing the user specified note at the required volume to| the sound
|
||
generation chip. The FRC interrupt service routine is the routine that actually writes the data to the sound
|
||
chip. As it is an interrupt service routine, it cannot gain addressability to its client data space. Thus the
|
||
sound data to be played must be copied into the device driver space. This has a side effect that|the
|
||
maximum number of notes that can be played (by this driver) is limited by the size of the internal buffer
|
||
as defined by the driver. The buffer can be made any size although in the majority of cases a larger buffer
|
||
will most probably waste space. |
|
||
|
||
|
||
The device driver could be written to handle arbitrarily long sequences of notes. When the interrupt
|
||
service routine reaches a ‘low water mark' of notes to play, it can signal the wait handler routine which
|
||
|
||
|
||
we yee gs eee a |
|
||
|
||
|
||
100 |
|
||
|
||
|
||
&
|
||
|
||
|
||
wis." "8" EXAMPLE DEVICE DRIVERS
|
||
|
||
|
||
will eventually run to copy more data from the client process space into the internal buffer. This is;.‘>~
|
||
however, a fairly complex task. niece Le et Ge: f ne
|
||
|
||
|
||
When all the notes in the device driver's antecnal buffer iiave een played; the: interrupt service routine:
|
||
will call the JoSignalByPidNoReSched system service to signal t the. client Process that the playing of sound
|
||
|
||
|
||
1: ¥ i: rs Per ee
|
||
has completed: er a oe
|
||
om vi Jf oe ad hoes . mes : St eet ‘ i a cee : vty - oe ag f: ety
|
||
3 be Nee Bl Poe ges hoa. ho eM
|
||
|
||
|
||
The wait handler function will pick up the fact that the interrupt service routin has finished (from the
|
||
SoundChan.WriteStat variable) and report the completion status to the client; the:wait handler runs,in the
|
||
context of the client process and can thus write back the completion status word. oe
|
||
|
||
|
||
ag See ap ve the Lome, oy semen of
|
||
AY “a s nek ae dass Meese 7 waa : ak, wre Aree ey pate Se i Oreee Ber) 2 dat
|
||
|
||
|
||
The loFuncCancel service. simply petee any ‘outstanding write request by: mopoing any.1 more FRC:: :.«:
|
||
interrupts, stopping the’ sound generation, switching off the hardware.and‘then:completing. the cae es
|
||
request with:the €_FILE_CANCEL bases eines status. Sst wait: handler is: also eirpiceay anda seta? hecaam
|
||
performance reasons. Se a, tT ae Sa, UME Oa
|
||
|
||
|
||
The loFuncClose' request will cancel any outstanding write, cancel. the. eniion vars and ewaas the sound
|
||
and FRC resources back to the opoaims system. OT SR ERT Oath EME Sal ed te cthts
|
||
|
||
|
||
¥
|
||
Y ' aa as ens Oe Std ne. ta x oem “ose iS Se 2) Fad ay 1 Oe ed
|
||
: ae . Cr) 7 eed ii hee. ~ oj ! Lira cD | are a 2° ty in oe be ORE Ke ae ee eee ’ 4 ON, rm a Wier a
|
||
s *4 e re hie oe ~
|
||
a ae a me axa ey , i aN the gay ot, er wee : v Peomras 3 + ah atone ae 2 Ae \ Wee ve
|
||
fe! RE eae teat ves tan zr Ts Pes, 8 ; oo ae . a i ae dees vhs ad
|
||
|
||
|
||
The Wait Handler Function
|
||
|
||
|
||
This function should check whether all the notes have been played in which case it has completed the ~-
|
||
users request. |
|
||
|
||
|
||
’ 4 “ ® et . s vies * i” ae : a. 8 a
|
||
|
||
tos & art ’ 8 . ‘oN Lite Rane rad ee _o™ Ls Cons bs Oe po § iw,
|
||
ee ¥ ‘
|
||
|
||
' - . + tiome 8 oy! pom
|
||
|
||
‘ fa ; = As fjom a ni mare % rit 2 Le Dts org ite q 2 D ethene he Note tet
|
||
|
||
a t . : toy — : : Set YE L Beating J vhoot Seeds ies Riots Sa ea eit
|
||
|
||
yay oo: ty vet Dag Op og! : ooo te che aleg wpe ite ars oki Lae hye a : : » *y ‘ a : ren ty
|
||
|
||
ae ee me . SONG ee BO cee im ce Gad ee TR nara a] 6 a Pk
|
||
|
||
Ror eee a8 3 as y aect go wigs ty ope vay s. ro oe GE 3
|
||
|
||
a. Sa i es eae 5 ed . : Boe hore a . THel abet dee? F
|
||
|
||
|
||
: ‘ Aves nee Ne AAR Gr Lat a . api vor: a + ary ae 4 rake)
|
||
Oo, sic ot soivedeue. Bui lp te ae OO ted A at rept dine as jee Dyes at
|
||
‘ . ie
|
||
|
||
|
||
pee a er a Po Sah TR OV ire ate auwan cid eg: aaah los Gey og 8 $id nSEATS
|
||
|
||
|
||
bi as
|
||
. ay : a a4 p oon « cr’ . py os es eo #4 ‘ ona owe Saget a be at og rs Z oe 4
|
||
, oe te Tey . go | A came a elie + r : * a ate _ 2 “t wa i€9 i er oes EN hw aa : Lis “y rit AGH foot. a } eRe ste ie ae
|
||
|
||
|
||
SEP va GELS OSH
|
||
|
||
|
||
‘ eR: yo we here pan b spa: i ne 3 ee at <
|
||
. ee : ans an wee an , 25 43 - % a
|
||
s : ured a ae eee A oe tees aes as) ea é thks e ek Bu 3 tt ay ers ad 3 BRAY hae rt | alt i) ae orey 7 LE wate
|
||
wa d
|
||
- : x
|
||
' . wa ; mo peck Aaya aay ae gt ee gee
|
||
ae. gage ai . i" a, ee ! at . . in ae fom ay Cr led a ey oe ‘ ay ‘ TER
|
||
ne Was ae See Se ee wats Boe ee EE Ge te ee a ar ia as WO s 3 toe ue sad igs | eer ass:
|
||
: age : : - ; | ee
|
||
: 3 od Beg | 1 eed eae : Lf ng ri Roni SP, Sa Ge RE ENE eS are wee aaa a heros Ws
|
||
te 2 Ee ee Ee Ge Ee Oy, Ps hg i ed ase eae ene ee
|
||
: : : :
|
||
Fs 5 eed . o , esti a toca jest
|
||
et ars ae mR) Ok ae a ‘ cer 0 yey ° ef we yh me ae ean sia S4
|
||
sean ron . “ “i ra) Ms ee « epee : hits re ” a , o oe lB aye 3 “ a4 ee ay
|
||
: . me
|
||
oe ie : 2 SRD oS gee : oe Ta eee a can acetate ar oe. tLe a. mi
|
||
o. : ee $ , ead | a . ee tee! ape y S34 ee ea es she » oat ft CRS ae ae ay ix war zg rAd. caahe oe ade hay a 6
|
||
"oe & eae awe ‘* hee é ée ‘
|
||
: 5 : : f : ; sex
|
||
aa . : Eyre capes ac ar * sont Oey ee ee De OM Mees 233 Be me oY oeey
|
||
* : : 2 o fee Oe tos, aot BS ton fae : t gue I. Cae ;
|
||
; Dog tele AU USI « aE OS Bee RSE OM ee as tO ROO EE UES PU ad-
|
||
' . .
|
||
a ae €. nee 2 * » o.8 see ae re wh tote x f t gt
|
||
5 ra : a4 meas oe oa % a ase 3 rit a fe
|
||
Oy et oa a a as 2th oe me Le dio ay. ve ahs jute dt . ae fo fy 7% = mh ts ai
|
||
: : “ 14
|
||
. “ : Does : Se te a oa sy ‘ Ri ey TES a vl Medal: fhe
|
||
PPE as Sahat se 1 te We I wo ees oe St eee “ to oe ee Seer | seat dda ok i
|
||
Py q
|
||
. es. : : ~~ op Wa ene A a8 arts . ges sh
|
||
a tate Buby, ’ Aeon ey 4 a . ee . 1 8. we: : ‘ “3 ; £ a sabe Sate pL se a: ; ! WSS tf: & 4
|
||
. Cae ws og - : fe
|
||
|
||
|
||
Bats bee ae
|
||
|
||
|
||
; ; : » ne | ‘ Sa y
|
||
|
||
* . a . Bes? ae # Oar) . Ne re Z 4 Ad ton We v, agtey rate eg a] Pr a a ’ :
|
||
} : Cs y af ‘ " r a} ‘ahs ‘ 7 = : : t, : : we * of Pa Terodbe §. 4@e ee ia oe” Ast ra Ey ae ™ if r Lae ra Bangle, ve ad
|
||
|
||
Ul ee aoe ae foe en a gi aa et ’ 0 e
|
||
|
||
|
||
r : é : “ : sg A wees rr ‘ Sat Ce 4 a PRIM af 50 Ot oa 5
|
||
aw ‘ « eae Be eget “oe ‘ bate ot ar 4ge. ee yea Yat ea at mo Weed a x1 akeee. ; “os 2) }
|
||
oe rae eo | =e woo gee at, 3" ees Bg OE ee re Li fe Bees tits ate TALE os < aA baad res
|
||
, t foo ‘ 2 ‘ ,
|
||
|
||
7 : a See . o s ~ on — ao Cate
|
||
|
||
ogi eg Shred tee . ae -. 8 a fh . . yt 4 ote: vy nk te. : : ae 4 ace
|
||
|
||
a} Ia ee. eee ae hee wR tA GF ; z a Lee see to et cttes s
|
||
4. Set debe) —_
|
||
|
||
sem a ar 4 2
|
||
|
||
ers 4 . ca t a hes Pid i tw she 7 Y au
|
||
|
||
. . « + qeaye
|
||
: . ' 5 ‘ ;
|
||
<4 : ' ett igs ignites eg ate! ee 2 nm i my tee ne” ae 7 ‘ eyrtiay a 2 e
|
||
mee ey ap? See : ‘ re mre ca ene fs eM a Dee en Ms ee eee ilar) Bee hee
|
||
wee Oe : eo o : “a ie
|
||
6 ope ere ba
|
||
: : ag cugy teas ts ey te yor resets oS rep errs, ae § aa ag Nee eae
|
||
tem 7 Se oe ’ Ee ee ee Ve ‘ ‘i J Sy. sh. oy aah 5 ay att ' ae e shea ee . n% On Ped q ° iC. esa: *
|
||
zs RVD ee Re ~ rod
|
||
z s on te -
|
||
tees : seed ns yee. és seh iis se tee ; be SE Es Tf - Be “gga Vee tsi
|
||
sete a Sev at we 8 Sa BG Me Boss Mo hs i ree ay
|
||
~ set 58 ae sot we ‘
|
||
|
||
|
||
SOOPER.
|
||
|
||
|
||
eee,
|
||
°} . we t . Bfe . . ” + rat Ls ontay'g 4
|
||
ei Pes ec tym . Pee eR MES See CN DE ? Cc y aa 61% Saeed e
|
||
eee Re Se OF See ee a ae Neat cme Ca ela Pe wee BER orgy FAB ; =
|
||
te er) af ie . ‘© ‘5
|
||
: je ; : oa rr aa cr rr vite je FTC, 73
|
||
* xt phe toy oagk tyre Sg tet oe er aa "hee : Sige ee Soe
|
||
. gos ‘, eee TF og tase oP ey SR Ba Pha See iat Pk wedi. wee, a so a
|
||
: ba z B ?
|
||
° : . . ahh: Sh . “4 f - an
|
||
; i ae oe aes Roe Nan VTE AY Ey PM Se : are kd pe Gly eon oe oe, ace an in A.
|
||
. eS Stee ea Vee ae ee . SOM Ale eT Nei aT Sa puter ies je hos ve i be Dan
|
||
4 i . ; " 5 4 : Se ree wi bees ‘ i : Pee. oy
|
||
7 “¢ ea oe opagr ele eh ovree th, om tyra ee ig Poe be ee
|
||
age Pe oe f we geate had LRT cage She er Re ed i : 4 % Petal
|
||
Ae ; .
|
||
ce aye ~ \o™ are
|
||
ws H te - vy ey . x Ves. art 3? « : hat; : at aN lee
|
||
- Noa + dle. es =
|
||
|
||
|
||
. hae fool
|
||
a bn FL a
|
||
: , rey : rye ers Va ae ey i gat wail vt rapa “nk £
|
||
va Pee
|
||
ihe ~. ‘ CE Md vise as ees a ie
|
||
pee} : mat i seky ag h Ls) ey ee
|
||
«
|
||
|
||
|
||
¢ 201
|
||
|
||
|
||
- base
|
||
a is ii RSS ~~ we te ba
|
||
BE OR eS
|
||
|
||
|
||
“. && DS, Bo. Sala aoe:
|
||
»
|
||
593 cae “yee Tigi} . ars
|
||
oe L wrt ar Lek
|
||
|
||
|
||
Ru
|
||
oe #fT : Ji: Y oe aes ee ar he a ° : .
|
||
ne) 4 - a ct ATES f J see y t 4 feed? fale. Bs 5 vw hoy
|
||
Me i 2 ae ae Bs Bite
|
||
Be aay oe seers ae aery : ate
|
||
rou a : . ott ie
|
||
cs ‘i eomatetehs ok. at?
|
||
‘
|
||
aie Ryser oe ices
|
||
a Nas? ye, rae Pees wh ® epee
|
||
|
||
|
||
a
|
||
obweBe CS
|
||
|
||
|
||
»
|
||
ty. syne
|
||
|
||
|
||
RY ve
|
||
. nf
|
||
|
||
|
||
at:
|
||
|
||
|
||
got tag
|
||
ay. cm caine:
|
||
~ " é. 74 .
|
||
1 fe vr - 22,2 wet * G a €eo4
|
||
hee we i? ates wets bade we, . $a
|
||
. S's
|
||
we moe yetie.
|
||
Valk wa Je a
|
||
' . ”
|
||
° gis } ‘ te ae ir bar » -
|
||
or Stam Alt ite ve 5s i wat, ne.) Eat 3
|
||
"tr : } 2 ar eee 7 > . wh ‘ ‘ ce
|
||
3 Pan Py Se ? ao oe. ae 4, ey
|
||
a Rise 8 ges Ba. ahd i. y a€ +a “
|
||
* @
|
||
Lome go 2 - bd
|
||
: i «age aye ren * os ge ean Teo
|
||
ar ay os. te NE ete z 7 at, ‘
|
||
aal 4 eth Deg 5 toe f ue" Po mr aN ae 4 SEPP LES
|
||
7 pe ae a oe a
|
||
wae ee ® a we owen f ¥é
|
||
Par rae cae oe a oe
|
||
BREAN 4 mPa,
|
||
. ite 3
|
||
© 4 wet Lawl” eo Na oat
|
||
Pr a ces . . oe fay 300 on is fe t; i
|
||
' ae wee . ay PERN oF a ce 4g.” ’ "es oae Ft es, 2 et ee
|
||
: wd, re , kt. roa ce vy bea Aa vee OM TAD COAL aoe + hd ne Po a aa 3 Bd we “ wa hte 7 + Bali aes
|
||
?
|
||
, aR he
|
||
. Corey ee Y Lak ve
|
||
1 cet s A . eee Qe ‘
|
||
rah i! z : 2 My * ‘ , Os eg : LFS tye Set meee oe
|
||
a Niele yes er 4 . ; Ee ae ee Oe: Pe
|
||
7 ‘ ton te i,
|
||
me fe ~ % Z a “ . ‘i *: be o
|
||
‘. ; : tes pte pee — Wee hatte air sae eb
|
||
abel Sate: . Pi eee age, oe Pr a 3 “4 a Sa * Sati rf ree Spire ee
|
||
are AS? vaey: Pe ro ofee ee ee st a ee eee ee ;
|
||
j . a . ‘ . : yok vee : “f * a . che
|
||
Syr8 0 So ads ee Bf, ale eee at dea ye ees rer ¢ ceca fe wifte th St
|
||
rit verhe ger "een > a oa ei, ge . 4 o oe .
|
||
. . 2 i : Pow 4% oF : weit N, é “art
|
||
a . 7
|
||
Cat pee ag " : i f :
|
||
: \ nae a @ -Pyer sew or es Lm re . é .
|
||
Oy 5 Adie weitad £ ie 3 MOB. ly TTES ree VAS by : wet ae re
|
||
aaa . 5
|
||
Sabre Feb 4 ws footie , t wos Pa : :
|
||
», i ee 27 Cb bn Y ek ¢ Yam hota ee oe wa ct ‘ ‘ae er
|
||
G te we bs. Ses : Hy : ee “soe 7 OG BMS ¢. . “ Pa aaee, tar ee, a8 ay pea ied i we 7 & vege
|
||
£ ae ae ee ‘ thom lepdtt We RN tks wa iB 3 wet oe) ale vedas daARd a OG! ag a eae tele the Bacnies LA. t we
|
||
+e Sip © wey 4 a ee x Ns Ee ’ : ‘ eof. ' : es :
|
||
30) SRLS Ketek. eg a a SO Shes oe Aime meh se. ee Be. es eC, Ae |
|
||
. oe se tee F. aa ad 4 res YS | saeod wee Roe, A is : re “y Ativite ge 3, ee ee
|
||
. sf
|
||
¥ erage yo. *, td
|
||
4 Bo Mee Oe A
|
||
' 48% mm. . tee, i rere : as
|
||
bog ; "p tie 4 SS ‘ .
|
||
ar eae SR te Pa reer bo a rT a ry
|
||
‘ . .
|
||
+ Lay ue a: i wen aS ' ’ , cfGa. 4% ' os
|
||
oe are Vanes ne ALOR PURO FR oo :
|
||
ae ; ; ot
|
||
: SEA ET Ee 2 £FF7- ;
|
||
x A Ee be ode a a3 ro
|
||
-¢ aaa 7 > 7 . ‘ +
|
||
honey Syee fo of amt ay ?
|
||
A eos oo. Stdad oc: 7 APE gs ' , ee ae
|
||
my . 7 ei ‘ ’ 1 ee ~&
|
||
cag hs ’ soe
|
||
4 a 2 er ae a ee : . a ‘ .
|
||
rae we ns at a fey 7 os ae: r ee Bite ? 2 be b eerie yng . + om shat 4:
|
||
oy ri . . fate tw 04 heh
|
||
.
|
||
te
|
||
weak oe .
|
||
oF wos t
|
||
tl en me = wee
|
||
0 el Sl SET LE aie, ag eerie + . Fates nPrmene tC OOS 8 SoA ms "58? amar 8 Aw br! epee ies aw NOW de ele th Prd Sherk EU Om terete sen ou a oe oe eo
|
||
|
||
|
||
TENE RED Reape, JOT HEUER Be Mee 6 -
|
||
|
||
|
||
CHAPTER 9
|
||
|
||
|
||
PCMCIA CARDS AND SSDs
|
||
|
||
|
||
Certain manufacturers of hand-held computers have recently been vigorously promoting the so-called
|
||
PCMCIA standard for plug-in cards for portable computers. The idea is that PCMCIA cards that can
|
||
plug into one hand-held computer ought to be able to plug just as easily into another.
|
||
|
||
|
||
However, the SSDs used in SIBO computers do not conform to this standard. This fact may be seen as a
|
||
potential problem - possibly as a disincentive against taking the time to learn how to program within the
|
||
Sibosdk system. More precisely, it may be seen as a reason why the SIBO range of computers might
|
||
enjoy but a limited lifetime in the marketplace, before being eclipsed by other, PCMCIA-based portable
|
||
computers - in which case, studying the Sibosdk system in any detail would be a poor investment.
|
||
|
||
|
||
This chapter aims to answer these worries by dispelling the hype around PCMCIA, through documenting
|
||
some of the considerable benefits of SSDs as compared to PCMCIA cards.
|
||
|
||
|
||
Mobility and robustness
|
||
|
||
|
||
Serious doubts can be raised over the suitedness of PCMCIA cards to genuinely mobile computing. The
|
||
simple fact is that SSDs are much more robust and portable than PCMCIA cards.
|
||
|
||
|
||
In the first place, these doubts revolve around the fact that PCMCIA cards require no fewer than 68
|
||
independent connections to the main body of the computer. This is an enormously large number of
|
||
connections for hardware to protect, and contrasts vividly with the 6 connections of SSDs.
|
||
|
||
|
||
There are two aspects to this: mechanical and electrostatic. At the mechanical level, the 68 pin edge
|
||
connector of PCMCIA cards is inevitably vulnerable to pin failure with constant removal and insertion.
|
||
At the electrostatic level, the fact that there are only two data lines in the SSD Serial Protocol means that
|
||
each data line can be amply electrostatically protected in a way impossible for PCMCIA cards. The
|
||
PCMCIA parallel interface has many more data lines, increasing the potential for data corruption.
|
||
|
||
|
||
The very name "PCMCIA" betrays the origin of this proposed standard as an accessory to the basic "PC"
|
||
architecture. PCMCIA was fundamentally designed as a plug-in extension of the memory map of PCs; in
|
||
contrast, SSDs were designed with secure data storage, ruggedness, and high mobility as the foremost
|
||
priorities. (SSDs actually developed out of Psion's long experience with DataPacks on the Organiser
|
||
range, in which it became clear how vital it is to keep data transmission lines to a minimum.)
|
||
|
||
|
||
Size considerations
|
||
|
||
|
||
Another important point is the sheer physical size of the PCMCIA cards. Although slightly thinner than
|
||
SSDs, they have a much larger body area - famously, the same profile as that of a credit card.
|
||
|
||
|
||
For example, were HCs to be converted, hypothetically, to the PCMCIA standard, it would mean only
|
||
having one drive, instead of two as at present. There would be no room in a standard-sized HC for two
|
||
PCMCIA card slots. Yet practical experience demonstrates how crucial having two SSD drives is - one
|
||
SSD (possibly a one-time-programmable one) containing a program, and another containing data files.
|
||
|
||
|
||
In general, the greater body area of the PCMCIA card means that SSDs are suited to a wider range of
|
||
different application devices.
|
||
|
||
|
||
Different standards for different purposes
|
||
|
||
|
||
In proposing their standard, the originators of PCMCIA had various different goals in mind for what
|
||
PCMCIA cards could do. In retrospect, the standard seems appropriate only to some of these goals.
|
||
|
||
|
||
PCMCIA is at its most impressive as a standard for detachable plug-in extensions to PC RAM memory;
|
||
it is significantly less impressive as a standard for secure off-line data storage. This is where the SSD
|
||
format (in particular, the Psion Serial Protocol) wins out.
|
||
|
||
|
||
103
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
It seems more than likely that the Psion Serial Protocol will also become a de-facto industry standard,
|
||
|
||
alongside the PCMCIA standard. Just as various different computers, from a variety of manufacturers,
|
||
currently contain PCMCIA card slots, so too will SSDs become incorporated 1 in an ever wider range of
|
||
computers and computer peripherals. (But it should be bome in mind that there are already not one but
|
||
three different PCMCIA standards, whereas there is only one Psion Serial Protocol standard.)
|
||
|
||
|
||
To this end, Psion is actively supporting interested third parties, supplying relevant ASICs, more detailed
|
||
documentation (see the Hardware Reference manual in the first instance), and other practical assistance.
|
||
Contact Psion for more information about the SSD Hardware Development Kit.
|
||
|
||
|
||
|
|
||
Hot insertion : |
|
||
|
||
|
||
Compared to PCMCIA cards, SSDs offer another significant advantage | in “hot insertion". What this
|
||
means is that SSDs can in general be inserted or removed from a computer without that computer first
|
||
having to be powered down. (After all, PCMCIA cards plug directly into the bus of a PC or PC-clone.)
|
||
|
||
|
||
Now whilst this is not directly relevant to the case of the HC (which automatically switches off whenever
|
||
its rear cover is opened), it is highly relevant for other computers in the SIBO range - such as the laptop
|
||
MC and the ubiquitous Series3. It is also relevant for PCs with attached SSD drives.
|
||
|
||
|
||
More generally, support for hot insertion makes SSDs behave like ssaaiesl and logical extensions of the
|
||
floppy disks of a PC. An SSD can be removed from one computer and plugged into another just as
|
||
|
||
|
||
easily as a floppy disk can; there is no need to power the computer down first.
|
||
|
||
|
||
| :
|
||
In order to achieve a similar result, PCMCIA cards need the addition of extra memory buffers, both in
|
||
|
||
|
||
the card and in the reading device - adding to the cost and design complexity of both.
|
||
|
||
|
||
Flash filing systems |
|
||
|
||
|
||
On the particular subject of Flash PCMCIA cards, whilst it may be eas for applications to read data
|
||
from such cards, it is much harder for them to write data back. This requires a sophisticated filing
|
||
|
||
system which is very different from the FAT (File Allocation Table) filing systems that work so well
|
||
with RAM memory.
|
||
|
||
|
||
At the time of writing, no full-featured Flash filing system exists for any PCMCIA card, and there seems
|
||
little prospect of one being produced in the near future. This absence contrasts sharply with the mature
|
||
SSD Flash filing system that is contained within Epoc.
|
||
|
||
|
||
Flash SSDs have been shipping since 1989, and Psion is now widely gnised as the world's leading
|
||
authority in the use of Flash memory.
|
||
|
||
|
||
Cost considerations
|
||
|
||
|
||
In view of these problems facing PCMCIA cards, it is hardly surprising that more SSDs are being
|
||
produced than cards conforming to PCMCIA. As a result, SSDs are well on the way (at the time of
|
||
writing) to being significantly cheaper. |
|
||
|
||
|
||
Another factor favouring SSDs being cheaper than PCMCIA cards is the simpler nature of their basic
|
||
|
||
|
||
construction. Inevitably, it is mechanically harder to manufacture a 68 | pin connector. Note that this
|
||
consideration is just as pertinent for the socket the memory card plugs into, as for the memory card itself.
|
||
Architectural openness
|
||
|
||
|
||
Possibly the most significant point of all still remains to be made. Namely, the SSD interface makes no
|
||
presumption on the architecture of the system that is driving it - unlike PCMCIA which is designed for
|
||
PC-hardware compatible systems. This gives the ee of the system considerably greater freedom:
|
||
SSDs are truly independent of the host system.
|
||
|
||
|
||
To re-emphasise: SSDs do not presuppose the Epoc or Sibosdk architectures in any way. The interface to
|
||
SSDs is actually extremely flexible, and can be addressed:
|
||
|
||
|
||
= via hardware, using an ASIC-2 card, or
|
||
=" via software, using just two microprocessor i/o lines.
|
||
Finally, two further points, each emphasising the greater flexibility ein by SSDs to system designers:
|
||
|
||
|
||
= at the level of engineering layout, SSDs can be located significantly further away from the main
|
||
processor than PCMCIA cards (by virtue of the different interfaces)
|
||
|
||
|
||
= there is no intrinsic design constraint to the address limit of . providing potentially
|
||
|
||
|
||
unlimited capacity.
|
||
|
||
|
||
7 7 _
|
||
|
||
|