10936 lines
359 KiB
Plaintext
Executable File
10936 lines
359 KiB
Plaintext
Executable File
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
Version 2.10
|
||
|
||
|
||
February 3, 1995
|
||
|
||
|
||
(C) Copyright Psion PLC 1990-95
|
||
|
||
|
||
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,
|
||
Psion Series 3a and Psion Workabout are trademarks of Psion PLC.
|
||
|
||
|
||
TopSpeed is a registered trademark of Clarion Software Corporation. IBM, 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
|
||
1. Melink, (Moeprint:and Sink 2. :00..<550..hccsie belive kiileseccoccecccceetasabecsaseteasseccecitverss 1
|
||
MIGIINK OX6 iis fe Serie oles tieaencoweaereensdovesasee cuettes Sea eete deemed oma cea eee ee Tee vers 1
|
||
Commands provided in MCLINK............:sscsecscsesccscscecenscceceveceseseentceceses 1
|
||
MCLINK and single floppy disk drive PCS ..............cccsccececcuscecscscuceeesens 2
|
||
Exiting the MCLINK Program .......csscscscsscsscccecscsececnsssesccerscuteccssonesencees 2
|
||
Display the version Of MCLINK ..............ccceccsesenercoscecetecanseeceaevsesacenense 2
|
||
MCLINK file-handling COMMAMAS ..............cecrerecsececscsesecsccecsseesscecscscvesvevecs 2
|
||
Rules: On TEMaMES iid occce tes cecdacsecnceadecceackeeet neat he ettees aut eeia 2
|
||
DIR feos cnc cedvevsevesvacese dete ci seaccade ide tacisesnde hstereee ete ee Bac sa ees ee eens 3
|
||
CON sc owctsciecevesictaen ste ceeds cove cu dvccedh ceca teas scale ccc Bh ce eee oe eed eens 3
|
||
RENAME cite crave vesta odes chon te sttecaccedcusstea cee ceeattvet tu ovteareie tee aaes wives mceeied ale 4
|
||
DEC ETE cc ctaccescccettsntcccit ee hcteteatoctea ts meere tee Merete te satin Marta eer oriaee 4
|
||
IMIR DIR iirc cette eteeearccccccc tere fed eens cae Ee ne Pa ee ee a 4,
|
||
Changing MCLINK communications SettingS.............:eseccsscesssscseececeucsesessees 4
|
||
Options for the SET COMMANGA ...........ccecsccscscsscecscsecncosensaccseesseencuceeeecs 4
|
||
Serial port and Baud rate Options ..........ccscsesscecscoececsrseseveesucecesscucceseees 5
|
||
Modem ptions oo. sicossisvicsecccrcsavcbes Saecnaseg oe dteas elles viele siuee es ote seeviaas sues ieee: 5
|
||
Examples of the SET command
|
||
Advanced use of MCLINK wis. . eccccncsas St teeeee Mevacor oi ia ee eiea bs ade buedbecesess 5
|
||
Running programs remotely on the MC, HC or Series 3.............cscsseeeees 5
|
||
MCLINK batch: files .......scs00c00ePhdeeee cee eet Meee tia nd De eiee sect ehate la ceses ness 6
|
||
MCLINK command line processing.............cscecscsescscececsccsceccuteescnerscueess 6
|
||
Invoking MCLINK inside an MS-DOS batch file...............c.csceseceeeecevessess 6
|
||
MCLINK and «modems oiei.s cocci ivcesssrcen Petra ire cach eet oe eeees sdogecetes ade cdewtbeces Wickes 6
|
||
MCLINK as a PC file server via the phone SySteM.........cccsssccscesceeceseecees 7
|
||
MCLINK and modem Baud rates..............cscscscsescscecscsscveesececraseceusaceves 7
|
||
Link on the MC/HC as a requestor Via MOCEM...........csccccsceresrssucecencncece 7
|
||
Link and Modem Baud rates............cececscecscnessncacscecsvssceeseeseenssscucennsrves 8
|
||
Link/MCEINK: with! MNP. s s0020c0.00c00.aceteeescteds oe PRUE tovdalivecediocsss 8
|
||
Examples With :MOdGEMS: «...0<ccsevesevtarsdl code vevtueneadsvedevsedcaddcadadeaecaveveedaccsaceas 8
|
||
Using a Dacom QuadPlus MNP 5 compressing modem...........cessseerseeeees 8
|
||
Using an Amstrad SM2400 modem. ............cecscscssscocsecececeeescatececeucseves 8
|
||
Using a Dowty Quattro SB2422 000. eccccscscscecsccveeeecsceeseveecensecees 9
|
||
Using a WorldPort 1200 pocket Modem. ........sscecscrssstssscsevenccccasececeesens 9
|
||
An HC with a Psion Quad modem ..............cscecscscececsvevescsceceesevensaversens 9
|
||
An HC with the Amstrad SM2400 modem ............cccssscnscetscescesscccscsenes 9
|
||
MCBLIRT CXC 28 ieee ccs ccaee Dt viene tins cues desides eve dswaieeea tev Ueactne than sec voeseepeses@ betes velebecesns 9
|
||
Using: MCPRINT sscssccsiccsoeeeeptac cievtecbeves hes the cise do Sieb ave cedecasas deccw ys: 9
|
||
Exiting: MGRRINT csi. .ccslsevesssceececcnaeecs sect eeeestecee Sei vciesbseter atta 9
|
||
Printer configuration ON the MC ...........cccecesscesceescsceceestsceceecensesessenees 10
|
||
Printer configuration on the SerieS 3...........scecscesescececscsstereceeceneesceeceens 10
|
||
Parameters’. ivccs.scasavdtciSes wanes 2akeckcks eeeeee fae05 Jeni y wseee Fema tea Sea aee ete ose tae tee 10
|
||
THe. < prdev->: ParaMeters...cc.scicccescacesstensveesonsssaudievandedenaveskscesdoeecedeees 10
|
||
The: -C< POrt > PALAMECtEH,...ccceccccssceccecceeveveeasevesdsceevvenscoeedeuse vovevdauvecss 10
|
||
The -t<tiMeOut> Parametel...........cccescecscescescencesccccereccesescensecesesssaues 11
|
||
TGQ" Parameter’. siiccecvicasscuestetuis csana tienes oe vadee does Gen le cane sas boscuenseeemeesete 11
|
||
SINK LOX is sisesseeceds canes esis tice wus sre ccewesvaeauees vend as daly cae''ss swaaddarev cateue Lvaue ooeoeobeeane 11
|
||
2 “Resource Fil@s ciciacsssccsccvceses canes ce cede serctvcloseensccencsiclescSuscusevee cadet calaeenesgeioes oactee 13
|
||
IMEROGUCTION SG vite A tecicic crews ies Ae ec ec po a danse eae seh ed edean ope aad eos sae gsree eee eenels 13
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
Format of Sibo resource fileS............csesceccecescescecscescccseseecescsesnentseressseceens 15
|
||
WhestormatOLAsCwtilOS sc. cece ccset cores roses cbcece x coinc covuiateruscus dead ca ute tos eecsae 15
|
||
Some strategies for reading .rsc fil€S.............csccecscseecscececetsceccusesvenceece 15
|
||
Example of reading resource files directly..............csccsssececscscevesesscvsscecs 16
|
||
|
||
Using the rscfile class im OliD...........cccccccecececsscececetcecsecscnsoecteecaccecessececenes 16
|
||
Basic services of the rscfile ClaSS.............cscscsccsteeceececscsssccecceusceteancaves 16
|
||
Reading compressed resource files with the rscfile class ...........cecssesecees 17
|
||
InitialiSing: aN rSCTIIC OD/SCT... cicc2s. cs cess cen dtecsis sae seoceunu Vadencstecgees baaGeessee ee’ 17
|
||
Which header files are ME@dEd...............ceccesecscnscnccececscecscersucscaseeaseures 18
|
||
Run-time errors with the rscfile ClasS.............ccccscscscsesescesececevecseecarecess 18
|
||
Possible errors during initialisation ..............ccccscesecesecseovevscacersnseseseenees 18
|
||
Eprorssduring tS readcOrgs ReAGNDUP <3, foci sicnesset eerie rene ctoststtaey aeacdesscss 18
|
||
How rscfile errors are reported ..............cccscecsecscneceeesescececscecscseucssecese 19
|
||
Dealing with errors in rs_read or rS_read_DUF........ccssceeeeeceesensceesceecescees 19
|
||
|
||
Advice on where to locate resource files ............csccsseeceececsescsscnccccsacceseeces 21
|
||
Mono-lingual applications ........sccsssscscscsvssctsscscascsrencetssaccsescsececsccerecss 21
|
||
Multi-lingual applications ..............cccececscecececenecscecatcuceccetevscacererseueecuss 21
|
||
Copying! Of applications + sicielisccaccis vies disascacaveciaeacs oe dedasdacvazathasstee evens 22
|
||
|
||
General comments on multi-lingual applications............ccececesesvercecseccesvcscens 22
|
||
The basic principle of independence of code from resource file .............. 22
|
||
Careful design of screen layout ...........cccecscececcscsecsceecscecsteveseaventsatececs 23
|
||
Codesize’problemsitisv.... 203.00 ne a Ee Re ee 23
|
||
MAPYINGRKCYDOSrdS sic sieisevescdscdeccestca consee cere ot oa tee a soascieteleel ber ee tecct ease 23
|
||
CONCIUSIONS 2: cccacedectsssccadeccutaciscaseehestet tase atte ec estoe rte conten merit rene cake 23
|
||
|
||
Creating .rsc files USING FCOMP.EXE..........scscececscecececscneersccceescseveseseetensesses 23
|
||
Generated s1SG- TIES « «cisco. sive necdendocseeiescccecssanedsostacesucesaceeseouessvevessdenes 24
|
||
The syntax of the rcoMp COMMANGA............sscscscecseeeceasccovarcvevscesccssseses 24
|
||
Include files within a reSOUFCe SCIIPt ........ccccccecsecseecncscecceascoeeecscesessees 25
|
||
Conditional compilation in resource fileS ............csscsececseecssevcesssensesoeenes 25
|
||
|
||
Contents Of <(SS: TICS 5. oc ccsacie.cosvcdaccvtedest vee es cane sceeecedcus vans ise sagcesasieaadassaves 25
|
||
Declaring STRUCT wciccccvesdecessccccvecsenseuscivevescscevs secs cevavivesdecsevencseveds. 26
|
||
Possible member types in STRUCTS..............ccececscsecscecentsecrcessecncaseeeees 26
|
||
Declaring?RESOURGES 7h 5s. PRA rete its wnyetacevedes sescets cenecd eves 27
|
||
Declaring the values Of SUD-STRUCTS...........cccsscescetsescteseeseecsenssecnscees 27
|
||
Leading byte and word length values...............:scecsececesesterevescsceecseasaces 28
|
||
Arrays within resource files ..............ccccsacsceceserecsececensctccscescssececsasavecs 29
|
||
Creating SYSTEM resource files ..............sccccecsccecsscsceseeascnccececesuscseeees 30
|
||
|
||
SaeWV DR BMINtinG) .22ci00c60 cs 5 cancccsecctossceccscviceasseeteacsscechotaberduscscuscadeevaccesoeteesraetaes es 31
|
||
|
||
INTRODUCTION oi. vols edeis oa cases sodceun casts au tene trams taal oue tes aonon tet en ees based wets aseees cs 31
|
||
Creating: . WO TIES 65s catccucces i orek cond ss eee cree oe eed Saag OE eae et oats 31
|
||
The WDR printing environment variables.............scceccscscscseescesssenceeesenns 32
|
||
A note on reading environment variables ...........cscscececcevcecscsesceureceeeeees 32
|
||
|
||
Overview of the contents of a .wdr file...........cccccsccsceececescsenceetecscsscseeses 32
|
||
Deciphering general. wr ...........cscscscscsvesccececencsesceesceecseterssensscessaseceucs 33
|
||
The: Header PeSOUrCe co .sc5is cust eecve covcews Does MRT Weve vote da bee ce valved Mielvcacsoess 33
|
||
ThE COMMANAS FESOUICE........ccccsessscccnccestncenvecsossacecesceseecececeesssussensese 34
|
||
Model resources v2: 2s; sscctteess secs cecuaseadsecte ates sswsveceusets vas ceaedgittieeadevtas scees 34
|
||
TY¥PCTACEsFESOULCES so: else ci ssc vedcceseetucescascatnast certeee holeeiebes Tema acti helacns 35
|
||
TRANSISTES [ESOULCES 2505. <cscesicecevazencvcadacn olecntenseskecuaued tec ctacdwcesteaetensbes 35
|
||
Summary of resource types in a .wdr fil€..............cecceecececscececeeesecssesees 35
|
||
|
||
More details on the contents of .wdr fileS .............ccscscecscscncececececscscnesceeees 36
|
||
Possible: Wdr=flaQs .22..cccsetc.ccce coi leceactededacesvsrecstevancaesasvandenusnbi ceed vedvets 36
|
||
The notion of "printer models” ...............ceeeceecseneceeeeecerecesersseeseeceasesaes 36
|
||
Overview of the different CoOMMANA SHIriNGS...........cecscecerecscerscecvessvescess 36
|
||
Special characters in ComMMand StringS .............cccecsececsecesscnsscsceeererecens 37
|
||
The MOVE RIGHT Commands............ccccsscscsssseesssereccersvcseeesesecesenees 37
|
||
PRiMterURitSis. <a. esSeescend ic cvessse bites iacesb vee sdadesdsteaegeeeedseteadaueswerss ablecusos 37
|
||
Possible; moOdel=tlags yi ic. cis c.cciecccacs coaticaec cnc sts esenvees weores spaitgaestonctenscicess 38
|
||
Typefaces ANd TOMS os. eas ececcecve ce tacden¥esceses’ss4esws bee bl bedesd cesuw es caaseesoayers 38
|
||
Ty petaceiMuUmbers c.etiv..iscadss swacen se oesdees coeds ceatwertalSveves lewcvvegscasdensoness 38
|
||
|
||
|
||
CONTENTS
|
||
|
||
|
||
Possible typeface-flags ...........ccceressonscersescssecetsecscecesereceversessssencarsacs 39
|
||
Heights. Of fonts ss sre occ iccsheoccadowyn acces canes seeteateucs oateec beuodinee ek tkedalvaane 39
|
||
Widths of characters in fonts............ccccscsccecsscecscccuecescuesscceseveseusassenees 39
|
||
Creating .wdr files Using WdtraNn.exe .........ceccsecsscoersceecesaececccescesevsscsssesees 40
|
||
Contents Of. Wd sfiles ic ciccses.ctockeocecsscss cs ath eae eae SP, 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.................0.. 42
|
||
Allowed typeface NUMDETS .............ccsccsecsccestseceseecesuccececaveeccesssaesonseess 43
|
||
|
||
4. (DBR eS oic sie sc citisc ci conn ceed sedi cesecatcsics coy oddeceda ve vedas seateneatseate seteee tae e ee cca ee Rein beke 45
|
||
IMTFOGUGTION ccs cat sccossvcrdesgenedsvetscn cecetercneagetvetessed csiansecusesecisuambecasecurisncases 45
|
||
Basic structure of DBF fileS....c..05.cccesedccvascesvevsvecsabsd css ees bettie Peres ccawee 45
|
||
The: standard: header sc.....sssscie secswewe clic egessacen tacchtes paeeETs Mac et code mt ese Veeees 46
|
||
The, extended ‘headericcsschisccccssstecevvagiveasacact ewes veceveetttbeweel thee esuvdecesan 46
|
||
The field information reCOrd...........ccscscsscetecsscuseesscvcscecseasssoesessesenscncnss 46
|
||
Thesformat- ofvall reCords si: csecsccuscnesevdbecesedv ovectveeeseeous coleman sso lineven 47
|
||
Deletedirecords:osicc. ans. oscis ecco eeecunn coaccu dv acee seh sevesttee seh ctecn Ae at vedas 47
|
||
Descriptive reCOrdS «05... ssieccecacuesdueeviseanetsseatesssoocsoseescieccceciececesueeeeans 48
|
||
MoresOn: type: 1 *feCOrdS). iii. ists icvecssecsewicecesvsesvececersicseisusadadvevesisasctoces 48
|
||
The Series 3 Database .............cccccecsscscaccscsseueccetncessccsesceccessecseneesensercens 48
|
||
Field information (type 2) reCOrd ........cccecessscevscecsceesececessesecacecscesrceences 48
|
||
Extended Meader oi. ceic.sccesevsssccesavevescscasdeuciiades oda vavcdesbexeeinensevduscvasvedws 49
|
||
Descriptive: (type+3): record scccsvecsteceestacetereveeie os eee eeeete Tee 49
|
||
Flags options for the Series 3 Database ...............cecscscssevstcecececscceeeceees 50
|
||
Flags options for the Series 3a Database...............ccccecsccesccecscecesavcecsecs 50
|
||
TYPO AV TSCOPdS i 2.30556 odsisesietvaveve vcr ocestiocvedyvevedeesteseueesss Si0s ces uiwdivewesscdes 50
|
||
Continuation SUD-fieldS ..........ccccsssscnscecsccecstencsssscecesscscecvcessestscesseeeeses 51
|
||
The: Series: S!Agenda.c..c.0cb seven cte cA etek clots essen Chav aes bea tn au bhetuoees 51
|
||
Field information: records: Sete. ce ne ST siactics ab koesues castes tisccceavescvevecs 51
|
||
Extended iNeaGer i csc.insccatevetectn eeter rete caches ctecasee cuss sianca Pe asteet erates cvasens 51
|
||
DOSCMIPTIVE FECOMG (oi sco. ea chil heeee aad tes cvceve cote coacue od eed a beeas ck oen eb tei uae 51
|
||
TYPO PTA ECOLdS 5 cs az. cece dan Seesaw svocd vcs ccte Rete a eee See ee aks ee EE an eed 52
|
||
Calculating with AlarmTime...........:.:sccsscescescoscercnesscesscsuseccssncessessesacs 52
|
||
The text Of AN APPOINTMENL ...........cscecececcausceeccrensctscuceuccscecceseccecensaees 53
|
||
TODO ATEMS 2 65.0.05650 cP MEA, etic eee el sk Bed satan inedouss 53
|
||
REPEAL ITEMS, ciiecescensvssenees evades scscsuasdesesdcsesaaarencessvuucacauasegaceen abe monneatede 53
|
||
|
||
5 Series 3a Agenda File Format .............:cscssscocssccecestontceceessscesecnssescccescecescussecees 55
|
||
Basic structure of Agenda files ............cscsccecsccecsscecesacccescacsavecevessercetscsensss 55
|
||
Phe sStandard: NEAdSr osc ccs.co.csccenncseoteetesseaescacwacseracdouvestiecacnceesseacene 55
|
||
The extended header ........csssccscscsscstescscerssenecscatacceecessanceeossccsacesesenace 55
|
||
EMG! Gata reCOrds si. 3 iccscsvoil cabataveseyevoneas eicouss dacs ediewe Concnsas sane bowstncdesets 55
|
||
RECOrd TY PSiss.cc sacs casusnieodencugeudads sven sueuedencnededesdvea cue cdstaucdies dened Mewscotteedys 56
|
||
Type 0.= deleted reCord 2. vccccesnciccecsccsceck ccossctecacdestsvecesedevccessesedicssisseenivdes 56
|
||
Types. 1 to:4 entry records ccccicissccseesceacists SEA ed ed sia eas as vevtentecsouend 57
|
||
Entry.detailS: tleldsscse..< ca, dona s Bere Mises dee S een oe sos ete tias eco ee falls ER SRERE awe 57
|
||
Aheztitle Field A seceececcscaewesietoteecussateuroed anes easbaaes cbeenaee vaniaehub ein redness 59
|
||
Phe alert Hel? asc. se cieeces ceecacrvuetavs cove ence cabeeede s¥eWw cossvcec sass devbececsacs 60
|
||
THE MEMO TED: Mess cect seas cseascieeccvasstaran. voseceteres dbececeetese ee toesc ten robes aes 60
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
TY PO.5 EPCOS s vie Soa ca sevens veVecacemeecedesdetedieesleasaewetoe fetta ettlad oo Taaeoten, 61
|
||
Type 6 - ANONYMOUS ata ........ cc ccecscccscetceresecseaccscececeteceseseceseseseteeaeaeneeees 62
|
||
Types: 7 and:8 ~ reserved. evs. isivsece cede ci tideens vocnts cis olsclenstets ciiesedsvenssescstes ns 62
|
||
Type 9 - to-do list information ............cccscscsccccsscectscsstcesesceceesesssaseescssenens 62
|
||
Types 10 to 14 - descriptive records .........cccccscessccecececscecssecnssseeeeatotesaeneas 64
|
||
Type 10 - styles descriptive reCOrd.............ececsseececscececerecneeetetescsseceserevecs 64
|
||
Type 11 - to-do manager descriptive reCOrd..........ccccccscecscesecscececeeeeateseeuees 64
|
||
Type 12 - frequently changing data descriptive record ...........ccccsescsceeterecees 65
|
||
Type 13 - general descriptive reCord ...........cscscesccerscserececsececeseecssonesseersenss 65
|
||
Diamondélistssetup*field sss 2c ie tieess otis eteis csi a eedeaeede tever set MA Aste 65
|
||
Day entry defaults field ...........ccccersessenecccccerersretecececseecacessceteatetessseses 66
|
||
Anniversary entry defaults field ............cccccscorscsccscecvcrsssetatssssecsacscessees 67
|
||
Generaltdefaultsifield ters nec Pn aR cae Seis ccde ceadahaoteeatatetecess 67
|
||
Day ViGW:-SCtHNGS TIGIG Si ics. cs cesccesecheeedsccensvassedeeeee Tie stuavcaie tees Js ota 67
|
||
Week view ‘settings field. .........c.csccscecscscscecseqscnesedevdsescortcdedeeseterseatcers 68
|
||
Year view: Settings Field ins... sidess cesses seat ss stvonds cceesteGssceevader Tier basceerosdese 68
|
||
TOzdO. VIEW SCTHINGS, TICIG soi csicn tsa cacedenedacsttesiatiesaess cokasasestecesdattsteetesses 68
|
||
Anniversary View Settings field .............cecccenesscssccnscecnesccessesestecetcceaners 68
|
||
List VIEW SETTINGS TIEIG.s... ic. .ccntscsassteessecscsticeesccncas cecsdssesueuneseesreveceestars 68
|
||
Type 14 - print setup descriptive reCOrd .........ccccceceseecesenerececececcseterssseeeeees 69
|
||
TY Pe 152M Gal cs vec ckieiseteae decade vdeetSansedsacetvssessvaecyetioeosnseascasseavselesebces 69
|
||
6 Word Processor File: Format 2... 3.0cc ccc. vcscccescsdescccnscelscsevcisccsVorevetedvcrecesesessssactecas 71
|
||
The-document- head e@tssvssvscissececrevesrrsaereraveseverestyreveeeeitec ae eerste eer eT 71
|
||
RECOLA TYPOS: conc cc cccccdssorscsteve cs dveseecanesstedarevesseteegisrseeeberteeeeuasseaesureseceetyey 72
|
||
The options data record (type 1, length 10) .............c..cesesceseeceseeseseesces 72
|
||
Printer-related data record (type 2, length 58) .............cecssevcscsessseccscees 72
|
||
Printer model data record (type 3, variable length).................csscsceceeeeees 75
|
||
Page header record (type 4, variable length) .............cecessseseseecscscscsseeees 75
|
||
Page footer record (type 5, variable length) ..........-....-cesssecesseeseveseeereces 75
|
||
Style data record (type 6, length 80)...........cccccecscscececscevevsseseseseeceencnen 75
|
||
Emphasis data record (type 7, length 28).............:cccesensorsssoterecsceseataces 76
|
||
Document text record (type 8, variable length) ..........c.ccecsesceceeeeneeesenees 77
|
||
Document index record (type 9, variable length) ...........cscsecssesscseesseneees 77
|
||
TEMplatetil€Stitrcrscctecsesavcistsiscresscceesttcctertotertsrttterstistsenseetesscrcstvorniesion cs 78
|
||
Printer Criver fONt MAPPING.........ccceccccssecscsescueseesessecscesnesssecteseseaeacecerectoss 78
|
||
7 Series 3/3a and MC Spreadsheet File Format .................cscecscecscncscncscscssossccnvens 81
|
||
FUG MOS OR cee: sews enstiiesveneevnsetesbiveesalsecaaters caseueettecdccddacedehevt coseousecvevedoctoaxe 81
|
||
RECOPGS west ves scvcccccdvenccuesceeevedswcccsctcswed secs vets sua Miuadsssebncsrdeucececdscededeleud 81
|
||
Range reTerenCeS.. ioisc.cnevcsactneesaveisececccesevassesececactsesacscecaceeeveasinaseedees 82
|
||
Formula record (type 1, variable length) ............cccsesescsescseeeserererecseeesees 82
|
||
Cell record (type 2, variable length)..............cccscecscscecscecscecscnessessceserens 85
|
||
Column width (type 3, length 2) .............cccccscscsesecececeeteeencececssensseceeees 86
|
||
Default column width (type 4, length 2)................ccececeeceesreeseesseseesees 86
|
||
Status information (type 5, length 4).........ccsescsesensreecerserenseseevseceeseenes 86
|
||
Display information (type 6, length 26)...........c.cccscecsescseseeescsrersetsoeeeees 87
|
||
Named range (type 7, length 26) ...........cccscscsessecsscceseseserscteesetseataeerens 87
|
||
Print range (type 8, length 8) ..........ccscsccesecscececsersesstcescessceseeeseeseseeeees 87
|
||
Database, criterion settings (type 9, length 16)..........ccccccsssecsceceseeeeetees 87
|
||
Table information (type 10, length 16) ................ceceeecececeeececeeeseeneeeaeas 87
|
||
Print setup (type 1:1, length 2): ciceccccesscaacchesecsctessbadhen cdedeesteasegeseevdeaace 88
|
||
Eont:(typest:2 length. 8) oes ter ctecds cee cane deteatasescsagiastasadantecstvn.verersess 88
|
||
Graph (type 13, variable length) ............cccccsseccseerseeeseescessceterssseesteeaees 89
|
||
Current graph index (type 14, length 2)..........cccccscecscseescsceecscensnesceeeoes 89
|
||
|
||
|
||
iv
|
||
|
||
|
||
CONTENTS
|
||
|
||
|
||
Font palette (type 15, length 24)..............cccsccesssscerercececavensecsscusesesceees 90
|
||
Print data (type 16, length 58)..............ssccsssscsscusnscvcovevesscssseeceveserceans 90
|
||
Printer model (type 17, variable length)............cccscececssscccevesesececeaceeevess 90
|
||
Header text (type 18, variable length) .............ccscscecscscsccscscevsscecsasecesees 90
|
||
Footer text (type 19, variable length) ...............cscccscsuscscscvesnscesesecseceuces 90
|
||
Display extras (type 20, length 2) ............c.cecseceecscecsrencecvecessevsceneaueeess 91
|
||
3a Display extras (type 21, length 4) ..............csecscoreceseseeeenscunsescececesees 91
|
||
Password (type 22, length 18).............cscscssssescessevencessesececusucsecceeecesens 91
|
||
8. Writing) Device Drivers iii .25. ins sbi oso Sooe ck Site saci css cacsnseadeccasscticces eitets ctvs sweetie 93
|
||
INTRODUCTIONS. 0255. ccecardicaececedvore red eaeavedesue eet be Tore loth eo tee score tes Per oh not Sveti 93
|
||
The location of device Arivers ...........cccscsccecsecceseccasscecescsceccscecersenceeses 94
|
||
Device Driver Names. .........cccccssscssonsncssccscsseuecsceccecencecceccucesensatesseseenes 94
|
||
Device Driver*Ghannels:stesvrecetn eens oe ade eo ons ea asd eee ea nae’ 94
|
||
SearchingiforRDDs ici. vccvsesatevs cevaceecavesesaveten see vase eee eee a eal! 95
|
||
Device Driver Hierarchies And Attached Drivers ............ccccccscscsescsensecees 95
|
||
Interrupts and Interrupt Service ROUTINES ..............c.sescocossenscereseceeccsevceensses 96
|
||
Device Driver I/O Semaphore Waithandlers ..............scccscscsoscecscesecscsacees 96
|
||
Loadable Logical Device Driver Structure ..............sccsessevcscecececsssvcnscecesscescs 97
|
||
SINGICT COGS SEGMENT. .is..cc2escsvencace siete seetervecepascnecssdeenonreionseoetantetMestssee 97
|
||
MHeEsMIDENt: SrUCtUies 525 ii. ceva s cscs cdeadseeweehecascecdanceedlissicnccdendacieessceuteess 97
|
||
Mandatory‘ EDD: FUNCtIONS «6.060.005. sscecsnarecescscdeseanctasedontorceesstonsveeaecseoeve 98
|
||
DEVEUNCINStall meres cce. i cccn ovensssl<cencrceas soeescescesos soedensesvact tasesestsaneanwadaeeeds 98
|
||
DEVEUNCREMOVE ai.52.ccscccs ssa ce cvocsteeedaedescstacGennuedases ees wdiweceue sees dae cekvens 99
|
||
DeVEUNCHOlde in. ciccceccrcscncs yeh actebatesenceecevesssccees seeaees vas csaestuenadisaulennbadee 99
|
||
D@VEUNCRESUME oi. cvcsicccesncsecscbescssceascscssieccccsccdcaddeasccccloeceecddcceatwetacsive 101
|
||
De@VEUNCRESCE avis. scucssecetascecves srassieds cae 3ss0cnehveedssdleadcccgeesavavinwedesiexvers 101
|
||
DEVEUNCU RIS weve se cuis svenevasscavensvcdtedgeeseeuded nace cagece dec entdacau lee teeasenue cues 102
|
||
DEVEUNCOPEN sis cisceeccce ta caevocadaasisaessccuasasuavieoecceedteeten snot caetaet oufeatieateass 103
|
||
DOVEUNCSEATEGY: ss cence ececcssetacasseveids Ptecectescuetetass foes daseeceteleseens MetNeauaats 105
|
||
Loadable Physical Device Driver Structure...........ccccccccccccsceccccscsccccececesacsecs 106
|
||
Single Code SEQGMent ..........ccssesecscecscaceceususcuccsescecccccesancetecusececeeecesess 106
|
||
The BIDENt StrUCture: s vscccccesacsceccesscctetcs. caus ccoctresasuscvactsvstecectstas de wcecs vs 106
|
||
Mandatory PDD functions ...............cccesecsesecececsceceescscccseterecseecsasanscecs 107
|
||
DevFEunclnstallPDD on5 55 scccccacccscvecccuccvevnevecevescncelswoesedescsessechcoscdsesnsceess 107
|
||
DevFUNCREMOVEPDD ..........cccceseccsenescercccceavscscscsceseucesssacscesscsersceesesere 108
|
||
DeVEUNCOpenPDD ii... ceseccedsccesssseses see pensesvicscgedsintadersbicvaseusrtisansn eee 109
|
||
DéevFuneStrategyRDD. esses oeeccacestssicseeseveasanesa cOSveedd a doeaas sdesee ohavero eee se 109
|
||
9 Example: Device: Drivers ci. ceccccsecccxcevcscscosdevoscasuesodcatasudaccascdenuacteoeciaedvevedeSeusees 111
|
||
An Attached Device Driver Example ...........cccesecesccecsscececcenscesccssecssesscceeuses 111
|
||
Thesde vice: table iis.5.2 cise i te code eciwiscacececctceves cocacecosccstiteucacteudesdelecns cas 111
|
||
TheslnstallsFUNCUON we vevesvecssssicesasvavavesesesesese sees covasnce cos sessesceesdieteereeacted 111
|
||
THe Remove Function ay..ecccicssciescucetecscescedsccdscecess nave lgsWeevdcticiedssst ones: 111
|
||
WHE HOMD FUN CMON wes sees Scccsvscuveeccesvebeuwessipecevscansasecersregeedes Meee socehe bees 111
|
||
The ReSume Function ...........ccccscsesessceavccceecccsreceseucescaccccseeceaceseueecuers 411
|
||
he RESCH FUTICTION s sewssvissestececcsceedofedeotels ieee asuon sete sia eee ee 111
|
||
THEAUMITS FUN CHONG ese Scceeccn ceed scccavavccecedabcecasevcdeoses tec sctlccnisezdefecescants 112
|
||
THE OPEN FUNCTION vice. csiesaseevesavcevesneccececcuscesbevetacanechuasaececedscbasieaccceenss 112
|
||
The Strategy FUNCHON .iicccseciecicccceeeeccdsuchwasievccsedecenestsdessdussevasasdwededecs 112
|
||
The Wait Handler Function ............:cccscscesecsccscscscscecssececcvcesscesaeausoucenes 112
|
||
Non Interrupt Based Sound Driver ..............scsccosscsecsestecsrscnsececsesceeveseeensens 113
|
||
Phesdevice table ses. scscsdscsnecaaveteea vesecereseasevewnesddecdesacveceediaodseecced cdsceued 113
|
||
Ehe: Install PUNCUON . 3.005660 scacevecesad chee cedewancedscteeschssadevssabiascscecdsandecsans 113
|
||
The Remove Function............ccccecscscvecsccccvansccsesccusesceseceeasvesanevesensecuens 113
|
||
THE HOIGIFUNGTION. « ficiedset ees tis cos ee ne tencc eee veadeeekencades sea dciexdeedaatheteexsesoweos 113
|
||
The Resume Function ..............ccccsccecsescscecccccssscsceccccencesnccsssnseesseessaces 114
|
||
THEXRESCE- FUNCTION oic5co3c20 sacks bo celeb ode ductecdieseceuesedavestinuxieweusewanedesmeendea’s 114
|
||
Tes WMitssPUNCION Sc. oeaste scene sec te ee See cece aca cates tease dobdbcasenadtcssesesstaundsots 114
|
||
THE OPC MIEUNCUON srececccvecssporesscrsauecnceweutegecdutesesisiced @ocdeetess iaaces tune axe 114
|
||
The: Strategys¢ RUA CON co5 res. fhe sax. cescecevecsvesdhccstececieok sleds etotaes ves onies ooaene ds 114
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
The: Wait: Handler: Functions... s.seio..otee et eed Stee SPE ST eee ees 114
|
||
EXERCISING: the: VECIOIS Feces ener sseetiessccsscetterectacseteoncecsieeesene cette sete wieter ats 115
|
||
Interrupt Driven Sound Driver ..........ccsceccecsarsccsccecccececsnensseerscenssseesesseesons 115
|
||
Thecdevice table sie co criscoccccccccnceca cesses ccoke cuveeces Suuzte lens cess ev cstetoaseteeds 115
|
||
TheslnstallFFuncton Aik ove, cee eeaw as cevarsocceeees ec ecsees vecuatensctsnceceuece ccs 115
|
||
TERREMOVE FUNCTION ci nese icteet nes ccce ch ease ccna fe ceecmeesevesceuddcsineetaetsedecuecats 115
|
||
GHEHHOIGKFUNETIONG.. .ccctevcessnecoctessexercewsataceces tears ssissadecouse ocesineu dec cet te cs 116
|
||
THEIRESUMELBUNCH OM Mec.ccs sca cescesancectcccccecvasetestsecodacnmsitetcanestscisecasesees 116
|
||
TRENRESCTEUNCHON aii e.c3 si lesceccecdssdestesescaes caacesenceves feser core sista se duentecever 116
|
||
THELWNAITSTRUN CHONG Soe5 5 2oiceadadiieedeneveecs et -ntianen tagcat gabe tee steers tested) sa 116
|
||
THEOL ODEMLEUNCHON F ooveccaeistcocae tees aceuceusladdaei ils ones oaeeace cetaceans sees cnn suneeceees 116
|
||
The StrategyitFunCtOn). co sccccediwesescusceesecssce sche saswendnenensdeestisveeesnatsteueres 116
|
||
The Wait: Handler Function. cs... ..scieccciccscccctcadescdadevctescstecssteteesesttetcedes 117
|
||
|
||
10 Word File Format Conversion DYLS.............:sccscescscsssceccccccsceccsessnsccnssascassnesesens 119
|
||
SAVE\INTEPTACE: SEPVICES sic iicdeessccsscccesessccearseecsvccvsdseseestecesosvetenceverssdeesesedes 119
|
||
Present file OVErwrite GialOG .........cscccscscsscccesccestcsscsaescesceascoesesassesessses 119
|
||
COUNT INDEXAAGS vases cc cc Seccea Sect cote n ac cee aee nea cas Pee eee Mca b ec oebeseneeecewes 120
|
||
SONSE AN IMGEX CAG re: oiases ce ceie inca cecashosnaedevsncconsesdavasevedscucerertscgawenseeees 120
|
||
COUNT Paragraph-StyleS \<. 0c... cccasccssecdessscsesavecrecsctaneccteedsvecettonesrctoces woes 120
|
||
Count EMPNASIS*SIVIES: F...cceveseccs chs edsesescaete wceeeracesgensietecereiseausescsetees 120
|
||
Sense a paragraph style by index..............cscceceecencecseeecneesunecesesceseceners 120
|
||
Sense an emphasis style by INde@x........ccccscsccsscsacsscscecssoescsseesscveaneeeees 120
|
||
Sense a paragraph style by short Code ..........cccecececseecscseseereessoreeetonsees 120
|
||
Sense an emphasis style by Short Code ...........cccececscerecereeseeerecsoneeaeaees 120
|
||
Copy document text to DUPPEr ....... cece ee ee scene eee eceeencnceeteeeenseeneeceeesens 121
|
||
Set afileverrOns: eescecizs foes oswi avs tack vase tabs saewtadeaededsaccadsucnstverce rector esate cass 121
|
||
Load jinterface:ServViGeS:.....c.0c ccs iswctesseddecacadscsdscdederenaderntesacreeesat esse beceseees ed 121
|
||
CIOSECUIreNntly: OPEN TICs secessccdees cose iene clbeterbacstvecnccadenssebeteodscendedees sei 121
|
||
Record name of file ANd redraw ..........cecesecceceecssceceeseesceescecreceessecceseess 121
|
||
Append a paragraph Style ...........cccccecscsecsccscscnesccsceessenseccescseesesteesesens 121
|
||
Append an emphasis style ...........ccssscsecrscenrscescscrscesseescececeeseeeseetecemens 121
|
||
Apply a paragraph Style..........cccccccscccsenscesescecneserseensessssnessoncnseseseeeoess 121
|
||
Apply ansOMPHaSisSs si ceiieis seoccdes isa eacacesdedeccnes cocesieteactcvesatsceedocesvened 122
|
||
Create: default Styles .....c.cccssssccctesececsaasscdeccccsevecdacentetesteleasdacdusnscsoeees 122
|
||
ISOPT TEX Gace scccteecrcevossccsnecacecevensccactieinscaeucospiwecetecdersteitessccsonesseuans 123
|
||
Delete: Text nce. coleceSesvatecsvanaessaeedeiiacesndcueceedessssesdaceecssseaetaierssseeacesst es 123
|
||
COMMON interface SELVICES ........cscecsececscsscctsceceecessseserecossscesenteneescensensenes 123
|
||
Start active object file CONVErSION .........ccccscsececenceeteceesececsetenoeeeeesosaeees 123
|
||
Stop active object file CONVErSION ............. ceca ececessenceeeencssteneecseeeeerenes 123
|
||
Set/clear Busy Status vsecscctive visiaievawedea cases cube ss Se teacceeeslndteuts Peiweeedecahe 123
|
||
Senserprinter data yc... cece c cosas ves cevisedsivesvssaecsvedeusescudetevensereceeenceranwebes 123
|
||
Sense printer model data .................ccceeeeecececeeceeecereceeneeseeenueteceeeeeoeaes 124
|
||
SENSO PINTER CIVEN ss cec se vcscssteccentetevetesenssaevescsascnes da cdcacsussesvasisesesegee 124
|
||
Example Code isis. icdisc iced Mitten cities deten a iedsiaa cs secwavagebecevewedecesisaneetssietess otletes 124
|
||
SAVE DIAINtOXtiai ce cliees ces ceeesiacdeekosn casnsccecevescacetecdescetancertenteree sowssanset 124
|
||
|
||
LQ ad PIAIN, TEX ccs ictc cave sais cs caaic bY ea scien ve ete wc siaw's cule sine’s Seecetedsdledvcets Shan vee Petes’ 126
|
||
Debugging a Conversion DYL............:cccenseeecsc recent eeecesencetscesnesesscetneesereees 129
|
||
|
||
|
||
CHAPTER 1
|
||
|
||
|
||
IMICLINK, MICPRINT AND SLINK
|
||
|
||
|
||
The directory \sibosdk\sys contains (amongst others) the following programs, all of which can be run on
|
||
a PC connected to a SIBO computer:
|
||
|
||
|
||
mclink. 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.
|
||
|
||
|
||
(a a eee a ee
|
||
Miclink.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 assiaN command before running the MCLINK program, like this:
|
||
ASSIGN B=A
|
||
|
||
Then DIR 8: will be read as DIR A: and the program will not be halted. See your MS-DOS manual for
|
||
|
||
further details of the ASsiIGn command.
|
||
|
||
Exiting the MCLINK program
|
||
|
||
Type EXIT to return to MS-DOS.
|
||
|
||
|
||
Display the version of MCLINK
|
||
Type VER to display the version number.
|
||
|
||
|
||
Le ce Se ee ae ae eT
|
||
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, <filing system is
|
||
= oc:: for files on the PC (local)
|
||
= remM:: 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
|
||
s if no filing system is specified, the PC is assumed.
|
||
|
||
|
||
When specifying a directory or sub-directory in the file-handling commands, 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
|
||
|
||
|
||
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 o1r command, the following file information is given:
|
||
|
||
« 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
|
||
|
||
|
||
Syntax: COPY filespec1 filespec2
|
||
Optional flags:
|
||
|
||
|
||
<i 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 .txtT 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 .poc files from the sm1tu 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::Mz\
|
||
|
||
|
||
copies files from the current directory on the PC to the root directory of the remote machine's internal
|
||
disk.
|
||
|
||
|
||
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 filespec1 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 REMs:B:\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:
|
||
|
||
|
||
-j delete files of the same name in sub-directories, eg DEL *.TxT -i would delete all .TxT 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).
|
||
|
||
|
||
SSS SSS SS ee ee
|
||
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 example:
|
||
SET -pi -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.
|
||
|
||
|
||
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\N3
|
||
|
||
|
||
Examples of the SET command:
|
||
|
||
|
||
SET -b1200 1200 Baud
|
||
|
||
SET -p2 -m waits for a call using the modem in port 2 (com2)
|
||
|
||
SET -pi -b2400 -n314159 modem connected to port 1 dials the phone number 314159
|
||
SET -cm0 turns off the modem speaker.
|
||
|
||
|
||
SSS eS Sa ee
|
||
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 nm 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.1mMG 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
|
||
————$ $e
|
||
|
||
|
||
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 .1xT and .poc files in the current directory to be copied to this
|
||
directory, then MCLINK to exit.
|
||
|
||
|
||
MCLINK command line processing
|
||
|
||
|
||
MCLINK understands a command line entered when running MCLINK from 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 .TRM 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 S3SETUP.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 Series 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 is 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 simply by typing
|
||
SEND_ALL
|
||
|
||
|
||
from the MS-DOS command line.
|
||
|
||
|
||
ESS ES eee eee ee a oe eee ea
|
||
MICLINK 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.
|
||
|
||
|
||
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 xp: 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.
|
||
|
||
|
||
= 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 "ox" reply was received.
|
||
|
||
|
||
MCLINK then sends the following command stream to the modem to configure it:
|
||
"ATX4E0SO=1" if the modem's maximum Baud rate was 2400 Baud or above
|
||
“ATX1EOSO=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 'ok' 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.
|
||
|
||
|
||
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 configure it:
|
||
"ATX4E0SO=1" if the modem's maximum Baud rate was 2400 Baud or above
|
||
"ATX 1E0SO=1" otherwise.
|
||
|
||
|
||
Link then reads the user command configuration strings 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 ‘ox' response is received the command worked, otherwise an error is 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 between 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 between the PC and HC.
|
||
|
||
|
||
EES eee SS SS ee ee ee)
|
||
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 QuadPlus 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 .TRM file, eg QUADPLUS.TRM and type
|
||
MCLINK @QUADPLUS.TRM
|
||
|
||
or call the .TRM file MCLINK.TRM and just type
|
||
|
||
|
||
MCLINK
|
||
|
||
|
||
Using an Amstrad SM2400 modem
|
||
Run MCLINK with the following command line:
|
||
|
||
|
||
MCLINK -m
|
||
|
||
|
||
1 MCLINK, MCPRINT, AND SLINK.
|
||
a ee ee ee
|
||
|
||
|
||
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>
|
||
|
||
|
||
Ee ee a ae ee a er eee
|
||
Mecprint.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 comi, 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 application to display the Printer
|
||
dialog. Set one of the configurations to output to Serial. You don't normally have to click on the SET
|
||
SERIAL... button to change any of the Serial options because MCPRINT 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 Processor, 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 used 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 mope 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
|
||
|
||
|
||
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
|
||
time-out 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").
|
||
|
||
|
||
SS SSS SS > ee ee, A)
|
||
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
|
||
|
||
|
||
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.
|
||
|
||
|
||
aS Sa a en Sea ee EE Te
|
||
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");
|
||
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 language. But this latter approach makes
|
||
the problem of maintaining code much harder; each different change made 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 transcription 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", "%d items found", and so on, are kept in a separate file, not as part of the
|
||
dataspace of the program, and are loaded into RAM only when they are needed.
|
||
|
||
|
||
Thus the above call
|
||
winfoMsg("Scanning");
|
||
|
||
would be replaced by a call such as
|
||
InfoMsg(RESOURCE_SCANNING);
|
||
|
||
|
||
where RESOURCE_SCANNING is a symbolic constant (#define) giving the index 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);
|
||
wiInfoMsg(&buf [0] );
|
||
}
|
||
|
||
|
||
and in turn LoadResourceString would read data from the appropriate resource 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_getlanguage).
|
||
|
||
|
||
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 individual items 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 application 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 WDR
|
||
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
|
||
|
||
|
||
(Se a ee a a ee ee i ee eer |
|
||
Format of Sibo resource files
|
||
There are in fact three kinds of Sibo resource files:
|
||
|
||
|
||
a .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 .rs¢ 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 .rss. 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):
|
||
|
||
|
||
O: 31 00 08 00 53 74 61 72 74 69 6e 67 20 63 61 &c 1...Star ting cal
|
||
10: 63 75 6c 61 74 69 6f 6e 00 53 63 61 6e Ge 69 Ge culation .Scannin
|
||
20: 67 00 25 64 20 69 74 65 6d 73 20 66 6f 75 be 64 g.%4d ite ms found
|
||
30: 00 04 00 1900 220031 00 — ~— Jeeee ws 1s
|
||
|
||
|
||
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 LoacResource 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_FA8S,&fpos);
|
||
|
||
p_read(fcb, &tmp[0] ,4); /* read two words from index table */
|
||
fpos=tmp [0] ;
|
||
|
||
p_seek(fcb,P_FABS,&fpos);
|
||
|
||
p_read(fcb, pb, tmp[1]-tmp[0] );
|
||
|
||
>
|
||
|
||
|
||
where:
|
||
|
||
|
||
« feb is the file control block of the open resource file
|
||
|
||
|
||
15
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
= ~ixpos is the value of the first word in the resource file (ie the file offset of the beginning of the
|
||
index table), and has been read into memory during program initialisation, for the sake of
|
||
efficiency
|
||
|
||
|
||
® the passed value of index in this case would be 1 for the first resource, 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 the 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 application'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 .afl 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.
|
||
|
||
|
||
bn |
|
||
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 rscfite 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 .7zc
|
||
format files instead of .rsc format, without any need to alter or recompile existing code
|
||
|
||
|
||
= 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 rscfitle class clarifies and documents all the possible error conditions that
|
||
need to be catered for
|
||
|
||
|
||
= Learning about the rscfile class is a useful step along the route to learning about Psion's
|
||
proprietary object-oriented programming system - since this system 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 i/o
|
||
device control blocks. Subsequent rscfite 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 allocate 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 InfoMss:
|
||
|
||
|
||
LOCAL_C VOID InfoMsg(INT index)
|
||
{
|
||
TEXT buf £60] ;
|
||
|
||
|
||
p_send4(rcb,0_RS_READ_BUF, index, &buf [0] );
|
||
wInfoMsg(&buf [0] );
|
||
>
|
||
|
||
|
||
with reb 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(reb,O_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 .7sc), 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 *InitReb(TEXT *rscname)
|
||
{
|
||
HANDLE OlibCat;
|
||
VOID *reb;
|
||
INT ret;
|
||
|
||
|
||
p_findtib("OLI8.DYL",&0libCat);
|
||
rcb=p_newlibh(Ol ibCat,C_RSCFILE);
|
||
if (reb)
|
||
{
|
||
ret=p_entersend3(rcb,O_RS_INIT,rscname);
|
||
if Cret<0)
|
||
p_exit(ret);
|
||
D
|
||
return(rcb);
|
||
>
|
||
|
||
|
||
For overtly object oriented programs, the lines
|
||
|
||
|
||
p_findlib¢"OLIB.DYL",&0libCat);
|
||
reb=p_newlibh(OlibCat,C_RSCFILE);
|
||
|
||
|
||
17
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
can be replaced by a line such as
|
||
reb=p_new(CAT_HWIF_OLIB,C_RSCFILE);
|
||
|
||
|
||
with the category number CAT_HWIF_OLIB being replaced by the suitable reference 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 o_pEstroy (defined in olib.g) is 0. (See below for use of o_DESTROY.)
|
||
|
||
|
||
Run-time errors with the rscfile class
|
||
|
||
Broadly speaking, there are five kinds of run-time error that can arise with resource files:
|
||
there is insufficient memory to create or initialise the rscfile object
|
||
|
||
the resource file cannot be found (when the program starts)
|
||
|
||
the data in the resource file is bad
|
||
|
||
|
||
the SSD containing the resource file is removed or cannot be accessed
|
||
|
||
|
||
vA F&F WwW NY &
|
||
|
||
|
||
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 InitReb 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 passed) 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 program exited.
|
||
|
||
|
||
Errors during rs_read or rs_read_buf
|
||
|
||
|
||
The only errors that an application should in practice worry about, for the 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 declared 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 OF 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,0_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 rscfite 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,O_RS_READ, index, ppcell);
|
||
if (ret>=0)
|
||
return;
|
||
while (ret<0)
|
||
¢
|
||
if (ret==E_GEN_NOMEMORY)
|
||
{
|
||
*ppcell=NULL;/* signal failure to caller */
|
||
Tel LNoMemory( );
|
||
return;
|
||
>
|
||
wsAlertW(WS_ALERT_CLIENT,0O,ReplaceDisk,0);
|
||
p_send2(rcb,0_DESTROY);
|
||
FOREVER
|
||
€
|
||
reb=p_newlibh(OlibCat,C_RSCFILE);
|
||
if (reb)
|
||
break;
|
||
Tel LNoMemory();
|
||
>
|
||
ret=p_entersend3(rcb,O RS_INIT,rscname);
|
||
>
|
||
}
|
||
>
|
||
|
||
|
||
One way to implement the routine Tel \NoMemory - which must never itself run out of memory - would be
|
||
as follows:
|
||
|
||
|
||
LOCAL_C VOID Tel lNoMemory(VOID)
|
||
€
|
||
TEXT buf £40];
|
||
|
||
|
||
p_errs(&buf [0] ,£_GEN_NOMEMORY );
|
||
wsALertW(WS_ALERT_CLIENT,0,&buf[0} ,0);
|
||
>
|
||
|
||
|
||
The way ReadResource works, in cases when the user has removed the SSD 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 accessed:
|
||
|
||
|
||
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 read
|
||
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
|
||
|
||
|
||
SSS ee ee 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 .afl 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,O_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 .rsc (or .7zc) 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 language 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 \imng\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:
|
||
|
||
|
||
21
|
||
|
||
|
||
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\\archivz0ed.rsc",p getlanguage());
|
||
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_getlanguage 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.
|
||
|
||
|
||
ee ee es ae ee ee a en eee
|
||
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 assumptions 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 (01);
|
||
|
||
|
||
However, when the application is translated into German (say), with the entry for "Weekly" in the
|
||
resource file being changed into "Wéchentlich", the new application will 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
|
||
"Weekly", is not long enough to contain "Wéchentlich".
|
||
|
||
|
||
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 inform 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 account 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, ail 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?
|
||
|
||
|
||
LSS LSS ee a |
|
||
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 .rss being the usual extension for a resource script.
|
||
|
||
|
||
23
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
As an example, suppose a file eg.rss has the following contents:
|
||
|
||
|
||
STRUCT STRING
|
||
€
|
||
TEXT str; /* zero terminated text string */
|
||
>
|
||
|
||
|
||
RESOURCE STRING res_start_cale {str="Starting calculation";}
|
||
RESOURCE STRING res_scanning {str="'Scanning";}
|
||
RESOURCE STRING res_items_found {str=""%d items found"';}
|
||
|
||
|
||
Then invoking the command line
|
||
rcomp eg
|
||
|
||
|
||
produces as output a file eg.7sc whose contents are exactly as described in the earlier section on the
|
||
format of .7sc 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 the 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:
|
||
|
||
|
||
#define 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 #inctude 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 .7sc
|
||
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 these 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 file to an .. \include\ directory.
|
||
|
||
|
||
24
|
||
|
||
|
||
2 RESOURCE FILES
|
||
ee SS Eee
|
||
|
||
|
||
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=%INCLUDEX
|
||
set INCLUDE=..\include
|
||
\sibosdk\sys\rcomp %1
|
||
set INCLUDE=ZOINCLUDEX
|
||
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
|
||
|
||
|
||
#1 fdef BUILD_ONE
|
||
|
||
|
||
#endif
|
||
and
|
||
|
||
|
||
#ifndef BUILD_ONE
|
||
|
||
|
||
#endi 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
|
||
|
||
|
||
ESE ———— ee a ee ae el
|
||
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_8AR_ITEM and with two members, the first with type LINK and the second
|
||
with type TEXT.
|
||
|
||
|
||
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:
|
||
|
||
|
||
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, including the terminating zero
|
||
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 for more on variable length items).
|
||
worDs are stored low byte first then high byte. Similarly, LonGs are stored 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 Lonc can similarly be interpreted either as
|
||
signed or unsigned.
|
||
|
||
|
||
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 values, and symbolic constants:
|
||
str="This is a string.";
|
||
|
||
or
|
||
str=<84><104>"is a str’<0x69>"ng"<46>;
|
||
|
||
or even
|
||
|
||
|
||
#def 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
|
||
|
||
a the identifier of the RESOURCE
|
||
|
||
= = 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";
|
||
>
|
||
|
||
|
||
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
|
||
s 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 ne_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;};
|
||
>
|
||
|
||
|
||
In the majority of cases, when a sTrucT is declared as having a sub-sTRUCT member, this member will be
|
||
intended to be a strucT of one particular type. Note, however, that the type of the sub-strucT member is
|
||
not specified by the struct in which it is declared (for example, Test does not specify that the sub-sTRuCT
|
||
more is of type NceDIT). In consequence, it is possible to have two or more resources that are both based
|
||
on the same struct definition, but use different types 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
|
||
€
|
||
BYTE one;
|
||
>
|
||
|
||
|
||
STRUCT SECOND WORD
|
||
€
|
||
BYTE two;
|
||
>
|
||
|
||
|
||
STRUCT THIRD
|
||
€
|
||
BYTE three;
|
||
>
|
||
|
||
|
||
STRUCT FOURTH BYTE
|
||
{
|
||
STRUCT a;
|
||
STRUCT b;
|
||
STRUCT c;
|
||
}
|
||
|
||
|
||
RESOURCE FOURTH test
|
||
€
|
||
a=FIRST {one=1;);
|
||
b=SECOND ({two=2;};
|
||
c=THIRD {three=3;);
|
||
>
|
||
|
||
|
||
28
|
||
|
||
|
||
2 RESOURCE FILES
|
||
|
||
|
||
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 FourtH. These leading length values are inserted 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>[ J;
|
||
LEN <type> <member-name>{ 1;
|
||
or
|
||
LEN BYTE <type> <member-name> [ 1;
|
||
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> {<initialisations>} 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 strist{(];
|
||
>
|
||
|
||
|
||
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!";}
|
||
7
|
||
|
||
>
|
||
|
||
|
||
produces a single resource in which:
|
||
= the first word is zero (the supplied default value for the topic_id member)
|
||
® 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 juxtaposed.
|
||
|
||
|
||
Creating SYSTEM resource files
|
||
|
||
|
||
For completeness, it should be mentioned that the resource compiler enters 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 negative of the correct value.
|
||
Thus whereas the resource script
|
||
|
||
|
||
STRUCT STRING {TEXT str;}
|
||
STRUCT TEST {LINK Lnk;}>
|
||
|
||
|
||
RESOURCE STRING alpha {str="Xyz";}
|
||
RESOURCE TEST beta {Lnk=alpha;}>
|
||
|
||
|
||
results in the second resource consisting of the word 1, inserting a line
|
||
SYSTEM
|
||
at the beginning of the resource script changes the value of this resource 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. This system resource file
|
||
is built into the ROM of all machines that support HWIM programming. See the Resource Files chapter
|
||
of the Object Oriented Programming Guide and the APPMAN Application Manager Class chapter of the
|
||
OLIB Reference manual for more details.
|
||
|
||
|
||
30
|
||
|
||
|
||
CHAPTER 3
|
||
|
||
|
||
WDR PRINTING
|
||
|
||
|
||
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
|
||
|
||
|
||
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,
|
||
hPrintSetSI, 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 psp,
|
||
PSS, PSF, and PSM:
|
||
|
||
|
||
PSD is one byte long, having the value '0' to denote that the user has chosen to print using the
|
||
parallel port, '1' to denote the choice of the serial port, and '2' to denote printing to file
|
||
|
||
|
||
PSS 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 bear 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 .xof f=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 .war file - so 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
|
||
|
||
See the discussion on p_getenviron and p_getenv in the Plib Reference manual.
|
||
|
||
|
||
Note that it is also possible to read and modify environment variables (eg for experimental purposes) by
|
||
using the SIBO Debugger.
|
||
|
||
|
||
SS ee Se ee ee 6 a a |
|
||
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
|
||
|
||
|
||
Just about the simplest possible .wdr file would have the following contents, when dumped:
|
||
|
||
|
||
0: 89 00 Oc 00 57 44 52 30 35 00 00 00 01 00 05 00 eee -WORO 5.......
|
||
10: 47 65 6e 65 72 61 6c 00 00 00 00 00 00 00 00 00 General. .....2..
|
||
20: 00 00 00 00 00 00 00 00 1700 00 00 00 00 0000 .......... wee eee
|
||
30: 00 00 00 00 00 00 00 01 Oc 01 Od 02 2a 0a 00 02~—i......... wee a ete
|
||
40: 2a 20 00 00 00 00 00 00 01 00 02 05 23 4d 6f Ge ME cicvelorere}..olsis #Mon
|
||
50: 6f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Ove ea ccc a snes
|
||
60: 00 00 00 00 00 03 00 01 O00 f0 00 00 00 0000 00_~—i........
|
||
70: 00 00 01 00 01 00 01 00 01 16 00 90 00 f0 00 00... wee eee
|
||
80: 00 00 00 00 00 01 00 04 00 04 00 28 00 48 00 4d_—ig..... sc (HOM
|
||
90: 00 7b 00 89 00 oleae
|
||
|
||
|
||
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, .wdr 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
|
||
.rzc and .7sc 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 .wadr 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
|
||
= 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 Ox7b.
|
||
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
|
||
|
||
|
||
s 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 .wdr
|
||
files which contain more than one printer model, the first resource will be larger.
|
||
|
||
|
||
33
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
The commands resource
|
||
The second resource in any .wdr is always the commands resource. This consists of:
|
||
= an array of command strings
|
||
= preceded by a count byte (the first byte in the resource)
|
||
= followed by a trailing word whose meaning is reserved for future expansion.
|
||
In general.wdr above, the value of the count byte is 0x17, ie 23.
|
||
|
||
|
||
Each command string that follows is given with a leading byte count, and without any terminating zero
|
||
(as is appropriate, given that the command strings can in general contain embedded zeros).
|
||
|
||
|
||
As can be seen, for general.wdr, all the 23 command strings are zero, except for (starting counting at
|
||
zero):
|
||
|
||
|
||
string 14 which has the value 0x0c
|
||
string 15 which has the value 0x0d
|
||
string 16 which has the value '*' 0x0a
|
||
string 18 which has the value '*' 0x20
|
||
|
||
|
||
The first 21 of the command strings in the command block have reserved meanings, best described in
|
||
simple terms by giving the descriptive text associated with these commands in .wd files (see Contents of
|
||
.wd files section later):
|
||
|
||
|
||
"RESET"
|
||
"FORM_LENGTH"
|
||
"PREAMBLE"
|
||
"POSTAMBLE"
|
||
"UNDERLINE_ON"
|
||
"UNDERLINE OFF"
|
||
"BOLD_ON"
|
||
|
||
"BOLD OFF"
|
||
"ITALIC_ON"
|
||
"ITALIC_OFF"
|
||
|
||
10 “SUPERSCRIPT_ON"
|
||
11 "SUPERSCRIPT_OFF"
|
||
12 "SUBSCRIPT_ON"
|
||
13 "SUBSCRIPT_OFF"
|
||
14 “NEW PAGE"
|
||
|
||
15 “CARRIAGE_RETURN"
|
||
16 "MOVE_DOWN"
|
||
|
||
17 "MOVE_RIGHT_PREFIX"
|
||
18 "MOVE_RIGHT"
|
||
|
||
19 "MOVE_RIGHT_SUFFIX"
|
||
20 “LANDSCAPE
|
||
|
||
|
||
OMNAUEP WN Oo
|
||
|
||
|
||
Additional command strings can be used to set various fonts, and are referenced by typeface resources,
|
||
discussed below.
|
||
|
||
|
||
Model resources
|
||
|
||
|
||
The resource identifiers of all model resources are listed in the header resource. As mentioned above, the
|
||
only model resource in general.wdr has identifier 5. Consulting the index table for the file indicates that
|
||
this resource starts at file offset 0x7b (recall that resource identifiers start at 1).
|
||
|
||
|
||
The structure of a model resource is as follows:
|
||
|
||
|
||
s The first five words give the values of the so-called minx, miny, skipx, skipy, and model-flags
|
||
for the printer model.
|
||
|
||
|
||
= Next comes a word giving the number of following typeface resource identifiers.
|
||
® This is followed by an array of the specified number of identifiers of typeface resources.
|
||
For general.wdr, the values of the various values are evidently as follows:
|
||
|
||
|
||
minx 0x90 (144)
|
||
|
||
|
||
34
|
||
|
||
|
||
3 WDR PRINTING
|
||
|
||
|
||
miny Oxf0 (240)
|
||
Skipx and skipy both zero
|
||
model-flags ZeTO
|
||
|
||
|
||
and there is just one reference to a typeface resource which, in this case, has resource identifier 4 (which,
|
||
via the index, locates it at file offset 0x4d).
|
||
|
||
|
||
Typeface resources
|
||
The structure of a typeface resource is as follows:
|
||
|
||
|
||
® The first 20 bytes contain the public name of the typeface, as a zero-terminated string. The text
|
||
of this name must not exceed 16 characters, not including the terminating zero.
|
||
|
||
|
||
= 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.
|
||
|
||
|
||
® Finally there is an array of WOR_FONT structs, one struct for each font size supported by the
|
||
typeface. Each 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
|
||
concludes 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 is only 1
|
||
WDR_FONT struct following in-line.
|
||
|
||
|
||
In a WOR_FONT struct:
|
||
® 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.wadr, 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
|
||
|
||
|
||
35
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
commands (always the second resource in the .wdr file) containing the character command
|
||
sequences for resetting the printer, controlling the text format, moving the
|
||
print head position, selecting specified fonts, 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 proportional 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.
|
||
|
||
|
||
A ee re ||
|
||
More details on the contents of .wdr files
|
||
|
||
|
||
Possible wdr-flags
|
||
|
||
|
||
The only wdr-flag of any general significance is woR_DYL_LOAD, with value 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 driver 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 in the extra print dyls.
|
||
|
||
|
||
The notion of “printer models”
|
||
The notion of a printer model is essentially a device to cover more than one printer using the same data.
|
||
|
||
|
||
Different printer models can be described in the same .wdr 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 any dialog offering a list of
|
||
“printer models" for selection.
|
||
|
||
|
||
Overview of the different command strings
|
||
|
||
|
||
As well as the command strings to select various fonts, a .wdr file contains commands to have the printer
|
||
perform other functions. These commands are by and large clearly named in the listing given earlier, eg
|
||
"ITALIC_ON" and "ITALIC_OFF", "BOLD_ON" and "BOLD_OFF", and "SUPERSCRIPT_ON" and "SUPERSCRIPT_OFF".
|
||
|
||
|
||
If a printer cannot support a given feature, the corresponding command string would generally be left
|
||
null (*"), One possible exception is italic which, if not supported, could 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 font, 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 printer to enter landscape mode (as
|
||
opposed to portrait mode).
|
||
|
||
|
||
The string of commands sent to the printer when printing starts are among 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.
|
||
|
||
|
||
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 zo 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
|
||
|
||
|
||
« 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)
|
||
|
||
|
||
= likewise the string "%c"' means to substitute the specified value as a single byte (character), and
|
||
"%w" 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, "move_pown" is defined as "<27>&at+%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.wadr 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_bpoWN" 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 minx and miny, respectively. Thus if
|
||
skipy is given as 36 whereas miny is given as 20, this translates to an actual 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:
|
||
|
||
|
||
™ WDR_MODEL_LANDSCAPE_AVAILABLE (0x01) has to be set if the model supports being put into
|
||
landscape mode
|
||
|
||
|
||
®@ WDR_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, bear in mind that double height
|
||
fonts generally look much better than double width fonts, so given a choice it is better to omit the latter.
|
||
|
||
|
||
Typeface numbers
|
||
|
||
|
||
The main significance of the typeface number of a typeface is when a document 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.
|
||
|
||
|
||
38
|
||
|
||
|
||
3 WDR PRINTING
|
||
|
||
|
||
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:
|
||
|
||
|
||
S 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)
|
||
|
||
|
||
" WDR_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
|
||
|
||
|
||
= =WDR_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{21
|
||
« 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 tur, 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.
|
||
|
||
|
||
ia ee ee ee ee ee ee
|
||
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 there are 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 of 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
|
||
|
||
|
||
3 WDR PRINTING
|
||
|
||
|
||
and the definition of a comMANDS resource looks like (this is the commanps resource for the file general.wd):
|
||
|
||
|
||
COMMANDS
|
||
RESET ut
|
||
FORM_LENGTH me
|
||
PREAMBLE Hes
|
||
POSTAMBLE wet
|
||
BOLD_ON eat
|
||
BOLD_OFF anet
|
||
ITALIC_ON aM
|
||
ITALIC_OFF a
|
||
UNDERLINE_ON me
|
||
UNDERLINE _OFF a
|
||
SUBSCRIPT_ON baat
|
||
SUBSCRIPT_OFF He
|
||
SUPERSCRIPT_ON es
|
||
SUPERSCRIPT_OFF st
|
||
|
||
|
||
MOVE_DOWN Wee 10>"
|
||
|
||
MOVE_RIGHT_PREFIX ="
|
||
|
||
MOVE_RIGHT We 32>"
|
||
|
||
MOVE_RIGHT_SUFFIX =o
|
||
|
||
NEW_PAGE m<12>u
|
||
|
||
CARRIAGE_RETURN N<13>"
|
||
END_COMMANDS
|
||
|
||
|
||
Parameters to keywords inside a resource definition may be of four types:
|
||
|
||
|
||
Numeric a decimal number which is interpreted as a value (eg a font width)
|
||
|
||
Constant an unquoted string which is interpreted as a numeric value (used only by TYPE
|
||
in a TYPEFACE resource definition)
|
||
|
||
Identifier a lower case unquoted string, used by a command to reference another
|
||
specified resource
|
||
|
||
Quoted string a sequence of characters in quotes that is sent to the printer to perform a
|
||
specific function (eg BOLD_oN); the string may contain control characters (see
|
||
below).
|
||
|
||
|
||
The printer driver translator ignores any characters between an exclamation mark ! and the end of a line
|
||
(unless the ! is in a quoted string). Blank lines are also ignored.
|
||
|
||
|
||
The block indentation scheme in standard .wd files is for convenience only.
|
||
|
||
|
||
Acceptable syntax within a COMMANDS resource definition
|
||
|
||
|
||
Any of the commands listed in the earlier section on command resources in .wdr files can be given.
|
||
However, command strings used to set individual fonts should be given within the relevant TYPEFACE
|
||
resource definition.
|
||
|
||
|
||
Control codes may be needed in the COMMANDS resource definition, or in the COMMAND keyword of a font
|
||
definition. A control code is specified by placing its decimal value in angle brackets ("<" and ">"). For
|
||
example the Esc control code (decimal value 27) is specified as <27>.
|
||
|
||
|
||
Other syntax that may occur within a COMMANDS resource definition are:
|
||
|
||
|
||
USE_DYL to set the woR_DYL_LoaD flag in the wdr-flags in the header resource for the .wdr
|
||
file
|
||
|
||
FLAGS <flags> to or in <flags> to the wdr-flags in the header resource
|
||
|
||
HP_PCL_COMPATIBLE of purely historical significance.
|
||
|
||
|
||
Acceptable commands within a TRANSLATES resource definition
|
||
|
||
|
||
Each line within the definition of a TRANSLATES block should be made up of one or more translations, with
|
||
adjacent translations on any one line being separated from each other by white space.
|
||
|
||
|
||
Individual translations should have the form
|
||
|
||
|
||
<byte>:<byte>
|
||
|
||
|
||
41
|
||
|
||
|
||
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 wiptus 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 typeface-flags
|
||
MULTIPLE_FONT_WIDTH_TABLES of purely historical interest
|
||
|
||
NAME <name> to give the public name of the typeface
|
||
|
||
TYPE <type> to give the typeface number of the typeface
|
||
TRANSLATE <identifier> to specify a TRANSLATES resource 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 COMMAND - 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_AVAILABLE 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
|
||
|
||
|
||
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 tums out
|
||
that two MODEL blocks would otherwise be identical. Note that one MopEL 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:
|
||
|
||
|
||
0 COURIER 22 OPTIONAL_SB 44 RUSSIAN
|
||
|
||
1 PICA 23 OPTIONAL_SC 45 OPTIONAL_B
|
||
|
||
2 ELITE 24 TIMES_ROMAN 46 OPTIONAL_C
|
||
|
||
3 PRESTIGE 25 CENTURY 47 OPTIONAL_D
|
||
|
||
4 LETTER_GOTHIC 26 PALATINO 48 NARRATOR
|
||
|
||
5 GOTHIC 27 SOUVENIR 49 EMPHASIS
|
||
|
||
6 CUBIC 28 GARAMOND 50 ZAPF_CHANCERY
|
||
7 LINEPRINTER 29 CALEDONIA 51 OPTIONAL_DA
|
||
8 HELVETICA 30 BODONI 52 OLD_ENGLISH
|
||
9 AVANT_GARDE 31 UNIVERSITY 53 OPTIONAL_DB
|
||
10 SPARTAN 32 SCRIPT 54 OPTIONAL_DC
|
||
11 METRO 33 SCRIPT_PS 55 COOPER_BLACK
|
||
12 PRESENTATION 34 OPTIONAL_SCA 56 SYMBOL
|
||
|
||
13 APL 35 OPTIONAL_SCB 57 LINE_DRAW
|
||
|
||
14 OCR_A 36 COMMERCIAL_SCRIPT 58 MATH_7
|
||
|
||
15 OCR_B 37 PARK_AVENUE 59 MATH_8
|
||
16 STANDARD_ROMAN 38 CORONET 60 DINGBATS
|
||
|
||
17 EMPEROR 39 OPTIONAL_SCC 61 EAN
|
||
|
||
18 MADELEINE 40 GREEK 62 PC_LINE
|
||
|
||
19 ZAPF_HUMANIST 41 KANA 63 OPTIONAL_SYA
|
||
20 CLASSIC 42 HEBREW
|
||
21 OPTIONAL_SA 43 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 III printer driver. Times Roman on the Laserwriter and CGTimes on the HP IT both have a
|
||
TYPE Of TIMES_ROMAN and so the Times 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 printer's monospaced typefaces should be assigned a Type of courteRr: 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.
|
||
|
||
|
||
See also the Printer driver font mapping section of the Word Processor File Format chapter.
|
||
|
||
|
||
43
|
||
|
||
|
||
CHAPTER 4
|
||
|
||
|
||
DBF FILES
|
||
|
||
|
||
ey a a oe ae ee ee a ee 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 ee ee a eae
|
||
Basic structure of DBF files
|
||
|
||
|
||
The following discussion is based around a DBF file created by a simple OPL 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") :delete "test.dbf" sendif
|
||
create "test.dbf",a,f1%, 2%, 3%, f4
|
||
a. f1$="Hello"”
|
||
a. feg=au
|
||
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 \opd\ 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 £18, f2$, £3%, 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
|
||
|
||
|
||
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 10 05 48 — wane wee eee H
|
||
20: 65 6c 6c 6f 07 32 03 00 00 00 00 00 00 00 10 40 eOLlLO.2.. weeccee a
|
||
30: 12 10 05 57 6f 72 6c 64 01 32 03 00 00 00 00 00 eeeWorkd .2......
|
||
40: 00 00 10 40 ee)
|
||
|
||
|
||
This conforms to the standard DBF format of
|
||
|
||
|
||
<standard header><extended header><field information record><other 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 I 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-terminated string "opLDatabasef ile". 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 offset 0x10 and the two bytes at offset 0x14 represent software version numbers. See
|
||
the System Information section of the General System Services chapter of the PLIB Reference manual for
|
||
an explanation of the format of a version number.
|
||
|
||
|
||
The two bytes at file offset 0x10 represent the version number of the software that generated the file.
|
||
Files generated by the Series 3 and Series 3a Data applications have these bytes set to <0f><10>. Files
|
||
generated by OPL set these two bytes differently on different machines: on the HC and Series 3 they are
|
||
set to <Of><11> and on the Series 3a and Workabout they are set to <1f><11>. If generated by version 1 of
|
||
ISAM the two bytes are set to <00><10> (which, strictly speaking, is not a legal version number).
|
||
|
||
|
||
The two bytes at file offset 0x14 represent the minimum version number of DBF software that is required
|
||
to interpret the contents of the file. Files generated by the Series 3 and Series 3a Data applications have
|
||
these bytes set to <0f><10>. Files generated by OPL set these two bytes to <0f><11> on all machines. If
|
||
generated by version 1 of ISAM the two bytes are set to <00><10> (which, strictly speaking, is not a legal
|
||
version number).
|
||
|
||
|
||
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>.
|
||
|
||
The extended header
|
||
|
||
A DBF file has an extended header only if an application calls the PLIB function pbf€xtHeaderwrite. 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 rype J record (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.
|
||
|
||
|
||
46
|
||
|
||
|
||
4 DBF FILES
|
||
|
||
|
||
= 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 records 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>.
|
||
|
||
|
||
In the example DBF file (see above) the record immediately following the field information record has
|
||
<12><10> as its header and is thus a type J record, with a body of length 0x12 bytes.
|
||
|
||
|
||
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 ] 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 0 deleted record.
|
||
|
||
type 1 standard record.
|
||
|
||
type 2 field information record.
|
||
type 3 descriptive record.
|
||
|
||
|
||
Deleted records
|
||
Consider the following OPL program, which differs from the earlier one in only one line:
|
||
|
||
|
||
PROC writedbf:
|
||
if exist("test.dbf") :delete "test.dbf" sendif
|
||
create "test.dbf",a,f1$, f28, 3%, £4
|
||
a.fi$="Hello"
|
||
a.f2g="2"
|
||
a.f3%=3
|
||
a.f4=4
|
||
append
|
||
a. f1$="Wortd"
|
||
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 0005 48 ~~... wee H
|
||
20: 65 6c 6c 6f 01 32 03 00 O00 00 00 00 00 00 10 40 COE. oasis s.0'e0 a
|
||
30: 12 10 05 57 6f 72 6c 64 01 32 03 00 00 00 00 00 ---World .2......
|
||
40: 00 00 10 40 oo of
|
||
|
||
|
||
47
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
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 0xic 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 bbfxxx calls and the OPL
|
||
database functions such as find and count).
|
||
|
||
|
||
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. Each field has a two
|
||
byte header that contains the field's type and length, in the same format as for a record header.
|
||
|
||
|
||
The types have 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 I record to have entries for each field 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 (type 2} 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 J record in the file
|
||
consists of a variable arbitrary number of string fields (where this number can exceed or fall short of 32).
|
||
|
||
|
||
48
|
||
|
||
|
||
4 DBF FILES
|
||
|
||
|
||
Extended header
|
||
|
||
|
||
There are no extended headers on any Series 3 Database files.
|
||
|
||
|
||
Descriptive (type 3) record
|
||
|
||
|
||
For an example of a descriptive (type 3) record consider the following dump of a default newly-created
|
||
and exited Series 3 Database .dbf file (see below for a Series 3a example):
|
||
|
||
|
||
O: 4f 50 4c 44 61 74 61 62 61 73 65 46 69 Gc 65 00 OPLDatab aseFile.
|
||
10: Of 10 16 00 Of 10 20 20 03 03 03 03 03 03 03 03 1... cee eee
|
||
20: 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 nc cack cece ween
|
||
30: 03 03 03 03 03 03 03 03 31 30 02 10 04 0002 50_~=(i........ . .. ht ee P
|
||
40: 05 00 27 40 05 4e 61 6d 65 3a 07 05 20 48 6f 6d ..'d.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:
|
||
|
||
|
||
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.
|
||
|
||
|
||
The body of a Database descriptive record contains a series of fields, each of which has a header that
|
||
gives its type and length, in the same format as the record header. A Series 3 descriptive record contains
|
||
the following fields:
|
||
|
||
|
||
® afield of type 1 and length 2.
|
||
= a field of type 5 and length 2.
|
||
= a field of type 4 and variable length; in the above example, the length is 0x27.
|
||
|
||
|
||
Series 3a Database files are longer because the descriptive records contain more fields. Here is a newly-
|
||
created and exited Series 3a Database .dbf file.
|
||
|
||
|
||
QO: 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~—(iw.a
|
||
20: 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03
|
||
30: 03 03 03 03 03 03 03 03 aa 30 02 10 04 00 02 50
|
||
40: 14 00 3a 60 82 2e c6 41 08 07 08 07 72 20 b6 33 we cipeecA cecal 33
|
||
50: dO 02 dO 02 00 00 00 00 01 00 ff ff 00 00 00 00
|
||
60: 0 00 00 00 00 00 00 00 f0O 00 O02 00 00 00 00 00
|
||
|
||
|
||
70: 00 00 00 00 00 00 f0 00 00 00 00 00 00 00 Od 70. ........ .... weep
|
||
80: 00 52 4f 4d 3a 3a 42 4a 2e 57 44 52 00 Oc 80 00 «ROM::BuJ .WDR....
|
||
90: 00 00 25 50 00 82 2e c6& 41 08 07 Oc 90 25 50 00 oehPoces Aree APe
|
||
a0: 82 2e c6 41 08 07 08 07 72 03 a0 01 00 01 04 bd SoA Mee” Mele e-c cee
|
||
|
||
: 00 00 ff ff 2e 40 05 4e 61 6d 65 3a 07 05 20 48~—tiw.... @.N ame:.. H
|
||
|
||
|
||
cO: 6f 6d 65 3a 07 05 20 57 6f 72 6b 3a 06 05 20 46 ome:.. Work:.. F
|
||
dO: 61 78 3a 08 41 64 64 72 65 73 73 3a 00 06 4e 6f ax:.Addr ess:..No
|
||
e0: 74 65 73 3a tes:
|
||
|
||
|
||
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 3a Database descriptive record contains the three fields described above, together
|
||
with the following additional fields:
|
||
|
||
|
||
= a field of type 6 and length 58.
|
||
= afield of type 7 and variable length.
|
||
= afield of type 8 and variable length.
|
||
= a field of type 9 and variable length.
|
||
= a field of type 10 and length 3.
|
||
= a field of type 11 and length 4.
|
||
The currently used field types are as follows:
|
||
type 1 the width of a tab, in columns.
|
||
|
||
|
||
type 4 template data, containing leading-byte-counted text for the labels of
|
||
consecutive lines of the display of a database entry (a line that has no label is
|
||
represented by a single zero byte).
|
||
|
||
|
||
49
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
type 5 general flags options, described below.
|
||
|
||
type 6 printer setup information, in the form of a PRINTER_PARAMS Structure.
|
||
|
||
type 7 printer model: a zero terminated string that starts with the model number and
|
||
continues with the full file specification of the printer driver file.
|
||
|
||
type 8 text for the page header: a zero terminated string.
|
||
|
||
type 9 text for the page footer: a zero terminated string.
|
||
|
||
type 10 the diamond bar settings: bytes zero, one or two are non-zero if 'Find',
|
||
|
||
|
||
‘Change’ or 'Add', respectively, are included in the diamond bar.
|
||
|
||
|
||
type 11 the current search field data: the first two bytes specify the start field (with
|
||
0x0000 meaning search in all fields), the second two bytes specify the end field
|
||
(with Oxffff meaning search from the specified start field to the last field in the
|
||
record. For example, values of 0x0010 and 0x0020 would imply a search from
|
||
field sixteen to field thirty two inclusive.
|
||
|
||
|
||
For further details of the content of fields of type 6, 7, 8 and 9, see Saving and restoring print context
|
||
from file in the Printing chapter of the Object Oriented Programming Guide.
|
||
|
||
|
||
Other descriptive record field 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.
|
||
|
||
|
||
In the above example it can be seen that the width of the tab is equal to 4 columns, as given by the third
|
||
and fourth bytes of the type J field that starts at offset 0x3b (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.
|
||
|
||
|
||
Note that the first character in a template field name can be a telephone symbol (0x05) in which case the
|
||
content of the corresponding field in any type 1 record can be used for automated dialling.
|
||
|
||
|
||
Flags options for the Series 3 Database
|
||
The meanings of possible bits in the general flags options (field type 5) are as follows:
|
||
|
||
|
||
0x01 the permanent status window is on
|
||
0x02 entries are word-wrapped
|
||
0x04 a template should be displayed.
|
||
|
||
|
||
All other bits are ignored and should, by default, be set to zero.
|
||
|
||
|
||
Flags options for the Series 3a Database
|
||
The type 5 field in a Series 3a Database descriptive record supports the following flags:
|
||
|
||
|
||
0x01 this bit is ignored by the Series 3a Database
|
||
|
||
0x02 entries are word-wrapped if this bit is set
|
||
|
||
0x04 a template should be displayed if this bit is set
|
||
|
||
0x08, 0x10 if both bits are clear there is no permanent status window; if bit 0x08 is set and
|
||
|
||
|
||
bit 0x10 is clear a small status window is displayed; if bit 0x10 is set and bit
|
||
0x08 is clear a large status window is displayed (bits 0x08 and 0x10 should not
|
||
both be set)
|
||
|
||
|
||
0x20, 0x40 these two bits record the zoom size of the text in the main display window
|
||
according to the following table:
|
||
|
||
|
||
0x00 Roman-11
|
||
0x20 Roman-13
|
||
0x40 Roman-16
|
||
0x60 Roman-8
|
||
|
||
|
||
All other bits are ignored and should, by default, be set to zero.
|
||
|
||
|
||
Type 1 records
|
||
Entries in the Database are stored as single type J records in the corresponding .dbf file.
|
||
|
||
|
||
50
|
||
|
||
|
||
4 DBF FILES
|
||
|
||
|
||
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 side 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 preceding byte count)
|
||
|
||
|
||
= additional continuation sub-fields of up to 254 characters are used as required, in each case again
|
||
being preceded by the 0x14 character.
|
||
|
||
|
||
The continuation sub-field prefix character was in fact specially chosen so as to give a suggestive display
|
||
on the MC, should the .ddf file be read into the MC Database application.
|
||
|
||
|
||
5 a SS |
|
||
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.
|
||
|
||
|
||
Descriptive record
|
||
|
||
|
||
For an example of a descriptive record, consider the following, which is a dump of a default newly-
|
||
created (and exited) Series 3 .agn 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 05 20 00 00 00 00 03 0e 30 Oc ww... wwe 0.
|
||
20: f0 a4 01 3c 00 01 00 OF 00 1c 02 2e 00 seSecee. ome
|
||
|
||
|
||
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 ox0c. 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
|
||
|
||
|
||
51
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
= 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.
|
||
|
||
|
||
For example, if the value of Time is 0x3fc and the value of AlarmTime is 0x1b2, the actual alarm pre-time
|
||
is
|
||
|
||
|
||
Ox3fe + Ox1b2 - (23*60 + 59)
|
||
ie 15 minutes (for an appointment actually at Spm in the afternoon).
|
||
|
||
|
||
In the case of untimed appointments, the integer value obtained when AlarmTime 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.
|
||
|
||
|
||
52
|
||
|
||
|
||
4 DBF FILES
|
||
|
||
|
||
Finally, note that if an appointment does not have an alarm set for it, the value of AlarmTime should be
|
||
set to Oxffff.
|
||
|
||
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 contents of the field. For repeated
|
||
items, the final six bytes of the Text field have a special meaning, as discussed below.
|
||
|
||
|
||
In all cases, the length of the actual text for an appointment cannot exceed 63 characters.
|
||
|
||
|
||
ToDo items
|
||
|
||
|
||
ToDo items have a DayNumber of Oxf#ff, 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 normal timed and untimed items,
|
||
except that they have a DayNumber of Oxfffe.
|
||
|
||
|
||
The specific repeat details are stored in the six bytes at the end of the Text field and have the following
|
||
format:
|
||
|
||
|
||
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.
|
||
|
||
|
||
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
|
||
|
||
|
||
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.
|
||
|
||
|
||
SESE SS SS a a a ae ae TT
|
||
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 (AGD_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 "AgendafiteType*". This is used to
|
||
identify the file as an Agenda file.
|
||
|
||
|
||
The two byte parameter version, at file offset 0x0010, is the file version number, as described in the
|
||
General System Services chapter of the Plib Reference manual. This is currently always 0x100F. The most
|
||
significant nibble is the major version number; 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 is reserved for future use by Psion.
|
||
|
||
|
||
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, with the type and length combined
|
||
into a single word (two bytes). The most significant nibble of the word gives the record type. The type
|
||
|
||
|
||
55
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
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 not used.
|
||
|
||
|
||
SSS SS eee ee en eS ee ee ee)
|
||
Record Types
|
||
|
||
|
||
There are sixteen record types as follows.
|
||
|
||
|
||
Type Record
|
||
|
||
0 Deleted
|
||
|
||
1 Appointments Gimed 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 a 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).
|
||
|
||
|
||
aS 6 ee eee oe ee ae
|
||
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 0 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.
|
||
|
||
|
||
There may be any number of such records in the file.
|
||
|
||
|
||
56
|
||
|
||
|
||
5 SERIES 3A AGENDA FILE FORMAT
|
||
|
||
|
||
ESE SSS SS SS ee ee ee ee eS a
|
||
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.
|
||
|
||
|
||
coe
|
||
|
||
|
||
AIK
|
||
|
||
|
||
This field contains most of the non-textual information describing when an entry occurs, what other
|
||
fields it has and various bits of type specific information, such as the duration for timed appointments.
|
||
|
||
|
||
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 daynur 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.
|
||
|
||
|
||
stot is the time slot (in minutes from midnight) in which the entry will appear in
|
||
the Day and Week views. For example a stot 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.
|
||
|
||
|
||
attr is the attributes byte (see below).
|
||
|
||
|
||
57
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
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.
|
||
|
||
|
||
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 structured 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 Ipm slot. If this is oxffff 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 and 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 AD
|
||
|
||
|
||
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 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 disptayFrom daynum is Oxffff, then this is an un-dated to-do i.e. one that
|
||
always appears on today. In this case the dueDate will also be Oxffff.
|
||
|
||
|
||
slot the time slot (in minutes from midnight) in which the entry will appear in the
|
||
Day and Week views. If this is oxffff then the entry will appear in the default
|
||
slot of the appropriate to-do list.
|
||
|
||
|
||
58
|
||
|
||
|
||
5 SERIES 3A AGENDA FILE FORMAT
|
||
|
||
|
||
attr the attributes byte (see below).
|
||
|
||
|
||
code 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 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 the ID (in the range 0 to 255 inclusive) of the to-do list in which the entry will
|
||
|
||
|
||
appear. Note that a value of zero does nor necessarily mean that the entry
|
||
appears on the first to-do list in the To-do view - the order is determined by
|
||
the contents of a type 11 record. See the description of type 9 records for
|
||
further details of this ID.
|
||
|
||
|
||
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:
|
||
0 - Automatic, shown as a date until within one week of the due date, then
|
||
|
||
shown as, for example, "Next Wed".
|
||
|
||
1 - Always shown as a date.
|
||
2 - Shown as the number of days until the due date.
|
||
3 - The due date is 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 ‘aftr’.
|
||
|
||
|
||
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 wie Geld
|
||
The title field must be present for entry records of all four types. This field follows immediately after the
|
||
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.
|
||
|
||
|
||
The format of the title field is:
|
||
|
||
|
||
59
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
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 not zero terminated.
|
||
|
||
|
||
This fixed length field is only present if the attributes byte does not have 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 of a 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 ten 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.
|
||
|
||
|
||
This variable length field is only present if the attributes byte (in the details field) does not have bit 4
|
||
(0x10) set, i.e. there is a memo attached to the entry.
|
||
|
||
|
||
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;
|
||
UWORD Leni;
|
||
|
||
UWORD len2;
|
||
|
||
UBYTE data [I];
|
||
UBYTE data2[];
|
||
|
||
|
||
dataLength is the length (in bytes) of the data in the memo field. This can be between 0
|
||
and 3600 (inclusive) and includes two separate blocks of data.
|
||
|
||
tent the length of the first block of data, with the two most significant bits used for
|
||
flags
|
||
|
||
len2 the length of the second block of data
|
||
|
||
data contains len1&0x3fff bytes of data. If teni has the bit 0x4000 set, the first ten
|
||
|
||
|
||
bytes contain options data, as described for the options data (type 1) record in
|
||
the Word Processor Files Format chapter, otherwise a default set of options
|
||
(the word processor default options) is used. If ten1 has the bit 0x8000 set, the
|
||
memo is password-protected. In this case the next eighteen bytes contain
|
||
password-matching information and the following data is encrypted. The
|
||
remaining bytes contain the plain text of the memo, with each paragraph
|
||
terminated by a zero byte. As described for the word processor file format, the
|
||
data does not include the final zero terminator.
|
||
|
||
|
||
60
|
||
|
||
|
||
5 SERIES 3A AGENDA FILE FORMAT
|
||
|
||
|
||
data2 len2 bytes of data containing the document index for the memo. This is in
|
||
exactly the same format as described in the Word Processor File Format
|
||
chapter for the document index (type 9) record.
|
||
|
||
|
||
EEE ee ee eee ee ee ea
|
||
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 record 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
|
||
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.
|
||
|
||
|
||
The repeat record is structured as follows:
|
||
|
||
|
||
UBYTE alg;
|
||
|
||
UBYTE ival;
|
||
|
||
UWORD endDate;
|
||
UBYTE type;
|
||
|
||
UBYTE tags[n];
|
||
ULONG filePos;
|
||
UWORD exceptions [];
|
||
|
||
|
||
alg 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.
|
||
|
||
|
||
ival 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.
|
||
|
||
|
||
endDate 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.
|
||
|
||
|
||
Note that the Agenda does not support anniversaries that repeat for limited
|
||
periods. In consequence, it is recommended (but not required) that a repeat
|
||
record for an anniversary (type 3) record should have an endDate set to the
|
||
value Oxffff.
|
||
|
||
|
||
type is the type (1-4) of the associated entry record. The Agenda requires this
|
||
information to be present, even though it is technically redundant (since it can
|
||
be determined from the associated record itself).
|
||
|
||
|
||
61
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
tags 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.
|
||
|
||
|
||
filePos 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 FitePos fields to be recalculated.
|
||
|
||
|
||
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 is
|
||
determined by the length of the record. Although 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 non-displayable 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
|
||
merging files. In this case incoming anonymous data records are added to the file into which data is being
|
||
merged.
|
||
|
||
|
||
Types 7 and 8 - reserved
|
||
|
||
|
||
These record types are reserved for future expansion and should not be used.
|
||
|
||
|
||
Type 9 - to-do list information
|
||
|
||
|
||
There is one record of this type for each to-do list in the Agenda. Each contains the settings 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:
|
||
|
||
|
||
5 SERIES 3A AGENDA FILE FORMAT
|
||
|
||
|
||
UBYTE sig;
|
||
|
||
UBYTE cat;
|
||
|
||
TEXT name[16+1};
|
||
UBYTE catid;
|
||
UWORD flags;
|
||
UWORD vis_slot;
|
||
UBYTE advance_days;
|
||
UBYTE yearcode;
|
||
AGPREF_ALARM a;
|
||
UBYTE style;
|
||
UBYTE spare;
|
||
|
||
|
||
sig a signature byte which determines the format of the rest of the record.
|
||
Currently the only legal value is Oxff
|
||
|
||
|
||
cat the ID, in the range 0 to 255 inclusive,! of the to-do list to which the type 9
|
||
record refers. The settings apply to all to-do entries (type 4 records) that have
|
||
a value of the ListNo field that is equal to the value of cat. See the description
|
||
of the type 11 record for the order of appearance of to-do lists in the To-do
|
||
|
||
|
||
view.
|
||
|
||
name [1 the name of the to-do list, containing up to 16 characters. The remaining bytes
|
||
of name] are all NULL
|
||
|
||
catid the to-do list ID, as in cat, repeated for reasons of coding convenience
|
||
|
||
flags the contents of this field are described below
|
||
|
||
vis_slot the default position in the Day view, in minutes from midnight
|
||
|
||
|
||
advance_days
|
||
|
||
|
||
the default number of days advance warning for alarms. The value is retained
|
||
|
||
|
||
even when the list is not dated
|
||
|
||
|
||
yearcode the ASCII code of the character used in the year view. This character is always
|
||
specified, even if the to-do list is not visible in other views
|
||
|
||
|
||
a an AGPREF_ALARM struct that specifies any untimed alarm. See the explanation of
|
||
this struct in the later description of the General Descriptive (type 13) record
|
||
|
||
|
||
style the default style for entries. Its value is either G_STY_NORMAL, or any
|
||
combination of G_STY_BOLD, G_STY_ITALIC and G_STY_UNDERLINE
|
||
|
||
|
||
spare this field is not currently used in Agenda files, but should be set to zero. It is
|
||
reserved for use by future file versions.
|
||
|
||
|
||
The flags field
|
||
|
||
|
||
This field contains, in its least significant four bits, a value between one and nine inclusive. This
|
||
specifies the lowest priority of item that will be displayed in other views.
|
||
|
||
|
||
The two flag values 0x0010 and 0x0020 are mutually exclusive and determine the order in which items are
|
||
listed. If bit 0x0020 is set, the items in the to-do list are listed in a user-specified order. Alternatively, if
|
||
bit 0x0010 is set, the items are ordered by priority, with items of the same priority listed by date. If
|
||
neither bit is set, items are listed in date order, with items of the same date listed by priority.
|
||
|
||
|
||
If bit 0x0040 is set, crossed-out entries are shown in the list.
|
||
If bit 0x0080 is set, crossed-out entries are shown in other views, provided that bit 0x0200 is also set.
|
||
|
||
|
||
If bit 0x0100 is set, the entries are displayed with sequentially numbered bullets, otherwise they are
|
||
bulleted with their priorities.
|
||
|
||
|
||
Setting bit 0x0200 specifies that the entries are displayed in other views.
|
||
Setting bit 0x0400 specifies that entries are dated by default.
|
||
|
||
|
||
Bit 0x0800 is used internally by the Agenda application and may be set or clear in a type 9 record. It is
|
||
ignored when the record is read.
|
||
|
||
|
||
1 There is no need for to-do list IDs to be consecutive. An ID can have any value up to, and including,
|
||
255. However, a to-do list ID generated from within the Agenda application will always lie within the
|
||
range O to 98 inclusive.
|
||
|
||
|
||
63
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
The most significant four bits are not used, and should be set to zero. (
|
||
|
||
|
||
ee ea et et ee eee ee ey eee
|
||
Types 10 to 14 - descriptive records
|
||
|
||
|
||
Records of types 10 to 14 inclusive 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 of each type 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 header 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 TLV fields should not added even though
|
||
these would be ignored).
|
||
|
||
|
||
Type 10 to 14 records are described in greater detail below.
|
||
|
||
|
||
== SSeS ee ee ey (
|
||
Type 10 - styles descriptive record
|
||
|
||
|
||
The styles descriptive record contains the styles and emphases that are used by the Memo editor for all
|
||
memos in the file.
|
||
|
||
|
||
This record is written when a memo has been created for the first time, and thereafter whenever its
|
||
content has changed.
|
||
|
||
|
||
The body of this record contains the following:
|
||
|
||
|
||
UWORD stylen;
|
||
|
||
UWORD emphlen;
|
||
|
||
UBYTE stydata[stylen];
|
||
UBYTE emphdatalemphlenj;
|
||
|
||
|
||
stylen the total length of the following style data
|
||
emphLen the total length of the following emphasis data
|
||
stydata styten bytes of data, consisting of one or more styles. Each style occupies 80
|
||
|
||
|
||
bytes and is of the same structure as described in the Word Processor File
|
||
Format chapter for the body of the word processor style data (type 6) record
|
||
|
||
|
||
emphdata emphlen bytes of data, consisting of one or more emphases. Each emphasis
|
||
occupies 28 bytes and is of the same structure as described in the Word
|
||
Processor File Format chapter for the body of the word processor emphasis
|
||
data (type 7) record
|
||
|
||
|
||
SS Se Se en a re
|
||
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
|
||
has in the To-do view. The body of the record consists of three or more bytes, structured as follows:
|
||
|
||
|
||
UBYTE sig;
|
||
UBYTE ncats;
|
||
UBYTE catid[ncats]
|
||
|
||
|
||
sig is the signature and is always Oxéc.
|
||
|
||
|
||
neats is the number of categories, and must not exceed 99.
|
||
|
||
|
||
5 SERIES 3A AGENDA FILE FORMAT
|
||
|
||
|
||
catidincats] determines the order of appearance of to-do lists in the To-do view. The array
|
||
contains the IDs, in display order, of all the to-do lists in the Agenda file.
|
||
Thus catidt0] holds the ID of the first displayed list, catid(1] the ID of the
|
||
second, and so on, up to a maximum of catid[98}.
|
||
|
||
|
||
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. The body consists of a TLV
|
||
header word (type zero, length 18) 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
|
||
(0 = 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.
|
||
|
||
|
||
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.
|
||
|
||
|
||
This record contains entry defaults and all individual view preferences (to-do entry defaults are stored in
|
||
to-do list records). Each record has the normal Agenda type/length header followed by one or more TLV
|
||
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
|
||
|
||
8 Day view settings
|
||
|
||
9 Week view settings
|
||
10 Year view settings
|
||
11 To-do view settings
|
||
12 Anniversary view settings
|
||
13 List view settings
|
||
|
||
14
|
||
|
||
|
||
Diamond list setup field =
|
||
|
||
|
||
The diamond list setup field indicates which views should be included in the diamond list. It consists of
|
||
six bytes structured as follows:
|
||
|
||
|
||
UBYTE fnbar [6] ;
|
||
|
||
|
||
65
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
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.
|
||
|
||
|
||
The day entry defaults field contains the defaults for entries in the Day view. The field consists of 38
|
||
bytes structured as follows:
|
||
|
||
|
||
UWORD DefUntimedEntViewT ime;
|
||
UWORD DefTimedEntT ime;
|
||
|
||
UWORD DefTimedEntDuration;
|
||
UBYTE DefTimedByDefault;
|
||
UBYTE DefYearSym;
|
||
AGPREF_ALARM UntimedAlarmefs;
|
||
AGPREF_ALARM TimedAlarmefs;
|
||
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, otherwise it is 0.
|
||
|
||
DefYearSym is the character code for the default year symbol.
|
||
|
||
Unt imedAlarmDefs contains details of the default alarm for untimed 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 c_sTy_xxx flags: 0x00 for normal, 0x01 for bold, 0x02
|
||
for underline and 0x20 for italics.
|
||
|
||
|
||
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).
|
||
|
||
|
||
The SE_SND structure contains details of the default alarm sound. It consists of ten bytes structured as
|
||
follows:
|
||
|
||
|
||
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 len characters. When
|
||
len is less than eight the first unused byte contains a NULL character. Any
|
||
remaining unused bytes can take any value.
|
||
|
||
|
||
66
|
||
|
||
|
||
5 SERIES 3A AGENDA FILE FORMAT
|
||
|
||
|
||
zero_term contains the NULL character.
|
||
|
||
|
||
An anniversary entry defaults field contains the defaults for entries in the Anniversary view. It consists of
|
||
20 bytes structured as follows:
|
||
|
||
|
||
UWORD DefEntViewT ime;
|
||
UBYTE AutoApplyYearSym;
|
||
UBYTE DefYearSym;
|
||
AGPREF_ALARM AlarmDefs;
|
||
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.
|
||
|
||
Alarmefs 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 ored
|
||
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.
|
||
|
||
|
||
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.
|
||
|
||
|
||
teft 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:
|
||
|
||
|
||
67
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
UWORD flags;
|
||
UWORD begintime;
|
||
UWORD beginvis;
|
||
UWORD endvis;
|
||
UWORD endtime;
|
||
UWORD slotdur;
|
||
|
||
|
||
flags oo a combination of the slot lines on flag (0x01) and the slot times on flag
|
||
x .
|
||
|
||
begint ime 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.
|
||
|
||
|
||
The Week view settings field consists of two bytes as follows:
|
||
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.
|
||
|
||
|
||
The Year view settings 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.
|
||
|
||
|
||
The To-do view settings field consists of two bytes structured as follows:
|
||
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.
|
||
|
||
|
||
The Anniversary view 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).
|
||
|
||
|
||
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).
|
||
|
||
|
||
68
|
||
|
||
|
||
3 SERIES 3A AGENDA FILE FORMAT
|
||
|
||
|
||
—SSS SSS ee ee ee ee ee
|
||
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 TLV 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.
|
||
|
||
|
||
LSS SSS SS ee ee ee ae ee ae)
|
||
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.
|
||
|
||
|
||
This record type is probably best thought of as an End Of File record, and any program finding a file
|
||
with a type 15 record should start by setting the end of the file to the start (the type length word) of the
|
||
record.
|
||
|
||
|
||
CHAPTER 6
|
||
|
||
|
||
WORD PROCESSOR FILE FORMAT
|
||
|
||
|
||
This document describes the structure of a Psion word processor document file. The description to a level
|
||
that allows other software to read and write non-password-protected document files.
|
||
|
||
|
||
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
|
||
|
||
|
||
Document files created by the word processor will contain records in the order listed above. Each record
|
||
consists of:
|
||
|
||
|
||
# atwo-byte record type
|
||
= atwo-byte record length, len
|
||
= 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.
|
||
|
||
|
||
ee ee ee ae aR a eS a a,
|
||
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 OxeEA.
|
||
|
||
|
||
The remaining two bytes of the header are reserved for future use.
|
||
|
||
|
||
71
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
3 == ae en ee a ee
|
||
Record types
|
||
|
||
|
||
The options data record contains the following items:
|
||
|
||
|
||
UWORD cpos the saved cursor position
|
||
UBYTE symbols specifies the visibility of screen symbols, as indicated below
|
||
UBYTE backup/statzoom on the MC, a non-zero value indicates that backup files are to be maintained
|
||
|
||
|
||
on the Series 3a this byte stores the current status window and zoom states: the
|
||
top four bits indicate the current zoom state (0x22 by default) and the lowest
|
||
four bits indicate the status window size: 0, 1 or 2 for off, small or big
|
||
respectively
|
||
|
||
|
||
this byte is not used on the Series 3
|
||
UBYTE style TRUE to show style bar at the left of the text
|
||
|
||
|
||
for the OPL program editor, a TRUE value sets the use of a bold typeface
|
||
|
||
|
||
UBYTE mono TRUE to load text by line, else by paragraph
|
||
’ for the OPL program editor, a TRUE value sets the use of a monospaced
|
||
typeface
|
||
UBYTE outlevel lowest outline level to display
|
||
|
||
|
||
not used for the OPL program editor
|
||
|
||
|
||
UBYTE spare! reserved for future use, but may contain the OPL program editor data as
|
||
follows:
|
||
|
||
|
||
used by the OPL program editor, where a TRUE value specifies the use of auto
|
||
indentation. Set to TRUE by default
|
||
|
||
|
||
UWORD spare2 reserved for future use, but may contain the OPL program editor data as
|
||
follows:
|
||
used by the OPL program editor, to specify the column spacing for tabs. Set to
|
||
2 by default
|
||
|
||
Displayed screen symbols are determined by any combination of the following bit fields in symbols:
|
||
|
||
0x01 show tabs
|
||
|
||
0x02 show spaces
|
||
|
||
0x04 show paragraph end markers
|
||
|
||
0x08 show hyphens
|
||
|
||
0x10 show forced line breaks
|
||
|
||
|
||
i ta record {t: 1 2
|
||
This record contains information required to format the document for the printer and to control the
|
||
|
||
|
||
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 PAGES HEADER structs, defined as:
|
||
|
||
|
||
typedef struct
|
||
{
|
||
WORD x;
|
||
WORD y;
|
||
} P_POINT;
|
||
|
||
|
||
72
|
||
|
||
|
||
6 WORD PROCESSOR FILE FORMAT
|
||
|
||
|
||
typedef struct
|
||
€
|
||
P_POINT tl;
|
||
WORD width;
|
||
WORD height;
|
||
> P_EXTENT;
|
||
|
||
|
||
typedef struct
|
||
€
|
||
UWORD fid;
|
||
UWORD style;
|
||
UWORD height;
|
||
}> SCRLAY_FONT;
|
||
|
||
|
||
typedef struct
|
||
€
|
||
SCRLAY_FONT f;
|
||
UBYTE align;
|
||
UBYTE first_page;
|
||
} PAGES_HEADER;
|
||
|
||
|
||
/* typeface number */ (1)
|
||
/* font style */ (2)
|
||
/* height of font in twips */
|
||
|
||
|
||
/* font data */
|
||
/* header alignment */ (3)
|
||
/* TRUE to emit on first page */
|
||
|
||
|
||
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
|
||
|
||
|
||
page width
|
||
|
||
page height
|
||
|
||
body print region, with respect to top left of page (4)
|
||
|
||
page header position (5)
|
||
|
||
page footer position (6)
|
||
|
||
0 for portrait, 1 for landscape
|
||
|
||
can be 3 or 0, depending on whether the document has or has not been printed
|
||
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
|
||
|
||
|
||
73
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
Notes
|
||
(1) Typeface numbers are defined in the following list:
|
||
|
||
|
||
0 COURIER 22 OPTIONAL_SB 44 RUSSIAN
|
||
|
||
1 PICA 23 OPTIONAL_SC 45 OPTIONAL_B
|
||
2 ELITE 24 TIMES ROMAN 46 OPTIONAL_C
|
||
3 PRESTIGE 25 CENTURY 47 OPTIONAL_D
|
||
4 LETTER_GOTHIC 26 PALATINO 48 NARRATOR
|
||
|
||
5 GOTHIC 27 SOUVENIR 49 EMPHASIS
|
||
|
||
6 CUBIC 28 GARAMOND 50 ZAPF_CHANCERY
|
||
7 LINEPRINTER 29 CALEDONIA 51 OPTIONAL_DA
|
||
8 HELVETICA 30 BODONI 52 OLD_ENGLISH
|
||
9 AVANT_GARDE 31 UNIVERSITY 53 OPTIONAL_DB
|
||
10 SPARTAN 32 SCRIPT 54 OPTIONAL_DC
|
||
11 METRO 33 SCRIPT_PS 55 COOPER_BLACK
|
||
12 PRESENTATION 34 OPTIONAL_SCA 56 SYMBOL
|
||
|
||
13. APL 35 OPTIONAL_SCB 57 LINE_DRAW
|
||
|
||
14 OCR_A 36 COMMERCIAL_SCRIPT 58 MATH_7
|
||
|
||
15 OCR_B 37 PARK_AVENUE 59 MATH_8
|
||
|
||
16 STANDARD_ROMAN 38 CORONET 60 DINGBATS
|
||
|
||
17 EMPEROR 39 OPTIONAL_SCC 61 EAN
|
||
|
||
18 MADELEINE 40 GREEK 62 PC_LINE
|
||
|
||
19 ZAPF_HUMANIST 41 KANA 63 OPTIONAL_SYA
|
||
20 CLASSIC 42 HEBREW
|
||
|
||
21 OPTIONAL_SA 43 OPTIONAL_A
|
||
|
||
|
||
A typeface that is not supported by the current printer will be mapped to a supported typeface. See the
|
||
later Printer driver font mapping section.
|
||
|
||
|
||
In addition, a typeface number of -1, indicating an inherited font, is allowed in all emphases and in all
|
||
paragraph styles except Body text. An emphasis inherits its font from the surrounding paragraph; a
|
||
paragraph style inherits its font from the Body text style.
|
||
|
||
|
||
(2) The font style may be zero, or any sensible combination of the following attributes:
|
||
|
||
|
||
0x01 underline
|
||
0x02 bold
|
||
|
||
0x04 italic
|
||
|
||
0x08 superscript
|
||
0x10 subscript
|
||
|
||
|
||
Styles or style combinations that are not supported by the current printer are ignored.
|
||
|
||
|
||
The value 0x4000 is used internally by the word processor and may or may not be set in the font style data
|
||
in the document. If set, it can safely be ignored.
|
||
|
||
|
||
(3) The running page header alignment may be any one of:
|
||
|
||
|
||
0 left aligned
|
||
|
||
1 right aligned
|
||
2 centred
|
||
|
||
4 2-column
|
||
|
||
5 3-column
|
||
|
||
|
||
(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 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.
|
||
|
||
|
||
74
|
||
|
||
|
||
6 WORD PROCESSOR FILE FORMAT
|
||
|
||
|
||
(8) The page number style is one of:
|
||
|
||
|
||
i) 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 Pagetype Width Height
|
||
A4
|
||
|
||
|
||
0 11906 16838
|
||
1 Custom - -
|
||
2 Executive 10440 15120
|
||
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:
|
||
|
||
|
||
0
|
||
"ROM: :\BJ.WDR"
|
||
|
||
|
||
The record contains the page header text as a zero terminated string. The string may not exceed 80 bytes.
|
||
|
||
|
||
eee
|
||
|
||
|
||
The record contains the page footer text as a zero terminated string. The string may not exceed 80 bytes.
|
||
|
||
|
||
The file may contain up to 64 such records, each of which defines a single style.
|
||
|
||
|
||
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:
|
||
|
||
|
||
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;
|
||
|
||
|
||
75
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
In these terms, the content of the style data record is:
|
||
|
||
|
||
TEXT sc([2] two-letter short code (5)
|
||
TEXT tag[16] style tag name (6)
|
||
|
||
UWORD sflags style control flags (7)
|
||
SCRLAY_FONT f paragraph base font (8)
|
||
UWORD inherit inherited attributes (9)
|
||
|
||
|
||
SCRLAY_MARGINS marg margin positions
|
||
|
||
SCRLAY_SPACING spe paragraph vertical spacing
|
||
|
||
UWORD olevel outliner level
|
||
|
||
UWORD ntabs number of tabstops in following table
|
||
SCRLAY_TABSTOP tabI[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:
|
||
|
||
|
||
i) 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 short code must contain two alphabetic characters and must be unique (it must not be duplicated
|
||
in either a style or an emphasis). If no meaningful short code can be assigned, it is recommended that
|
||
unique short codes be generated in the sequence ZA,ZB,...,ZZ,YA,...,YZ,XA,...
|
||
|
||
|
||
(6) Although not currently enforced by the software, the text of the tag name should be unique (it should
|
||
not be duplicated in either a style or an emphasis). If no meaningful tag name can be assigned, it is
|
||
recomended that the tag name should duplicate the short code.
|
||
|
||
|
||
(7) 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.
|
||
|
||
|
||
The value 0x8000 is used internally by the word processor and may or may not be set in the style control
|
||
flags data in the document. If set, it can safely be ignored.
|
||
|
||
|
||
(8) In addition to the typeface numbers listed earlier, a typeface number 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.
|
||
|
||
|
||
(9) 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.
|
||
|
||
|
||
Emphasis data record (type 7, length 28}
|
||
|
||
|
||
The file may contain up to 16 such records, each of which defines a single emphasis.
|
||
|
||
|
||
76
|
||
|
||
|
||
6 WORD PROCESSOR FILE FORMAT
|
||
|
||
|
||
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 (1)
|
||
TEXT tag{16] emphasis tag name (2)
|
||
UWORD sflags emphasis control flags (3)
|
||
SCRLAY_FONT f emphasis font (4)
|
||
|
||
UWORD inherit inherited attributes (5)
|
||
Notes
|
||
|
||
|
||
(1) The short code must contain two alphabetic characters and must be unique (it must not be duplicated
|
||
in either a style or an emphasis). If no meaningful short code can be assigned, it is recommended that
|
||
unique short codes be generated in the sequence ZA,ZB,...,ZZ,YA,...,.YZ,XA,...
|
||
|
||
|
||
(2) Although not currently enforced by the software, the text of the tag name should be unique (it should
|
||
not be duplicated in either a style or an emphasis). If no meaningful tag name can be assigned, it is
|
||
recomended that the tag name should duplicate the short code.
|
||
|
||
|
||
(3) 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.
|
||
|
||
|
||
(4) In addition to the typeface numbers listed earlier, a typeface number 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.
|
||
|
||
|
||
(5) 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 styte field of the scRLAY_FONT struct must be clear.
|
||
|
||
|
||
Inherited attributes are taken from the enclosing paragraph style (which may itself inherit from the
|
||
default style).
|
||
|
||
|
||
terminated by a zero.
|
||
|
||
|
||
The content conforms with the IBM Code Page 850 symbol set, together with the following additional
|
||
symbols:
|
||
|
||
|
||
Symbol ASCH Meaning
|
||
|
||
END_PARAGRAPH 0x00 paragraph terminator
|
||
|
||
HARD_HYPHEN 0x07 unbreakable hyphen, not a word delimiter
|
||
TAB 0x09 tab character
|
||
|
||
LINE_FEED Ox0a forced line break
|
||
|
||
SOFT_HYPHEN Ox0e ‘optional, or potential, hyphen
|
||
|
||
HARD_SPACE Ox0f unbreakable space, not a word delimiter
|
||
|
||
|
||
nt index record (type 9, variable length}
|
||
|
||
|
||
This record contains a number of six byte entries which are used to apply style and emphasis to the
|
||
document text. Each entry consists of:
|
||
|
||
|
||
= a length (word)
|
||
|
||
|
||
= the two character short code of a style
|
||
|
||
|
||
77
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
= 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 that is not contained in the document
|
||
text record).
|
||
|
||
|
||
= there is at least one index entry for each paragraph in the document
|
||
= the final index 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
|
||
|
||
|
||
It must be stressed that a single index entry may not apply to text that is contained in more than one
|
||
paragraph.
|
||
|
||
|
||
aS re ee a ee Se a a]
|
||
Template files
|
||
|
||
|
||
Word processor template files have exactly the same structure as normal word processor files. The only
|
||
differences are that they:
|
||
|
||
|
||
= have a.wrt extension, rather than .wrd;
|
||
® are stored in a \wdr directory.
|
||
Template files for program editor aliases of the word processor contain only:
|
||
= a40 byte header, as for other word processor files;
|
||
= atype 1 options data record;
|
||
® atype 8 document text record.
|
||
The meanings of some items in the options data record differ from those of a normal word processor file:
|
||
UWORD cpos the saved cursor position, as for normal word processor files
|
||
UBYTE symbols the visibility of screen symbols, as for normal word processor files
|
||
|
||
|
||
UBYTE backup/statzoom backup state or status window and zoom settings, as for normal word
|
||
processor files
|
||
|
||
|
||
UBYTE style TRUE to set the use of a bold typeface
|
||
|
||
UBYTE mono TRUE to set the use of a monospaced typeface
|
||
|
||
UBYTE outlevel always TRUE for program editor aliases, to enable the use of templates
|
||
UBYTE spare TRUE to specify the use of auto indentation
|
||
|
||
UWORD spare2 the spacing, in column units, for tabs
|
||
|
||
|
||
LSS ae ae a
|
||
Printer driver font mapping
|
||
|
||
|
||
The font ID associated with a particular emphasis or paragraph style is determined by a selection from
|
||
the fonts available from the current printer driver at the time the emphasis or style was created. When a
|
||
different printer driver is installed, the font IDs associated with emphases and styles do not change (so
|
||
that the exact appearance of the document will be restored when the original printer driver is reinstalled).
|
||
|
||
|
||
The actual font to use when printing the document is determined by mapping each fixed font ID to one of
|
||
the available fonts supplied by the current printer driver. A perfect match occurs when the font ID
|
||
matches the font number of one of the fonts supported by the printer driver. Otherwise, an attempt is
|
||
made to make a simple fixed mapping, by font characteristics, onto a basic set of COURIER (mono),
|
||
HELVETICA (proportional, sans serif) or TIMES ROMAN (proportional, serif).
|
||
|
||
|
||
78
|
||
|
||
|
||
6 WORD PROCESSOR FILE FORMAT
|
||
|
||
|
||
If the current printer driver does not contain fonts with font numbers HELVETICA or TIMES ROMAN,
|
||
thease are also mapped to COURIER (font number zero). This is assumed always to be set for the
|
||
printer's default font - usually a 10 or 12 point font - whatever it is called.
|
||
|
||
|
||
79
|
||
|
||
|
||
CHAPTER 7
|
||
|
||
|
||
SERIES 3/3A AND MC SPREADSHEET FILE FORMAT
|
||
|
||
|
||
This document describes the structure of the .spr files that are used by the MC, Series 3 and Series 3a
|
||
spreadsheets. The description is to a level that allows other software to read and write non-password-
|
||
protected spreadsheet files.
|
||
|
||
|
||
i a re ae ee eee a
|
||
File header
|
||
The spreadsheet starts with the following header:
|
||
|
||
|
||
TEXT fid£16]="SPREADSHEET" packed with trailing zeros
|
||
UWORD vers=0
|
||
|
||
UWORD offset=0
|
||
|
||
UWORD rtvers=0
|
||
|
||
|
||
This header must be supplied exactly as described, otherwise all current versions of the Spreadsheet will
|
||
refuse to load the file. The only exception is that a password-protected Series 3a spreadsheet file has a
|
||
file type identifier string (in fid(}) of "SPREADSHEETB". This prevents it from being recognised on Series 3
|
||
and MC machines, where password protection of spreadsheet files is not supported.
|
||
|
||
|
||
Sa a a es ee ee a ee ee a eee
|
||
Records
|
||
The remainder of the file consists of type/length records, each of which has the following structure:
|
||
|
||
|
||
UWORD type the record type
|
||
UWORD Len the record length
|
||
record body len bytes of data
|
||
|
||
|
||
The structure of the data in the record body is dependent on the record type. Currently the following
|
||
types are defined:
|
||
|
||
|
||
Formula
|
||
|
||
Cell contents
|
||
|
||
Column width
|
||
|
||
Default column width
|
||
Status information
|
||
Display information
|
||
Named range
|
||
|
||
Print range
|
||
Database/criteria ranges
|
||
10 Table
|
||
|
||
11 Print setup (MC)
|
||
|
||
12 Font (MC)
|
||
|
||
13 Graph (S3)
|
||
|
||
14 Current graph index (S3)
|
||
15 Font palette (S3)
|
||
|
||
16 Print data (S3)
|
||
|
||
17 Printer model (S3)
|
||
|
||
18 Header text (S3)
|
||
|
||
19 Footer text (S3)
|
||
|
||
|
||
WO IA MAR WHR
|
||
|
||
|
||
81
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
20 Display extras (S3)
|
||
21 3a Display extras (S3a)
|
||
22 Password (S3a)
|
||
|
||
|
||
As indicated in the above table, some of the above types are specific to the MC version and some to the
|
||
Series 3/3a.
|
||
|
||
|
||
In general records can appear in any order, but there are currently three exceptions:
|
||
|
||
|
||
= All formula (type 1) records must appear before the cell (type 2) records that access them, and
|
||
the order in which the formula records appear must be preserved.
|
||
|
||
|
||
= The 3a Display extras (type 21) record, when present, should immediately precede the Display
|
||
information (type 6) record. Otherwise the 3a Display extras record will be ignored.
|
||
|
||
|
||
«s The Display extras (type 20) record, when present, should immediately precede the 3a Display
|
||
extras (type 21) record, if one exists. In the absence of a 3a Display extras record, the Display
|
||
extras record should immediately precede the Display information (type 6) record. Otherwise the
|
||
Display extras record will be ignored.
|
||
|
||
|
||
Some record types may appear many times, and not all record types need be present. Some record types
|
||
are expected to appear only once in the file. If more than one of each record of such a type is present, the
|
||
last record will be read and earlier records of the same type will be ignored. The number of times that a
|
||
particular type of record is expected to occur is indicated in the following descriptions of the record
|
||
|
||
|
||
types.
|
||
|
||
|
||
Range references
|
||
|
||
|
||
Within any record, a range reference specifies the top left and bottom right cells of the range in column
|
||
and row units. These references are inclusive so that, for example, the range reference {0,0}, 1,23}
|
||
describes the range A1:B3.
|
||
|
||
|
||
A Spreadsheet file may contain any number of Formula records.
|
||
|
||
|
||
Each formula is stored separately from the cell or cells that use it. This allows memory savings to be
|
||
made by storing only one copy of a commonly used formula.
|
||
|
||
|
||
The order in which the formula records appear is significant. This determines the index, counting from
|
||
zero, used to reference a formula from a cell record.
|
||
|
||
|
||
The body of a Formula record is structured as follows:
|
||
|
||
|
||
UWORD use usage count
|
||
UBYTE Len formula length (253 bytes maximum)
|
||
UBYTE form{Len] the formula
|
||
|
||
|
||
The formula is stored in reverse Polish notation (RPN). Each operand is preceded by a byte that
|
||
identifies its type. Each function or operator is identified by a single byte that follows the operands upon
|
||
which it acts.
|
||
|
||
|
||
Brackets are stored in the formula exactly as they were entered, but are ignored when a formula is
|
||
evaluated. They are retained only so that the formula can be reproduced and displayed in exactly the
|
||
same form as it was typed in.
|
||
|
||
|
||
The RPN structure is broken for the set of functions that act upon argument lists of variable length
|
||
(AVG, COUNT, MAX, MIN, STD, SUM and VAR). For these functions a Start token precedes the
|
||
argument list and an End token follows it. In addition, each operand within the list is preceded by a
|
||
special token.
|
||
|
||
|
||
The tokens used in formulae are as follows:
|
||
|
||
|
||
Operators
|
||
|
||
|
||
0x01 ~— Less than
|
||
|
||
0x02 _—_—_ Less than or equal
|
||
0x03 = Greater than
|
||
|
||
0x04 Greater than or equal
|
||
0x05 = Not equal
|
||
|
||
0x06 = Equal
|
||
|
||
0x07. 3=Add
|
||
|
||
|
||
82
|
||
|
||
|
||
0x08
|
||
0x09
|
||
Ox0a
|
||
0x0b
|
||
Ox0c
|
||
Ox0d
|
||
Ox0e
|
||
Ox0f
|
||
0x10
|
||
Ox11
|
||
|
||
|
||
Delimiters
|
||
|
||
|
||
0x12
|
||
0x13
|
||
0x14
|
||
0x15
|
||
|
||
|
||
Operands
|
||
|
||
|
||
0x16
|
||
0x17
|
||
0x18
|
||
0x19
|
||
Oxla
|
||
|
||
|
||
Functions
|
||
|
||
|
||
Subtract
|
||
Multiply
|
||
Divide
|
||
Power
|
||
|
||
Unary plus
|
||
Unary minus
|
||
Logical NOT
|
||
Logical AND
|
||
Logical OR
|
||
|
||
|
||
String concatenate
|
||
|
||
|
||
Open bracket
|
||
Close bracket
|
||
Comma
|
||
|
||
End of formula
|
||
|
||
|
||
7 SERIES 3/3A AND MC SPREADSHEET FILE FORMAT
|
||
|
||
|
||
Double constant (IEEE floating point number)
|
||
|
||
|
||
Integer constant (WORD)
|
||
|
||
|
||
Text string (leading-byte-counted string)
|
||
Cell reference (WORD col, WORD row)
|
||
Range reference (WORD tiCol, WORD tlRow, WORD brCol, WORD brRow)
|
||
|
||
|
||
Column and/or row references can be either absolute or relative. If the top bit of the WORD is set, the
|
||
reference is relative, otherwise the reference is absolute. Relative references are treated as a signed offset
|
||
(ignoring the top bit) from the cell that uses the formula. Note that cell Al is 0,0.
|
||
|
||
|
||
In the following list, 'x' refers to a numeric argument, 'str' a string and ‘range’ a range reference.
|
||
|
||
|
||
Ox1b
|
||
Oxlc
|
||
Oxld
|
||
Oxle
|
||
Oxl1f
|
||
0x20
|
||
0x21
|
||
0x22
|
||
0x23
|
||
0x24
|
||
0x25
|
||
0x26
|
||
0x27
|
||
0x28
|
||
0x29
|
||
Ox2a
|
||
0x2b
|
||
Ox2c
|
||
Ox2d
|
||
Ox2e
|
||
Ox2f
|
||
0x30
|
||
0x31
|
||
0x32
|
||
0x33
|
||
0x34
|
||
0x35
|
||
0x36
|
||
0x37
|
||
0x38
|
||
0x39
|
||
Ox3a
|
||
0x3b
|
||
Ox3c
|
||
0x3d
|
||
|
||
|
||
Cellpointer(x)
|
||
Char(x)
|
||
Code(str)
|
||
Cols(range)
|
||
Cos(x)
|
||
Datevalue(str)
|
||
Day(x)
|
||
Exp(x)
|
||
Hour(x)
|
||
Int(x)
|
||
Iserr(range)
|
||
Isna(range)
|
||
Isnum(range)
|
||
Isstr(range)
|
||
Len(str)
|
||
Ln(x)
|
||
|
||
Log(x)
|
||
Lower(str)
|
||
Minute(x)
|
||
Month(x)
|
||
N(range)
|
||
Proper(str)
|
||
Rows(range)
|
||
|
||
|
||
83
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
84
|
||
|
||
|
||
0x3e
|
||
Ox3f
|
||
0x40
|
||
0x41
|
||
0x42
|
||
0x43
|
||
0x44
|
||
0x45
|
||
0x46
|
||
0x47
|
||
0x48
|
||
0x49
|
||
Ox4a
|
||
Ox4b
|
||
Ox4c
|
||
Ox4d
|
||
Ox4e
|
||
Ox4f
|
||
0x50
|
||
0x51
|
||
0x52
|
||
0x53
|
||
0x54
|
||
0x55
|
||
0x56
|
||
0x57
|
||
0x58
|
||
0x59
|
||
Ox5a
|
||
0x5b
|
||
Ox5c
|
||
Ox5d
|
||
OxSe
|
||
Ox5f
|
||
0x60
|
||
0x61
|
||
0x62
|
||
0x63
|
||
0x64
|
||
0x65
|
||
0x66
|
||
0x67
|
||
0x68
|
||
0x69
|
||
Ox6a
|
||
Ox6b
|
||
Ox6c
|
||
Ox6d
|
||
Ox6e
|
||
Ox6f
|
||
0x70
|
||
0x71
|
||
0x72
|
||
0x73
|
||
0x74
|
||
0x75
|
||
0x76
|
||
0x77
|
||
0x78
|
||
0x79
|
||
Ox7a
|
||
0x7b
|
||
Ox7c
|
||
Ox7d
|
||
Ox7e
|
||
Ox7f
|
||
0x80
|
||
0x81
|
||
|
||
|
||
S(range)
|
||
|
||
Second(x)
|
||
|
||
Sin(x)
|
||
|
||
Sqrt(x)
|
||
|
||
Tan(x)
|
||
Timevalue(str)
|
||
Trim(str)
|
||
Upper(str)
|
||
Value(str)
|
||
|
||
Year(x)
|
||
|
||
Atan2(x,x)
|
||
Cell(x,range)
|
||
Exact(str,str)
|
||
Irr(x,x)
|
||
|
||
Left(str,x)
|
||
Mod(x,x)
|
||
|
||
Npv(x,x)
|
||
|
||
Not used
|
||
Repeat(str,x)
|
||
Right(str,x)
|
||
Round(x,x)
|
||
String(x,x)
|
||
Cterm(x,x)
|
||
Date(x,x)
|
||
Davg(range,x,range)
|
||
Dcount(range,x,range)
|
||
Dmax(range,x,range)
|
||
Dmin(range,x,range)
|
||
Dstd(range,x,range)
|
||
Dsum(range,x,range)
|
||
Dvar(range,x,range)
|
||
Find(str,str,x)
|
||
Fv(x,xX,X)
|
||
Hlookup(x,range,x)
|
||
If(x,x,X)
|
||
Index(range,x,x)
|
||
Mid(str,x,x)
|
||
Pmt(x,x,x)
|
||
Pv(x,x,X)
|
||
Rate(x,x,x)
|
||
|
||
Sin(x)
|
||
|
||
Term(x,x,X)
|
||
Time(x,x,x)
|
||
VLookup(range,x,x)
|
||
Ddb(x,x,x,x)
|
||
Replace(str,x,x,str)
|
||
Syd(x,x,x,x)
|
||
End of avgQ
|
||
|
||
End of chooseQ)
|
||
End of count()
|
||
|
||
End of maxQ
|
||
|
||
End of minO
|
||
End of stdO
|
||
End of sumQ)
|
||
|
||
End of varQ)
|
||
|
||
Start of avg()
|
||
|
||
Start of choose()
|
||
Start of count(Q)
|
||
Start of maxQ)
|
||
|
||
Start of minQ
|
||
|
||
Start of stdQ
|
||
|
||
Start of sum()
|
||
|
||
Start of var()
|
||
|
||
Range in avgQ
|
||
Range in choose()
|
||
Range in count()
|
||
Range in max()
|
||
Range in min()
|
||
|
||
|
||
7 SERIES 3/3A AND MC SPREADSHEET FILE FORMAT
|
||
|
||
|
||
0x82 Range in stdO
|
||
0x83 ~—s- Range in sumQ)
|
||
0x84 ~=—- Range in var()
|
||
Ox85 = Cell in avg0)
|
||
0x86 ~—- Cell in chooseQ
|
||
0x87 = Cell in count()
|
||
0x88 = Cell in maxQ)
|
||
0x89 = Cell in minQ)
|
||
Ox8a = Cell in std
|
||
Ox8b = Cell in sum()
|
||
Ox8c Cell in varO
|
||
|
||
|
||
file.
|
||
|
||
The body of a Cell record is structured as follows:
|
||
|
||
UWORD column Cell co-ordinates (cell Ai is 0,0)
|
||
UWORD row
|
||
|
||
UBYTE flags See below
|
||
|
||
UBYTE format See below
|
||
|
||
|
||
cell contents
|
||
|
||
|
||
Flags
|
||
|
||
The ftags byte contains information about the display alignment of the cell and the cell type.
|
||
|
||
Xeussene used by the natural order sort and should be left as is
|
||
|
||
sXeusces changed flag, TRUE if (and only if) the cell has changed since the last recalc
|
||
ooXeunes numeric alignment, 1 left aligned, 0 right aligned
|
||
|
||
oeeXXene text alignment, 00 repeated, 01 left, 10 right, 11 centered
|
||
|
||
200 eXXX cell type, defines the format of the contents data as follows:
|
||
|
||
|
||
000 (0) Blank - contains only the format data shown above and has no contents
|
||
data
|
||
|
||
|
||
001 (1) Double - contains a floating point constant as a DOUBLE value
|
||
010 (2) Text - contains leading-byte-counted text
|
||
011 (3) Integer - contains an integer (WORD) constant
|
||
|
||
|
||
101 (5) Double formula - contains a formula that evaluates to a numeric result.
|
||
The contents data is a WORD containing the formula reference, immediately
|
||
followed by a DOUBLE that contains the current resultant value for the cell
|
||
|
||
|
||
110 (6) Text formula - The cell contains a formula that evaluates to a text
|
||
result. The contents data is a WORD containing the formula reference,
|
||
immediately followed by the leading-byte counted text that represents the
|
||
current resultant value for the cell.
|
||
|
||
|
||
Each formula reference is an index, counting from zero, determined by the order in which the formula
|
||
records appear in the file.
|
||
|
||
|
||
85
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
Format
|
||
|
||
|
||
The format byte records whether or not the cell is currently protected and the way in which numeric
|
||
values should be displayed.
|
||
|
||
|
||
Xevensce Set if the cell is currently protected
|
||
aXXXXXXX Gives the numeric display format as follows:
|
||
|
||
|
||
s000XXXx Fixed (xxxx decimal places)
|
||
»001XXXxX Scientific (xxxx decimal places)
|
||
#010Xxxx Currency (Xxxxx decimal places)
|
||
©011XXXX Percentage (xxxx decimal places)
|
||
» 100Xxxx Comma (xxxx decimal places)
|
||
«1110000 Bargraph
|
||
|
||
»1110001 General
|
||
|
||
*1110010 Date (Lotus DD-MM-YY)
|
||
#1110101 Show formulae
|
||
|
||
1110110 Hidden
|
||
|
||
©1110111 Time (Lotus HH:MM:SS)
|
||
»1111111 Default
|
||
|
||
|
||
For the MC Spreadsheet this is the full extent of the cell record. In files generated on the Series 3/3a
|
||
there is an extra trailing byte, following the cell details described above. This extra byte contains a font
|
||
style number, in the range 0-3 inclusive, allowing selection of one of the four fonts that are defined by a
|
||
Font palette (type 15) record. The presence or absence of this additional byte can be deduced by
|
||
calculating the length of the other data in the record and subtracting this value from from the length of
|
||
the record.
|
||
|
||
|
||
A record of this type is present for each column that is not of the default width. The record body is as
|
||
follows:
|
||
|
||
|
||
UBYTE column the column number (0 for column A)
|
||
UBYTE width the width of the column (in characters)
|
||
|
||
|
||
A Spreadsheet file contains only one record of this type. The record body is as follows:
|
||
|
||
|
||
UWORD width width (in characters)
|
||
|
||
|
||
This record specifies the width of all columns for which there is no specific Column width (type 3)
|
||
record.
|
||
|
||
|
||
A Spreadsheet file contains only one record of this type. It stores assorted information that relates to the
|
||
spreadsheet as a whole. The body of a Status information record is structured as follows:
|
||
|
||
|
||
UWORD flags see below
|
||
UBYTE defForm the default numeric display format
|
||
UBYTE defAlign the default text and numeric alignments
|
||
|
||
|
||
The numeric display format is one of the values described earlier for a Cell (type 2) record. It is the
|
||
display format used for all cells whose Cell record specifies the default numeric display format. Clearly,
|
||
defForm may not itself be set to the default value.
|
||
|
||
|
||
The value of defAlign contains the default text and numeric alignments, as described earlier for a Cell
|
||
(type 2) record. Each newly created cell is set to use the alignments specified by defAtign.
|
||
|
||
|
||
Flags
|
||
|
||
The four least significant bits of flags are used for the following purposes:
|
||
eusenesX set if auto recalc is on
|
||
|
||
seseoeXe set is protection override is on
|
||
|
||
sunenXee set if cells have been deleted since last recalc
|
||
anenXene set if Table recalc is on
|
||
|
||
|
||
86
|
||
|
||
|
||
7 SERIES 3/3A AND MC SPREADSHEET FILE FORMAT
|
||
|
||
|
||
ory one Display information record is ae to appear in the file. The ebaGFOI of a record of this type
|
||
contains the current state of the display for the spreadsheet. It is structured as follows:
|
||
|
||
|
||
UWORD titleTLCol range for the titles
|
||
UWORD titleTlRow
|
||
|
||
UWORD titleBrCol
|
||
|
||
UWORD titleBrRow
|
||
|
||
UWORD topCol
|
||
|
||
UWORD topRow
|
||
|
||
UWORD selTICol select range
|
||
|
||
UWORD selTLRow
|
||
|
||
UWORD selBrCol
|
||
|
||
UWORD selBrCol
|
||
|
||
|
||
UWORD cursorCol position of cursor
|
||
|
||
UWORD cursorRow
|
||
|
||
UBYTE lines true if grid lines are to be displayed
|
||
UBYTE hideZeros TRUE if zero values are hidden
|
||
|
||
Ni ; e 7, length
|
||
|
||
|
||
Each Named range record specifies a range or cell to be associated with a name. There may be any
|
||
number of such records in a file. The body of the record is structured as follows:
|
||
|
||
|
||
TEXT name [16] zero terminated text string
|
||
UWORD the range associated with name
|
||
range_left_column
|
||
|
||
UWORD range_top_row
|
||
|
||
UWORD
|
||
|
||
range_right_column reference type
|
||
|
||
UWORD range_bottom_row
|
||
|
||
UWORD type
|
||
|
||
|
||
The value of type is 25 (0x19) for a cell reference and 26 (0x1a) for a range reference. These values are
|
||
chosen to match the reference tokens used in formulae.
|
||
|
||
|
||
A record of this type specifies a range to be offered for selective printing. There may be any number of
|
||
these records in the file. The body of a Print range record is structured as follows:
|
||
|
||
|
||
UWORD the range
|
||
range_left_column
|
||
|
||
UWORD range_top_row
|
||
|
||
UWORD
|
||
|
||
range_right_column
|
||
|
||
UWORD range_bottom_row
|
||
|
||
|
||
oe 9, length 16) —
|
||
|
||
|
||
A record of this type ne ihe criterion and database ranges to be used by the database commands. A
|
||
Spreadsheet file is expected to contain zero or one Database/criterion records. The body of the record is
|
||
structured as follows:
|
||
|
||
|
||
UWORD crit_left_col criterion range
|
||
UWORD crit_top_row
|
||
|
||
UWORD crit_right_col
|
||
|
||
UWORD crit_bottom_row
|
||
|
||
UWORD dbase_left_col database range
|
||
UWORD dbase_top_row
|
||
|
||
UWORD dbase_right_col
|
||
|
||
UWORD dbase_bottom_row
|
||
|
||
|
||
formation {type 10, length 16)
|
||
|
||
|
||
A Spreadsheet file is expexted to contain zero or one Table information records. The body of the record
|
||
is structured as follows:
|
||
|
||
|
||
87
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
UWORD range_left_col table range
|
||
UWORD range_top_row
|
||
|
||
UWORD range_right_col
|
||
|
||
UWORD range_bottom_row
|
||
|
||
|
||
UWORD input1_col input cell i
|
||
UWORD input1_row
|
||
UWORD input2_col input cell 2
|
||
|
||
|
||
UWORD input2_row
|
||
|
||
|
||
For table 2 both input cells are valid. For table 1 input2_colt must be set to Oxf fff (65535).
|
||
|
||
|
||
to appear in the file. The body of the record is structured as follows:
|
||
UWORD type
|
||
|
||
|
||
Allowed values for type are:
|
||
|
||
|
||
eensesnnX if TRUE show values, else show formulae
|
||
sescccsXe if TRUE, show hidden cells
|
||
|
||
scccasXen if TRUE, show column seperators
|
||
sueeeXeas if TRUE, show headers
|
||
|
||
|
||
The Font record only appears in an MC Spreadsheet file, and only only one such record is expected to
|
||
appear in the file. The body of the record is structured as follows:
|
||
|
||
|
||
UWORD type
|
||
TEXT name[16] font name
|
||
|
||
|
||
The value of type specifies the associated style, as indicated below:
|
||
|
||
|
||
eanesnnX bold
|
||
euseXaca double height
|
||
|
||
|
||
88
|
||
|
||
|
||
7 SERIES 3/3A AND MC SPREADSHEET FILE FORMAT
|
||
|
||
|
||
A Graph record dtcaly, appears in a Series 3/3a Spreadsheet file, and there may be any number of records
|
||
of this type in the file. Each record defines a displayable graph. The body of the record is structured as
|
||
follows:
|
||
|
||
|
||
TEXT name [16] zero terminated name for the graph
|
||
UWORD A_range[4] a data range left_col, top_row, right_col, bottom_row
|
||
UWORD B_range[4]
|
||
|
||
UWORD C_range[4]
|
||
|
||
UWORD D_range[4]
|
||
|
||
UWORD E_range([4]
|
||
|
||
UWORD F_range[4]
|
||
|
||
UWORD X_range[4]
|
||
|
||
UWORD A_labels [4] range containing labels for data set A
|
||
UWORD B_labels[4)
|
||
UWORD C_labels [4]
|
||
UWORD D_labels [4]
|
||
UWORD E_labels [4]
|
||
UWORD F_labels [4]
|
||
UBYTE fmts [6]
|
||
|
||
UBYTE aligns [6]
|
||
|
||
UBYTE xAxisScaling
|
||
UBYTE xAxisFormat
|
||
DOUBLE xAxisLowerLimit
|
||
DOUBLE xAxisUpperLimit
|
||
UBYTE yAxisScaling
|
||
UBYTE yAxisFormat
|
||
DOUBLE yAxisLowerLimit
|
||
DOUBLE yAxisUpperLimit
|
||
UBYTE graphType
|
||
|
||
UBYTE gridFlags
|
||
|
||
UBYTE colour
|
||
|
||
UBYTE rangefF lags
|
||
|
||
UBYTE LabelFlags
|
||
|
||
UBYTE otherF lags
|
||
|
||
WORD skip
|
||
|
||
ten strings
|
||
|
||
|
||
There are ten zero terminated strings packed consecutively, following skip. These strings are, in order:
|
||
|
||
|
||
First line of title - max length 40
|
||
Second line of title - max len 40
|
||
Title for x axis - max len 40
|
||
Title for y axis - max len 40
|
||
Legend for A range - max len 20
|
||
|
||
|
||
Legend for F range - max len 20
|
||
|
||
|
||
A record af this type shine appears in a Series 3/3a a Sorseithioet file, and vail one Current sn avanhite index
|
||
record is expected to appear in the file. The body of the record is structured as follows:
|
||
|
||
|
||
UWORD curGraph
|
||
|
||
|
||
It contains the index of the graph that is currently selected, as set by the 'Use graph’ menu item. Graphs
|
||
are indexed in the order that the corresponding Graph (type 13) records appear in the file, with an index
|
||
of 0 referring to the first graph.
|
||
|
||
|
||
89
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
penewate
|
||
|
||
|
||
A record of this type only appears in a Series 3/3a Spreadsheet file, and only one Font palette record is
|
||
expected to appear in the file. The body of the record is structured as follows:
|
||
|
||
|
||
SCRLAY_FONT font1
|
||
SCRLAY_FONT font2
|
||
SCRLAY_FONT font3
|
||
SCRLAY_FONT font4
|
||
|
||
|
||
Each ScRLAY_FONT structure determines one of the four selectable fonts and their corresponding styles
|
||
(bold, italic etc.). The SCRLAY_FONT struct is defined in scrlay.g as:
|
||
|
||
|
||
typedef struct
|
||
{
|
||
|
||
|
||
UWORD fid; window server font id
|
||
|
||
UWORD style; font style (eg bold)
|
||
|
||
UWORD height; height of printer font in decipoints
|
||
} SCRLAY_FONT;
|
||
|
||
|
||
A Print data record only appears in a Series 3/3a Spreadsheet file, and only one record of this type is
|
||
expected to appear in the file.
|
||
|
||
|
||
This record contains a PRINTER_PARAMS struct that supplies information required to format the document
|
||
for the printer. It includes, amongst other items, descriptions of the page size and margins, the page
|
||
numbering style, header and footer position and alignment.
|
||
|
||
|
||
The detailed description of this record is outside the scope of this document. For some further details of
|
||
this record, and of the other printer-related records (types 17, 18 and 19), see Saving and restoring print
|
||
context from file in the Printing chapter of the Object Oriented Programming Guide.
|
||
|
||
|
||
A Printer model record only appears in a Series 3/3a Spreadsheet file, and only one record of this type is
|
||
expected to appear in the file. The body of the record is structured as follows:
|
||
|
||
|
||
UBYTE model Index
|
||
TEXT ztsDriver
|
||
|
||
|
||
The data 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:
|
||
|
||
|
||
0
|
||
"ROM: :Bd.WDR"
|
||
|
||
|
||
This record type only appears in a Series 3/3a Spreadsheet file, and only one Header text record is
|
||
expected to appear in the file. The body of the record is structured as follows:
|
||
|
||
|
||
TEXT zts
|
||
|
||
|
||
The zero terminated string contains the text used for the page header when printing.
|
||
|
||
|
||
Foote
|
||
|
||
|
||
This record type only appears in a Series 3/3a Spreadsheet file, and only one Footer text record is
|
||
expected to appear in the file. The body of the record is structured as follows:
|
||
|
||
|
||
TEXT zts
|
||
|
||
|
||
The zero terminated string contains the text used for the page footer when printing.
|
||
|
||
|
||
90
|
||
|
||
|
||
7 SERIES 3/3A AND MC SPREADSHEET FILE FORMAT
|
||
|
||
|
||
A Display extras record only appears in a Series 3/3a Spreadsheet file. A record of this type is ignored
|
||
unless it immediately precedes either the 3a Display extras (type 21) record, if it exists, or the Display
|
||
information (type 6) record. The body of the record is structured as follows:
|
||
|
||
|
||
UWORD flags
|
||
Only two bits of flags are used:
|
||
|
||
|
||
sescenoX set if grid labels are shown
|
||
euseeaXe set if small font is used (this is over-ridden if a 3a Display extras (type 21)
|
||
record is present.
|
||
|
||
|
||
A 3a Display extras record only appears in a Series 3a Spreadsheet file. A record of this type is ignored
|
||
unless it immediately precedes the Display information (type 6) record. The body of the record is
|
||
structured as follows:
|
||
|
||
|
||
UBYTE font font used
|
||
UBYTE statwin status window
|
||
WORD spare for future expansion
|
||
Font
|
||
This takes one of the values:
|
||
255 smallest font available
|
||
8 Swiss 8 pixel font
|
||
9 Swiss 11 pixel font
|
||
10 Swiss 13 pixel font
|
||
11 Swiss 16 pixel font
|
||
Statwin
|
||
This takes one of the values:
|
||
0 No status window
|
||
1 Small status window
|
||
2 Large status window
|
||
|
||
|
||
SBS AAS ESA ASAE RSNA BERANE ANI st NaS tomate ae NS ames SSL anette
|
||
|
||
|
||
This record is present only if the spreadsheet is password-protected. Its content is used as part of the
|
||
spreadsheet encryption/decryption process.
|
||
|
||
|
||
91
|
||
|
||
|
||
CHAPTER 8
|
||
|
||
|
||
WRITING DEVICE DRIVERS
|
||
|
||
|
||
waa SS re ee ee ee Se 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 J/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.
|
||
|
||
|
||
93
|
||
|
||
|
||
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:
|
||
= TTY: is the serial LDD
|
||
8 TIM: is the timer LDD
|
||
m@ 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
|
||
m 6TTY.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
|
||
TTY: 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 1o0pen 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 DevOpenPop operating system service.
|
||
Typically only LDDs open PDDs. The p_open library function can be used to open a PDD indirectly as
|
||
described below.
|
||
|
||
|
||
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)
|
||
* 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 Try: device hunts for an appropriate 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
|
||
channels, '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.
|
||
|
||
|
||
94
|
||
|
||
|
||
8 WRITING DEVICE DRIVERS
|
||
|
||
|
||
PDDs have been designed to be accessed by an LDD either via far calls or the Devvector operating system
|
||
function.
|
||
|
||
|
||
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 DevFind 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 DevOpenPbD 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 1oFuncAttach 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 loFuncWrite 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.
|
||
|
||
|
||
a5
|
||
|
||
|
||
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 1oFuneWrite request.
|
||
|
||
|
||
An attached driver is written in exactly the same way as any other driver. However, if the driver does not
|
||
support a requested function, the strategy vector of an attached driver calls the toSuper operating system
|
||
service rather than the 1oRoot system service.
|
||
|
||
|
||
R———E—E—EE EE ES ee
|
||
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
|
||
Teentrancy.
|
||
|
||
|
||
= Interrupt service routines run in the context of whatever process 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 1oSignalByPidNoReSched 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 10SignalByPidNoReSched) 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 1/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.
|
||
|
||
|
||
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:
|
||
|
||
|
||
96
|
||
|
||
|
||
8 WRITING DEVICE DRIVERS
|
||
|
||
|
||
« A handler will always run in the context of the process that has opened a channel. An interrupt
|
||
service routine will run in the context of whatever process happens to be running at the time of
|
||
the interrupt.
|
||
|
||
|
||
=» 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.
|
||
|
||
|
||
=s 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.
|
||
|
||
|
||
Eur ee a a ee eee
|
||
Loadable Logical Device Driver Structure
|
||
A loadable LDD must obey the following rules:
|
||
|
||
= There must be a single code segment and no data segments.
|
||
|
||
s The code segment must start with a Lib€nt 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
|
||
pce aie for 'freeing' the hardware after a process terminates must exist in the code space of the device
|
||
The LibEnt Structure
|
||
A Libént structure has the following format:
|
||
|
||
= two byte signature
|
||
|
||
= eight byte name
|
||
|
||
=" two byte vector count
|
||
|
||
= A vector table
|
||
The two byte signature should contain the 'LopSignature’ 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:
|
||
|
||
|
||
97
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
dw LODSignature 3; Its an LOD
|
||
|
||
db 'DVR',0,0,0,0,0 ; Name of the driver
|
||
|
||
dw (VectorEnd-Vector)/2 ; Number of vectors
|
||
Vector:
|
||
|
||
dw Dvrinstall 3; Install vector
|
||
|
||
dw DvrRemove ; Remove vector
|
||
|
||
dw DvrHold ; Hold vector
|
||
|
||
dw DvrResume ; Resume vector
|
||
|
||
dw DvrReset ; Reset Vector
|
||
|
||
dw DvrUnits ; Units Vector
|
||
|
||
dw DvrOpen ; Open Vector
|
||
|
||
dw DvrStrategy ; Strategy vector
|
||
VectorEnd:
|
||
|
||
|
||
The vector table contains the offsets within the device drivers code segment 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.
|
||
|
||
™ 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 called to open a channel to an LDD.
|
||
|
||
= DevFuncStrategy called to access the device drivers functionality 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 return back to the operating system.
|
||
|
||
|
||
Since the FAR retum 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.
|
||
|
||
|
||
This function is called by the operating system when the device driver is loaded in order to initialise any
|
||
internal variables. It can not be called directly by an application process.
|
||
|
||
|
||
The Devinstall operating system service will cause this function to be called. 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. 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 mules 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.
|
||
|
||
|
||
98
|
||
|
||
|
||
8 WRITING DEVICE DRIVERS
|
||
|
||
|
||
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.
|
||
BD chemo 0
|
||
|
||
|
||
This function will be called by the operating system when the device driver is requested to be unloaded.
|
||
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 Dewelete 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 heid 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.
|
||
|
||
|
||
hold vector is called in the context of the operating system.
|
||
|
||
|
||
The DevHold 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.
|
||
|
||
|
||
= The machine is about to switch off due to the auto switch off timeout or user request, it enters
|
||
the standby state.
|
||
|
||
|
||
99
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
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 driver 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
|
||
will be lost including the device driver code! On power fail there is about 2ms available to power down
|
||
all 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 fail 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 resume 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
|
||
® DevHoltdNormal Device memory is about to be moved.
|
||
= = DevHoldPowerDown The system is about to enter the standby state.
|
||
= ~DevHoldPowerFail The system has lost its power supply.
|
||
RETURN
|
||
None.
|
||
PANIC
|
||
|
||
|
||
The hold vector must not panic: it will cause an operating system kernel fault if it does.
|
||
|
||
|
||
100
|
||
|
||
|
||
8 WRITING DEVICE DRIVERS
|
||
|
||
|
||
PRESERVE
|
||
The SS, SP and BP registers must be preserved by the hold vector.
|
||
|
||
|
||
resume vector is called in the context of the operating system.
|
||
|
||
|
||
The DevResume 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 DevGetPopAddress 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.
|
||
|
||
|
||
“uncReset 2 se.
|
||
This function will be called by the operating system when the device driver is requested to reset a
|
||
channel. The reset function is called in the context of the operating system.
|
||
|
||
|
||
101
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
The device driver must request that the operating system call the reset function. This is achieved by
|
||
calling the 1oRequestReset system service, usually in the open vector. To cancel this request, the device
|
||
driver should cali 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 operating system memory pool
|
||
and is no longer valid.
|
||
|
||
|
||
If a device driver can handle multiple channels then the data passed to the 1oRequestReset 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.
|
||
|
||
|
||
This function will be called by the operating system when the device driver is requested to report the
|
||
number of units (i.e. channels) the device driver can support. This function is called in the context of the
|
||
operating system.
|
||
|
||
|
||
The operating system places no significance on the number of channels a device driver can support. It is
|
||
primarily used for informational purposes.
|
||
|
||
|
||
An application may use the number of units to attempt to open any available channel on that device
|
||
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.
|
||
|
||
|
||
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
|
||
example, might only support two channels (TTY:A and TTY:8) whereas the file device driver can open an
|
||
unlimited number of files.
|
||
|
||
|
||
102
|
||
|
||
|
||
8 WRITING DEVICE DRIVERS
|
||
|
||
|
||
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.
|
||
|
||
|
||
This function w system when a channel to the device driver is required to be
|
||
opened. This function is called in the context of the process that called the 100pen system service.
|
||
|
||
|
||
The device driver is passed two parameters, its device handle and a pointer to an OpenEnt 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 ibHandle field of the chanent 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
|
||
loOpen system service. For example, if the to0pen service was passed a name of PaR:A, the OpenNamePtr
|
||
field would point to the colon. If the 1odpen service was passed a name of TTY.AS5:B 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 LocateCelt
|
||
|
||
jc noMemory
|
||
|
||
mov bx, ax ; cell handle
|
||
|
||
|
||
If the device driver requires a WaitHandler (described later):
|
||
|
||
|
||
mov al, (VectorHandler-Vector)/2
|
||
ToAddkKandler
|
||
|
||
jc endFreeMemory
|
||
|
||
mov [bx] .OriverHandler, ax
|
||
|
||
|
||
If the device driver's DevFuncReset vector is required to be called:
|
||
|
||
|
||
push bx
|
||
|
||
mov cx, ChannelIndicator 3 unique per channel
|
||
mov bx, dx ; the device handle
|
||
ToRequestReset
|
||
|
||
pop bx 3 restore alloc cell
|
||
|
||
|
||
The chanent field of the priverEnt 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 loFuncAttach and IoFuncDetach functions manipulate these fields. The
|
||
I/O system uses this field to direct the I/O request to the correct driver.
|
||
|
||
|
||
103
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
The ChanSignature field is checked by the operating system during any I/O requests for the value
|
||
loChanSignature. 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:
|
||
|
||
|
||
allocated channel
|
||
channel attaching to
|
||
return in BX the
|
||
channel attached to
|
||
|
||
|
||
mov cx, bx
|
||
|
||
mov bx, [si] .OpenChan
|
||
mov al, IoFuncAttach
|
||
ToWithWait
|
||
|
||
|
||
ma me me Be
|
||
|
||
|
||
Finally, if the channel has been successfully opened:
|
||
|
||
|
||
cic ; Opened Ok
|
||
ret ¢ return BX and DX
|
||
|
||
|
||
The error recover code typically follows the following pattern:
|
||
|
||
|
||
endFreeReset:
|
||
push ax
|
||
push bx
|
||
mov cx, Channel Indicator
|
||
mov bx, dx
|
||
loRequestResetCancel
|
||
pop bx
|
||
pop ax
|
||
endFreeHandler:
|
||
push ax
|
||
push bx
|
||
mov bx, [bx] .DriverHandler
|
||
loRemoveHandler
|
||
pop bx
|
||
pop ax
|
||
endFreeMemory:
|
||
push ax
|
||
HeapFreeCel L
|
||
pop ax
|
||
ste
|
||
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 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 tntEnt
|
||
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.
|
||
|
||
|
||
104
|
||
|
||
|
||
8 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.
|
||
|
||
|
||
When an application makes an I/O request on the opened device driver channel the request is routed to
|
||
this vector by the operating system. A device driver defines the set of functions that it supports. These
|
||
typically include 1oFuncSet, loFuncSense, IoFuncRead, IofuncWrite and IoFuncClose. A device driver does
|
||
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 1oFuncWwrite 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,
|
||
RqStatusPtr, RqAiPtr and RqA2Ptr.
|
||
|
||
|
||
The RqFunction field contains the function number as passed to the 1oWithWait (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 J/O request may complete within the strategy vector or it may complete some time in the future,
|
||
presumably from some interrupt.
|
||
|
||
|
||
The RqAiPtr and RqAzPtr fields contain the argument 1 and 2 parameters as passed to the IoWithwait (or
|
||
loAsynchronous) 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
|
||
IoFuncxxx 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:
|
||
|
||
|
||
= ToFuncRead ; read from the device.
|
||
|
||
B [oFuneWrite ; write to the device.
|
||
|
||
B loFuncClose ; close device channel.
|
||
|
||
= = IoFuneCancel ; cancel an I/O request.
|
||
|
||
= JoFuneSet ; set driver characteristics
|
||
|
||
B® —IoFuncSense ; sense driver characteristics.
|
||
® = loFuncFlush ; flush any buffers.
|
||
|
||
|
||
The PLIB library functions p_read, p_write and p close will call the device driver with the I oFuncRead,
|
||
loFuneWrite 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:
|
||
= A cancel request will cancel any outstanding requests. A cancel request will not return any error.
|
||
|
||
|
||
= A close 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.
|
||
|
||
|
||
105
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
Any functions that the strategy function does not support should be passed on to the next driver down the
|
||
driver hierarchy. If the driver is a root driver (attached driver), this is achieved using the IoRoot
|
||
(IoSuper)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 RqEnt 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 carry 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 J/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.
|
||
|
||
|
||
a eee re
|
||
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 space 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:
|
||
|
||
|
||
106
|
||
|
||
|
||
8 WRITING DEVICE DRIVERS
|
||
|
||
|
||
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 z Its an PDD driver
|
||
db ‘DVR.HW1',0 ; Name of the driver
|
||
dw (VectorEnd-Vector )/2 ; Number of vectors
|
||
Vector
|
||
dw Dvrinstall 3; Install vector
|
||
dw DvrRemove ; Remove vector
|
||
VectorEnd:
|
||
|
||
|
||
Most PDDs also define a further two vectors:
|
||
|
||
|
||
dw DvrOpen
|
||
dw OvrStrategy
|
||
|
||
|
||
Open Vector
|
||
Strategy vector
|
||
|
||
|
||
=e
|
||
|
||
|
||
me
|
||
|
||
|
||
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:
|
||
|
||
B DevFuncInstal LPDD called on device installation.
|
||
|
||
® 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.
|
||
|
||
|
||
This vector will be called 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 DevLoadPpp 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.
|
||
|
||
|
||
107
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
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 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 vector.
|
||
|
||
|
||
ePD
|
||
|
||
|
||
This vector will be called by the operating system when the device 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 Dewelete 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 kernel fault if it does.
|
||
|
||
|
||
PRESERVE
|
||
|
||
|
||
The SS, SP and BP registers must be preserved by the remove vector.
|
||
|
||
|
||
108
|
||
|
||
|
||
8 WRITING DEVICE DRIVERS
|
||
|
||
|
||
When an application opens a channel to an LDD, it normally uses the todpen system service. If the name
|
||
specifies, or the LDD requires, a PDD then it needs to open a channel to a PDD. The Devopenpod system
|
||
service will call this PDD vector to establish a channel. The LDD now has a choice of calling a PDD
|
||
vector using the Dewvector 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 DevGetPDDAddress.
|
||
When an LDD receives a DevFuncResume it should call DevGetPpDAddress 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 Dewvector 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 Devopenppp 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 DevOpenPpp 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.
|
||
|
||
|
||
This function is defined as a convenience function for the LDD-PDD interface.
|
||
|
||
|
||
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.
|
||
|
||
|
||
109
|
||
|
||
|
||
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.
|
||
|
||
|
||
110
|
||
|
||
|
||
CHAPTER 9
|
||
|
||
|
||
EXAMPLE DEVICE DRIVERS
|
||
|
||
|
||
This chapter contains explanatory notes for the example device drivers supplied with the Psion C SDK.
|
||
The source code for these examples can be found in \sibosdk\ldd. The Borland Turbo assembler is used
|
||
throughout.
|
||
|
||
|
||
See also the preceding Writing Device Drivers chapter and the appropriate chapters in the J/O Devices
|
||
Reference manual.
|
||
|
||
|
||
SaaS SS SS ea a ee eT
|
||
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 Pp_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 shows how 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
|
||
|
||
|
||
111
|
||
|
||
|
||
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 to system memory and timer
|
||
channel availability.
|
||
|
||
|
||
The Open Function
|
||
|
||
|
||
The open function is called by the operating system when an application uses the Io0pen 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 that process.
|
||
|
||
|
||
The open function allocates enough memory to hold all of the required internal variables and initialises
|
||
the memory to zero. It then makes function nine in the device table a wait handler function by using 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.
|
||
|
||
|
||
A channel to a timer device is opened, the name TIM: is generated on the run time stack.
|
||
|
||
|
||
The I/O system channel header is set up, the I/O system requires that a device driver has a Chanent
|
||
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 will be routed
|
||
to the strategy function of the ‘attached to’ driver and not to the strategy function of our attached driver.
|
||
|
||
|
||
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 loSuper system service (note that a root device driver
|
||
would make an foRoot system service request to pass on any meaningless I/O requests).
|
||
|
||
|
||
Some requests may be redefined; the example driver redefines the meaning of the IofuncSet 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 using these
|
||
services, since they produce different results depending on whether the time out driver has been attached
|
||
or not (in one case they set and sense the serial characteristics and in the 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 1ofuncRead service identically regardless of
|
||
whether this time out driver has been attached (the IoFuncRead service will of course not time out if this
|
||
driver has not been attached).
|
||
|
||
|
||
Because the loFuncRead service effectively runs two I/O requests, that is the lower driver's loFuncRead and
|
||
a timer channel's toFuncRead, 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 1oFuncClose (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
|
||
loFuncClose 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
|
||
|
||
|
||
112
|
||
|
||
|
||
9 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.
|
||
|
||
|
||
SSS ae ee ae ee ee ae Sree pee pe ee ae)
|
||
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 is
|
||
to be played.
|
||
|
||
|
||
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 tenth of a
|
||
second. This is not a particularly high resolution for the note duration.
|
||
|
||
|
||
As well as the system timer, the device driver makes use of a wait handler function in order play the
|
||
notes.
|
||
|
||
|
||
The example code in ¢_mus.c shows how the device driver is loaded and the functions provided are used
|
||
to generate sound.
|
||
|
||
|
||
The device table
|
||
|
||
|
||
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.
|
||
|
||
|
||
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 requests.
|
||
|
||
|
||
The Remove Function
|
||
|
||
|
||
If the device driver currently owns the sound channel, the remove function will stop the playing of sound
|
||
and release to the operating system the sound channel resource.
|
||
|
||
|
||
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 (e.g. alarms) will be adversely affected when this driver is removed.
|
||
|
||
|
||
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.
|
||
|
||
|
||
113
|
||
|
||
|
||
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,
|
||
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 nine 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
|
||
the I/O channel. Once successfully opened, the internal variable is set to indicate this.
|
||
|
||
|
||
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 loFuncCancel
|
||
(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 channel 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 only does an
|
||
application have to be waiting for an I/O request to complete but it must also be able to obtain 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 1oFuncClose request will cancel any outstanding write close the timer channel, cancel the reset
|
||
request and release the sound resource back to the operating system.
|
||
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
|
||
completion status.
|
||
|
||
|
||
114
|
||
|
||
|
||
9 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.
|
||
|
||
|
||
a a ar a Oe ee ee ee a ea a al
|
||
Interrupt Driven Sound Driver
|
||
|
||
|
||
The code in sndfrc.asm contains an example of a root device driver that uses the FRC (free running
|
||
counter) as an interrupt source to drive a sound system.
|
||
|
||
|
||
The driver accesses the sound chip within the Series3 and has the ability to play the notes passed 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 services) as mutual exclusion semaphores.
|
||
|
||
|
||
Similarly the FRC should only be accessed by a single process at a time. If a second process grabs the
|
||
FRC without the first knowing then the first will probably never receive another FRC interrupt and hence
|
||
appear to hang.
|
||
|
||
|
||
When the channel to the sound driver is opened, it requests 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 to be made
|
||
that the hardware is switched on and the notes played.
|
||
|
||
|
||
This device driver uses the FRC as a timer to time the duration of notes. The FRC can be programmed to
|
||
Tun 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 a very high percentage of the processor bandwidth to be used.
|
||
|
||
|
||
For this driver an eight bit number is used to specify the duration of a note and hence the maximum
|
||
duration is 2.56 seconds.
|
||
|
||
|
||
Since the notes are changed in the interrupt service routine which is independent of most other system
|
||
activity, a high level of accuracy of note duration can be obtained.
|
||
|
||
|
||
The example code in ¢_musfrc.c shows how the device driver is loaded and the functions provided are
|
||
used to generate sound.
|
||
|
||
|
||
The device table
|
||
|
||
|
||
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 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 in order 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 should set the fact 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 requests.
|
||
|
||
|
||
The Remove Function
|
||
|
||
|
||
The remove function will, if the driver currently owns 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.
|
||
|
||
|
||
115
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
The Hold Function
|
||
|
||
|
||
The hold function will, if the driver currently owns the systems sound resource, 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 current note (duration) it has got;
|
||
when the resume function is called the following note (if any) will be played.
|
||
|
||
|
||
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.
|
||
|
||
|
||
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.
|
||
|
||
|
||
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 stops 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 available 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 KwGetCombo 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.OpenFrcChan 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 the playing and closing the
|
||
channel. This implementation chose to use the IoFuncwrite (P_FWRITE) service to mean play sound, the
|
||
loFuneCancel (P_FCANCEL) service to cancel playing and the 1oFuncClose (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 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
|
||
|
||
|
||
116
|
||
|
||
|
||
9 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.
|
||
|
||
|
||
When all the notes in the device driver's internal buffer have been played, the interrupt service routine
|
||
will cali the 1oSignalByPidNoReSched system service to signal the client process that the playing of sound
|
||
has completed.
|
||
|
||
|
||
The wait handler function will pick up the fact that the interrupt service routine 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.
|
||
|
||
|
||
The loFuncCancel service simply cancels any outstanding write request by stopping any more FRC
|
||
interrupts, stopping the sound generation, switching off the hardware 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 loFuneClose request will cancel any outstanding write, cancel the reset request and release the sound
|
||
and FRC resources back to the operating system.
|
||
The Wait Handler Function
|
||
|
||
|
||
This function should check whether all the notes have been played in which case it has completed the
|
||
users request.
|
||
|
||
|
||
117
|
||
|
||
|
||
CHAPTER 10
|
||
|
||
|
||
WORD FILE FORMAT CONVERSION DYLS
|
||
|
||
|
||
This chapter describes the creation of file format conversion DYLs that may be used with the Series 3/3a
|
||
Word application. If suitable file conversion DYLs are placed in a \wdr subdirectory of the root of any
|
||
local drive they will be detected by the Word application and used to offer additional options in the 'File
|
||
type’ list of both the 'Open' and ‘Save as’ dialogs.
|
||
|
||
|
||
The associated software can be installed into a \sibosdk\fconv directory from the Optional disk.
|
||
|
||
|
||
Two file conversion DYLs are required for each file format: one to read (load) the file and one to write
|
||
(save) it. A loader file conversion DYL must have a name of the form wifxxx.dyl and a saver file
|
||
conversion DYL must have a name of the form ws$xxx.dyl. In both cases the characters given as xxx
|
||
identify the nature of the file conversion. This part of the DYL name may be from three to five
|
||
characters in length and is presented as the corresponding entry in the ‘File type' list. Thus, for example,
|
||
the Microsoft Rich Text Format (RTF) conversion dialogs that are included in the software supplied with
|
||
the 3Link serial interface are named wi$rtf.dyl and ws$rif.dyl, and add an 'Rtf' file type option. The text
|
||
file conversion examples that are described at the end of this chapter would add a 'Txt' option. Where
|
||
feasible, this text should be restricted to three characters and should represent the file name extension of a
|
||
file in the corresponding format.
|
||
|
||
|
||
If a file conversion is selected in the 'Open' or ‘Save as’ dialogs, the Word application loads the
|
||
appropriate DYL, creates an instance of the first class that it contains (with class number zero) and sends
|
||
this instance a message with message function number one (in most objects this is usually some form of
|
||
initialisation method). This method is expected not to return until the file conversion is complete.
|
||
|
||
|
||
It is expected that the file conversion mechanism will use an active object to provide overall control, thus
|
||
maintaining the Word application's responsiveness to other events. A standard file converter has this
|
||
active object as the first class in its category. Word will therefore create an instance of this class and send
|
||
it am AO_INIT message (since, for an active object, this is the method with method number one). The basic
|
||
mechanism is illustrated in the example code later in this chapter.
|
||
|
||
|
||
The code of the file converter interfaces with the Series 3/3a Word application via an interface library,
|
||
|
||
s3fconv.lib, whose services are described in the following three sections. The services are classified by
|
||
their intended usage, although there is no formal restriction as to their actual use. If necessary for some
|
||
particular purpose, save interface services may be used in a loader file conversion and vice versa.
|
||
|
||
|
||
Communication between the Word application and the DYL is via the magic statics DatApp1 to DatApp5
|
||
inclusive. DatAppi, DatApp2, DatApp3 and DatApp4 are used by the interface software and must not be used
|
||
by DYL code. pDatApp5 points to a buffer, guaranteed to be at least P_FNAMESIZE bytes in length, containing
|
||
a file name. The file name in this buffer may be read and, if necessary, modified by DYL code. patAppé
|
||
and DatApp7 are available for use by DYL code.
|
||
|
||
|
||
Save interface services
|
||
|
||
|
||
The services described in this section are mainly intended for use in a file conversion DYL that saves a
|
||
word processor document to a file in some other format.
|
||
|
||
|
||
__ Present file overwrite dialog
|
||
|
||
|
||
INT DoConfirmOverwrite(VOID);
|
||
|
||
|
||
Present a dialog to confirm the overwriting of an existing file.
|
||
|
||
|
||
119
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
Returns TRuE if the used confirms that the file is to be overwritten, otherwise returns FALSE.
|
||
|
||
|
||
UINT CountTags(VOID);
|
||
|
||
|
||
Return a count of the current document's index tags, in preparation for one or more calls to SenseTag! tem.
|
||
|
||
|
||
UINT SenseTagItem(UINT item, PAR_STYLE *par, PHR_STYLE *phr);
|
||
|
||
|
||
Write, to the structs pointed to by par and phr respectively, copies of the paragraph and emphasis data for
|
||
the text associated with index tag number item.
|
||
|
||
|
||
Returns the number of characters to which the tag refers.
|
||
|
||
|
||
UINT CountParaStyles(VOID);
|
||
|
||
|
||
Return a count of the total number of the paragraph styles associated with the current document. This is
|
||
normally called in preparation for a sequence of calls to SenseParaStyleByIndex.
|
||
|
||
|
||
UINT CountEmphStyles(VOID);
|
||
|
||
|
||
Return a count of the total number of the emphasis styles associated with the current document. This is
|
||
normally called in preparation for a sequence of calls to SenseEmphStyl eBy!I ndex.
|
||
|
||
|
||
ryieB:
|
||
|
||
|
||
PARA_STYLE *SenseParaStyleBylIndex(UINT index);
|
||
|
||
|
||
Return a pointer to the PARA_STYLE struct containing the paragraph style data for style number index.
|
||
|
||
|
||
It is a programming error if the value of index does not lie between zero and n-1 (inclusive) where n is
|
||
the value returned by an earlier call to CountParaStyles.
|
||
|
||
|
||
EMPH_STYLE *SenseEmphStyleByIndex(UINT index);
|
||
Return a pointer to the EMPH_STYLE struct containing the emphasis style data for style number index.
|
||
|
||
|
||
It is a programming error if the value of index does not lie between zero and n-1 (inclusive) where n is
|
||
the value returned by an earlier call to CountEmphStyles.
|
||
|
||
|
||
PAR_STYLE *SenseParaStyleBySC(TEXT *psc);
|
||
|
||
|
||
Return a pointer to the PARA_STYLE struct containing the paragraph style data for the style with the two-
|
||
character shortcode pointed to by psc. The text pointed to by psc does not need to be null terminated. A
|
||
paragraph style with this shortcode must exist.
|
||
|
||
|
||
EMPH_STYLE *SenseEmphStyleBySC(TEXT *psc);
|
||
|
||
|
||
Return a pointer to the EMPH_STYLE struct containing the emphasis style data for the emphasis with the
|
||
two-character shortcode pointed to by psc. The text pointed to by psc does not need to be null terminated.
|
||
An emphasis style with this shortcode must exist.
|
||
|
||
|
||
120
|
||
|
||
|
||
10 WORD FILE FORMAT CONVERSION DYLS
|
||
|
||
|
||
VOID ExtractText(UINT pos, TEXT *buf, UINT len);
|
||
|
||
|
||
Copy len bytes of document text, starting at document position pos, into the buffer pointed to by buf.
|
||
|
||
|
||
VOID SetFileErrCINT err);
|
||
|
||
|
||
Set the Word application's file read/write error to err, for subsequent error reporting by Word.
|
||
This would normally be used only for reporting a failure to write a converted file.
|
||
|
||
|
||
ee a a ee Pee eee ee ee eee ee en ee
|
||
Load interface services
|
||
|
||
|
||
The services described in this section are mainly intended for use in a file conversion DYL that loads a
|
||
word processor document from a file in some other format.
|
||
|
||
|
||
VOID CloseCurrentFile(VOID);
|
||
|
||
|
||
Close the Word application's current file. This action must be performed before new data is loaded.
|
||
|
||
|
||
UINT SwitchToNewFile(TEXT *pname);
|
||
|
||
|
||
Direct the Word application to open the file whose full file specification is pointed to by pname. This
|
||
action must be performed on successful completion of the loading of a file.
|
||
|
||
|
||
PARA_STYLE *AppendParaStyle(PARA_STYLE *pstyle);
|
||
|
||
|
||
Append the paragraph style described by the PARA_STYLE struct pointed to by pstyle. A paragraph or
|
||
emphasis style with the same shortcode must not exist.
|
||
|
||
|
||
EMPH_STYLE *AppendEmphStyle(EMPH_STYLE *pstyle);
|
||
|
||
|
||
Append the emphasis described by the EMPH_STYLE struct pointed to by pstyle. An emphasis or paragraph
|
||
style with the same shortcode must not exist.
|
||
|
||
|
||
VOID DoApplyParaStyleCUINT spos, UINT epos, PARA_STYLE “*par);
|
||
|
||
|
||
Apply the paragraph style described by the PARA_STYLE struct pointed to by par to the text between the
|
||
start and end document positions spos and epos.
|
||
|
||
|
||
The paragraph style is applied to to entire paragraphs, from the start of the paragraph that contains the
|
||
position spos, to the end of the paragraph containing position epos. The end of the extended range
|
||
includes the NULL that terminates the last paragraph in the range.
|
||
|
||
|
||
When adding text to a document, paragraph styles must be applied to each single paragraph in turn, and
|
||
never to a range of two or more paragraphs. To ensure that application of the style does not extend to any
|
||
following paragraph, value of epos passed to DoApplyParaStyle should not include the paragraph's
|
||
terminating NULL. It is an absolute requirement that the range never includes the NULL that terminates the
|
||
last paragraph of the document.
|
||
|
||
|
||
121
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
VOID DoApplyEmphasis(UINT spos, UINT epos, EMPH_STYLE emph);
|
||
|
||
|
||
Apply the emphasis described by the EMPH_STYLE struct pointed to by emph (which must point to a struct
|
||
that was previously set up by either SetDefaultStyles or AppendEmphStyle) to the text between the start and
|
||
end document positions spos and epos.
|
||
|
||
|
||
The specified range may extend across paragraph boundaries but, while inserting text, should preferably
|
||
lie within a single paragraph. If the end of the range is immediately before a paragraph's terminating
|
||
NULL, the emphasis will also be applied to the terminating NULL.
|
||
|
||
|
||
To ensure that application of the emphasis does not extend to any following paragraph, the value of epos
|
||
passed to DoApplyEmphStyle should not include a paragraph's terminating NULL. It is an absolute
|
||
requirement that the range never includes the NuLL that terminates the last paragraph of the document.
|
||
|
||
|
||
VOID SetDefaultStyles(INT npara, INT nemph);
|
||
|
||
|
||
Delete the document content and any exisiting paragraph and emphasis styles. Create a set of standard
|
||
paragraph styles and text emphases.
|
||
|
||
|
||
Setting npara to a value of one to four inclusive causes from one to four standard standard paragraph
|
||
styles to be created. These are the same as the default paragraph styles that are provided by Word when a
|
||
new document is created:
|
||
|
||
|
||
No. Name Shortcode
|
||
|
||
1 Body text BT
|
||
|
||
2 Heading A HA
|
||
|
||
3 Heading B HB
|
||
|
||
4 Bulleted list BL
|
||
|
||
Thus, setting npara to three causes the three paragraph styles BT, HA and HB to be created.
|
||
|
||
|
||
Setting nemph to a value of one to six inclusive causes from one to six standard emphasis styles to be
|
||
created. These are the same as the default emphasis styles that are provided by Word when a new
|
||
document is created:
|
||
|
||
|
||
No. Name Shortcode
|
||
1 Normal NN
|
||
2 Underline UU
|
||
3 Bold BB
|
||
4 Italic Il
|
||
5 Superscript EE
|
||
6 Subscript ss
|
||
|
||
|
||
Thus, setting nemph to four causes the four emphasis styles NN, UU, BB and 11 to be created.
|
||
|
||
|
||
A special case is selected by calling setDefaultStyles with a value of -1 (in this case the value of nemph is
|
||
ignored). This creates default styles and emphases suitable for loading a Microsoft Rich Text Format
|
||
(RTF) file. This option is used by the RTF file conversion DYLs that are supplied with 3Link. It creates
|
||
a single Body text paragraph style, with shortcode B1, and six emphasis styles, with names and
|
||
shortcodes as listed above. The attributes of these styles are adjusted to be suitable defaults for the
|
||
loading of RTF files.
|
||
|
||
|
||
On return from this call the document content is a single empty paragraph, to which the Body text (BT)
|
||
paragraph style and Normal (Nn) emphasis are applied. The character content is a single NULL (the
|
||
paragraph terminator). Note that this terminator must never be deleted, and characters must never be
|
||
inserted after it.
|
||
|
||
|
||
122
|
||
|
||
|
||
10 WORD FILE FORMAT CONVERSION DYLS
|
||
|
||
|
||
VOID InsertText(UINT pos, TEXT *buf, UINT Len);
|
||
|
||
|
||
Insert Len bytes of text, from the buffer pointed to by buf, at document position pos in the current
|
||
document.
|
||
|
||
|
||
The intended use is for the serial insertion of document text that has been read from the inpiut file. In no
|
||
circumstances should the insertion position be set to be after the document's final terminating NULL.
|
||
|
||
|
||
VOID DeleteText(UINT post, UINT pos2);
|
||
|
||
|
||
Delete and discard the text between document positions posi and pos2 in the current document.
|
||
|
||
|
||
The document's final terminating NULL must never be deleted.
|
||
|
||
|
||
SSeS SS aS ee ee ee a ee ee a ey
|
||
Common interface services
|
||
|
||
|
||
The services described in this section are intended for use in all file conversion DYLs, regardless of
|
||
whether they save or load files.
|
||
|
||
|
||
VOID StartActive(VOID *hand);
|
||
|
||
|
||
Start the active object, with handle hand, that performs a file conversion.
|
||
|
||
|
||
The active object is first added to the application manager's active object queue with priority
|
||
PRIORITY_ACTIVE_FILES. The Word application is set to a 'Busy' status and, on the Series 3, is marked as
|
||
locked, so that it will not respond to Switchfiles or Shutdown messages from the System screen.
|
||
|
||
|
||
The active object is started by sending it an AO_QUEUVE message and the application manager is sent an
|
||
AM_START message. The call to StartActive will not return until stopActive has been called at the
|
||
completion of the file conversion.
|
||
|
||
|
||
VOID StopActive(VOID);
|
||
|
||
|
||
Mark the termination of the active object file conversion, removing the ‘Busy status from the Word
|
||
application and, on the Series 3, removing the lock so that it will respond to Switchfiles or Shutdown
|
||
messages from the System Screen.
|
||
|
||
|
||
Sends the application manager an am_sTop message, allowing the earlier call to startactive to return.
|
||
|
||
|
||
Void SetBusyStatus(UINT flag);
|
||
|
||
|
||
If #lag is TRUE, set the Word application's ‘Busy’ status, otherwise clear it.
|
||
|
||
|
||
: _ sé printer data
|
||
PRINTER_PARAMS *SensePrinterParams(VOID **phand);
|
||
|
||
|
||
Return a pointer to the Word application's PRINTER_PARAMS struct. The data in this structure may be read
|
||
or written.
|
||
|
||
|
||
If phand is not NULL, the handle of the Word application's instance of the PRINTER class is written to
|
||
*phand. File conversion software is free to use all the methods of the PRINTER class.
|
||
|
||
|
||
123
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
WDR_MODEL *SensePrinterModel (VOID);
|
||
|
||
|
||
Return a pointer to the Word application's printer model data, contained in a WOR_MODEL struct. The data
|
||
in this structure may be read or written.
|
||
|
||
|
||
VOID *SenseWDR(VOID);
|
||
|
||
|
||
Return the handle of the Word application's instance of the wor class. File conversion software is free to
|
||
use all the methods of the wor class.
|
||
|
||
|
||
SS SSS a a Se ae
|
||
Example Code
|
||
|
||
|
||
This code in the following examples provides file conversions to and from a simple plain text format.
|
||
|
||
|
||
Save plain text
|
||
|
||
|
||
To avoid obscuring the basic mechanisms, the nature of the conversion and the format of the saved file
|
||
has been kept as simple as possible. The end of each text record is marked by a single carriage return
|
||
character.
|
||
|
||
|
||
Each record in a text file must not exceed 256 characters in length, but the example code makes no
|
||
attempt to enforce this. It simply saves each paragraph as a single plain text record, regardless of its
|
||
length. In order to create files that can be loaded by the following plain text loader example, the Word
|
||
file that is saved must not contain paragraphs that exceed 256 characters in length. A more robust
|
||
converter would break longer paragraphs into two or more records of less than 256 characters, and could
|
||
use an empty record to mark the end of a paragraph.
|
||
|
||
|
||
The saver DYL's category file, ws$nxt.car, is listed below:
|
||
|
||
|
||
LIBRARY wsStxt
|
||
EXTERNAL olib
|
||
|
||
|
||
INCLUDE p_std.h
|
||
INCLUDE p_object.h
|
||
INCLUDE olib.g
|
||
INCLUDE appman.g
|
||
|
||
|
||
CLASS txtsave active
|
||
NB Must be first class in the category
|
||
|
||
€
|
||
|
||
REPLACE destroy
|
||
|
||
REPLACE ao_init
|
||
|
||
REPLACE ao_run
|
||
|
||
REPLACE ao_abrun
|
||
|
||
CONSTANTS
|
||
€
|
||
CHAR_CR 13
|
||
TXTSAVE_BUFFER_LEN 256
|
||
>
|
||
|
||
PROPERTY
|
||
€
|
||
UINT ntags; total number of index tags
|
||
UINT curtag; current tag number
|
||
UINT pos; current position in document text
|
||
TEXT buf {TXTSAVE_BUFFER_LEN]; buffer for extracting document text
|
||
>
|
||
|
||
}
|
||
|
||
|
||
As can be seen, it only contains the single class TXTSAVE - a more complex converter may need additional
|
||
classes. The converter's active object class must be the first class in the category file and will always
|
||
replace the destroy, ao_init, ao_run and ao_abrun methods. It may optionally replace the ao_queue
|
||
method, as illustrated in a later example.
|
||
|
||
|
||
124
|
||
|
||
|
||
10 WORD FILE FORMAT CONVERSION DYLS
|
||
|
||
|
||
The methods of the TxTsave class are as shown in the following listing:
|
||
|
||
|
||
/*
|
||
TXTWRITE.C
|
||
ies
|
||
|
||
|
||
#include <p_std.h>
|
||
|
||
#include <p_file.h>
|
||
#include <ws$txt.g>
|
||
#include "wofconv.h"
|
||
|
||
|
||
GLREF_D VOID *DatApp5;
|
||
|
||
|
||
LOCAL_C INT OpenFile(PR_TXTSAVE *self)
|
||
/* forces a .TXT extension */
|
||
|
||
€
|
||
|
||
TEXT extension[6];
|
||
|
||
P_INFO info;
|
||
|
||
TEXT name {P_FNAMESIZE] ;
|
||
|
||
|
||
*(CUWORD *)&extension(0) =". '+¢'T'<<8)>
|
||
*(CUWORD *)&extension[2] ='X'+('T'<<B);
|
||
extension(4]=0;
|
||
f_fparse(&extension [0] ,DatApp5 ,&name(0] , NULL);
|
||
if (!p_finfo(&name [0] ,&info))
|
||
|
||
{
|
||
|
||
if (!DoConfirmOverwrite())
|
||
|
||
return(FALSE);
|
||
|
||
>
|
||
f_open(&sel f->active. pcb, &name [0] ,P_FUPDATE |P_FREPLACE |P_FSTREAM_TEXT);
|
||
return(TRUE);
|
||
>
|
||
|
||
|
||
LOCAL_C VOID ReplaceNulls(TEXT *p,UINT len)
|
||
/*
|
||
Replace the end-of-paragraph nulls with CR characters
|
||
*/
|
||
{
|
||
TEXT *pe;
|
||
|
||
|
||
for (pe=p+len;p<pe; p++)
|
||
|
||
|
||
€
|
||
|
||
if (!*p)
|
||
*p=CHAR_CR;
|
||
|
||
}
|
||
|
||
|
||
>
|
||
|
||
|
||
#pragma METHOD_CALL
|
||
|
||
|
||
METHOD VOID txtsave_ao_init(PR_TXTSAVE *self)
|
||
{
|
||
OpenFile(self);
|
||
self->txtsave.ntags=CountTags();
|
||
StartActive(self); /* does not return until the conversion is complete */
|
||
>
|
||
|
||
|
||
125
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
METHOD INT txtsave_ao_run(PR_TXTSAVE *self)
|
||
{
|
||
PARA_STYLE style;
|
||
EMPH_STYLE emphasis;
|
||
UINT taglen, txtlen;
|
||
|
||
|
||
taglen=SenseTagI tem(sel f->txtsave.curtagt+, &style, &emphasis);
|
||
while (taglen)
|
||
{ /* looping here means that a record is too long to read with WLSDYL */
|
||
txtlen=taglen>TXTSAVE_BUFFER_LEN ? TXTSAVE_BUFFER_LEN : taglen;
|
||
ExtractText(self->txtsave.pos,&sel f->txtsave. buf [0], txtlen);
|
||
ReplaceNul ls(&sel f->txtsave.buf [0] , txtlen);
|
||
f_write(sel f->active.pcb, &sel f->txtsave.buf [0] ,txtlen);
|
||
self->txtsave.post=txtlen;
|
||
taglen-=txtlen;
|
||
>
|
||
if (self->txtsave.curtag<sel f->txtsave.ntags)
|
||
p_send2(self,O_AO QUEUE);
|
||
else
|
||
p_send2(self,O DESTROY);
|
||
return(RUN_ACTIVE_USED);
|
||
>
|
||
|
||
|
||
METHOD VOID txtsave_ao_abrun(PR_TXTSAVE *self)
|
||
€
|
||
p_close(sel f->active.peb);
|
||
StopActive();
|
||
p_supersend2(self,O_AO_ABRUN);
|
||
p_supersend2(self,O0_DESTROY);
|
||
>
|
||
|
||
|
||
METHOD VOID txtsave_destroy(PR_TXTSAVE *self)
|
||
€
|
||
StopActive():
|
||
p_supersend2(sel f,O_DESTROY);
|
||
>
|
||
|
||
|
||
The document is scanned by use of the document's index tags, each of which marks a range of characters
|
||
that are formatted in the same way. If the conversion format includes formatting information, the format
|
||
of the text may be read from the emphasis and paragraph styles that are associated with each index tag
|
||
(pointers to these are supplied by each call to SenseTag! tem).
|
||
|
||
|
||
This example uses a synchronous write to the file in the active object's ao_run method and uses the
|
||
ao_queue method of the AcTIve superclass.
|
||
Load plain text
|
||
|
||
|
||
This example opens the input file as a true text file and thus assumes that no single record contains more
|
||
than 256 characters. Each record is considered to be a whole paragraph.
|
||
|
||
|
||
LIBRARY wl$txt
|
||
EXTERNAL olib
|
||
|
||
|
||
INCLUDE p_std.h
|
||
INCLUDE p_object.h
|
||
INCLUDE olib.g
|
||
INCLUDE appman.g
|
||
|
||
|
||
126
|
||
|
||
|
||
10 WORD FILE FORMAT CONVERSION DYLS
|
||
|
||
|
||
CLASS txtread active
|
||
NB Must be first class in DYL
|
||
|
||
€
|
||
|
||
REPLACE destroy
|
||
|
||
REPLACE ao_init
|
||
|
||
REPLACE ao_queue
|
||
|
||
REPLACE ao_run
|
||
|
||
REPLACE ao_abrun
|
||
|
||
CONSTANTS
|
||
{
|
||
TXTREAD_BUFLEN 256
|
||
}
|
||
|
||
PROPERTY
|
||
{
|
||
UWORD pos; current document character content offset
|
||
UWORD lastpos; document offset to start of the previous paragraph
|
||
TEXT eopara; NULL - the end of paragraph marker character
|
||
TEXT dummy;
|
||
UWORD Len; length of text in buf {J
|
||
TEXT buf CTXTREAD_BUFLEN] ; input text buffer
|
||
>
|
||
|
||
>
|
||
|
||
|
||
As in the previous example, the category file contains only the single class TXTREAD - again, a more
|
||
complex converter may need additional classes. The converter's active object class must be the first class
|
||
in the category file and will always replace the destroy, ao_init, ao_run and ao_abrun methods. In this
|
||
example the ao_queue method is also replaced.
|
||
|
||
|
||
The methods of the TXTREAD class are as shown in the following listing:
|
||
|
||
|
||
/*
|
||
TXTREAD.C
|
||
*f
|
||
|
||
|
||
#include <p_std.h>
|
||
|
||
#include <p_file.h>
|
||
#include <wl$txt.g>
|
||
#include "wofconv.h"
|
||
|
||
|
||
GLREF_D VOID *DatApp5; /* used for file conversion DYLs... */
|
||
#define FileName DatApp5 /* ...to point to the source file's name */
|
||
|
||
|
||
LOCAL_C VOID InsertBuf(PR_TXTREAD *self, TEXT *buf, UINT len)
|
||
€
|
||
InsertText (sel f->txtread.pos, buf, len);
|
||
self->txtread.post+=len;
|
||
}
|
||
|
||
|
||
LOCAL_C VOID ApplyPlainStyle(PR_TXTREAD *sel f)
|
||
€
|
||
PARA_STYLE *para;
|
||
EMPH_STYLE *emph;
|
||
TEXT paracode (2);
|
||
TEXT emphcode [2];
|
||
|
||
|
||
*(WORD *)¶code[0]='B'+('T'<<8);
|
||
|
||
para=SenseParaStyl eBySC(¶code [0] );
|
||
DoApplyParaStyle(sel f->txtread. lastpos, sel f->txtread.pos, para);
|
||
*(WORD *)&emphcode [0] ='N'+('N'<<8);
|
||
|
||
emph=(EMPH_STYLE *)SenseEmphStyleBySC(&emphcode [0] );
|
||
DoApplyEmphasis(sel f->txtread. lastpos,sel f->txtread.pos,emph);
|
||
>
|
||
|
||
|
||
127
|
||
|
||
|
||
ADDITIONAL SYSTEM INFORMATION
|
||
|
||
|
||
#pragma METHOD_CALL
|
||
|
||
|
||
METHOD VOID txtread_ao_init(PR_TXTREAD *selLf)
|
||
/*
|
||
Keep the supplied filename extension.
|
||
*7
|
||
{
|
||
f_open((VOID **)&sel f->active.pcb, FileName, P_FOPEN|P_FTEXT);
|
||
CloseCurrentFile();
|
||
SetDefaultStyles(4,6);
|
||
StartActive(self);
|
||
d
|
||
|
||
|
||
METHOD VOID txtread_ao_queue(PR_TXTREAD *self)
|
||
€
|
||
self->active. isact ive=TRUE;
|
||
sel f->txtread. len=TXTREAD_BUFLEN;
|
||
p_ioc5(self->active.pcb,P_FREAD,&self->active.stat,&sel f->txtread.buf [0],
|
||
&self->txtread. len);
|
||
>
|
||
|
||
|
||
METHOD INT txtread_ao_run(PR_TXTREAD *self)
|
||
|
||
€
|
||
|
||
if (self->active.stat==E_FILE_EOF)
|
||
€
|
||
ApplyPlainStyle(self); /* apply style to the final paragraph */
|
||
SwitchToNewFilecFileName);
|
||
p_send2(self,O_DESTROY);
|
||
return(RUN_ACTIVE_USED);
|
||
>
|
||
|
||
f_leave(sel f->active.stat);
|
||
|
||
|
||
if (sel f->txtread.pos)
|
||
{
|
||
ApplyPlainStyle(self); /* range does not include the terminating NULL */
|
||
InsertBuf(self,&self->txtread.eopara, 1);
|
||
self->txtread. lastpos=sel f->txtread.pos;
|
||
}
|
||
InsertBuf(self ,&sel f->txtread.buf [0] ,self->txtread. len); /* add text of next paragraph */
|
||
|
||
|
||
p_send2(self,0_AO_QUEUE);
|
||
return(RUN_ACTIVE_USED);
|
||
>
|
||
|
||
|
||
METHOD VOID txtread_ao_abrun(PR_TXTREAD *self)
|
||
/*
|
||
The application is shut down after reporting any error on Loading.
|
||
No data is ever lost by doing this, since any previous file will
|
||
already have been saved.
|
||
ied
|
||
|
||
{
|
||
|
||
StopActive();
|
||
|
||
p_supersend2(sel f,0_AO_ABRUN);
|
||
|
||
p_exit (0);
|
||
|
||
>
|
||
|
||
|
||
METHOD VOID txtread_destroy(PR_TXTREAD *self)
|
||
€
|
||
StopActive();
|
||
p_supersend2(sel f ,O_DESTROY);
|
||
>
|
||
|
||
|
||
As an alternative to the code of ttwrite.c, this example reads the file asynchronously by means of a call
|
||
to p_ioc in the replacement ao_queue method.
|
||
|
||
|
||
128
|
||
|
||
|
||
10 WORD FILE FORMAT CONVERSION DYLS
|
||
|
||
|
||
Na a EE HET Te SI
|
||
Debugging a conversion DYL
|
||
|
||
|
||
Although the conversion DYLs will run on both the Series 3 and the Series 3a, debugging a conversion
|
||
DYL must be performed on a Series 3a machine. You should use the normal arrangement, with the Series
|
||
3a set up for debugging from a PC by means of the SIBO debugger provided with the 'C' SDK.. The
|
||
DYL must, of course, have been built for debugging, and must have been copied into a \wdr
|
||
subdirectory of the root of any local drive on the Series 3a.
|
||
|
||
|
||
Since the DYL is only loaded into memory just before it is used, and is unloaded immediately after its
|
||
work is done, it is not possible to use the debugger to set a breakpoint directly in the DYL code. The
|
||
easiest solution is to set a breakpoint at a suitable point in the Word application and step into the DYL
|
||
code. Once the debugger is displaying the code of the DYL, you can then debug it in the normal way,
|
||
setting any further breakpoints that you need.
|
||
|
||
|
||
The Series 3a's Word application is in the machine's ROM, so it is not possible to set a breakpoint in it.
|
||
For this reason, a copy of the Word application is provided. Copy the supplied word.app into the
|
||
m:\app\ directory of the Series 3a. From the System screen's App menu, use the Remove option to
|
||
remove the built-in Word application and then use the Install option to install the copy from Internal.
|
||
Then run this Word application.
|
||
|
||
|
||
From the PC, start up a remote debugging session and break into the running Word application, using the
|
||
Break into option of the Debugger's Process menu. Then set a breakpoint at 0x30a3 and apply the break
|
||
point by selecting the Apply BP option from the Debugger's Process menu.
|
||
|
||
|
||
At this point you can cause a Word conversion DYL to run by selecting either Save as or Open file from
|
||
Word's File menu. In the resulting dialog, select the drive and file as normal, but select the File type to
|
||
be the one that will use the appropriate DYL. For example, to debug ws$nxt.dyl, use the Save as option
|
||
and select a File type of Txt. Then press Enter to exit the dialog.
|
||
|
||
|
||
The Word application will hit the breakpoint, with the window showing the line:
|
||
WORD:30A3 €81724 CALL 54BD
|
||
|
||
Step into this call, and then step to the following Lib€nter call, when the window will show the line:
|
||
WORD:54DF CDD2 LibEnter
|
||
|
||
Step into this call, when the window will show the line:
|
||
WORD:54FF CDCF = LibSend
|
||
|
||
|
||
Stepping into this LibSend call will bring you to the first executable line of the DYL code, at the top of an
|
||
ao_init method. If, for example, you are debugging ws$nt.dyl, you will be at the start of the
|
||
txtsave_ao_init method function.
|
||
|
||
|
||
From this point the DYL code can be debugged as normal.
|
||
|
||
|
||
129
|
||
|
||
|
||
7 h:
|
||
on : 7 a Pas
|
||
Aion epee te Gree .
|
||
|
||
= SS a ee SSeS vr - ae = ®
|
||
|
||
|
||
ppmmscecveraess
|
||
|
||
|
||
‘ dere hate fab
|
||
moa Poin Ae bp Seems 2
|
||
|
||
|
||
«Mm Sra, i a tral ye ag
|
||
7 Rotts ihe hack, “ioe rey ity 4
|
||
|
||
|
||
dea sri u of a?
|
||
Fatt de nye m we'd a ge rere feat on 7 o > ueG t * lay
|
||
> aa. | we pria oy uhm
|
||
|
||
|
||
> Je ee aa) eT ae me igo ii tre wd tlie Bier i
|
||
5 “er Sea
|
||
or Letre are atl? parse
|
||
i ae el eo Newil Hs 4
|
||
rl BEA)
|
||
|
||
|
||
eters 2a 9 bat gf LM tg, ged kat meth: AP poe . ue
|
||
ion she 4 Goma qurnen J tee a? am. lp wt a8) omelt ©
|
||
: me 40 ans tena of Ynud wa accel * yom ~
|
||
|
||
|
||
weg) P40 © > ere ers wae! ue area Wt vrs (uty sith?
|
||
|
||
= Po de in aw oil green Orel lene vw i i oon pe Fe
|
||
|
||
wap.) @ @ a? Wu Pee! atehin onan | ie i 1M ashi aru nal ol
|
||
het = - =~ wnejeedY Yas ewe aA we Tarai = 9%
|
||
|
||
|
||
nd ~ ee : @ s te + ‘
|
||
|
||
|
||
=’ ‘> OP aa «@ sees te an Pe pe ow Me oil ap
|
||
|
||
|
||
Rene" 2* em ee
|
||
sg) oll eae Op fe & safe fy Sli oe ey
|
||
|
||
mi; 9) * ed
|
||
- 7. ™- = = & = | — = @ A » Ge, Cary, 4m, is
|
||
bd Ce en = gor * 2° tates A on
|
||
|
||
|