From 538705a8079ff0bd5f5ae75e447dcf5be11d225b Mon Sep 17 00:00:00 2001 From: Lyra Thorpe Date: Mon, 6 Jul 2026 18:30:29 +0100 Subject: [PATCH] docs: add extra sdk docs --- docs/2-01 PLIB Reference 2.30_djvu.txt | 24890 +++++++++++ ...2-02 Window Server Reference 2.30_djvu.txt | 19786 +++++++++ docs/2-03 IO Devices Reference 2.30_djvu.txt | 14945 +++++++ docs/2-04 The SIBO Debugger 2.10_djvu.txt | 3286 ++ ...ware Reference (2.15 beta update)_djvu.txt | 161 + docs/2-05 Hardware Reference 2.10_djvu.txt | 1898 + ...amming in HWIF (2.15 beta update)_djvu.txt | 86 + docs/3-01 Programming in HWIF 2.10_djvu.txt | 10904 +++++ ...t Oriented Programming Guide 2.01_djvu.txt | 24907 +++++++++++ ...t Oriented Programming Guide 2.30_djvu.txt | 23578 ++++++++++ docs/3-03 ISAM Reference 2.10_djvu.txt | 1861 + docs/3-04 OLIB Reference 2.30_djvu.txt | 17132 +++++++ docs/4-01 FORM Reference 2.20_djvu.txt | 14412 ++++++ ...HWIM Reference (2.15 beta update)_djvu.txt | 215 + docs/4-02 HWIM Reference 2.11_djvu.txt | 37082 ++++++++++++++++ ...XADD Reference (2.15 beta update)_djvu.txt | 1231 + docs/4-03 XADD Reference 2.11_djvu.txt | 4598 ++ 17 files changed, 200972 insertions(+) create mode 100755 docs/2-01 PLIB Reference 2.30_djvu.txt create mode 100755 docs/2-02 Window Server Reference 2.30_djvu.txt create mode 100755 docs/2-03 IO Devices Reference 2.30_djvu.txt create mode 100755 docs/2-04 The SIBO Debugger 2.10_djvu.txt create mode 100755 docs/2-05 Hardware Reference (2.15 beta update)_djvu.txt create mode 100755 docs/2-05 Hardware Reference 2.10_djvu.txt create mode 100755 docs/3-01 Programming in HWIF (2.15 beta update)_djvu.txt create mode 100755 docs/3-01 Programming in HWIF 2.10_djvu.txt create mode 100755 docs/3-02 Object Oriented Programming Guide 2.01_djvu.txt create mode 100755 docs/3-02 Object Oriented Programming Guide 2.30_djvu.txt create mode 100755 docs/3-03 ISAM Reference 2.10_djvu.txt create mode 100755 docs/3-04 OLIB Reference 2.30_djvu.txt create mode 100755 docs/4-01 FORM Reference 2.20_djvu.txt create mode 100755 docs/4-02 HWIM Reference (2.15 beta update)_djvu.txt create mode 100755 docs/4-02 HWIM Reference 2.11_djvu.txt create mode 100755 docs/4-03 XADD Reference (2.15 beta update)_djvu.txt create mode 100755 docs/4-03 XADD Reference 2.11_djvu.txt diff --git a/docs/2-01 PLIB Reference 2.30_djvu.txt b/docs/2-01 PLIB Reference 2.30_djvu.txt new file mode 100755 index 0000000..143c93d --- /dev/null +++ b/docs/2-01 PLIB Reference 2.30_djvu.txt @@ -0,0 +1,24890 @@ +SIBO 'C' Software Development Kit + + +PLIB REFERENCE + + +Version 2.30 + + +March 1, 1999 + + +(C) Copyright Psion PLC 1990-98 + + +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, Psion Series 3c, Psion Siena and Psion Workabout are trademarks of Psion PLC. + + +TopSpeed is a registered trademark of Clarion Software Corporation. Intel 8086 and 80286 are registered +trademarks of Intel 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 Introduction...............scccscscssscrsscrsceseserseesessessseesssesseeeseesseesseesseesseesseessesscsesceessesscesscessessaeeseees 1-1 +PLIB, SIBO and: EPO eihcne sca .ansaunedehsanuedons aoaddthecaaltineehe 1-1 +The SIBO architecture::.:2.: sts2iess a Aleit: eters ede keene kt 1-1 +The: BPOG ‘operating: systerin.s..cescr)iccstasstisastesicctapatasscanddsisteanassicuss gauss agagenstiauaens 1-2 +The EPOC programming CnvirOnMent .......... ce eeeesceceseeceseeeeseeesseecsaeecseecseecesaeeesaeeesaeers 1-2 +Small: programming Model s,s. i255: 3eshesscstiessdacieas asides, dapbestoussbers esdisi aspen Aeedios Ad 1-2 +Hardware protect oni.ssii.sis: cessing ies Pexvs Poss tavshea avis est Seevased stung sas ideosdea deehe reel devsceupabesee dey 1-3 +More about memory moving and the 8086 segment registers...........eeeeeeeeeeneeeeeees 1-3 +The Clarion TopSpeed C compiler ...........cecceesccesseeceseeesseecesaeeesseecsaeecseeesneesssaeeesaes 1-4 +SYSLEM:SELVICES ssshe18 ccd Soap esidephie Asphials todos etiesieioindarhadietiadaehatddeisdaehis: 1-4 +PLIB Header! files s2i sss es covstaess oa ius foistness Oasis cote teossids Ban peetaess Ts hia Aateestos Rana ave 1-4 +PSU Biz: scasss cic vetoes csuczeiovstas vet aueahvovasiassc ssaginneeanaavee cane sisaeanaanas shagsuseeanaceageasasuigestases’ 1-5 +Callins conventions scs.s:ic15: Sstiothascii eet iotiows Sibi sthctosss oa ieiaciossesehilaedieseniieres 1-6 +Small proprawms sss vs.ssss lapivossesdbeed seabed sesh dacs sesesees ovsa sees sesv sues sustoese deavoassouatbase nesweeee AS 1-7 +The PLIB C startup modules 20.0.0... ceececesecsseeceseeeesaeecseecseeceseeessseessaeersneeesseeeesaes 1-7 +Related -teference: marital §:1s..s:::sccsndasstesssccassatlavetesbeceassnndauteestea ansendaicasteieatendaneestea isin: 1-8 +TopSpeed C library reference ........ eee eeeeeeceesseecsseecsseecsseecesceeesaeecsacecsseessseeeesaeeesaeers 1-8 +Window server reference :.:/:s.0 hahaha siderite ii 1-9 +W/O devices teferen Ce: 25.5 cis: eotstevss st: Find eotstavss batyek ets thors baths beiateese ds hibsaiteesiatsiredetes 1-9 +EPOC O/S System Services reference Manual...........eeeeeseeesseeceseeeesteeeseessneeeeteeeesaes 1-9 +Object dynamiclibraries y..:2.:) Asch elcid es aed ee eg eed a Love 1-10 +2 Characters, Strings and Buffers ................ccsssccssssssccsscsscssscscesssscesssscssesssscssessssessesssssessssees 2-1 +General string and buffer fUNCtIONS 00.0.0... ee eee eeseeceneeeeteecesaeeesaeecsaeecsseeseeecesaeeesaeeesaeers 2-1 +Copy memory to Memory (P_DCPY)..........eeeceeeesseecesseeeceeseeesessseeeseseeeeseseeesesseeeees 2-1 +Return string length (p_slen)............ccscccecsssscceeeecceeeesneeceeseaeeeceseaeeeeeeeaeeeeesneeeeeeneeeees 2-1 +Copy a: Stlin' © (Pe2SCpy,) cu. sess scagsset tea pbeouetey oes seca detboeg sdauevey bet hte ocaneyh pact ide poteaenbepeteeyy 2-1 +Copy multiple strings (P_SCPyM) ...........:ceseccseseecsseecsseeesseecesseeesaeecsaeecseeesseeeesaeessaeees 2-2 +Concatenate two Strings (P_SCat) .......eeeeeeeeesneessneeceseeesseeceseeeesseecseecseeceseeeesaeessaeers 2-2 +Concatenate many strings (P_SCAtM) ......... sees eeeseecsseeesseeeeseeeesneecsaeecsseeesseeeesaeersaeers 2-2 +Replicate a buffer (p_brep) .0..........ccceeeeecceeesneceeeseneeeessneeeeeeaeeeeesnaeeeceeneeeeessneeeeeeeeeeess 2-2 +Replicate a string (p2srep) se.vsieccaece.ciesyseeecaigtesecovsees Digi desovdevsgapdeb begaeoeebidepeel beanies 2-3 +Swap two buffers (p_Ds wap) ..........s:ccsssccssecsscecsseeceseeeesaeecsseecseeesseecssaeeesaeesseesseeeses 2-3 +Fill a buffer with a value (p_Dfil) 0.0.00... eeeccccceeencceeesneeeeeeeeeeeceseaeeeeesneeeeeesneeeessnaeeeess 2-3 +Ali gtisbutter: (psjtob) ssn: seccscocscevssce cou pbeesetey ote cue suet btes adthaveg beep sdhy oannest poekt ede podeaeeopanthees 2-3 +Generate the CRC number (p_crc)..........ccsssccccessnceecesnceeeeeeeeeeessneeeeseneeeeessneeeeseeeeeess 2-4 +Character classification and COMVELSION...........::cescccesceecesseecssceceseeeesaeecsaeecsaeecsseeeesaeeeeaeers 2-4 +Test for upper case character (P_iSUPPeT)...........ceeeeseeesseceseeeesseecseecsneeceseeeesaeessaeers 2-5 +Test for lower case character (p_1slOWeL) ............::ccceseeeceeeeeneeeeeeeeeeceeneeeecesteeeeesneeeess 2-5 +Test for alphabetic character (p_isalpha) ...........ceseeseeeeseeceseceseeceeeceseeceseeeesaeeesaeers 2-6 +Test for numeric digit (p_isdigit)....... eels eesecsseecsseeesseeceseeeesseecsseecseeseseeeesaeessaeers 2-6 +Test for alphanumeric character (p_isalnUmM).............c:eeeeeeeseeeeseecsneecsseeeeseeeesaeessneers 2-6 +Test for hexadecimal digit (p_isxdiQit) 0.0.0... eee eeseeeseeceseeceseeeseecseessseessseeeesaeessneers 2-6 +Test for whitespace character (Pp_1SSPace) .........eeseeeseeeeseecesseeeseecsaceceeeseseeeesaeessaeers 2-6 +Test for control character (p_iscntr]) ..........c:ccceeesceceeseceeeeesneeeeeesaceeeeeneeeeeneneeeeeeneeeees 2-6 +Test for punctuation character (p_iSpUNCt)..........eseeeseeesseeceseeeseecseecseeeeseeeesaeersaeers 2-6 +Test for printable graphic character (p_isgraph) .............s:cessseesseecsseeceseeceseeeesaeereaeers 2-6 +Test for printable character (P_iSPrint) .0....... ee eeseeeseceseeceseeeesaeecseecseeesseeeesaeessaeers 2-6 +Skip whitespace characters (p_Skipwh) ......cccccccccsscecsssecsscecesseeesseecsneessseeceseeeesaeeesneess 2-7 +Skip non-whitespace characters (p_Skipch)............sscsessecsseecsseeeeseeceseeeesseesseessneeeees 2-7 +Fold a character (p_tofld) ..0.......:.:cceesscceesescceeeeeneeeceeneeeeeseaeeeceseneeeesenneeeeseneeeesseneeeess 2-7 +Copy string with fold (p_Scpyf) ........eeeeeseessneeesseecsseecsseecesaeeesseecsaeecseeceseeeesaeeesaeers 2-7 +Fold ‘string (p USCOnf): 2. ssc. tt en oan eiet dees bithak eid cecal acckaeeeidide cucaeshoweeitibede tact sae 2-7 +Convert character to upper Case (P_tOUPPeP)......... eee ee eeeeeeceeseeeeeeeseeeeeeseeeeeenaeeeees 2-7 + + +Convert character to lower case (p_tolOWe?) ...........ceeeeesseeeeceeeeeesenneeeeceeeeeessneeeeeeeeeees 2-8 + + +PLIB REFERENCE + + +Capitalise string (P_SCap) .......eeseescecssceceseeeesseecsseecescecsseecesaecesseecsseecseessseeeesaeeesaeers 2-8 +SPINS COMMParISON Ger scse2.cesen gst ook, hot Shea etek Uoeist one sig oa Yaeek shes ited Taest oae Oe tant canes ak 2-8 +Compare two buffers (p_DCMp)..........cscceseecssseessseecsneeceseecesaeeesseecsaeecseessseeeesaeeesaeers 2-8 +Compare two Strings (P_SCMP) ........:eeseceeseecesseessseeceseecsseecesaeeesaeecsaeecseeceseeeesaeeeeaeers 2-9 +Case independent buffer compare (p_DCMP Ii) ...........eeeeeeeeceesecesseeceneeeseeseseeeesaeersaeers 2-9 +Case independent string compare (P_SCMP1)............esecesseccesseeeseecsneecsteeeeseeeesaeeesaeers 2-9 +String Searchin .sisi.sai sek dise tetera nl soared ates wei nel anavainbi autagineta. 2-10 +Locate byte in buffer (pP_DIOC) ...... eee eeeeeeesneeceneecsseeceseeceseecesaeecsaeecseecesaeeesaeessaeers 2-10 +Locate character in string (P_SIOC).........eeecceesseeeseecsseeeeseecesseeesaeecsaeecseeesseeeesaeeesaeers 2-10 +Case independent locate character in buffer (p_bIOCi) ....... eee eee eeeeeeeseeeeseeeeeeeeneers 2-10 +Case independent locate character in string (P_S]OC1).........eeeeeeseeeseeeseeeeseeeeeeeeeeneers 2-10 +Locate last matching character in a string (P_SIOCT) ............::cceeeeseeeeeeeeeeeeeneeeeeseeeeees 2-11 +Locate last matching folded character in a string (p_SIOCT1) ............cceeesceeeeeeeeeeeteeeees 2-11 +Locate sub-buffer in buffer (p_bsub) ...............cceeecsceeeesceeeeeeeeeeeesneeeeeeeaeeecseneeeesseeeeees 2-11 +Locate substring in string (P_SSUD) ...........ccesccecceesenseceeeneceeeeeneeeceseneeecseeeeeeseaseeeesaees 2-11 +Case independent locate sub-buffer in buffer (p_bsubi) ........... eee eeeeeeseeeeneeeeeeeeeeeee 2-11 +Case independent locate substring in string (P_SSUD1) 00.0... eeeeeeseeeeeseeeeeeeeeeeteneers 2-12 +Pattern match a buffer (p_bmatch).............cccccceeesseceeeenceeceeeneeecesneeeeeeeaeeecseneeeeeseeeeess 2-12 +Pattern match a buffer, case independent (p_bmatch1) ..............c:::ceesesseeeeeseeeeeeeneeeees 2-12 +Pattern match a string (p_smmatch) ............ceeccceeeeeeceeeeeeceeeenseeceeeceeeeseaeeeceenneeeeseeeeess 2-12 +Pattern match a string, case independent (p_smatchi)..............:cccccesesseeeeeseeeeeeeteeeees 2-12 +3 ATTAYS ANd QUEUES ............sccscesscssccseccsscscecssccseessscseesssscceessscesesssseseesesssccsesssscesesssscseesssccseeeees 3-1 +ATTAYSssiscisabsssorehhsiaidaaspsshasshessaciassostasibespigahaeakdsids sandals coatgsiar aids Mooedg secede Gecatdsieuuls hens 3-1 +Binary search an array of records (p_Dsrch) .........eesceeseeeeseessseeceseeeeseeeesaeerseeesseeeesaee 3-1 +Sort anarray of records: (PAqsOrt) si Jccbsss-esesests apie Aaadess Lap dedi Aesvdeadseedeh Aesvteas eeeaieh ees 3-2 +Doubly linked. ques’ #0. :s2s205cossvinsboedyosi ots keueubs these Sacks sodsthess Mh bseetstievsus Raeebeiess ts Beas 3-3 +Add entry to queue (p_CNqQue)........ eee eesecesecsseeesseeeesseecsseecsscecsseeeesaeecsaeecsaeeeseeesaes 3-4 +Remove entry from queue (p_Geque).......... eee eeeeesssecesseeceseessseeceseeeesseecsaeecseeesseeeesaes 3-5 +Delta: QUeCUGS: 53 is52css sor asians Aistdiee pcascass cus vaess Ase cass osst beds sua stissoustbans det duss sent dussseasduascunaiteaays 3-5 +Add entry to delta queule (p_emqued) 0.0... eeeeeesseceeseeceneesseeceseeeesseessaeesseeesseeeesaes 3-5 +Remove entry from delta queue (p_dequed) ........ eee eeseeeseecesceceseeeeseeecseecseeeeneeensaes 3-6 +4 Integer Conversion and Rectangle Functions ................ssccccssscssssssccsssssecssscseecssscseessscesessssees 4-1 +CORVETTE ANTE SETS LOTER Eases co, sede ecg shee Mnsedseseesseh sWastes sees ansheateeteesdupbuehest vant sees eebeats east ex 4-1 +Convert an INT to decimal buffer (p_i1tob) ..............ceeeesceceescceecesneeeeeeeeeecesneeeeeeeneeeees 4-1 +Convert a LONG to decimal buffer (p_Itob) 00.0.0... eeeecceeeescceeeeneeeeeeeeeeeeeeneeeeeseeeeees 4-2 +Convert a UINT to buffer any radix (p_gtOb) 0... eee eesecsseeceseeesseeessseecseeeeseeeesaes 4-2 +Convert a ULONG to buffer any radix (p_gltob) ...... eee eeeeeceseeeeeeeeseeseeeseseeeesaes 4-2 +Convert multiple arguments to buffer (P_atob)......... eee eeeeeeseeceseeeeeeeeeseeceeeeeteeeesaes 4-2 +Convert multiple arguments to string (P_AtOS) ........eeeeeeseeesseeceseeeeeeeeesseessaeeseteeeesaes 4-4 +Converting text to INtEQeLS ..... eee eee eeeeeceseeeesseecseecsseecsseecesaeeesaeecsaeecseeseneeeesaeessaeessneeeses 4-4 +Convert a signed decimal string to a WORD (p_StOi).........eeeeeeeeeeeneeeeneeseneeeeneeeeseee 4-4 +Convert a signed decimal string to a LONG (p_stol)....... cee eeeeeseeeeeseeeeneeesneeeeneeeesaes 4-4 +Convert an unsigned number in any radix toa UWORD (p_st0g)..........eceeeeeeeeeeeeeee 4-5 +Convert an unsigned number in any radix to a ULONG (p_stogl)...... eee eeeeeeeeeeeee 4-5 +Convert a string to arguments (P_StOd) ........eceeseeseeeesseeceneecseeceseeessaeecsaeersaeessneeeesaes 4-5 +Rectangle function ses esses tah ccccetaekcsceacieheseva gee seeid tebe cues deea uneesda deus cusadynetavadyen Gevsbyedeeda duke delts 4-7 +Offset:a rectangle: QP sOfirec) + a.25sss2ssseztdesetas ess canes iovadiass Sasagstaaeanasts cabigieszeaneaes Sausegansess 4-7 +Inset a rectangle (po Insrec): oc. ied lakh eG itiedegiciel nee Pandas 4-8 +Union of two rectangles (P_UMILCC)........ ee eeeeeeseeeeseeesseecsseeeseeceseeeesaeessaeersaeessseeeesaes 4-8 +Intersection of two rectangles (P_iMtreC) ....... eee eeeeeeesseeesneeesseeceseeeesaeecsaeessaeessseeeesaes 4-8 +Test if a point is inside a rectangle (P_PINTEC)........ eee eeseeeeseeeeseeeeseeeesaeerseeeeteeeesaee 4-9 +Test if a rectangle is empty (P_CMPTe€C) ....... eee eeeeeeeseeeeseeceseeceeeeeesaeetsaeerseeesteeeesaes 4-9 +Convert to an absolute rectangle (p_aDsrec) ........eeseesceceseessseeceseeeeseeeesseerseeesseeeesaes 4-9 + + +CONTENTS + + +5 FlOating: PONE .cc.ccsssacecessssvecensoovessassasennasoeceneasssdenendeosunansessusacdsodesasdssiesesdeosanassossaiosdensesoasensenee 5-1 +PlOatinie! POM tC oso, seses ceysditseantaced sensed stutievbcepseea sunpeecpoaete eee staeaate beste ceevatetpaeeth epee tease 5-1 +The: 8087 emulators: ais nice cesta hese ee eA SAG a A AE ay 5-1 +Avoiding the 8087 emulator .......... cee eeeceesseccssneecseecseecsseecesaeeesaeecsaeecseecsseesesaeessaeers 5-2 +MAaCTOS s:Aieitsevtesis ties ioti nse Re ad ee ed ee 5-3 +Converting doubles to and from text... eee eee esseeseeceeeeeeceeeseesseesseesseeseesseeseeeags 5-3 +Double. to.string: (pu dtob)sz.e.ss:.c.c cscs sesteieeeieeeeeib capt tedeydevbede poe besidebbezeneesbeeaeaes 5-3 +String to double (p_StOd) .........eeccceeesscceessceeeesneeeeeseeeeeceseeeeeeeeeeeceseaeeeeeenaeeecseneeeeeeees 5-4 +Get number representation preferences (p_getctd) ........eeeeeseesseeceseeceneeeeseeeesneessneers 5-5 +LON INtE Ber MIN CHUONS 2. sede leseleecsecusees secesbensctesesesesdeard oars sausvens sadesarvsadebars seudbanveatabereyegs 5-6 +Long random number (p_rand]) .00......ececeeesccceeeseceecesnceeeeeenceeeeseaeecesenneeeensneeeeesneeeees 5-6 +SCIEN AG TUNCHONS 55. 122. fs ses ook saet ee eaaes cet bea tese chit castes bce daunt ots duerees Sauet one beeeecaesineote 5-6 +Sime (PSI) x. scvvdsscesveisdaceee shaves pacdaceeedeceevcedesensced aves vesdaveancauaessscedacvat cesdevacccdesvarceaeates 5-6 +COSING: (PD =COS) os csce ced ce. g tis reneececetsteceenscecededs bedivesetadegetasedesndace ceded tedevsdnsadeisteseteatcatates 5-7 +‘Lancent, (potan)nivsicetst ste nvtisrisr tert rata eahiaeen sens pesiahesyen ened he bheveddu ayo ouss 5-7 +ATCSINE! (ASIN) 3d seh eskstue ooh aiden aye deh GUM eek Aiea aoe Au deh GoM otek de au obedient Hee 5-7 +AT CEOS. (Pp: 2aCOS) cs tscaecesseestceaa ces eenvavat cana cevvensvaeetcaancusudsanecst casereavdvaeas censsenvdtantabecetes 5-7 +ALCLANPSNE:(PAltAN):vsss0s dapsew cede gs lou ee siacetees sah pesos svdyedes aN pecedeedfeveuhety sveteetpedaseedpeincoregess 5-7 +Natural logarithm (p_In) .0..... eee eeeeeescecsseeceseeeesseecsseecsseecesaeeesaeecsaeecseeceseeeesaeessaeers 5-7 +Exponential (p2exp) cece bt ee eA RR Re A ee a 5-7 +Logarithm: (p::108) 2.02) savei heehee av hil arene hi ei ih ell eed ees 5-8 +SQUAT: TOOL (PASE). 25. discsatseedeces edusacessvevecesevepaceteenyetatsdusouetscsbedegstapedebsnnvedesosupaeebeaty 5-8 +Raise to the power (P_POW) .........cesccessceceseceeseeeesseecseecsseecesaeeesaeecsaeecseecsseeeesaeessaeers 5-8 +Double random number (long seed) (p_rand)...........eeeeceeeeessceeeeeeeeeeeeeeeeeesneeeeeenneeeees 5-8 +Double random number (p_frand) ...........cceccceeeesceeeeseceeeeeseeeeeseaeeeeeeneeeeessneeeeeseeeeess 5-8 +Floating point arithmetic without the 8087 emulator ........ eee ee ee eee ees eeseeeeeeeseeteeeeees 5-8 +Assignment: (pfld) ss: cs:c..ccaseestespiesdeoeekieegie des bebediyieel hye dvlal haben ane 5-8 +AG (ot fad) a cco sev ieetese ceed eas ebtee eh Gave enable ak Veh vada vite WVedcl ces esetecundersstieedaee eh 5-9 +Subtract: (p= fsub) si cc. ses. ccseseanceeeccaaceesceaaceescodaceescedescavecda seaucdueecsucedacvat ceudevanceseevancesendea 5-9 +Multiply (p7tmull) s.0 cece iecescedestecitbcstecavese tect acotechesda tue bestecugecetestbaeetecevetetesiprentedy 5-9 +Divide (Pp: f01V). i sccccc. cede ciescaciissceaeideesardes sess viesvesanieseeserdcseisardeveiderd covasardessitandeneacandens 5-9 +Compare-(p-ACMp)) 5.62 ccksttee cet eaiet eas teel aha eos thatch ait teeta aie ae a aie eaten 5-9 +Neate: (p: Mee) .3.ssciasiiatisivevaiiaten carga esisavaisel astvainelamginnieines 5-10 +Modiilus (pin) wiecccscaiee focaceteveducavedecatadedelasich Goiatededelace dagninteds dedsededncnsededadaeredaaneeey 5-10 +Integer part (pant): 5 2eescp.cenyazsdeghs testes ees etig tes eee apa eee aad eee est 5-10 +Convert double to integer (P_inti)...... eee eeeeceseecsneeceseecesaeeesaeecsaeecseecsseeeesaeessaeers 5-10 +Convert double to long (P_int])...... eee eeeeesseeesneecsneeceseecesaeeesaeecseecsseeesseeeesaeessaeers 5-10 +Convert integer to double (p_itof) 0... eee eeseeeeseecneecsseeeesseeesseecsacecseecsseeesseeessaeeesaes 5-10 +Convert long to double (p_longtof) ........ eee eeeeeeseceseecsseeceseeeesseecseesseeesseeeesaeessaeers 5-10 +OG Error Handling .icis.ciscccsiesscessecsvussccsvadeoctavssccvetedeccveassecevesedeocseasiseutadsdeerdacsseessededeactooedenssstoaes 6-1 +Process teriminatiOn:.c:istsisoutislarss dation tialineaids ica tia docauisties Mathoauethon Maer des Mate iad 6-1 +‘TLermifiatin e this: process: f.5.56$:sciesesccuectehsdetevsa cg vbevsiedehestnoyntevsbcschqueadyes enubedeleces yeaewuncd 6-1 +‘Terminating another process 24. :.i:0.d..0i.isstedistdaciestticeiish daciestdsedib ischial ons halen 6-1 +Finding out when other processes terminate ............ceeeeesseecsseeesneeeceseeeesaeersaeessneeeees 6-2 +The process termination WOId...........cccccesecssecssceeseceeesseecsaeecseeceseeeesaeeesaeesseeesneeeesaes 6-2 +PAIS his oh otafh ish scebsc chads ostocseuitevaoes saghe Sete eu boc edna tus Saestocnsiane Sui geigonsibabeoesseiedbiabesueags 6-2 +System: PANIC NUMDELS ssc. sssisessvesiees des dees ves does aves seessees does sves dues svapbues svasdabaovapbibesvasdues 6-3 +Terminate this process (P_€Xit).........ceesseesecssseecsseecsneecsseecssaeeesaeecsaeecseecsseeeesaeeesaeers 6-5 +Terminate after an unrecoverable error (P_PAaniC) ..........eseeeeeeesseeseneecsseeeeseeeesaeeesaeers 6-5 +Unilaterally terminate a process (p_pKill) 0.0... eee eeseceeseeceseeeeeeceeecsneeceseeeesaeeesaeers 6-5 +Terminate a process (p_ptermimate).........eeeeseesseceseceeseeeeseeeesaeecsacecseeeeseeeesaeessaeers 6-6 +Elect to receive termination message (p_onterminate) 0.0.0.0... ceseeeseeeeseeeseeeeeeeeeneers 6-6 +Panic a process by id (P_PPanic).........eeceeeeccssseeesseecsseecsseeeeseeeesaeecsaeecseeceseeeesaeeesaeers 6-6 +Request notification of process termination (p_logona)...........eseeeseeesseeeeeeeeseeesneees 6-6 +Cancel notification of process termination (p_logoffa) ...........eeeeeeseeeeseeeeseeeeeeeeneees 6-7 +Request message on process termination (P_lOQON)............essceesseeesseeceneeeeeeeeeeeeeeaeers 6-7 +Cancel message on process termination (p_logoff)...........eeseeeseeeesecsseeeeseeeesaeeeeaeees 6-8 +Cancel message of specific type on process termination (p_logoffx)..........eeeeeeeees 6-8 +Watching:all-exaits: (p“watchall) - 2.5. cis.ctcsastesidsepbssdspscdnsscespdticonssddasceapdescoverdedevapoeye 6-8 + + +ill + + +PLIB REFERENCE + + +Error Tetum: a.iestawest eis t at iste inte tia GS a A Ena eet 6-8 +Convert error number to string (P_errs)........cesccesssecesseessseeesseeceseeeesseecsaeecseeesteeeesaes 6-9 +Notifierservices isi iiiseiesictsea sated aia avei nied dohavhs edvuh ai asinr abate eae 6-9 +Present the user with a message and get response (p_Mnotify) .......... ee seeeseeeeseeeeseeeeeeee 6-9 +Notify user of error and get response (p_notifyerr)..........eeeesccceseeeesseeesneeteteeeeseeeesaes 6-10 +Setnotify. state:(pSemotity) :e: be seviee ons .e el ied eat itn abe eS ale eM 6-10 +Get notify state (p_getnotifY) 0.0... eee eeeeeesceceseeceseeeesseecseesseecesaeeesseessaeesseeesteeeesaes 6-10 +Hook the notifier interface (p_notifyhOOk) ......... eee eeseeeseeeeseeceseeeeseeessaeecseeesseeeesaes 6-11 +Unhook the notifier interface (p_notifyunhook) ............ceseeseeceseeeesneeesneeseneeeeseeeesaee 6-11 +Bnterand leaves: i.cicitssaceucatsccesis its. ossiasineectas seaste saves leaseanblaissetdaseen ladveetiaseeunlaecetast 6-11 +Enter a function (p_enter)............cccccceeeesccceesnececeeneeeeeeeaceecesnaeeeceseeeeeenaeeeeesaeeeeeseneeeees 6-12 +Unwind stack and return from last p_enter (p_leave) 0.0... eeeeeeeeeeseeeeeneeteneeeeseeeesaee 6-13 +Unwind stack and return from last p_enter if error (f_leave)............ceesseeeessteeeeeeeees 6-13 +7 Memory Allocation. .............cccscccsscssscssscssecssssseesscsscsscsssscscesssssesssscseesssscsesssscssesssscssesssccsessees 7-1 +Overview of systeM MEMOTY USAGE ......... ce eeeeseseecsseessseecsseeeesaeeesaeecsaeesseessseecesaeeesaeessaeers 7-1 +Memory Seaments..2.ccciiishs otictovesdbehdeacned cova deeladuneais ceesguube doteweh eqveqate dea couh Suesduvacsedees 7-2 +OEPMENE NAMES isc sssiisis esos dissdsetseandesk Aissdekd aseesh Aapoestousecisbovsecasteenpass daxsiasddexdeseets 7-2 +Segment handle, address and SiZe...........eeescceeseceesecesseeeseeesseeceseecesaeecsaeessneeesneeeesaes 7-3 +Process: data Segments’, .:siccsissctes.scisagaliass iat sassgatioes ise tavteanaeteapensasicasigaasgeasaaycaaiass 7-3 +Phe Heap: allocatOrs. sce cis.k oeloeeses sida dhecbeseeaanhdeet bietoess cei teed aehoasbensd obeedevsodyemebouva gueyodenecebed 74 +Heap Structure: ii.c.dctesec avbisefcnadesscvsvassdvandessovevioss doandvasdvacbest sostdassapbacesvataesioastaseoes 7-4 +Growing and shrinking the heap... eeeeseseecsseeseseeceseeeesaeeesseecsaeecsaeessseeessaeensaes 7-4 +AllOC- DEAVEn fetiehvis eA Ree wale ila ie inhi in ial eats. 7-5 +Internal fragmentation .......... eee eeeeeeseecsseecsseeceseeceseeeesseecsscecscecsseesesaeeesaeecsaeeseneeeses 7-5 +Allocate a memory Cell (p_allOc) ...... ieee ee eeeseceeeseeccesaeeecessaeeecesaeeecesaaeesesseeeess 7-5 +Free an allocated cell (p_firee)..........ccececccceesncceeeeseeceeseeeeeeenneeecesneeeeeseaeeeeesneeeeeseeeeees 7-6 +Change cell size (p_realloc) sic. scvccesicvsscus ces veguetesi cesta nceuneesieceesvanegseevevocas dan evsicesbeds 7-6 +Insert or delete data in cell (pP_adjust) ...... eee ee eeeeeeecesseecsneeesseeceseeeesseeesaeesseessseeeesaes 7-6 +Getcell length: (pialen) ssi eat tpint itsdeiyied Gist testes ates benvieh iii bearietene 7-7 +Set heap granularity (pP_hgran) ..0...... ees seeesseeesseecsneeceseeceseeeesaeecseessseeseseeeesaeeesaeers 7-7 +Visit all:cells’ (pvallwalk)s:. .c..ccacseccdiecseccavevancedscvas ccaendercedescetccavscne consacencesvedaecesecte ees 7-7 +Check heap integrity (p_allchk)...... eee eesecceseceseeeeseecsaeecseecsseesesaeessaeessaeesseesees 7-8 +Get heap address and potential free space (p_allspc)..........ceseeeseceesseeesneersneeeeseeeeeaes 7-8 +SYSLEM: MEMONY USAGE so. cee. s cass Miveas auacees unt Seen atn, css alba subalta casateeses sabdesdstaebsds sabebonebee 7-9 +Get addressable system RAM size (p_getram) .........eeseeeseeesseeceseeeesseeeseesseeesteeeesaee 7-9 +Get total system RAM size (p_totalK) 0.0... eeeeeseecesseeesseeesseeceseeeesseecsaeessaeessseeeesaes 7-9 +Get size of available segmented memory (p_Sgfree) ......... ee eeeeeeeeeeesreeeeteeeeneeeeneeeesaes 7-9 +Get memory used by internal RAM disk (p_sgramdisk)...........escceeeseeesseeseneeeeneeeeeees 7-9 +Memory segments: 33:2 sesinciasi sas thous eat hinds ee atin ene ee Rv oe 7-9 +Create memory segment (P_SQcreate) 0... ee ee eeeeeceeeeeeeesseeeceesseeeceseeeseesaeeeens 7-10 +Delete memory segment (p_Sgdelete)..............cceeeccecesesceeeeeeeeeesneeeeeeeaeeeceeneeeeeseeeeees 7-11 +Open memory segment (P_SQOPeN).......... eee eeseeeeeesseeeceeseeeeeeseeecessseeesesseeeceeseeeees 7-11 +Copy to memory segment (P_SQCOPYtO)........e ee eeeeeceesseeeceesceceeseeectesseeeseseeeeeeseeeees 7-11 +Copy from a memory segment (P_SQCOPYAT)........eeeeeseceseessteeceseeeeseeecsseecseeesseeeesaes 7-11 +Get size of memory Segment (P_SQSIZC) ....... see seeeeeeeesseeesneeteseeseseeeesaeeesaeesseessteeeesaes 7-12 +Adjust the size of a memory segment (p_Sgadjust) ...........ccscceceesseceeeeeneeeceeteeeeeseneeeees 7-12 +Find segments by name (p_sgfind) ...........eecccceeesceceeeenceeceeeeeeeceseeeeeesaeeeceeneeeeesneeeess 7-12 +Close memory segment (P_SQClOSE) 0.0... eee ee eeseeeceesseeeceeseeeeeeseeeceesaeeeceseeeceeseeeess 7-12 +Increment segment usage count (Pp_S]OCK)........ ec eeeeeesecsseessneeceseeeseeeessaeesseeesseeeesaes 7-13 +Decrement segment usage count (p_SgUNIOCK).........eeeeeeseeesseeceseeeeeeeecsseersaeeesteeeesaee 7-13 +Environment variables: cecctsesey a eetesteceine reeset teed sta nebsdeesteaissiabeger vier aeeenebeenseleee 7-13 +Get environment variable value (p_QeteNv).........eeeesecsseeesseeceseeeesseeesseecseeenseeeesaes 7-14 +Get environment variable value (p_getenViTON) ........... se eeseeeeseeceseeeeseeeeseeteeeeeseeeesae 7-14 +Set environment variable value (p_setenv)..........:::cceeseeceeeeenceeceeeeeeeeeneeeeeseneeeeeseeeeees 7-14 +Set environment variable value (p_setenVirOn)............::cceeeesceeeeeenceeeeeneeeeeeeneeeeesnaeeeees 7-14 +Delete environment variable (p_delenv)..............ccccccesesscceeeeeeeceeneeeeeeeeeeeseneeeeeseneeeees 7-15 +Delete environment variable (p_delemviron) .............cc:cccceeeseeeeeseeeeeeeeeeeeeneeeeeeeeeeees 7-15 +Find environment variables (p_findenv) ............ccecccceeesccceeeeeeeeeeneeeceeeaeeeeeeneeeeeseeeeees 7-15 +Find environment variables (p_fimdenvirom).............cc:cccceseeceeeeeeeceeeeeeeecesnneeeeseaeeeees 7-15 + + +CONTENTS + + +8 Asynchronous Requests and Semaphore ..............cssscccssscssscsscsseccsscseecssssesssscsscsssscseesssesees 8-1 +DEMAPNOLES 2 aie ssassutss causes saepe dea suuseveyssuteveyssucedey saute dey stuteddysuute des stucedssndutedvestute Merdetavevsteaates 8-1 +Process; scheduling 3:ia.tincaniienriseniiiagis aniiia cis ii avin ain pin ie 8-1 +SHared:access uti asain Sod we Ae ee Rad ae ot et ae ot a Bl a hk, al 8-2 +Supphier-consumer vii) cveieecii aie all i navel a iene 8-2 +ASYNCHTONOUS TEQUESIS :..s205 dee scapsessedepsdpesebsubtedes onus scebsunsedebontpageroutaedetouspraubenagedebonepsantensy 8-2 +Ihe l/O: sémaphote.sicea tics arti nied ara esha egret getneeeey 8-2 +StAtUs: WOLdS: ei ie Seed ete ctet otitis Stati eal etet tal aie Aa Ai tt on 8-3 +Cancelling an asynchronous request ............scceseccesseeeseecseecssceceseeeesseecsaeesseeesseeeesaes 8-4 +Waiting for a particular Completion ........... ee eeeeeeseeceneeceseeeesceessaeecsseecseeesseeeesaeeesneees 8-4 +Constructing synchronous fUNCTIONS 2.0... eee eeeeeeeseeeesseecsseecseeceseeeesaeeesaeesseeesseeensaes 8-5 +Wearthhandlerss.. sti: sicch ccecstat oR slide cues ois sant ato Bact stna been ater ed ted ot cevadietah oat eet, 8-5 +Polling rather than Waiting... eee eeeecesseecsneecsseesscecsseeeesaeeesaeecsaeecseessneesenaeeesaes 8-6 +Attached W/O devices sox... ieeccees. (ban edie sessedey bashedvesvetecagudas step aveesdepsdehontpesebededadehontpeanbadeg 8-6 +Primitive semaphore fUNctions ............seeeeeeeseeesseeeeseeceeecscecesaeeesseecsaeecseessteesesseeeeeeeeses 8-6 +Create a semaphore (Pp_SCMCIt).........ece ce eeeseeceesneeecesseeeceesseeecessseeeseseeeeeeseeesesseeeees 8-6 +Delete a semaphore (p_semdel) .0....... cee eeseceesseessseeceseecsseeceseeeesaeecsaeecseecesaeeesaeessaeers 8-6 +Wait on a semaphore (p_Wait) ..........eceeseceseceseeeeseeeesseecsaeecseeceseeeesaeessaeessneeesseeensaes 8-7 +Signal a semaphore (p_sigmal)......... ces eeesecsscecsseeceseeeeseecsaeeceeeesseeeesaeeeseesseessneeenes 8-7 +Signal a semaphore n times (p_signaln) ......... eee eeeeeeeseeesseeceneeeeseeeeseeeesaeesseeseeeeee 8-7 +Signal a semaphore with no re-schedule (p_signalnr) ...........esceeseeeeseeeeneeeeneeteneeeees 8-7 +DHE TAO Seta ph Ores sc:5, si /ocatservevetsss cecebsvs, odes sunp eden savy sgesschyass bouts deetocey edetoaspraubonagstebouepsasbensy 8-7 +Signal the IO semaphore (p_iosignal)..........eecesecssseeesseecsseecsneeceseecesaeeesaeessaeesseeeens 8-7 +Signal the IO semaphore of another process (p_iosignalbypid) ...........:eeseeeeseeeeseeeeee 8-8 +Wait on the IO semaphore (p_10Walt) ........ cee eesceesseeesseeesneesseeceseeeesaeecsaeessaeessneeeesaes 8-8 +Allow any wait handlers to run (p_loyield) ..........eseeseeeesecceseeeesneecseeceseeesseeeesaeessneers 8-8 +Wait for a particular request to complete (p_waitstat) 0.0... ee eeeeeeseeesneeteneeeeneeeeeaes 8-8 +Woatt anidlers x. toe. a, Sug sogstede opes sia conte ones ales ente fs ove ts Uaoans Dace veaud otnabhbess atest scerbunteanteestotensts 8-9 +Add a wait handler function (p_svecadd)...........ccccccecssscceeeeeeeeeeeeeeeceseeeeeessneeeeessaeeeess 8-9 +Activate/deactivate a wait handler (p_sveccall).............:ccessccceesenceeeeeeeeeeeeeteeeeeeseeeees 8-10 +Remove a wait handler (p_Svecrem) ...........:::cccssesceeeeseceeeeeeceeeeesaeeeceeeeeeesseneeeeesneeeees 8-10 +QD. TO SYStEM sscsciscscscessoessnviscevevedssedevsssecdecedsocdonssssevosescocbasdesvenedsogeansdoscvensdeonbaosseentadedceeseatsenseso’ 9-1 +VO; Device Drivers .sitiscesslatie tise tatctieoktateentis entation dateactialleataticasttaiss 9-1 +LDDs :atid. PODS es. seienet Sous cosh Sioa grads eub gosh Sais thee dutewes Sesecoens dunes ceuscnes sdutgout covsaven sgt oes 9-1 +Extermal device drivers'::s.4.csst2,.nisnisdiedinsacnsihode Mindi stonsth Miia A 9-2 +Opening a channel to a deVICC oes eeeeceseecsnecesseeeesseecsseecsaceceeeeesseecsaeesseessneeeesaes 9-2 +Operations on an open I/O channel..........eeseesecesssecesseesseesseeceseeeesaeecsaeesseeesseeeesaes 9-2 +The file Server sisc.fo a sieties ihe dine shite ioievaeteesersiohntoes bavi Miedo aot haba 9-3 +Attached: drivers: jiis.:hstosss | iiiosscsetis hs sohassaetiest Asioesstentiess casidevarbiseAssetisscouedone soeepaeed 9-4 +Channel-based I/O functions .0....... eee eeececeseeceseeceseeesseecseecssceceseaeecsaeecsaeesseesesaeeesatessaeers 9-4 +Open a channel to a device (P_OPeM) .........seeesceeeseeesseeesseeeeseeeesaeecseecsneeseseeeesaeeesaeers 9-4 +Start an I/O operation (Pp_10)........sceeseeesecsseecssceceseeeesseecsaeecsneecsseecesaeeesaeesseeeeneeenes 9-5 +Start an I/O operation with guaranteed completion (P_i10C)........eeeceeseesseeeeneeeeneeeee 9-6 +Start an I/O operation and wait for completion (P_iOW) .........seceseeesreeeeneeeeneeteneeeeee 9-8 +Close:an:I/O:channel (p- ClOSe)i.c.35;scesncsiisassassecectesuaneetlaneteatadaabeysacatosniaeseeasenaseunansss 9-8 +Read from an I/O channel (p_read) ...........cescceeeescceeesecceeeeeeeeceseaeecceeneeeeenseeeeeeeaeeeess 9-9 +Write to an I/O channel (p_Write)............ccececccccessceceeeeneeeeeenneeeseeeeceeeeaeeeesenneeesseeeeess 9-9 +Cancel requests on an I/O channel (p_iow(P_FCANCEL))............ccssesceeeeseeeeeeeneeeees 9-9 +Device dfiver futict Ons: ssc..26sss2c.sscchoteilshtesteniaes ches Woaekdaeaceeddates sate oteendaieatesiateandiisoes Bees 9-10 +Load a logical device driver (p_load]dd) ........ eee eeseeeseeesseecesseceseecseecsseeceseeeesaeessaeers 9-10 +Load a physical device driver (p_loadpdd).......... eee eeeeeseeeesceessneeceneeceseeeeseeeesaeeesaeers 9-10 +Delete a device driver (p_devdel)............cceessccessesceeeesneeeeeeeeeeeesnaeeccsseeeeeeneneeeeeseeeeess 9-10 +Query the number of units supported by a device (p_devqu).........eseeseeeseeeeeneeeeneees 9-11 +Find all devices (p_devfind) ............cceeeecccessscceeeeseeeeeesneeeeeseaceecesnaeeeeesnaeeeeneneeeesenneeeess 9-11 +Simple; console O's. sss jets esicaseoeasdestoust csssass nethses Asseeisssestieeg ous tbass cent dose suesvaae Sorostedobi ons 9-11 +Redirecting COnSOle WIites ...........cceseceseccesnceeseecsseecsseeeceseecssceceeecesseeesaeecsaeecsseeeesas 9-12 +Changing the size of the console WiINdOW ............secseseceseeesteeeeseeeesaeessaeerseeesseeeesae 9-12 +Changing the console Window MOde.............essseseseecsseeesseecesseeesaeecsaeecseecsseeeesaeeesaeers 9-12 +Write a character to the console (p_pUtch).........eeseeeseecsseesssceceseeeesaeecsaeecsaeessteeensaes 9-13 +Write a string to the console (P_puts) 0.0... .e se eeeeessecesseecsneeesneeesseeeesseeesseerseeesseeeesaee 9-13 + + +PLIB REFERENCE + + +Convert arguments and write line to console (p_printf).......... ce eeesecesseeeeeeeeeeneeeeneers 9-13 + +Convert arguments and write to console (P_Print).........e ee eeeeesseeceseecsseeeeseeeesaeeseaeers 9-13 + +Get a character from the console (p_getch)...........seesscesseccessecesneecsseecseecsseeeesaeeesaeers 9-13 + +Get a string from the console (p_gets) ..........eeseeeseecesseecsneecssceceseeeesaeecsaeesseessteeeesaes 9-13 + +Get a string with prompt from the console (p_getl) ..........eeceeeeeesecceeseeeeneeeeneeeeneeeeeaee 9-13 + +10 Time, Timers and Dates ..............ccccccccccsssssssssssssssssssssssssssssssssssssssssssssscssssscccccssssccccscsccsssssssess 10-1 + +SYStEMM tM, 22.453 ciss is Movethsiicds iatcessas hoeatatiesatielsaaeits Mrestieieduls teas detioss sta ielelincestetioatia 10-1 + +Return the system time (p_date) oe. cece seceseeceseeeeseecseesseeceseeeesaeecsaeecseeseseeeesaes 10-1 + +Set:the- system: time: (Psdate) a .ssp.set. Ass testesaphesssatiapeeedads Ash bekse sodas: Aapdeadesedshecs 10-1 + +Absolute: and relative timers: s:.2..600i55c2.us seus cava teag eens coveeesciva seyaeuva cows dev see dune davesduchus eva sevedued 10-1 + +Suspend process for n tenths of a second (p_sleep) ..........:eeseeeseecsseecsseeeeseeeeseeeesaeers 10-2 + +Suspend process for n system ticks (p_Sleept) .........eseeseceesseeeseeecsneecseeeseseeeesaeeesaeers 10-2 + +Suspend process until absolute time (p_sleepa) ........... eee eee eeeeseeeeeeeeeetseeeseetseeeaes 10-3 + +ASYNChronOus tUMers's..53<.8sceseecsstevstes schvocsadteysceh acevseehatevscedscevecgestevscevscevacebaceyscebsdevsegestevsdd 10-3 + +Start an absolute timer (p_ioc(P_FABSOLUTE)).............cc::cccsssseceeeeeeeeeeeneeeeeseneeeees 10-4 + +Cancel a timer (p_iow(P_FCANCEL)) ...........ccccsscsceeeesseeeeeeneeecesneeeeeesaeeecnsneeeeeseneeeess 10-4 + +Close a timer channel (p_clOSe) ............cccceeeessceeesseeeeeeeeeeceenseeecsseeeceesaeeesseneeeeeseeeeess 10-4 + +Converting between binary representations Of tiMe......... cee eeseeeseeceseeeeseeeesecesaeeesaeereaeers 10-4 + +Convert system time to P-DAYSEC time (p_sttods) .00........eccceeessceceeeeeeeeeeteeeeeeeeeeees 10-5 + +Convert P_DAYSEC time to system time (p_Cstost) ...........c:cceesesecceeeseeeeceeeeeeeeeeeeeees 10-5 + +Convert P_DAYSEC time to P_DATE time (p_dstodt)........0.eceecceeesseeeeeseeeeeeeneeeees 10-5 + +Convert P_DATE time to PLDAYSEC time (p_dttods)..........ceecceeeeeseeeeeeeeeeeeneeeees 10-6 + +Find the number of days in the specified month (p_dayinm)............seeseeeeseeeeseeeeeeee 10-6 + +Convert day since 1900 to day in week (p_Wkday)..........eseeseceseecesseeeeneessneeesneeeesae 10-6 + +Calculate week number in year (pP_Weekn0)...........c:ceesceseseessseeceseeeesseeeseesseessseeessaes 10-6 + +Time and date components in text fOr ......... eles eeeeeceseeeseeesseeeneeceaeesseeceseeeesaeenaeeesaeers 10-7 + +Get the day name (p_nmday)........ eee eeseeeseecsseceesceeesseecsseecseeceseeeesseecsaeesseeesneeeesaes 10-8 + +Get the day name abbreviation (p_nmdaya) ............:eesscssseecsseeceseeeesseeesseesseeesseeeesaes 10-8 + +Get the month name (P_NMMON)......... ccc eeeeessssneeeeceeeeeeeenneeeceeeeeseeenaeeeeeeeeeeeeenaeeeeees 10-8 + +Get the month name abbreviation (p_NMMoma) ..............cccssccceeeseceeeeeneeeceeseeeeeseeeeees 10-8 + +Get the day-in-month suffixes (p_getsuffixes) 0.0... eeceeseeesseceseeeeeeeeeseecseeseneeeesaes 10-8 + +Get the am and pm suffixes (p_getampmtext)......... eee eeseeesseeceseeeesseecsseecsaeeesteeeesaee 10-8 + +Get time representation preferences (p_getctd) ........eeeeeeeseeesseeceseeeeseeeeseeceeeeeseeeesaes 10-9 +Generating time and/or date StringS............ceeeeeesecsseeceseeseeeceseeeesseecsaeecseecneecssaeeesaeersaeers 10-10 +Date and time format Strings 0.0.0.0... eeeeessseeesseeceecseecscecscecsaeeesecesaeeesaeesseesseeese 10-10 +Convert a P_DATE time to a string (p_dt2str) oo... eee eeseeeseeceseeeeseeesseesseeeeseeeesaes 10-13 +Convert a PDAYSEC time to a string (p_ds2str) oo... ee eeeeeeeseeceeneeeeeeseneeeeseeeesaes 10-13 +Convert a system time to a string (P_St2Str) 0... eee eeeeceseeesseeceseeeseneeesaeerseessteeeesaes 10-13 +Convert the current time to a string (P_NOW2SUL)........ eee eeeeesseeceseeeeeeeeesseeceaeeseneeeesaee 10-13 + + +11 Files 11-1 + + +vi + + +VEST POC ao aerate cedseen sirecattldstet sahlpeestl ts deies sles iat Sidi cokes Satis shat els tat he Sa lilo set iat 11-1 +The file server scs3.cicee teeing oaey bei aagiesd iv aid eng ne ea ae 11-1 +File: SYStems's... 32.8 2s te A Rea oe ek Qa Bek A ie a ak 11-1 +SSD drives. sibs ienyiethd aah ee a ee vd i ee 11-2 +Unattended applications 2.0.00... eeeeesecceseeceseecseecsscecsseecseecesaeessaeecsaeecsaeesseeesenaeensaes 11-3 +RAM SS Ds:z.t.cstiaistisd Slee eeste eden ahaa ape ae eee Gani eee eae ets 11-3 +Blash SSDS sss01 seis on GN lat Ao Maat sh Ge eit ah AGA eects gO AGN ute ae BON Ss 11-3 +File-specificati Ons .vessvccsescvcess sextcces sens cons ceaveeavacds ceanccavecancevvecaeseavesadccseeuaacevnuassccveenanes 11-4 +Detault:path: 2:03 /5:0..cissed test ctsss Maetest eniehs Aosdin A aeiehieetedciehs hardin Antes Anes 11-5 +Charinél-based Services's. is: szcsseees dies sch tuys sets bes tsteuscevsaubessh stexs cus sebesvelvevesvbateaetnivevest 11-5 +Non-channel-based: Services 1: ..235isccsaiedosetis ec seadanaoeetaa seca wdativeahaguacaesbiaaveandaaousdaiaes. 11-6 +Asynchronous file Operations...........:ccesscecesseeesseecsseecsceceseeessaeeesaeecsaeessaeesseeessaeeesaes 11-6 + +Manipulating file specifications............cccseccceseseceeesenceeceeeeeeecesceceeseaeeeeeeeneeeceeseeeeeeneaeeeess 11-7 +Parse a file specification (p_fparse)..........ccccssccccssececeeeeseceeeseneeecesneeecessaeeeceenneeeeseeeeees 11-7 +Using p_fparse across filing SYSteMS..........ceceeseesseeesseeessceeeseeeesaeecsaeerseeesneeesseeensaes 11-8 +Change the directory in a file specification (P_Chdir) 0.0.0... cee eeeeeeseeeeeseeteneeeeseeeesees 11-9 + +The default node, device and directOry ..........eeeeeseseecesseeceseeeseecseecseecsseeeesaeessaeesseeeses 11-10 +Set the system-wide default path (p_setdefaultpath) ......... ee eeeeeeseecsseeeeeeeeeeeeneers 11-10 + + +CONTENTS + + +Set the default path of this process (p_setpth) ..........eeeeeeecsseeessneessseeesneessseeeeteeeesaes 11-10 +Get the default path of this process (p_getpth) .........eeceeeeeeseeesseeesseeceneeeeseeeesaeersneers 11-11 +Get the default path by process id (p_getpthbyid)........ ee eee eesecsseecsneeeeseeeeseeeesneers 11-11 +Operations on, nodes and devicesieissc..cs.55 Sas destneceeissesobissseap des naubiasnipdest Sasssespdensneitaaedes 11-11 +Get node information (p_minfO) .............cceeesccceeseeceeeesnceeeeeeseeeeeseaeeeeeeneeeeeeseeeeeseseeees 11-12 +Check if LOC:: has changed (p_locchg) .........eceeseeeseeeeseceseeeseecseecsneeesseeeesaeessaeers 11-12 +Get a list of devices (p_open(P_FDEVICE))............:cccccccesesseceeeeneeeeeeneeeeeesneeeeeseneeeees 11-13 +Get device information (p_dinfO).............cccsccccesssceecesnceceeeeneeeceseneeceeeneeeeseeneeeeeeneeeess 11-13 +Read media information of a local device (p_locdevice).............e:ccceeeeeceeeeeseeeeeeneeeees 11-17 +Direct read of local SSD (p_locreadpdd)...... eee eee eeeseceeseeceseeeeseeceaeecsseeesseeeesaeeesaeers 11-17 +Operations on directories and files 1.0.0... eeeeeseeceseeesneeesseecececeseeeesaeecsaeecsaeecsteeeeseeeesaes 11-18 +Get a directory list (p_open(P_FDIR)) .............cceccccesseccceesenceeeeeseeeceeneeeeseeneeeeeseaeeeees 11-18 +Return file information (p_fimf0) ............cccccccceesesceeeeseceeeeeeeeeeeseaeeeeeeeeeeeseeeeeeeseeeeees 11-20 +Test for the existence of a directory (p_testpth) 0.0.0... ceeeeeescesseeseseeceseeeeseeeeseeeesaeers 11-20 +Rename a file or directory (P_renaMe)......... eee eeesecsseeeeseecesceeesseecsaeecseeceseeeesaeeesaeers 11-20 +Delete a file or directory (p_delete).............ccccceeeesseceeseeceeeeeneeeceseneeeceeneeeeeeeneeeeseeneeess 11-21 +Make a new directory (pP_MKdIL).............eeeeccccesseceeeesnceeeeeseeeeeseaeeecesneeeeeesneeeeeseeeeees 11-22 +Set file attributes or label medium (p_sfstat) .............::ccesesceceeseeeeeeeneeeeeeeeeeesesneeeeeeees 11-22 +Set file creation date (p_fdate) .............ceeeccccesssscceeseneeeeeseneeceesneeeeeseaeeeeeesaeeeeeeneeeeeeeas 11-23 +Binary. file:access\..2: ai acich devieichaccin dieses bantu dante Bani daar 11-24 +SAE ACCESS 25 5253 aoe use Us Heandhedi wack Seaaeeb abe eS e Saau vs cueady wb cada den Sues By eke Ta ayaeeTe Tyee eee 11-24 +Exammple‘of binary file-access szt25..cc.:ciussetialcesddcissandaistesiesisaeataslscesdesiapeatea.cesbaaianess 11-25 +Close a binary file channel (p_ClOS€) ........e ec eeseeeseceseeesseeeeseeeesseecseecseecesaeeesaeessaeers 11-27 +Read from a binary file channel (p_read)......... ees eeseeesseeeeseeeseeecsaeecseeeeseeeesaeessaeers 11-28 +Write to a binary file channel (Pp_WIrite) 0.0.0... eeeeesseeceseecsneeeeseeeesaeecsaeesseessseeessaes 11-28 +Position a binary file channel (p_seek) 00.0.0... eee eeeseeeseeesseeeeseeeesseecseecseeseseeeesaeeesaeers 11-29 +Cancel an asynchronous file channel request (p_iow(P_FCANCEL)) .............:::::08 11-30 +Stream: text Mle:ACceSsi a. -5.5..visscesebicteaseisbscassdevecaaws das daswisng cavsoeea Sosa edegcventics suvavaassvancigesvaanics 11-30 +Open a stream text file (p_open(P_FSTREAM_TEXT))............c::cceeeesseeeeeseeeeesetseeees 11-31 +THOXt TIE ACCESS: tacsiacstadsacancs sezesties exGeahesaece teats onde ist «anand saeateeeasagteauacaueaataseeetacnegaeesaas 11-31 +Open a text file (p_open(P_FTEXT))...........ccccecesceceessceeeeseneeecesnaeeecesneeeeeseneeeeesneeeess 11-32 +Close a text file channel (p_ClOse) ............eeesscceessneeeeesnceeeeeeaeeecessneeeceeneeeesseneeeessnseeees 11-32 +Read from a text file channel (p_read)............ceeeeecccesescceeeeneeeeeeeneeeeeeneeeeessneeeeesneeeees 11-33 +Write to a text file channel (P_WTite) ............cccceeeeecceseneeeeeeeeeeeceeeeeeeeeaeeeessneeeeeseeeeess 11-33 +Position a text file channel (p_seek) .00.........cccceeesceceesecceeeesceeeeeeneeeeeeneeeesssneeeeeeneeeees 11-34 +Flush internal file buffers (p_iow(P_FFLUSH)).............cccsscceeesssseeceeseeeeeeseeeeeseeeeees 11-34 +Set end of text file (p_iow(P_FSETEOP))..............ccccccceessseeceesneeeeeeeeeeeesseeeeessneeeeenees 11-34 +Cancel an asynchronous file channel request (p_iow(P_FCANCEL)) ..............::::008 11-34 +12 Processes and Inter-Process Messaging ..............scccsssssscssssssccsscssccssscseecssscsesssscssesssscseesssocsors 12-1 +PLOCESSES - snc oe isbadtpoast tee deveganspadeeededetehnuses cots vebetvennton cot deletuborie coho tela Tntoutel coaeteaaueerees oontedy 12-1 +SYSLEtM PLOCESSES sci sesstis laste asdebresindess tiptesbesaedesdapheansydncepha iasbhies Mish Geile 12-2 +Process ID and process control DIOCK ...........::cccesecceceeeeceeeeeeeeeeeeeaeeeeeenneeesseneeeesenneeeess 12-2 +PROCESS: SLALES we. y sas tstavccitens Velie teeteeeetstesis cevvdepei ar aaaceveeni nei eae ba vauiecaanecuiseavdsaseateceteey 12-4 +PHOGCESS: QUEUES frdac ised evsn sie oadatecs ¢ edsns ve poang eles auenach godecotesoDtgarn (bceteten eVatbengteeteds eadttecegbec envy 12-4 +PLOCESS: PTIOTItIOS 2 si ccieieseedandesbeseniesecdardeveedendcaeidandcvuidenta devise tecopicas cdesdeadedevadaecdeveceoees 12-4 +Preemptive Scheduling: : 05, .:.c¢...s0ies ek vavsd saeeshgscun cee va tedestiaast ots satniesh caesbecesduce sshavestonesats 12-5 +PFOCESS NAMES we ses se ceveedvevaeeci acess ebeavauadsaceseesusees deste verhnceet diay evens ouat ea ae uh Taree aS 12-5 +Reserved statics (Magic StatiCs).........:cesccesssscceeeeseeeeeeeneeeceseceeseaeeeceeneeeeeseeeeeeseeeseaees 12-6 +Shared Code:sepmients::, s1.5g.c2...egeysgidesspbestegeyhaibesrdesbgiyiesden reece duyoedesenebdieyoebeanaees 12-8 +Tra esl eS: se, Ses sod sane ted oer tcict seh Sioe coun test oak og caartaiec eh eal satan cee hides Western dlceaatt eet eee ts 12-8 +ProGess: terMinatiOM .cseevccsescsieeae ceveesanccaievcas cevedcatccesicna covvccancessccaa dus vecdaseaucdaaceauceseevseceseevanees 12-10 +Cr@atitiS asprocess ia... vess ta fedat eves tat hfs sdetcengyotetedadet tts ciutetesotes terppdase elas oveendauythdevecidpeiteth ets 12-10 +Load san: image:(p exec) s.2..5checyeet ey aekbedi gigs ceeedes dada piaed deeebeabegs pas edesbesbeepae eae 12-10 +Load an image asynchronously (p_eXeCCASyMC)..........eeccceeeeseceeeeeceeceeeeeeeeeeseeeeeeneeeees 12-12 +Create:a procéss (p= peréale).cctccii i atankt ined a iis 12-12 +Operations on the CULTeNt PLOCESS........ eee eeseceseecesceeeseeceseeessaeecsseecesaeeesaeecsaeecseeseteeeesaes 12-14 +Get this process ID (p_getpid) 0.0... eee eeseeeeseecsseecsneecsseecesaeeesseecsaeecseeesneesesaeeesaeers 12-14 +Mark this process as non-active (p_Ummarka)...........c:cccceeesscceeesneeeceeeeeeeseeneeeeeseneeeess 12-14 +Register activity (p_tickle)........ceeceeessccceesnceeeeseeeeeeseeeeceenneeecseeeeeeseaeeeeneneeeeeseeeeees 12-14 +Mark this process as active (pP_marka)..........cseeseccesseeseeceseeeesseeceaeecsseeceseesseesenaeeesaes 12-15 + + +vii + + +PLIB REFERENCE + + +Operations ON ANY PLOCESS 0.0... eeeeeeeessneeesseecsseecssceceseeeesseeesacecsaeecseecssaeeesaeeessneeeeseeeesaes 12-15 +Get a process priority (P_Qetpri) ....... eee eee seeeseecsseeeeseecseecseeceseeeesseecsaeesseessneeeesaes 12-15 +Set a process priority (P_SCtpTi) ........eeeeeeeecesseecsneecsseeceseeceseeeesseecsaeecseeessseeeesaeeseaeers 12-15 +Resume a process (P_PreSUME) ....... eee eeeeeeceeseeeeeeseeeceeseeeesesseeeceesseeeseseeeceesaeeeees 12-15 +Suspend a process (p_PSUSPeNd)...........seeeeeesseeesseecsseecsseeceseeeesseecsaeecseeseseeeesaeeesaeers 12-15 +Get a process name by ID (p_pname)............eesceessecesseecsseeceseeceseeeesaeecsaeesseeseneeeesaes 12-16 +Rename a process (P_PreMaMe) 200.0... eee eee eeeeseeeceesceecessececceseeecessseeecesseeeceeseeeess 12-16 +Get a process ID by name (p_pidfind)...... eee eeeeceneeceneessseeceseeeeseeecsaeesseeesteeeesaes 12-16 +Find all processes (p_pfind).......... cc eeceeeseceseecsseeceseeeesseecseecseeceseeeesseeesaeesseeesneeensaes 12-16 +Determine the owner of a process (P_gQetOWNET)...........::cceeeesceeeesseeeeeeeeeeeeeeneeeeseeeeees 12-17 +Accessing a process data SCgMent.............::cccesessceeeeeneeeceeeneeeeeeeeceeecesseeeeesnaeeeeesneeeeeseeeeess 12-17 +Copy data froma process (p=pCpyft) uc. sseccissd-ssiesedeas dseteestbedacsspdsicvesplaasdoapdossoeseeaabers 12-17 +Indirected string copy from a process (P_PISCPYfT) ..........:ccssccceeeseceeeeeeeeeeeeeeeeeeseeeeees 12-17 +Copy data to a process (P_PCPYtO).........eseeesccssseeceseeceseecseecsseeceseeeesseeesseecseeesseeeesas 12-18 +Titer process:messa gin gyi iesioc5ise nasa desi oteh Sek Seok donk Seehcbekbies Sock cdondeed Like on feud Waadasheaabee 12-18 +Message: slots:ssi ss s:cssissssustiess datbsie ostions Gapees avbins Aaadies assess Asians austen Asides nantes os 12-18 +What the:Server does. .2.s5 sci seus eszsths fet steyestasvis sel scveseusssube ful cevuscayssbes sd cavuscuvestbeavisveyest 12-19 +What: the CHent dOeS ¥:s.s.i:.4setesieccetlanissotgaletestdasbeentasiecestSawsvosteaiacs tlavivestastarent ladoeenace 12-19 +Atv example Of a SEL VEL if oct Seosccc) bach Schl coueess Sock bouie ceveoehcccaaed caveneus ohevedsaubbeguscven serene 12-20 +Corresponding client code example ...........cescceeseeesseecsseeceseeeeseeeesaeecsaeecsaeessneeesseeeesaes 12-21 +ASYNCHTONOUS: MESSAGING c s2.. 6225 cewek cea syea cadet eee ovs dank Sobtah we cov aaekg FuvTa estas Sea ndeVta seek eae 12-21 +Message processing OFeL ...........sseccccesscceeessceeceencecesseeeceesnneeeseeeeeeeeeaeeeeseneeeeeseseeess 12-22 +SERVED TUNCHONS 23 vose se oes26i Saf oak sslat es eeaaeuabaessckibe caged saubceeis lon Sedensoersyoseneodeduneeesentodougs fy 12-23 +Initialise for message reception (P_MIMIt) ...... eee eee ceseeesneeceneeeeeeeeesaeerseeesteeeesaes 12-23 +Wait for message reception (P_MIeCC1VEW).........-eeseceeseceeseeeseeessaeecseesseecsneeeeseeeesaes 12-23 +Asynchronous message reception (P_MIreCelVe) ..........::ccceeeesceeeeseeeeeeeeneeeeeeeeeeeeseeeeees 12-24 +Cancel a message receive request (p_Mcancel) ........ eee eeseeeseeceseeeeeseeesaeesseeesteeeesaes 12-24 +Freeda messagé-(p: mire): -i i ccssssbesed cedeaccvisdusecedesieacvtedusteoteasch dons vencsesege da Svansastoeseca tees 12-24 +Chent fun CH OSs syc0i. seus sdsiiecsets hesfiovtuesvevs Geis Goth Sd eedviiersts dase tees ea eases hase 12-25 +Senda. message’ (p mSend)ssc2.ics.sccsueissscennsseatesteasaceabsdesganhe sant sanoeaoebieaeoeetieenseahaase Ss 12-25 +Send a message and wait for a reply (p_msendreceivew)............:ceseceeseeceseeeesneeeeneers 12-25 +Asynchronous send message and get reply (p_msendreceivea)............eseeeseeeeseeeeeeee 12-25 + +13 General System Services ..............ssccsscscscssscssecssscecsscsccsssccessssescescssesssscssessssessesssscsssscsseessseees 13-1 + +SyStemn- in fOrMalOn ss si. ssestewes hos Abst ss cach shes pbsDeves cet dies Avs TG sous thug baDUS. cous hess TE cast heeds 13-1 + +Get the operating system Version (Pp_VeTSiON)..........::cescceesessseeceseeeesseeesseersneeesneeeesaee 13-1 + +Get the ROM version (P_romVversiOn)...........::ccccesccceeseeceeeeeeeeeeeesneeeeeseaeeeceeneeeeeseaeeeees 13-1 + +Get the cause of the last system shut-down (p_getres) .........eseceeseeseseeesneeesneeeeneeeesaes 13-1 + +Get operating system data (p_getosd)..........eseeseesseecesneessseesseeceseeeesaeecsaeesseeesseeeesaes 13-2 + +Get power supply type (p_QetPSu) ........ ee eee ec eeseeeceesseeeeeeseeeeceseeesessaeeeseeseeeceesaeeeees 13-2 + +Wan Sua Se AN" COUNTY 12 555 Sica Seok sheesh ok bees ek het Shek eebge sh Sues eoabe solwead yaebvil coleneh een eoid ewiete 13-3 + +Get the language code (p_getlanguage)...........eseeeseesseecsseessseeceneeeesaeessaeesseeesneeeesaes 13-3 + +Get operating system text (P_QetteXt).... eee eeeeesseecesneecsneecsseeceseeessaeeesaeecseeseteeeesaes 13-3 + +Get country-dependent data (p_getctd) 0.0... eee eeeeeessseecsseessseeceseeeesseeeseecsaeessseeeesaes 13-4 + +Set country-dependent data (p_setctd)...... 0. ee eeeseeesseecsseeceseeeesseecseecsseeceseeeesaeeesaeers 13-4 + +Switching on and off.s.e55s:3 iets teres Hides ede Penance diet aa meie alban demyinbe eaned ae 13-5 + +Switch-off: (Pp: Off): sees sec Gotia viet dette enti ee kaa ek Ae AN ae es 13-5 + +Get the auto-switch-off period (p_getauto) 00.0... eeeeseesseessseeceseeesseeessaeecseeeeseeeesaes 13-5 + +Set the auto-switch-off period (p_Setauto) 00... eee eeeceeeseecesneeeseecseecseecsseeeesseessaeers 13-5 + +Get switch-off state when mains is present (p_getautomaiNs)............:eeseeeseeeeseeeeeee 13-5 + +Disable/enable switch-off if mains is present (p_setautoMaiNS) ...........eeeeeeeeeeeeeeeeee 13-6 + +Allow auto switch off (p_allowoff)............cccecsceceesncceeeeeeeeseeeeeeeseeeeeeeneeensaeeeseeneeeeeeees 13-6 + +Enable/disable the ON key event (p_SetoneVent)...........eeeeeseeceseeeeeeesseesseeeeteeeesaes 13-6 + +Power SUPPLY ss. itccei ets oite Moiese eee Se tei nea ee eae 13-6 + +Get power supply status (p_SUPPLY)........0. eee eeeeeeceesseeeceeseeeeeesaeeeceesaeeesesseeeceesaeeeees 13-7 + +Get additional power supply data (p_supplyinfo) ..0...... eee eeeeeceseeeeeneeeeneeseneeesseeeesaee 13-7 + +Get battery warning and maximum levels (p_WSUPpLY)...........-.esecseseeeseeeeneeeeneeeeseee 13-9 + +Get the battery type (p_getbat) 0.0... eee eesecsseceseeeesseecseecsseeceseeeesaeessaeerseeesteeeesaes 13-9 + +Set the battery type (pi setbat)iaicc heli at ail etteelon ail iti hai Alaris 13-9 + +Keyboard yi.2325) aiteeiseseneidiveibaeyssyideoes esta iis ser egieiest Randy eines ieeeneai asi cetcenese eae don 13-9 + +Get the state of all keys (p_getscancodes) .0.........esseeeesecsseeesseeceseeeesseeesaeecseeeeneeeesaes 13-9 + + +viii + + +CONTENTS + + +Display iesesissaeusrestecei bess 2eveptazebs feistebesia loves paubteestna stvke eb tveslov dies Fevadhestoasieks seadvslovsenaeeedy 13-10 +Get the system display type (p_getled) oe. ee eeeeesseeceseeceseeeeseecsaeecseeeeseeeesaeersaeers 13-10 +Change the LCD contrast (p_Icdcontrastdelta)...........seeeeeeesecesseecsneeeeseeceseeeesaeersaeers 13-10 +Get the current LCD contrast (p_gethcdcontrast)..........ceecceeseesseeeeseeceneeeeseeeesaeeesaeers 13-11 +Switch the backlight on or off (p_backlight) ........ ee eeeeeeseeceseeeeseeeeeeeeesseessaeeseeeenes 13-11 +Set the backlight control value (p_setbacklight) 0.0.0... eecceeseeeseeeeseeceseeeeeeeeaeessneeenee 13-11 +Get the backlight enablement (p_getbacklight) ........ ee eeeeeeceesseeesseeeeseeceseeeesaeersneers 13-11 + +DOUMG aces satiets ibs. ee lrevsess deaesvisugedues Aavesesadsdouakach stbece Ausudeed evsbens sesmries susasdesheaatiesouaeeersaaaeaes 13-12 +Make a sound with the piezo (p_SOUNG)........... se eeseeeseeesseeceseeeesseecsacecseeessaeeesaeessaeers 13-12 +Get the:sounid flags (p~Setsnid )isvicic ascetic asesndausesenas aosendassceebaccaosondauseeeigacassendaseasieaiss 13-12 +Set the sound flags (p_setsnd)..........ceeseesceeesecsseeeeseeeesseecsaeecseeseseeceeaeeesaeesseeseeeese 13-12 + +SOuMGON the Series: Bais. ee sas sess baehiatesodses Aas dda ceagedads Sass deudcavedeua csnvseacouse cues cvsasiasoesecuessvaarces 13-13 +SOUMG: PCG 5 08 cece sek cteveznks Heekendedeesesha deesessadeecsseadies cubadu ys tadaduwasevgduncteds dyveceds tunesessdunssebane’ 13-13 +The A-Law-encodine Schemes. ic..i:ic-arisuiseuntaistanssoanaiianpadaiaiaieaniaiciet 13-13 + +Series 3a sound SySteM SELVICES..............::esececsoresesscrensetensnesnonersssevenseneneeesnenestosenenseteneeees 13-17 +Record a sound asynchronously (p_recordsounda) ...........::esecesesecsseecsseeeeseeeeseeesaeers 13-17 +Cancel sound recording (p_recordsoundcancel) ...........ceseceesseesseecsseecsseeeeseeeesaeersaeers 13-17 +Record a sound synchronously (p_recordsOundw)...........::ccsssccesseeesseeceseeeeseeeeseeesaeers 13-18 +Play back a sound asynchronously (p_playsounda)............ssseesseseseeeeseeeeeeeeeseeeesaeers 13-18 +Cancel sound playback (p_playsoundcancel)..........eeseeescceeseeeeeseeceseeesneeseseeeesaeessaeers 13-18 +Play back a sound synchronously (p_playsoundW) ...........:eesceeesecsseessseeeeseeeesaeeseaeers 13-19 + +Miscellaneous s..:is..ecstdsssecadeascest sssaacataateeatesssacateaustes teat beateaieceasodeipeubacntdonseuaeextanteaaneantss 13-19 +Exit t6:DOS:i(p Dwexit isi ocecissek deka oak cack aa hodee eae Pek elt HOLL Coheed Perel ote 13-19 +Null: action) (pdummy).sscc.2hse¢ssties, ccssdeas sosnbess diastase hethess Aanlanenerdass Aactasomarissnattass 13-19 + +14 Database Files............sccsssssscssscssscsssessscsssesssssssessscsssssssessssessssesssesssessscssscssscssscssscessesssessoeees 14-1 + +Overview of database files ............cccccceeesscceesseceecssnececeesnececeesneeeessaeeecsecaeeeessneeceesaeeessenees 14-1 +The file header ic.23 cc. cssccissctaecevvcuac deve stan devedansceseduvandeaesaceseiuarceneivan cons denecesecae ce seenvens 14-2 +ROCOLAS 3, fecsecth code ete doduaies Pout eteastuei ee deat edepetat eva vantedegeletecsertatedseslesedenransedevslehervaadteccey 14-2 +Strin Hels: .3:25 seysessegipassd abe dephaes aeseedaad ei gages ewes aivlshe hal aayoen iene: 14-3 +Number Of TECOrd S's. soitess ciecd oaks ice ah aed ca ae at ck Goenka ieee Uaehe ee eset cada een atid eae tient bec’ 14-3 +End. of file T6COrd sce. ceiscisvcestadeceuas seve evans cveiasaceae saute eeu ceaaceesceauceeycdda vescddaecsecddacvanceseeees 14-3 +Database files and OPL ............cceeccccessscceeeeseeeceeeceeeeeeeeeceenaeeecsseeeesenaeeecneneeeessneeeess 14-4 + +DBF fUnCtiOns y: s.ciscticcsisatcciviuek jevndsatecspasstecsvduetcdevdcedecus dene cevvacee cdevdeancdevecsoeds vacee ceeuecsbeseslade 14-4 +Open a database file (DbfOpen).......... eee eeeeeeseecsseeeeseecsscecssceceseeeesaeecsaeersaeessteeeesaes 14-4 +Open a database file (DbfQuickOpen).............ecceeeessseceeeeesreeesseecsaeesseeceeesneeesseeeesaes 14-6 +Close a database file (DDfCIOSE) ..........eccccccccccesessseeceececeeseesnseeeeeceessesseeeeeeceessesssaeeeees 14-6 +Flush a database file (DDfFIUSH) .............c cc ccceesssccceeccesssssseeeeeceeessesneeeeeeeeessesseeeeees 14-6 +Notify that the DBF buffer has been overwritten (DbfTrash)..............::cceessceeeeetteeees 14-6 +Copy down a DBF record (DbfCopyDown)........ eee eeeeeseecseceeeseessceceeeeeseeeesaeessaeers 14-6 +Compress a database file (DbfCompress) .............s:ceeseeesseeeeseeeeesececsseeceseeeenaeeeseeesaes 14-7 +Copy a database file (DbfCopyFile) 0.00.0... eee eeeeeceseeceeeeseeesseeceaeessseeceseeseeeesaeeesaes 14-7 +Find the size of a database file (DbfFileSize) ............cccccecssseceessessneeeeeeeeeseesseeeeeees 14-8 +Read a DBF extended header (DbfExtHeaderRead) ..............cccccccssscecceeeesessteeeeeeeeees 14-8 +Write a DBF extended header (DbfExtHeaderWrite) ..............ccccccccesssccceceeeesteceeeeeeees 14-9 +Read a DBF descriptive record (DbfDescRecordRead) ............::scccceseeceeeeteeeeeeneeeeeeee 14-9 +Write a DBF descriptive record (DbfDescRecord Write) ............ccsecceeeeeseeeeeeeeeesteeeees 14-9 +Get the DBF version number (DbfVersion)............ccccccccssccccccsssesseeeeeceeesssseeeeeeseseeaaee 14-10 +Read a specific DBF record (DbfAbsRead) ............ceeeecceeeeeeeeeeeeeeceeeneeeeesneeeeeeneeeess 14-10 +Read and sense a specific DBF record (DbfAbsReadSense)............:ccccccesssceeeeeseeeeeeeee 14-10 +Read the next DBF record (DbfNextRead) ..........ccccccsssscccceeesessneeeeeeeeeesessneeeeeeeeenes 14-10 +Read the previous DBF record (DbfBackRead) .............ccescccceeeseceeeeeeeeeeeneeeeeeeneeeeeees 14-11 +Read the first DBF record (DbfFirstRead)............000cccccccccccccscececceeeeeeeeessssssssessseseessees 14-11 +Read the last DBF record (DbfLastRead) 0.0.0.0... ccc ccscccccccccccccceeceeeceeeeeeeeceeeeeeeeeeeees 14-11 +Append a DBF record (DbfAppend) ..............ccceeeececeeseeceeeeeceeeeeeaeeeeeeneeeesseeeeeesnneeeess 14-12 +Erase a DBF record (DbfEraseRead)................ccccccccccsscscccccceeesesseeesestseeesessssstssseeeseees 14-12 +Update a DBF record (DbfUpdate)........ eee eeeeeeseeceseeceseesssececeseeeesseessaeessaeeesseeeesaes 14-13 +Find a DBF record (DbfFindReadField)..............:cccccccssssscccceeeeessesseeeeeesessessseeeeeeeeeees 14-13 +Find a DBF record (DbfFindRead)..............cccccccccccecccecceeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeees 14-14 +Sense the current DBF record number (DbfSense) ............:ccccccccsssscececeesesssssteeeeeeeeees 14-16 +Count the number of DBF records (DbfCOUNE)............ceeeceeccccccessessneeeeeeeeessesessstseeeeees 14-16 + + +PLIB REFERENCE + + +15 Object Oriented Programming ...............cccsscccsscssscssscssccssscsesssscsessssccessssesesssscsessssesesssssesoes 15-1 +CHASSES + + +at the beginning of your C source file. + + +3The code, written in 8086 assembler, that provides a C function interface to a ROM-based service is +sometimes called a C shell. + + +1-4 + + +1 INTRODUCTION + + +The plib.h header file collects a default set of header files that are sufficient for the functions described in +this manual. + + +For most source files, plib.h will include more than you actually need. Once you are familiar with PLIB +and if you can be bothered, you may wish to browse around the header files in the \sibosdk\include +directory to work out which files you need to include in a particular source file. + + +In all the structs in the PLIB headers, we have been careful to organise the members so that 16-bit (or +wider) variables are on even address boundaries - since the 8086 processor can fetch a 16-bit word in a +single cycle rather than two if the word is at an even address. + + +p_std.h + + +Because Psion has had ten years of working with C using tens of different C compilers to develop for tens +of different target computers, we have of necessity developed a fairly defensive approach to our C sources. +Rather than using the C variable types and declarations directly, we define our own to give us the +opportunity of re-defining their meaning, depending on the compiler. All these definitions are in p_std.h +that is included first by plib.h. + + +The following extract from the Clarion version of p_std.h is for declaring functions and data: + + +#define GLREF_D extern +#define GLDEF_D +#define LOCAL_D static +#define GLREF_C extern +#define LOCAL_C static +#define GLDEF_C + + +where the _c and _p refer to code and data respectively and where: + + +LOCAL_C are used to declare local functions and local static variables +LOCAL_D + +GLDEF_C are used to declare global functions and global variables + +GLDEF_D + +GLREF_C are used to declare function prototypes and external global variables +GLREF_D + + +The following extract from p_std.h declares operand types: + + +#define VOID void + + +typedef int INT,HANDLE;_ + +typedef unsigned int UINT;_ +typedef char BYTE;_ + +typedef unsigned char UBYTE;_ +typedef short int WORD;_ + +typedef unsigned short int UWORD;_ +typedef long int LONG;_ + +typedef unsigned long int ULONG;_ +typedef double DOUBLE; _ + +typedef char TEXT; + + +where the meanings of BYTE, UBYTE, WORD, UWORD, INT, UINT, LONG, ULONG and DouBLE are as suggested by +their names (and where a leading u means unsigned). + + +By convention, we favour the signed variant in cases where it does not matter whether the signed or the +unsigned variant is used. + + +The Text type is used to indicate character data as in, for example: +TEXT *str; +where str points to a character string. + + +The HanbLe typedef is used to refer to an instance of something - such as a process or a memory segment. +In many cases, a HANDLE is actually the offset into the operating system's data space. + + +1-5 + + +PLIB REFERENCE + + +This manual uses the above declarations in function descriptions and examples so you do need to know +about them to be able to understand this manual. + + +However, this does not mean that you have to use our declarations. For example, using our declarations, +you can write: + + +#include + + +GLDEF_C INT main(VOID) +{ +p_printf ("Hello world"); +p_getch (); +return (0); + + +} +or, not using our declarations, you can write: + + +#include + + +int main (void) +{ +p_printf ("Hello world"); +p_getch (); +return (0); + + +} +It is entirely up to you. +Calling conventions +The content of this section is quite technical. Provided you: +e include plib.h +e declare local functions before calling them +¢ use prototypes when calling your own global functions + + +you don't need to be particularly aware of the calling convention used and you don't have to understand +this section (although you may feel more comfortable if you do). + + +The only exception is for functions which take as a parameter the address of (and subsequently call) a +second function. In such a case you must declare an explicit calling convention for the second function. In +PLIB this occurs when using p_enter, used to handle errors, or when using an object-oriented +programming message-sending function such as p_send. In these two cases the descriptions of the +relevant functions include full guidance. + + +For a greater understanding of calling conventions and the #pragma cali declaration, refer to the +TopSpeed documentation. + + +With the TopSpeed C compiler you can change the calling convention using: + + +#pragma save to save the current calling convention + +#pragma call to set a new current calling convention as defined by parameters that follow +call + +#pragma restore to restore a previously saved calling convention + + +You can also declare functions to use a stack-based calling convention using CDECL. + + +The C header files containing the prototypes for the PLIB functions (and automatically included when you +include plib.h) also contain #pragma statements that declare calling conventions on a function by function +basis. + + +For example, the prototype for p_bcpy is effectively: + + +#pragma save + +#pragma call(reg_param =>(di,si,cx),reg_saved =>(bx,cx,dx,si,di,ds,st1,st2) ) +GLREF_C UBYTE *p_bcpy(VOID *,VOID *,UINT); + +#pragma restore + + +where the three parameters to p_bcpy are passed in the registers DI SI and CX as required by the +BufferCopy interrupt (described in the EPOC O/S System Services reference manual). + + +1-6 + + +1 INTRODUCTION + + +When defining a sequence of prototypes, you only need to bracket the sequence with #pragma save and +#pragma restore - not each individual prototype. + + +Prototypes for PLIB functions that take a variable number of parameters must use a stack-based calling +convention and are declared using cpEct as in, for example: + + +GLREF_C INT CDECL p_iow(VOID *,INT,...); + + +In many cases (where there is a limit to the number of parameters), the same function is also offered in +fixed parameter versions as in, for example: + + +INT p_iow2(VOID *pcb, UINT func); +INT p_iow3(VOID *pcb, UINT func, VOID *al); +INT p_iow4(VOID *pcb, UINT func, VOID *al, VOID *a2); + + +where you can use the appropriate fixed parameter variant to take advantage of a more efficient register +calling convention. + + +When calling your own functions, you don't need to worry about setting a calling convention since the +default calling convention will apply. The default (register) calling convention is: + + +#pragma call(reg_saved =>(ax,bx,cx,dx,di,si,ds,stl,st2),reg_param +=> (ax, bx, cx, dx) ,c_conv=>off) + + +When the compiler comes across a function that is declared as taking a variable number of arguments, +such as: + + +LOCAL_C VOID PrintToLog(TEXT *str, ...) +it ignores the current calling convention and uses a stack-based calling convention. +Small programs + + +Because the body of nearly all PLIB functions is provided by code in the ROM, C programs built for +EPOC are typically significantly smaller than, say, the standard C library on a PC. + + +The difference is at its most extreme when there is such a small amount of program-specific code that the +size of the program is dominated by the code that is brought in from the library. For example, the +following program: + + +#include + + +GLDEF_C INT main(VOID) +{ +p_printf ("Hello world"); +p_getch (); +return (0); + + +} + + +when compiled and linked for EPOC produces a program that contains fewer than 500 bytes of code. +Depending on the compiler, upwards of 10K is typical on a PC. + + +The amount of memory required to run an EPOC program (sometimes called the "working set") typically +ranges from 10K to 100K bytes. For example, when using the Spreadsheet on the MC400 (a large +program by any standard), you can load about 70K of code and open and manipulate a 10K spreadsheet +with less than 100K of free system memory. + + +In practice, it is quite possible to take advantage of the multi-tasking and run several programs at the +same time and especially (given that the code is only loaded once) to run more than one process of the +same program. + + +The PLIB C startup modules + + +When producing an executable using the linker, a C startup module is automatically linked in before the +program-specific modules and the libraries. + + +A number of C startup modules is supplied with PLIB where each module sets set up a different stack size +(typically ranging from 2K to 8K). Except for the different stack size, the different PLIB startup modules +are identical - they all declare the same basic structure for the process data segment - as described in the +chapter Memory Allocation. + + +The code in the PLIB startup modules is minimal - it just connects to the file server (using a Filconnect +interrupt) before jumping to main (most applications need the services of the file server and the overhead +to connecting to the file server is modest). + + +PLIB REFERENCE + + +Note that the PLIB startup modules do not set up the standard argv, argc parameters to main because +PLIB is not particularly designed for command line user interfaces (although there is a mechanism for +passing parameters when starting a process - see the chapter Processes and Inter-Process Messaging). + + +Not all the stack that is declared in the PLIB startup module may be used by the program and you should +subtract: + + +0x100 for any program + + +0x300 for programs that use the floating point emulator (as described in the Floating +Point chapter) + + +Related reference manuals + + +The ROM contains more system code than is directly accessed by the functions described in this manual. +In addition, a standard C library (CLIB) is provided. + + +TopSpeed C library reference + + +CLIB is a version of the TopSpeed C library for the EPOC operating system. The functions in CLIB are +described in the TopSpeed C Library Reference manual. Additional notes, including a list of the +TopSpeed C library functions that are not implemented, may be found in \sibosdk\doc\clib.doc. + + +The EPOC version of the TopSpeed C library supports the ANSI functions and most of the portable +functions that are commonly supported by MSDOS C libraries such as Microsoft C and Borland's +Turbo C. The less portable functions such as those that access the BIOS and graphics functions are not +included. + + +The benefits of using CLIB are: +e portability (existing C programs may easily be converted) +e less to learn for programmers already familiar with standard C libraries + + +Although the EPOC system services (and hence PLIB) has comprehensive support for floating point +operations, it does not provide this support in a way that supports the floating point C as generated by the +TopSpeed C compiler. This is described more fully in the chapter Floating Point in this manual. + + +As you might expect, using CLIB in place of PLIB makes less efficient use of the SIBO architecture. In +particular: + + +e many of the EPOC system services are not available from CLIB (eg asynchronous I/O, inter- +process messaging, the window server graphics functions) + + +e executables are larger and the process takes a larger data segment + + +The executables are larger because, although CLIB uses the ROM-based system services wherever +possible and fares better than the PC library, it is still a much "thicker" library than PLIB. The data +segments also tend to be larger because the various CLIB subsystems typically require large static buffers +and tables. + + +For example, the following CLIB program: + + +#include + + +int main (void) +{ +printf ("Hello world"); +getchar(); +return (0); + + +} + + +when compiled and linked for EPOC produces a program that contains 6K bytes of code (as compared +with 0.5K for the equivalent PLIB program). + + +Unless you are using the in-built user interface object dynamic libraries (accessed using object-oriented +programming) described below, you can freely mix PLIB calls with CLIB. We expect most experienced C +programmers to use CLIB and regard PLIB and WLIB (the window server library, described below) as +they would regard non-portable components of any C library. + + +1-8 + + +1 INTRODUCTION + + +It is worth converting completely to PLIB and WLIB when the desirability of making efficient use of +memory outweighs the benefits of portability and familiarity. + + +Window server reference + + +The window server is a system process that provides shared access to the screen and keyboard (and also a +pointing device, if present). + + +The PLIB library contains only primitive console functions to input typed lines (with simple backspace +editing) and to output lines of mono-spaced characters. The con: device driver provides row and column +positioning and printing of mono-spaced characters. + + +Although the PLIB console functions and the con: device driver ultimately call on the window server for +both user input and screen drawing, the window server is capable of far more than can be accessed via +these interfaces. In particular, the window server can be used to implement graphical user interfaces and +to display bitmap images such as maps and diagrams. The WLIB library contains a set of C functions that +can access all the services of the window server. These functions are described in the Window Server +Reference manual. + + +The window server supports the following features: +e =ahierarchical system of overlapping windows where all drawing is clipped to visible areas + + +e redraw events informing the client of areas of windows that need to be redrawn, with redrawing +clipped to the invalid areas + + +e =multi-font (proportional and mono-spaced) pixel addressable text drawing in a variety of text +modes and styles + + +e fast bitmap operations +e drawing of lines, boxes and pattern-filled areas in a variety of modes + + +¢ optional double drawing to a background bitmap as well as the window such that the window +server automatically redraws windows as necessary + + +Like PLIB, the WLIB library is a library of thin C shell functions that contain software interrupts to +ROM-based code. + + +I/O devices reference + + +This /O System chapter in this manual describes the EPOC I/O system in general and the PLIB C +functions that are used to access I/O devices. + + +A device driver may be built into the ROM or it may be loaded from an external source (such as an SSD). +To use a particular device you need to read a description of the device driver. + + +The files device driver and the asynchronous timer device driver are described in this manual - in the +chapters Files and Time, Timers and Dates respectively. All other device drivers are described in the /O +Devices Reference manual. + + +The I/O Devices Reference manual describes device drivers that have been written by Psion - many of +which are commonly supplied in the ROM. The device drivers described include the following: + + +e Parallel port (PAR:) + +e = Serial port (TTY:) + +e Console device (CON:) +e Sound driver (SND:) + + +Descriptions of additional device drivers will be added to the I/O Devices Reference manual from time to +time. + + +EPOC O/S System Services reference manual + + +The EPOC O/S System Services reference manual describes the software interrupt interface to the ROM- +based system services. + + +Nearly all of the services are available from C using the functions in PLIB. The CLIB library also uses the +system services where possible (the source for CLIB may be found in \sibosdk\src). + + +PLIB REFERENCE + + +Because the EPOC O/S System Services reference manual is intended to be used in conjunction with the +PLIB Reference manual, the descriptions in the EPOC O/S System Services reference manual are +comparatively brief. + + +You would refer to the EPOC O/S System Services reference manual if you were writing in 8086 +assembler or accessing a system service from OPL. In this case, you should refer to the corresponding +function in the PLIB manual for a fuller description of the service (there is a list of the corresponding +PLIB functions in an appendix of the EPOC O/S System Services reference manual). Being able to refer to +the description of a software interrupt can be useful when debugging C programs. + + +The EPOC O/S System Services reference manual also contains information on: +e writing device drivers +e writing an installable file system +e hardware interfacing + + +Object dynamic libraries + + +The Object-Oriented Programming chapter of this manual describes a set of functions that provide run- +time support for object-oriented programming where object classes are constructed by: + + +e using a proprietary tool to define class property structures and to declare methods +e using regular TopSpeed C to implement the declared method functions for each class + + +Object-oriented programming techniques are well-suited to implementation of graphic user interfaces and +multi-threaded application control. + + +The object dynamic libraries (DYLs) contain classes that may be used and/or subclassed to construct +applications with a consistent graphical user interface. The classes supplied in the libraries include the +following: + + +e dynamic variable length arrays and large character buffers for building complex in-memory data +structures + + +e active objects that represent a variety of event sources for controlling multi-threaded programs + + +e an extensive window class tree supporting such graphics user interface components as menus, +dialog boxes and edit boxes + + +The classes that are used to build user interfaces may vary for different SIBO machines. At the time of +writing, a user interface object library had not been constructed for the HC range (since there is no +requirement for a consistent user interface on a machine of this type). + + +The object classes are organised into dynamic libraries (DYLs) in the ROM. For example, the MC400 +has: + + +OLIB.DYL containing classes that are independent of the user interface +WIMP .DYL containing classes that implement the graphical user interface + + +The object-oriented message passing mechanism also serves as a means of calling far code (such as the +code in ROM-based DYLs). Large applications may be split into multiple DYLs to reduce their working +set and to overcome the 64K code segment limit. + + +The object classes are described in a manual per DYL. For example, the OLIB Reference Manual +describes variable arrays and active objects. + + +1-10 + + +CHAPTER 2 + + +CHARACTERS, STRINGS AND BUFFERS + + +General string and buffer functions + + +PLIB contains the following general string and buffer functions: + + +p_bcpy to copy a buffer + +p_slen returns the length of a string + +p_scpy, p_scpym to copy a string or multiple strings + +p_scat, p_scatm to concatenate a string or multiple strings + +p_brep, p_srep to fill a buffer or string with a repeated sequence + +p_bswap to swap the contents of two buffers + +p_bfil to fill a buffer with a repeated character + +p_jtob to left, right or centre align a buffer in a (normally wider) buffer with a fill +character + +p_ere to generate the CRC number of a buffer + +p_bcpy Copy memory to memory + + +UBYTE *p_bcpy(VOID *target, VOID *source, UINT len); + + +Copy len bytes of data from source to target and return the address following the last byte written (ie +targettlen). + + +The data is copied correctly when source and target overlap. +For example: + + +p_bcpy (str+1,str,p_slen(str)+1); +*str='A'; + + +inserts 'A’ at the beginning of str. + + +p_slen Return string length +UINT p_slen(TEXT *str); + + +Return the length of the zero terminated string str, not including the terminating zero. + + +p_scpy Copy a string +TEXT *p_scpy(TEXT *target, TEXT *source); + + +Copy the zero terminated string source, producing a zero terminated string at target and return the +address of the terminating zero of target. + + +The strings should not overlap. +For example: +p_scpy (buf, "hello"); + + +writes "hello" to buf. + + +PLIB REFERENCE + + +p_scpym Copy multiple strings +TEXT *p_scpym(TEXT *target, ...); + + +Copy and concatenate a list of zero terminated strings to target creating a zero terminated string at +target. + + +Returns the address of the zero that terminates the string at target. + + +The first string is copied to target and the following strings are concatenated to it. The list of strings +should be terminated by a NULL argument. + + +For example: +p_scpym(buf,"The cat"," jumped", NULL) ; + + +writes "The cat jumped" to buf. + + +p_scat Concatenate two strings + + +TEXT *p_scat (TEXT *lstr, TEXT *rstr); + + +Concatenate the zero terminated string rst r to the zero terminated string 1str and return the address of +the zero that terminates the new string at 1str. + + +For example: + + +p_scpy (buf, "hello"); +p_scat (buf," fred"); + + +writes "hello fred" to buf. + + +p_scatm Concatenate many strings +TEXT *p_scatm(TEXT *lstr, ...); + +Concatenate a list of zero terminated strings to the zero terminated string 1str. + +Returns the address of the zero that terminates the new string at 1str. + +The list of strings should be terminated by a NULL argument. + +For example: + + +p_scpy (buf, "The"); +p_scatm(buf," cat"," jumped", NULL) ; + + +writes "The cat jumped" to buf. + + +p_brep Replicate a buffer +UBYTE *p_brep(VOID *buf, INT buf_len, VOID *pattern, INT pat_len); + + +Replicate pattern as many times as necessary to exactly fill the buffer but of length buf_1en and return +the address of the byte following the last byte written (ie buf+buf_len). + + +If buf_1lenrbuf then return is greater than 0 +If lbuf==rbuf then return equals 0 + + +2-8 + + +2 CHARACTERS, STRINGS AND BUFFERS + + +The result of the comparison is based on the difference of the first two unsigned bytes to disagree. The +strings are equal if they have the same length and content. Where two strings have different lengths and +the shorter string matches the first part of the longer string, the shorter string is considered to be less than +the longer string. + + +For example: + + +p_bemp ("abc", 3, "abcd", 4) returns less than 0 +p_bemp ("abcd", 4, "abc", 3) returns greater than 0 +p_bemp ("abc", 3, "abc", 3) returns 0. + + +p_scmp Compare two strings + + +INT p_scmp(TEXT *lstr, TEXT *rstr); + + +Compare two zero terminated strings by comparing corresponding characters, returning 1str-rstr, +that is: + + +If 1strrstr then return is greater than 0 +If 1str==rstr then return equals 0 + + +The result of the comparison is based on the difference between the first two characters to disagree. The +strings are equal if they have the same length and content. + + +For example: + + +p_scmp ("abc", "abcd") returns less than 0 +p_scmp ("abcd", "abc") returns greater than 0 +p_scmp ("abc", "abc") returns 0 + + +p_bcmpi Case independent buffer compare + + +INT p_bcempi(TEXT *lbuf, INT lbuf_len, TEXT *rbuf, INT rbuf_len); + + +Performs a case independent comparison of the two buffers by effectively folding the characters in both +buffers before comparing them using p_bcmp. Returns as for p_bcmp, described above. + + +For example: + + +p_bempi ("abc", 3, "abcd", 4) returns less than 0 +p_bempi ("abcd", 4, "abc", 3) returns greater than 0 +p_bempi ("ABC", 3, "abc", 3) returns 0 + + +p_scmpi Case independent string compare + + +INT p_scmpi(TEXT *lstr, TEXT *rstr); + + +Performs a case independent comparison of the two zero terminated strings 1str and rstr by effectively +folding the characters in each string before comparing them using p_scmp. Returns as for p_scmp, +described above. + + +For example: + + +p_scmpi("abc", "abcd") returns less than 0 +p_scmpi ("abcd", "abc") returns greater than 0 +p_scmpi("ABC", "abc") returns 0 + + +2-9 + + +PLIB REFERENCE + + +String searching + + +The PLIB string searching functions are: + + +p_bloc, p_sloc, to search for a character +p_bloci, p_sloci, +p_slocr, p_slocri + + +p_bsub, p_ssub, to search for a sequence of characters +p_bsubi, p_ssubi + + +p_bmatch, p_smatch, to search for a sequence of characters that matches a wildcard specification +p_bmatchi, p_smatchi + + +p_bloc Locate byte in buffer +INT p_bloc(VOID *buf, INT buf_len, INT ch); + + +Locate the byte ch in the buffer at buf of length buf_1en returning the index of the first matching byte or +-1 if ch is not in the buffer. + + +For example: + + +p_bloc("abcde",5,'£') returns -1 +p_bloc("abcde",5,'a') returns 0 +p_bloc("abcde",5,'c') returns 2 + + +p_sloc Locate character in string + + +INT p_sloc(TEXT *str, INT ch); + + +Locate the first occurrence of the character ch in the zero terminated string str, returning the index of the +first matching character or -1 if ch is not in str. + + +For example: + + +p_sloc("abcde", '£') returns -1 +p_sloc("abcde", 'a') returns 0 +p_sloc("abcde",'c') returns 2 + + +p_bloci Case independent locate character in buffer +INT p_bloci(TEXT *buf, INT buf_len, INT ch); + + +Perform a case independent locate of ch in the buffer buf by effectively folding ch and the characters in +buf before using p_bloc to locate the folded character. Returns as for p_bloc, described above. + + +For example: + + +p_bloci ("abcde",5,'f£') returns -1 +p_bloci ("abcde",5,'A') returns 0 +p_bloci ("abcde",5,'c') returns 2 + + +p_sloci Case independent locate character in string + + +INT p_sloci(TEXT *str, INT ch); + + +Perform a case independent locate of ch in the zero terminated string str by effectively folding ch and the +characters in str before using p_sloc to locate the folded character. Returns as for p_sloc, described +above. + + +For example: + + +p_sloci ("abcde", '£') returns -1 +p_sloci ("abcde", 'a') returns 0 +p_sloci ("abcde", 'c') returns 2 + + +2-10 + + +2 CHARACTERS, STRINGS AND BUFFERS + + +p_slocr Locate last matching character in a string + + +INT p_slocr(TEXT *str, INT ch); + + +Locate the last occurrence of the character ch in the zero terminated string str, returning the index of the +matching character or -1 if ch is not in str. + + +For example: + + +p_slocr("abcabc", 'A') returns -1 +p_slocr ("abcabc", 'a') returns 3 + + +p_slocri Locate last matching folded character in a string + + +INT p_slocri(TEXT *str, INT ch); + + +Locate the last occurrence of ch in the zero terminated string str by effectively folding ch and the +characters in str before using p_slocr to locate the folded character. Returns as for p_siocr, described +above. + + +For example: + + +p_slocri("abcde", 'f£') returns -1 +p_slocri("abcabc", 'A') returns 3 + + +p_bsub Locate sub-buffer in buffer + + +INT p_bsub(VOID *buf, INT buf_len, VOID *sbuf, INT sbuf_len); + + +Locate sub-buffer sbuf, sbuf_len In buf, buf_len returning the index of the start of sbuf in buf or -1 if +sbuf does not exist in but (which must be the case if buf_len0 *pmatch belongs after record number *pmid + + +If two or more array elements exactly match the record at pmatch, the return value will be zero and *pmia +will contain the index of any one of the matching elements. + + +Each time p_bsrch needs to compare a record with the record at pmatch it calls: +compf (n, pmatch) ; + + +where n is the index of the record to be compared. This user-supplied comparison routine should return: + + +0 *pmatch 1s equal to record number n +<0 *pmatch is before record number n +>0 *pmatch is after record number n + + +As with any binary search, the array must be ordered. For p_bsrch, it should be ordered with respect to +compf, the user-supplied comparison routine. + + +In most cases the set of records will be a fixed array, but any arrangement which allows the routine to +identify a record by index (e.g. hashing) will be suitable. Likewise, pmatch may be any address suitable for +interpretation by compf, since pmatch is not used inside p_bsrch, other than being passed to compf. This +allows code using p_bsrch to be re-entrant. + + +If the whole table is created before being searched it is, in general, quicker to build the table unordered +and then sort it (see p_qsort) than to build the table in sequence by insertion. + + +3-1 + + +PLIB REFERENCE + + +Example + + +LOCAL_D INT array[]={5,8,13,19,25,30,41,48,51, 62,70, 76, 80, 90, 98}; + + +LOCAL_C intcompare (INT n,INT *pmatch) + + +{ +INT f£,m; + + +f=array[n]; +m=*pmatch; +if (f==m) + +return (0); +return (m>f£?1:-1); + + +} + + +VOID find(INT match) +{ +INT nrec; /* number of INTs in the array */ +INT result; +INT mid; +TEXT *pstr; + + +nrec=sizeof (array) /sizeof (INT) + + +, +result=p_bsrch(nrec, (INT (*) ()) intcompare, &mid, &match) ; +if (!result) + +p_printf("sd matches record number %d",match,mid) ; +else + +{ + +pstr=result<0?"before": "after"; + + +p_printf("%d belongs %s %d",match,pstr,array[mid]); + + +} + + +p_qsort Sort an array of records + +INT p_qsort (INT nrec, INT (*ordf)(), VOID (*excf) (), UBYTE *base) + +Sort a set of records into ascending order, using the quicksort algorithm. + +There are nrec records to sort. Each time the routine needs to compare two of these records it calls: +(*ordf) (n,m,base) ; + + +where n and mare the indexes of the two records to compare (starting at zero), and base is a parameter +that may be used or ignored by the ordering function. + + +The ordering function, ordf, should return: + + +0 record number n is equal to record number m +<0 record number n is less than record number m +>0 record number n is greater than record number m + + +Each time the routine needs to exchange two records it calls: +(*excf) (n,m, base) ; + + +where n and mare the indexes (starting at zero) of the two records to exchange. The user-supplied +exchange routine should exchange the records indexed by n and m. Again, the user-supplied exchange +function is free to use or ignore base, but its use should be consistent between the ordering and exchange +functions. + + +Normally, base will represent the address of a fixed length array, but any method of storing records may +be used, as long as the records can be accessed using the indices. The value of base is not used inside +p_gqsort, but is passed down to both the ordering and exchange functions to enable the writing of re- +entrant code that uses p_qsort. + + +The routine uses its own stack, declared locally, to avoid the need to be called recursively. This stack is +150*sizeof (INT) in length and, as such, could cause the main stack to overflow if the routine is called +from too deep inside a program. + + +The function p_gsort returns zero if successful, else a negative error. + + +3-2 + + +3 ARRAYS AND QUEUES + + +An error return value of £_GEN_FaIL is returned if the internal stack overflows. This is, however, unlikely +as an experiment to sort 50000 elements used only 80 stack elements. If this error is returned, the routine +can be called again, as it is likely that the array has been rearranged enough to permit the successful +completion of a second attempt. + + +Example + + +LOCAL _D INT array[]={98,90,80,76,70,62,51,48,41,30,25,19,13,8,5}; + + +LOCAL_C intcompare(INT first,INI second, INT *array) + + +{ +INT £,s; + + +f=* (array+first); +s=* (array+second) ; +if (s==f) + +return (0); + +return (f>s?1:-1); + + +} + + +LOCAL_C VOID intexchange(INT first,INT second, INT *array) + + +{ +INT r; + + +r=* (arrayt+first) ; +* (array+first) =* (array+second) ; +* (array+second) =r; + + +} + + +LOCAL_C VOID sort (VOID) + + +{ +INT n; /* number of INTs in the array */ + + +n=sizeof (array) /sizeof (INT); +if (p_qsort (n,intcompare, intexchange, &array[0]) ) +p_panic("Too many partitions"); + + +Doubly linked queues + + +This section describes functions for inserting and deleting entries from doubly linked queues. Each entry +in the queue contains a P_guz structure, defined in p_que.h as: + + +typedef struct p_que +{ +struct p_que *next; /* pointer to next item */ +struct p_que *prev; /* pointer to previous item */ +} P_QUE; + + +A special header entry consisting only of a p_ouz data structure provides a single address by which the +queue may be accessed. The empty queue consists only of the p_quz header with both next and prev +pointing to itself. A queue with n entries contains n+1 P_que structures - one for the header and one for +each entry. The queue is built such that the next pointer of the last entry points to the header and the prev +pointer of the header points to the last entry such that the n+1 p_oue structures form a doubly linked +circular queue. + + +The following extract from p_que.h: + + +#define P_INITQ(q) (q)-—>next=(q) ->prev=(q) +#define P_DECLAREQ(q) P_QUE q = {&q,&q} +#define P_ISEMPTYQ(q) ((q)==(q) ->next) + + +defines 3 macros where: + + +P_INITO may be used to initialise a header that represents an empty queue +P_DECLAREQ may be used to declare a header that represents an empty queue +P_ISEMPTYQ evaluates to TRUE if the queue header represents an empty queue + + +3-3 + + +PLIB REFERENCE + + +Entries are inserted into a queue using p_enque and removed using p_deque. Neither of these functions set +aside memory for entries or free memory - they merely make and break the links between entries. + + +The following example illustrates the use of p_enque and p_deque to set up a queue of zero terminated +strings that are allocated and freed from the heap (see the chapter Memory Allocation for a description of +f_alloc and p_free). + + +#include +#include + + +typedef struct +P_QUE pid; +TEXT name[1]; +} QUEUE_ENTRY; + + +LOCAL_D P_DECLAREQ (headq) ; + + +GLDEF_C VOID AddNameToEnd (TEXT *name) + + +QUEUE_ENTRY *p; + + +p=f_alloc(p_slen (name) +sizeof (QUEUE_ENTRY) ) ; +p_scpy (&p->name[0],name) ; + +p_enque (&p->piq, &headq) ; + +} + + +GLDEF_C TEXT *FirstName (VOID) + + +{ +TEXT *name; + + +name=é& (((QUEUE_ENTRY *)headq.next)—->name[0]); +if (P_ISEMPTYQ (&headq) ) + +name=NULL; +return (name) ; + + +} + + +GLDEF_C VOID DeleteFirstName (VOID) + + +{ +QUEUE_ENTRY *p; + + +p=(QUEUE_ENTRY *) headq.next; +p_deque (&p->pig) ; + +p_free(p); + +} + + +Names are allocated and added to the end of the queue using AddNameToEnd. The code that processes the +items in the queue uses FirstName to get the first item in the queue (which returns NuLt if the queue is +empty). After processing the first name, calling DeleterirstName removes it from the queue and frees the +memory used by it. + + +p_enque Add entry to queue + + +VOID p_enque(P_QUE *pNew, P_QUE *pEntry) ; + + +Insert entry pNew before pEnt ry (ie between pEnt ry->prev and pEnt ry) into the doubly linked queue that +contains pEntry. + + +If P_QUE hdq is the queue header: + + +p_enque (pNew, &hdq) adds pNew to the end of the queue (since queues are circular the previous +entry to the header is the entry at the end of the queue) + + +p_enque (pNew,hdq.next) adds pNew to the start of the queue + + +3 ARRAYS AND QUEUES + + +p_deque Remove entry from queue + + +VOID p_deque(P_QUE *pEntry); + + +Remove queue entry pEnt ry by linking the entries on either side of pEntry to each other, excluding +pEntry from the queue. + + +If P_QUE hdg is the queue header: +p_deque (hdq.next) removes the first entry from the queue + + +p_deque (hdq. prev) removes the last entry from the queue (since queues are circular the previous +entry to the header is the entry at the end of the queue) + + +If hdg is empty then p_deque (&hdq) will have no effect. Calling p_deque (ahdq) of a non-empty queue is +not a good idea as there will then be no way to get into the queue. + + +EEE +Delta queues + + +A delta queue builds on doubly linked queues, described in the previous section, to store entries ordered on +a tone key. + + +A delta queue consists of a p_oquz header and doubly linked entries, each containing a p_pELTA structure, +defined in p_que.h as: + + +typedef struct +{ +P_QUE q; +LONG key; /* Delta key */ +} P_DELTA; + + +where (except for the first entry in the queue) key contains the offset relative to the previous entry (the +delta). The value of an entry's key is determined by accumulating the deltas of its predecessors. For the +first entry, the key is just the delta. + + +The EPOC operating system uses a delta queue to implement timers. Each entry represents a timer where +the key is the relative time in system ticks to the expiry of that timer and the delta is then the number of +system ticks after its predecessor. This design minimises the system effort to maintain the timers - on each +tick the system only has to decrement the head of the queue. See the chapters Asynchronous Requests and +Semaphores and Time, Timers and Dates for more about the time delta queue and timers. + + +A delta list is set up much as a regular queue. A header is declared and initialised using (p_1INTTQ or +P_DECLAREQ) giving an empty queue. Entries containing a p_pELTAa structure are added to the delta queue +using p_enqued and are removed using p_dequed. + + +Neither function allocates or frees memory for entries - all they do is maintain the links and calculate the +deltas. + + +p_enqued Add entry to delta queue +P_DELTA *p_enqued(P_QUE *pHead, P_DELTA *pEntry, LONG key); + + +Inserts entry pEnt ry into the delta queue headed by pHeaa according to the key key and returns the +address of the first entry in the queue. + + +The queue is scanned, accumulating the key from the deltas, until an entry is found with a key that is +greater than key. The new entry pEntry is inserted (with an appropriate delta) before that entry and the +delta of that entry is recalculated. + + +3-5 + + +PLIB REFERENCE + + +p_dequed Remove entry from delta queue +P_DELTA *p_dequed(P_QUE *pHead, P_DELTA *pEntry); + + +Remove pEnt ry from the delta queue headed by pHead and return the address of the first entry or NULL if +p_dequed leaves the queue empty. + + +The delta of any following entry is updated to keep the accumulated key of each remaining entry constant. +If P_QUE hdgq is the queue header: +p_dequed(&hdq, (P_DELTA *)hdq.next); + + +removes the first entry from the queue. + + +CHAPTER 4 + + +INTEGER CONVERSION AND RECTANGLE + + +FUNCTIONS + + +This chapter describes functions for converting integer numbers to a textual representation (eg to print a +number) and vice versa (eg to input a number). + + +The chapter ends with a section that describes a set of functions that operate on rectangle data structures. +These are useful, for example, when organizing a screen display. + + +Converting integers to text + + +PLIB contains the following functions to convert various types of integers to a textual representation: + + +p_itob to convert an INT to a signed decimal number + +p_ltob to convert a Lonc to a signed decimal number + +p_gtob to convert a UINT to an unsigned number in any radix + +p_gltob to convert a ULONG to an unsigned number in any radix + +p_atob, p_atos for general purpose conversion and formatting of multiple arguments + + +The functions that handle "any radix" are typically used to handle a radix of 2 (binary), 8 (octal), 10 +(decimal) or 16 (hexadecimal). + + +Note that it is up to the caller to ensure that there is sufficient space in the target buffers for the output of +the conversion. + + +p_itob Convert an INT to decimal buffer +UINT p_itob(TEXT *buf, INT value); +Write a signed decimal representation of value to buf and return the number of characters written. +If value is negative, a leading '-' is written. +For example: +buf [p_itob (&buf[0],-24) ]="\0"'; + + +writes "-24" to buf. + + +PLIB REFERENCE + + +p_ltob Convert a LONG to decimal buffer +INT p_ltob(TEXT *buf, LONG value); + + +Write a signed decimal representation of the LoNG value to buf and return the number of characters +written. + + +If value is negative, a leading '-' is written. +For example: +buf [p_ltob (&buf[0],-240000L) ]="\0'; + + +writes "-240000" to buf. + + +p_gtob Convert a UINT to buffer any radix +INT p_gtob(TEXT *buf, UINT value, INT radix); +Write an unsigned base radix representation of value to buf and return the number of characters written. +For example: + +buf [p_gtob (buf, 0xaa55,16) ]='"\0'; + + +writes "AA55" to buf. + + +p_gltob Convert a ULONG to buffer any radix +INT p_gltob(TEXT *buf, ULONG value, INT radix); + + +Write an unsigned base radix representation of the ULONG value to buf and return the number of +characters written. + + +For example: +buf [p_gltob (buf, 0xaa5577,16)]='\0'; + + +writes "AA5577" to buf. + + +p_atob Convert multiple arguments to buffer + + +INT p_atob(TEXT *buf, TEXT *fstr, VOID *parg); + + +Write formatted text to buf as controlled by the format zero terminated string fstr and the argument list +parg and return the number of characters written. + + +The format string fstr contains literal text, embedded with commands for converting the arguments at +parg. The embedded commands are prefixed with the '%' character (two successive '%' characters count as +one literal '%'). The literal text is simply copied to buf and the % commands convert successive +arguments (which may be integers, longs or strings) at parg. + + +An embedded command takes one of the following forms: + + +3 for output (with no padding) of the converted data type that is one of b, +c, d, f, m, 0, s, u, w or x (as described below). Where appropriate, the type may +be widened to a long by preceding the type letter with an | or an L or by +providing the type letter in upper case. + + +% for right-aligned space-filled output in width where is either a +positive decimal number or a * to take the width as a u1nt from the argument +list. If more than characters is generated by the conversion, the output +is truncated. + + +%0 for right-aligned zero-filled output in width . + + +% for left, right or centre aligned output in width with fill character <£> +where is either -, + or =. If <£> is a *, the code of the fill character is taken +as a UINT from the argument list. (If you want to fill with «'s, you have to +supply it through the argument list). + + +4-2 + + +4 INTEGER CONVERSION AND RECTANGLE FUNCTIONS + + +A common requirement is for space-filled output. It is therefore worth enumerating special cases, using +the last of the above four forms of embedded command. Note that, in all cases, there is a space (the fill +character) immediately preceding . + + +%- for left-aligned space-filled output in width +%+ for right-aligned space-filled output in width +%= for centre-aligned space-filled output in width + + +The specifies the type of argument conversion to be performed, as follows: +b convert the urnt to a binary text representation +c convert the urnt to a single character corresponding to its code +d convert the mnt to a signed decimal text representation +f just output fill characters (does not use up an argument) + + +m_ convert the urnt to a two byte binary numeric representation, with the most significant byte first +(only available in EPOC version 2.17 or later) + + +o convert the urnT to an octal text representation +s copy the TExT * zero terminated string to the output, excluding the terminating zero. +u convert the urnT to an unsigned decimal text representation + + +w_ convert the urnt to a two byte binary numeric representation, with the least significant byte first +(only available in EPOC version 2.17 or later) + + +xX convert the urnT to a hexadecimal text representation + + +The type may be widened to a long by preceding the type letter with an | or an L or by providing the type +letter in upper case (ignored if is s or f). Output for types m and w will then occupy four bytes. + + +This function is normally used indirectly by the more immediately useful p_atos, described below. +However, p_atob is useful for constructing p_print£-like text output functions (p_print¢é itself is +described in the chapter I/O System). + + +For example, if file is static variable that contains the channel of an opened text file, the following +function behaves like p_printéf. + + +GLDEF_C CDECL VOID PrintToFile (TEXT *fmt,UINT arg,...) +{ +UINT len; +UBYTE buf[256]; + + +len=p_atob (&buf[0],fmt,&arg); +p_write (file, &buf[0],len); +} + + +If the int variable a contains 65: + +PrintToFile("[%b %c $d %o %u %x]",a,a,a,a,a,a) writes [1000001 A 65 101 65 41] +PrintToFile("[%04x]",a) Writes [0041] + +PrintToFile("[%*x]",3,a) Writes [ 41] + + +PrintToFile("[%+$4d.00 %s]",a,"over") writes [$$65.00 over] + + +PrintToFile("[%0*s]",10,"fred") writes [0O00000fred] +PrintToFile("[%=*4x]",'*',a) writes [*41*] + + +PrintToFile("[%—-**d]",'.',10,a) writes [S564 s es ee ] + + +PrintToFile("[%-A4f]",a) writes [AaaAA] and makes no use of the value of a. + + +4-3 + + +PLIB REFERENCE + + +p_atos Convert multiple arguments to string + + +VOID p_atos(TEXT *str, TEXT *fstr, ...); + +Convert multiple arguments to a zero terminated string at str under control of the format string fstr. +The content of fstr is described under p_atob, above. + +For example, if the variable a is a urnT that contains 65: + +p_atos(str,"%b %c %d %o %u %x",a,a,a,a,a,a) Writes "1000001 A 65 101 65 41"tostr +p_atos(str,"%04x",a) writes "0041" to str + + +p_atos(str,"%*x",2,a) writes "41" to str + + +Converting text to integers + + +PLIB contains the following functions to convert text to various types of numbers: + + +p_stoi to convert a signed decimal number string to a worD + +p_stol to convert a signed decimal number string to a LoNG + +p_stog to convert an unsigned number in any radix to a UwoRD + +p_stogl to convert an unsigned number in any radix to a ULONG + +p_stoa to convert multiple fields in a string to a series of arguments + +p_stoi Convert a signed decimal string to a WORD + + +INT p_stoi(TEXT **pstr, WORD *pval); + + +.Attempt to convert the signed decimal string at *pstr to a 16 bit number and, if a valid number is +recognised, write the number to pval, update *pstr to point to the terminating character and return zero. +Otherwise, neither *pstr nor *pval is written to and the function returns one of the following negative +error numbers (defined in p_gen.h): + + +E_GEN_OVER the number is too large (greater than 32767 or less than -32768) +E_GEN_FAIL the text could not be recognised as a number + + +Conversion continues until a non-decimal digit is found in the string, or the number overflows. For a +number to be recognised, the string must contain at least one decimal digit. + + +The string may be preceded by a '-' or a '+' (whitespace is significant and will terminate the conversion but +leading zeros are ignored). To convert unsigned data up to 65535, use p_stog. + + +For example, after: + + +INT ret; + +WORD val; + +TEXT *ptr="-123abc"; +ret=p_stoi(&ptr, &val) ; + + +val contains -123, ptr points to the 'a' and ret is zero. + + +p_stol Convert a signed decimal string to a LONG + + +INT p_stol(TEXT **pstr, LONG *pval); + + +Converts the signed decimal string at *pstr to write a 32 bit number to pval. Behaves and returns as for +p_stoi above except that it can handle decimal numbers in the range -2147483648 to 2147483647 +inclusive. To convert unsigned data up to 4294967295, use p_stogl + + +For example, after: + + +INT ret; +LONG val; +TEXT *ptr="-123456abc"; +ret=p_stol (&ptr, &val) ; + + +val contains -123456, ptr points to the 'a' and ret is zero. + + +4-4 + + +4 INTEGER CONVERSION AND RECTANGLE FUNCTIONS + + +p_stog Convert an unsigned number in any radix to a UWORD + + +INT p_stog(TEXT **pstr, UWORD *pval, INT radix); + + +Attempt to convert the unsigned number base radix (typically 2, 8, 10 or 16) at *pstr to a 16 bit number +and, if a valid number is recognised, write the number to pval, update *pstr to point to the terminating +character and return zero. Otherwise, neither *pstr nor *pval is written to and the function returns one of +the following negative error numbers (defined in p_gen.h): + + +E_GEN_OVER the number is too large (greater than 65535) +E_GEN_FAIL the text could not be recognised as a number + + +Conversion continues until a character that is invalid for the radix is found in the string or the number +overflows. For a number to be recognised, the string must contain at least one digit in the radix. +Whitespace is significant and will terminate the conversion but leading zeros are ignored. + + +For example, given: + + +UWORD val +TEXT *ptr="f£123"; + + +p_stog(&ptr,&val,10) returns E_GEN_FAIL + + +p_stog(&ptr, &val,16) returns O and writes Oxf123 to va1 + + +p_stogl Convert an unsigned number in any radix to a ULONG + + +INT p_stogl (TEXT **pstr, ULONG *pval, INT radix); + + +Converts the unsigned decimal number base radix at *pstr to write a 32 bit number to pvai. Behaves and +returns as for p_stog above except that it can handle numbers up to 4294967295. + + +For example, after: + + +INT ret; + +ULONG val; + +TEXT *ptr="f£123abz"; +ret=p_stogl (&ptr, &val,16); + + +val contains Oxf123ab, ptr points to the 'z' and ret is zero. + + +p_stoa Convert a string to arguments + + +INT p_stoa(TEXT **pstr, TEXT *fstr, ...) + + +Convert multiple fields within the zero terminated string *pstr to a series of arguments ... as controlled +by the format zero terminated string fstr. + + +Returns zero if successful and the text pointer *pstr is updated to point to the terminating character of +the last field converted. If an error occurred, *pstr points to the start of the field that caused the error and +one of the following negative error numbers is returned: + + +E_GEN_OVER the result is too large +E_GEN_FAIL fails to recognise a number +E_GEN_ARG the supplied buffer does not contain enough items + + +The format string fstr contains literal text, embedded with commands for converting the fields in *pstr +to the passed arguments. Any excess leading whitespace (as defined by p_iswhite) before a field in *pstr +is automatically skipped. + + +The embedded commands in fstr are prefixed with the 's' character (two successive 's' characters +count as one literal ''). Any non whitespace literal text causes characters in the *pstr to be scanned +until a match is made or until the end of the string is encountered (any whitespace characters in fstr are +discarded). If a match is not found in *pstr, the function returns. + + +4-5 + + +PLIB REFERENCE + + +The general form of an embedded command is: +%&[*] [] [] +:=a positive decimal number +:1|L +:=(B|b|c|c|D|d|N|n]|o]olalq|s|s|u]ulx|x) +where the square brackets indicate optional fields and '|' separates choices. + + +The mandatory parameter (optionally qualified by <1ong>) indicates the data type to be converted. + + +If the asterisk is present, conversion is performed but the result is not be stored. There should be no +corresponding value pointer in the argument list for a suppressed conversion. + + +The parameter is a positive decimal number that specifies the maximum input field width when + is s or q (in either upper or lower case) - if is other than s or q, it is ignored. Note that the +corresponding storage buffer must be large enough to hold characters plus | more for the +terminating zero (eg %19s requires a buffer of 20 bytes). + + +The specifies the type of argument conversion to be performed, as follows: +b convert an unsigned binary number to the uworp +c convert a character to its code, written to the uworD +d convert a signed decimal number (optionally preceded by a '-' or a '+') to the worp +n write the number of characters consumed so far to the uworD +oO convert an unsigned octal number to the uworp + + +q convert quote delimited text, copying the data in between the quotes (the delimiting quotes are +discarded) to produce a zero terminated string at the TExt * buffer. Although often used to +convert text delimited by quote (") characters, the first non whitespace character encountered is +taken to be the delimiter. + + +Ss convert contiguous non whitespace text to a zero terminated string at the Text * buffer. The +string is determined from the first non whitespace character to the first whitespace character (or a +zero terminator). + + +u convert an unsigned decimal number to the uworp +X convert an unsigned hexadecimal number to the uworp + + +When performing a numeric conversion, for a number to be recognised the string must contain at least +one digit in the radix. + + +If <1ong> is present, it should be L or | to specify that the corresponding argument address points to either +a LONG or a ULONG (ignored if is s, f or q). A long parameter can also be indicated by specifying the +conversion type in upper case. + + +For example, after: + + +INT ret; + +WORD dl1,d2; + +TEXT *ptr="111,-33"; +ret=p_stoa(&ptr,"%b, 3d", &d1, &d2) ; + + +di is 7 and d2 is -33, ptr points to the terminating zero, ret is zero. After: + + +INT ret; + +WORD dl,d2; + +TEXT buf[16] + +ptr="xxx @a “def ghi®* #44a"; + +ret=p_stoa(ptr,"@ Sc %15q # %d",&d1,buf, &d2) ; + + +di contains 'a', "def ghi" is written to buf and d2 is 44, ptr points to 'a' and ret is zero. + + +4-6 + + +4 INTEGER CONVERSION AND RECTANGLE FUNCTIONS + + +——————————————————————————————————————————————————————————————————————————————————————— +Rectangle functions + + +This section describes a set of functions that operate on p_reEct structs. A p_recT struct describes a +rectangle in terms of its: + + +e top left coordinates (internal) +e bottom right coordinates (external) + + +where the units of the coordinates depend upon the application. Typically, the coordinates count pixels +(for graphics displays) or monospaced character columns and rows (for character-oriented displays). + + +For example, a character display would normally be mapped to an (x,y) coordinate system as follows: +e corresponds to the character in the top left corner +e x increases to the right and counts the character columns +e yincreases downwards and counts character rows + +Using the above coordinates, the rectangle of as in the following character display: + + ++++++4+4+ +++AAA+++ +++AAA+++ ++4+4+4+4+Z4+ + + +is described by the coordinates of the top left a (internal) and the bottom right z (external) - that is, (2,1) +and (5,3). Subtracting corresponding coordinates gives the correct dimensions of the rectangle - (3,2). + + +The p_rect struct is defined in terms of two p_potnt structs. The definitions, in p_graf-h, are: + + +typedef struct +{ +WORD x; /* Horizontal coordinate */ +WORD y; /* Vertical coordinate */ +} P_POINT;. + + +typedef struct +{ +P_POINT tl; /* Top left point (internal) */ +P_POINT br; /* Bottom right point (external) */ +} P_RECT;. + + +An empty rectangle is a rectangle that has one or both of its sides zero or negative. + + +The rectangle functions are as follows: + + +p_offrec moves a rectangle by an offset + +p_insrec shrinks or expands a rectangle about its centre + +p_unirec calculates the union of two rectangles (the smallest rectangle that encloses both +of them) + +p_intrec calculates the intersection of two rectangles + +p_pinrec determines whether a point is inside a rectangle + +p_emprec determines whether a rectangle is empty + +p_absrec converts any negative sides of a rectangle to their positive equivalents + +p_offrec Offset a rectangle + + +VOID p_offrec(P_RECT *rect, INT xoffset, INT yoffset); + + +Displace rect by (xoffset, yoffset), without changing its size. + + +PLIB REFERENCE + + +p_insrec Inset a rectangle + + +VOID p_insrec(P_RECT *rect, INT xinset, INT yinset) ; + + +Adjust the width and height of rect by xinset and yinset respectively, in such a way as to produce a +rectangle concentric with the original. + + +A negative inset makes the rectangle bigger. +For example: +p_insrec(&rect,2,-1); + + +decrease the width of rect by 4 and increases the height by 2. + + +p_unirec Union of two rectangles + + +VOID p_unirec(P_RECT *rectl, P_RECT *rect2, P_RECT *result); + + +Write the union of the two rectangles rect1 and rect 2 (the smallest rectangle that encloses both of them) +to result - as illustrated by the following diagram: + + +Result + + +The parameter result may point to the same address as either rect 1 or rect 2. + + +For example: + + +LOCAL_D P_RECT rect1={{10,20},{30,40}}; +LOCAL_D P_RECT rect2={ {50,50}, {100,120}}; +LOCAL_D P_RECT result; + + +p_unirec(&rectl, &rect2, &result) ; + + +writes {{10,20},{100,120}} to result. + + +p_intrec Intersection of two rectangles + + +INT p_intrec(P_RECT *rectl, P_RECT *rect2, P_RECT *result); + + +Write the intersection of the two rectangles rect 1 and rect2 (the largest rectangle that is contained in +both of them) to result. + + +Rect 1 + + +Rect 2 + + +Intersection + + +If the rectangles do not intersect or if either rectangle is empty, the result is an empty rectangle. +The parameter result may point to the same address as either rect 1 or rect 2. + + +Returns TRUE if the rectangles intersect, raLsE if the rectangles do not intersect (or if either rectangle is +empty). + + +4-8 + + +4 INTEGER CONVERSION AND RECTANGLE FUNCTIONS + + +For example, after: +LOCAL_D P_RECT rect1={{0,0},{7,20}}; +LOCAL_D P_RECT rect2={{4,4},{100,120}}; +LOCAL_D P_RECT result; + + +ret=p_unirec (&rectl, &rect2,é&result) ; + + +ret 1S TRUE and result contains {{4,4},{7,20}}. + + +p_pinrec Test if a point is inside a rectangle + + +INT p_pinrec(P_POINT *point, P_RECT *rect); + +Return true if the point point is within the rectangle rect or FALSE if point is outside rect (or if rect is +empty). + +p_emprec Test if a rectangle is empty + + +INT p_emprec(P_RECT *rect); + + +Return True if the rectangle rect is empty (that is, if it has zero or negative width or height). + + +p_absrec Convert to an absolute rectangle + + +VOID p_absrec(P_RECT *rect, P_RECT *result); + + +Write the absolute of the rectangle rect (where any negative sides are converted to their positive +equivalents) to result. + + +The parameters rect and result may point to the same address. +For example: + + +LOCAL_D P_RECT rect={{7,20},{4,4}}; +LOCAL_D P_RECT result; + + +p_absrec(&rect, &result) ; + + +writes {{4,4},{7,20}} tO result. + + +4-9 + + +CHAPTER 5 + + +FLOATING POINT + + +Floating point C +The 8087 emulator + + +The code that is generated from floating point C requires that the 8087 floating point coprocessor +emulator be present and loaded. The 8087 emulator is implemented as an external logical device driver +(LDD), loaded from sys$8087.ldd. The PLIB (or CLIB) startup module (that is, the code which calls main) +automatically loads sys$8087./dd if the application program contains any floating point code. + + +The startup module searches for sys$8087.ldd in the following directories (in order of precedence): + + +e as specified by the zero terminated string in the environment variable with name "Ems" (if such +an environment variable exists) + + +e in the same directory that contained the program being executed + + +The startup module will fail with panic 80 the search for sys$8087.1dd fails. See the chapter on Error +Handling for an explanation of the panic mechanism. + + +The Ems environment variable may be set using p_setenv - as described in the chapter Memory +Allocation. For example, the following installation program causes the startup module to look for +sys$8087.ldd in the a:\sys\ directory: + + +#include + + +GLDEF_C main(VOID) +{ +p_setenv ("EMS", "A:\\SYS\\") ; +} + + +Note that environment variables names are case-sensitive - setting up (say) "ems" will not have the desired +effect. + + +Only one copy of sys$8087.ldd is loaded however many floating point processes are started. The LDD is +deleted (freeing the memory) when the last floating point process exits gracefully. If the last process +panics or is stopped by another process, the LDD will remain loaded - but it will be deleted by a +subsequent normal exit of a floating point process. The LDD has the device name Ems, so you can find +out if the device is loaded using: + + +LOCAL_C INT Is8087Loaded (VOID) + + +{ +TEXT bb [E_MAX_NAME+2]; + + +return (p_devfnd(0, "EM$",E_LDD, &bb[0])>0); +} + + +which returns TRUE if the LDD is loaded. If required, a clean-up program can delete the loaded LDD with: +p_devdel ("EM$",E_LDD) ; + + +which will only successfully delete the LDD if there are no floating point processes using it. The functions +p_devfnd and p_devdel are described along with LDDs in the //O System chapter. + + +PLIB REFERENCE + + +If sys$8087.ldd is not present in the ROM, it must be loaded into RAM at a cost of approximately 8K +bytes (but this does not detract from the code segment limit of the application). + + +If the LDD is present in the ROM, it still has to be loaded but at a reduced cost of RAM. You can find out +if sys$8087.1dd is present in the ROM using: + + +LOCAL_C INT Is8087InROM (VOID) + + +{ +P_INFO info; + + +return (p_finfo("ROM: :SYS$8087.LDD", &info) >=0) ; +} + + +which returns TRUE if sys$8087./dd is present in the ROM. +Avoiding the 8087 emulator + + +It is possible to perform floating point operations without using floating point C and without loading the +emulator. For example, a program that contains the following function (to evaluate sin(x)/x): + + +LOCAL_C INT Sinc(DOUBLE *pret,DOUBLE *parg) +{ +if (*parg==0.0) +{ +*pret=1.0; +return (0); +} +if ((ret=p_sin(pret,parg) ) <0) +return (ret); +*pret=*pret/*parg; +return (0); + + +} + + +will load the emulator because the expressions *parg==0.0, *pret=1.0 and *pret=*pret/*parg all +generate calls to the emulator. + + +However, if the function is implemented without using floating point C as in: + + +LOCAL_C INT Sinc(DOUBLE *pret,DOUBLE *parg) +{ +WORD x; +DOUBLE zero; + + +x=0; +p_itof (&zero, &x) ; +if (!p_fcmp(&zero,parg) ) +{ +x=1; +p_itof (pret, &x); +return(0); +} +if ((ret=p_sin(pret,parg) ) <0) +return (ret); +p_fdiv(pret,parg) ; +return (0); + + +} +then sys$8087./dd is not loaded. Furthermore, the code that is generated is smaller and runs faster. +The benefits of avoiding the emulator are: +¢ you do not need to worry about the presence of sys$8087.ldd +e the program is smaller and runs faster +The benefits of using the emulator are: +e you can use floating point C and use 32-bit float variables (as well as 64-bit doubles) + + +e the emulator works with 80-bit numbers internally and therefore gives more precise results + + +5-2 + + +5 FLOATING POINT + + +Macros + + +The following macros, defined in p_math.h + + +#define ABS(x) ((x)<0O ? -(x) : (x)) +#define MAX(a,b) ((a)>(b) ? (a) : (b)) +#define MIN(a,b) ((a)<(b) ? (a) : (b)) + + +can be used with integer or floating point expressions (although the code that is generated might be quite +lengthy). Using any of these macros with a floating point expression will cause the 8087 emulator to be +loaded. + + +The remaining functions in this chapter, with the exception of p_rand and p_randl, are implemented +independently of the emulator. Using them will not cause the emulator to be loaded. If the emulator is +loaded, they may still be used. + + +Converting doubles to and from text + + +p_dtob Double to string + + +INT p_dtob(TEXT *pbuf, DOUBLE *pval, P_DTOB *pformat) ; + + +Convert the double floating point number *pvai to text at pbuf using the pformat format specification. +This text is not zero terminated. + + +The p_pros structure is defined in p_math.h as: + + +typedef structure +{ +UBYTE type; /* conversion type */ +UBYTE width; /* width of representation in characters */ +UBYTE ndec; /* number of decimal places */ +TEXT point; /* decimal point character */ +TEXT triad; /* triad separator character */ +UBYTE trilen; /* threshold for triad character use */ +} P_DTOB;. + + +where: + + +type specifies the numeric format as being fixed, scientific or general. (Integer +format is obtained as a special case of fixed point format where the number of +decimal places ndec is zero.) + + +width specifies the maximum number of characters allowed to represent the number +(it must be in the range 1 to 255 inclusive). You must reserve width bytes at +pbuf. If the formatted string would be wider than width then =_GEN_FAIL Is +returned. (If you want the output aligned and filled, post-process pbuf with +p_jtob). + + +ndec specifies the number of digits following the decimal point when type is +P_DTOB_FIXED Of P_DTOB_EXPONENT where ndec must be in the range zero to +P_FLT_PREC (15) inclusive. + + +point specifies the character used for the decimal point. It would normally be either +""(dot) or ','(comma). + + +triad specifies the triad separator character used to delimit groups of 3 digits in the +integer part of a fixed point number. It would normally be one of '.'(dot) or +(comma) or ' '(space). + + +trilen is either zero to disable triad insertion, or a threshold number of digits above +which triad insertion takes place. In practice, trilen is set to 1 for normal +conventions and 4 to conform to the French convention. + + +PLIB REFERENCE + + +In all cases, negative numbers are represented by the insertion of a leading '-' sign (positive numbers do +not have a leading '+' sign). To obtain a bracketed representation of negative numbers you must post- +process the output string. + + +There can never be more than p_FLT_pRECc(15) significant digits. Where there are less than P_FLT_PREC +significant digits, the number is rounded to the number of significant digits displayed. + + +The detailed formatting details as a function of type is as follows: + + +P_DTOB_FIXED the number is represented with ndec decimal places, where ndec may be zero to +represent an integer (in which case no decimal point character is displayed). If +the ASCII form exceeds width (usually due to the number being large and +having too many digits before the decimal point), =_GEN_FAIL is returned. A +zero is displayed in the form "0.000" where there are ndec zeros following the +decimal point or as just "0" if ndec is zero. + + +P_DTOB_EXPONENT the number is represented in scientific notation with one non-zero digit before +the decimal point and ndec digits beyond the decimal point followed by 'E', a +sign ('+' or '-') and the exponent as two digits (with leading zero if necessary). +If ndec is zero, the number is rounded to one digit of precision and no decimal +point is displayed. A zero is displayed in the form "0.000E+00" where there are +ndec zeros following the decimal point or as "0E+00" if ndec is zero. Triad +separation is not available and triad separation parameters are ignored. + + +P_DTOB_GENERAL converts either as fixed format (with no triad separator) or scientific format, +making best use of width. Here, "making best use" is defined as showing the +greater number of significant digits and preferring fixed format when the +number of significant digits shown is the same. The number of decimal places +displayed depends on width (ndec is ignored). A zero is displayed as just "0". +Triad separation is not available and triad separation parameters are ignored. + + +P_DTOB_GEN_LIM as for P_DTOB_GENERAL, except that output is limited to not exceed 12 +significant digits. + + +Returns the number of characters written to pbuf if successful, or one of the following negative error +numbers: + + +E_GEN_UNDER the number is too small to represent (less than approximately 1E-99). If you +would prefer not to fail in this case, you can always write your own zero or re- +call p_dtob with a zero double. + + +E_GEN_OVER the number is too large to represent (greater than approximately 1 E99). +E_GEN_FAIL the representation exceeds width characters. +E_GEN_ARG either the double is illegal, or type is not one of P_DTOB_FIXED, + + +P_DTOB_EXPONENT Of P_DTOB_GENERAL. + + +p_stod String to double + + +INT p_stod(TEXT **pstr, DOUBLE *pval, INT point); + + +Scan the zero terminated string *pstr for a floating point number where point is the code of the decimal +point character (normally either '.' or ',') and write the value as a double float to *pval. + + +For a number to be recognised, the string must contain at least one decimal digit. + + +If p_stod is successful, it updates *pstr to point to the terminating character and returns zero. If it fails, +*pstr is not changed and it returns one of the following negative error numbers: + + +E_GEN_UNDER the number is too small (less than approximately 1E-99). The value zero is +written to *pval. + + +E_GEN_OVER the number is too large (greater than approximately 1E99). + + +E_GEN_FAIL fails to recognise a number. + + +5-4 + + +The supplied string at *pstr should take the form: + + +[+|-].[E|e] [+|-] + + +where: + + +the leading '+' sign may be omitted for positive numbers + and are optional but at least one should be present +leading zeros in are legal but have no effect + + +trailing zeros in are legal but have no effect + + +5 FLOATING POINT + + +there is no reasonable limit to the number of significant digits, but digits that are beyond the +precision of the floating point representation will not be reflected in the mantissa of the number +which is produced + + +the exponent field (which starts with 'E' or 'e') is optional + + +the leading '+' sign in the exponent field may be omitted for positive exponents + + +the resulting number should be in the range approximately 1E-99 to approximately 1E+99 + + +Example + + +LOCAL_D TEXT buf []="-134.43735abc"; +FAST INT ret; +DOUBLE val; + + +TEXT *ptr; + + +ptr=é&buf [0]; + + +After + + +ret=p_stod(&ptr,é&val,'.'); + + +val will be -134.43735, ptr will be pointing to 'a' and ret will be zero. + + +p_getctd + + +VOID p_getctd(E_CONFIG *pcfg); + + +Write a copy of the system &_conFTI¢ struct to pcfg. + + +Get number representation preferences + + +The =_conric struct is defined in p_config.h as: + + +typedef struct + + +{ + + +UBYT + + +UBYT +UBYT +UBYT +UBYT +UBYT +UBYT +UBYT +UBYT + + +UBYT +} EL + + +UWORD countryCode; +WORD gmtOffset; + +UBYTE +UBYTE +UBYTE +UBYTE +UBYTE +UBYTE +UBYTE +UBYTE +UBYTE +UBYTE +TE +E +E +E +E +E +E +E +E +E + + +dateType; + +timeType; +currencySymbolPosition; +currencySpaceRequired; +currencyDecimalPlaces; +currencyNegativelInBrackets; +currencyTriadsAllowed; +thousandsSeparator; +decimalSeparator; +dateSeparator; +timeSeparator; +currencySymbol [9]; +startOfWeek; +summerTime; + +clockType; +dayAbbreviation; +monthAbbreviation; +workDays; + +units; + +spare[9]; + + +CONFIG; . + + +5-5 + + +PLIB REFERENCE + + +In the context of this chapter we are interested in: + + +currencySymbol a zero terminated string containing the currency symbol +currencySymbolPosition which should contain either E_cURRENCY_BEFORE Of E_CURRENCY_AFTER +currencySpaceRequired which should contain either E_NosPACE_BETWEEN or E_SPACE_BETWEEN +currencyDecimalPlaces the number of decimal places for displaying currency figures +currency- TRUE if a negative currency should be displayed in brackets rather than +NegativeInBrackets with a minus sign + +currencyTriadsAllowed zero to disable triad separator insertion, or a threshold number of digits + + +above which triad separator insertion takes place. In practice a value of 1 is +used for normal conventions and 4 for the French convention. Note that, +despite the name of this element, triad separators are not restricted to +currency fields; they may be inserted in any numeric field. + + +thousandsSeparator the character code of the triad (thousands) separator + +decimalSeparator the character code of the decimal separator (normally either ',' or '.') + +units either E_IMPERIAL or E_METRIC to indicate a preference for imperial +or metric units (for example, to show page dimensions in inches or +centimetres) + + +IN NN +Long integer functions + + +p_randl Long random number + + +ULONG p_rand1l(ULONG *pseed) ; +Return the next pseudo random number and updates *pseed. + + +Used to generate a sequence of pseudo random numbers from an initial value of *pseed. Any given seed +will always produce the same sequence of random numbers. + + +The numbers generated may be any value between 0 and 4294967295 (oxffffffFfFf) or, if considered as a +signed result, between -2147483648 (0x80000000) and +2147483647 +(0x7ffffffF). + + +For example, to print reproducibly 100 random longs: + + +ULONG seed; +UINT i; + + +seed=01; +for (i=0;i<100;i++) +p_printf("%1ld",p_randl (&seed) ); + + +To generate a different set of numbers each time, seed the number with the system time, as in: + + +seed=p_date(); + + +Scientific functions + + +For all floating point functions that transform a single input parameter it is permissible to use the same +address for both parg and pret. + + +All trigonometric functions assume angles are measured in radians. + + +p_sin Sine +INT p_sin(DOUBLE *pret, DOUBLE *parg); +Write the sine of *parg to *pret. + + +Returns zero if successful or E_GEN_ARG if *parg was an invalid double. + + +5-6 + + +5 FLOATING POINT + + +p_cos Cosine +INT p_cos (DOUBLE *pret, DOUBLE *parg); +Write the cosine of *parg to *pret. + + +Returns zero if successful or E_GEN_arRG if *parg was an invalid double. + + +p_tan Tangent +INT p_tan(DOUBLE *pret, DOUBLE *parg); +Write the tangent of a *parg to *pret. + + +Returns zero if successful or =_cEN_arc if *parg was an invalid double or if it was greater than +149078413. + + +p_asin Arcsine +INT p_asin(DOUBLE *pret, DOUBLE *parg) ; +Write the angle whose sine is *parg to *pret. + + +Returns zero if successful or zE_GeN_arG if *parg was an invalid double or aps (*parg) >1. + + +p_acos Arccos +INT p_acos (DOUBLE *pret, DOUBLE *parg) ; +Write the angle whose cosine is *parg tO *pret. + + +Returns zero if successful or z_GEN_aARG if *parg was an invalid double or aps (*parg) >1. + + +p_atan Arctangent +INT p_atan(DOUBLE *pret, DOUBLE *parg) ; +Write the angle whose tangent is *parg to *pret. + + +Returns zero if successful or z_GEN_aRG if *parg was an invalid double. + + +p_In Natural logarithm +INT p_ln(DOUBLE *pret, DOUBLE *parg); +Write the natural (base e) logarithm of *parg to *pret. + + +Returns zero if successful or z_GEN_aRc if *parg was less than or equal to zero or if *parg was an invalid +double. + + +p_exp Exponential +INT p_exp(DOUBLE *pret, DOUBLE *parg); + +Write the value of the arithmetic constant e (2.71828...) raised to the power of *parg to *pret. + +Returns zero if successful or one of the following negative error numbers: + +E_GEN_ARG *parg 1s not a valid double. + + +E_GEN_UNDER underflow has occurred (the magnitude of the result is less than 1E-307), zero +is written to *pret. + + +E_GEN_OVER overflow has occurred (the magnitude of the result is greater than 1E307). + + +5-7 + + +PLIB REFERENCE + + +p_log Logarithm +INT p_log(DOUBLE *pret, DOUBLE *parg); +Write the base 10 logarithm of *parg to *pret. + + +Returns zero if successful or E_GEN_aRG if *parg was less than or equal to zero or if *parg was an invalid +double. + + +p_sqrt Square root +INT p_sqrt (DOUBLE *pret, DOUBLE *parg ); +Write the square root of *parg to *pret. + + +Returns zero if successful or E_cEN_aRc if *parg was negative or an invalid double. + + +p_pow Raise to the power +INT p_pow(DOUBLE *pret, DOUBLE *pargl, DOUBLE *parg2); +Write *pargi raised to the power of *parg2 to *pret. + + +Returns zero if successful or one of the following negative error numbers: + + +E_GEN_ARG the arguments are invalid (if *parg1<0, *parg2 must be integral), or at least +one argument is not a valid double. + +E_GEN_UNDER underflow has occurred (the magnitude of the result is less than 1E-307), zero +is written to *pret. + +E_GEN_OVER overflow has occurred (the magnitude of the result is greater than 1E307). + +p_rand Double random number (long seed) + + +DOUBLE p_rand(ULONG *pseed) ; + + +Return a DouBLE random number in the range zero (inclusive) to one (exclusive). As in the case of +p_rand1, the value pointed to by pseed is used to seed the random number generation and is updated for +the next call of p_rand. + + +This function requires the 8087 floating point emulator. + + +p_frand Double random number +VOID p_frand(DOUBLE *pret, DOUBLE *pseed) ; + + +Write a random number in the range zero (inclusive) to one (exclusive) to *pret. As in the case of +p_rand1, the value pointed to by pseed is used to seed the random number generation and is updated for +the next call of p_frand. + + +Floating point arithmetic without the 8087 emulator + + +This section describes the PLIB functions that would normally be used to perform floating point +arithmetic without having to load the 8087 floating point emulator sys$8087.ldd. + + +For all floating point functions with one parameter it is permissible to use the same address for both parg +and pret. + + +p_fid Assignment + + +INT p_fld(DOUBLE *pret, DOUBLE *parg) ; +Write the value of *parg to *pret (the 'Id' stands for load). + + +Returns zero if successful or E_GEN_ARG if *parg was an invalid double. + + +5-8 + + +5 FLOATING POINT + + +p_fadd Add + + +INT p_fadd(DOUBLE *pret, DOUBLE *parg) ; + +Write the sum of *parg and «pret to *pret. + +Returns zero if successful or one of the following negative error numbers: +E_GEN_ARG *pret OF *parg was not a valid double. + + +E_GEN_OVER overflow has occurred (the magnitude of the result is greater than 1E307). + + +p_fsub Subtract +INT p_fsub(DOUBLE *pret, DOUBLE *parg) ; + +Write *pret minus *parg tO *pret. + +Returns zero if successful or one of the following negative error numbers: + +E_GEN_ARG *pret OF *parg was not a valid double. + + +E_GEN_OVER overflow has occurred (the magnitude of the result is greater than 1E307). + + +p_fmul Multiply +INT p_fmul (DOUBLE *pret, DOUBLE *parg) ; + +Write the product of *parg and *pret to *pret. + +Returns zero if successful or one of the following negative error numbers: + +E_GEN_ARG *pret OF *parg was not a valid double. + + +E_GEN_UNDER underflow has occurred (the magnitude of the result is less than 1E-307), zero +is written to *pret. + + +E_GEN_OVER overflow has occurred (the magnitude of the result is greater than 1E307). + + +p_fdiv Divide +INT p_fdiv(DOUBLE *pret, DOUBLE *parg) ; + +Write *pret divided by *parg to *pret. + +Returns zero if successful or one of the following negative error numbers: + +E_GEN_ARG *pret OF *parg was not a valid double. + + +E_GEN_UNDER underflow has occurred (the magnitude of the result is less than 1E-307), zero +is written to *pret. + + +E_GEN_OVER overflow has occurred (the magnitude of the result is greater than 1E307). + + +p_fcmp Compare +INT p_fcmp (DOUBLE *pargl, DOUBLE *parg2) ; +Compare *pargi to *parg2, returning: + +1 if *pargl > *parg2 + +0) if *pargl == *parg2 + +-l if *pargl < *parg2 + + +The function only returns zero if *pargi and *parg2 are strictly equal. In some cases it may be more +appropriate to test for equality by evaluating the difference using p_fsub and then comparing the +difference with a suitably small number (such as, for example, 1E-10). + + +5-9 + + +PLIB REFERENCE + + +The return value is undefined if either *pargi1 or *parg2 is not a valid double. + + +Note that it is bad practice to compare floating point numbers for equality, since rounding errors may +make the result meaningless. + + +p_fneg Negate +INT p_fneg(DOUBLE *parg) ; +Negate *parg. + + +Returns zero if successful, or E_GEN_ARG if *parg was an invalid double. + + +p_mod Modulus +INT p_mod(DOUBLE *pret, DOUBLE *pargl, DOUBLE *parg2)j; +Write the remainder of *parg1 divided by *parg2 to *pret. + + +Returns zero if successful, or E_GEN_aRG if either *parg1 or *parg2 was an invalid double. + + +p_int Integer part +INT p_int (DOUBLE *pret, DOUBLE *parg); +Write the integer part of *parg to *pret. Negative numbers are rounded towards zero. + + +Returns zero if successful or E_GEN_ARG if *parg was an invalid double. + + +p_inti Convert double to integer +INT p_inti(WORD *pret, DOUBLE *parg) ; + + +Write the integer part of *parg to *pret if *parg is in the range -32768 to +32767 inclusive. Negative +numbers are rounded towards zero. + + +Returns zero if successful or one of the following negative error numbers: + + +E_GEN_ARG *parg is not a valid double +E_GEN_OVER *parg 1s outside the range -32768 to +32767 +p_intl Convert double to long + + +INT p_int1l(LONG *pret, DOUBLE *parg); + + +Write the integer part of *parg to *pret, if it is in the range -2147483648 (0x80000000) to +2147483647 +(0x7££fffff) inclusive. Negative numbers are rounded towards zero. + + +Returns zero if successful, or one of the following negative error numbers: + + +E_GEN_ARG *parg is not a valid double +E_GEN_OVER *parg is outside the range -2147483648 to +2147483647 +p_itof Convert integer to double + + +VOID p_itof (DOUBLE *pret, WORD *parg); + + +Convert *parg to a double and write it to *pret. + + +p_longtof Convert long to double +VOID p_longtof (DOUBLE *pret, LONG *parg); + + +Convert *parg to a double and write it to *pret. + + +5-10 + + +CHAPTER 6 + + +ERROR HANDLING + + +[a =I] +Process termination + + +A process can terminate itself or it can be terminated by another process. By whatever means a process +terminates, one or more other processes may be interested in being notified that a process has terminated. + + +Terminating this process. + + +A process terminates itself by calling: + +p_exit for normal graceful termination + +p_panic for abnormal termination, normally as a result of defective code + +C programs that fall off the end of main effectively call p_exit with the return from main. That is: + + +GLDEF_C INT main(VOID) +{ +p_printf ("Hello world"); +p_sleep (501); /* wait 5 seconds */ +return (0); + + +} +is equivalent to: + + +GLDEF_C VOID main(VOID) +{ +p_printf("Hello world"); +p_sleep (501); /* wait 5 seconds */ +p_exit (0); +} + + +It is poor practice to fall off the end of a voID main since this is equivalent to calling p_exit with a +random number (whatever happens to be in the ax register at the time). If there is a system component +(such as the shell) reporting process terminations to the user, it will give a misleading report. + + +Terminating another process + + +A process can terminate another process by calling: + + +p_pterminate or to terminate another process (typically in response to a user request) +p_pkill +p_ppanic to panic another process (normally following unreasonable behaviour from the + + +process being terminated) + + +To terminate a process, it is recommended that p_pterminate is used in preference to p_pkili as the +former allows the process being terminated to run any cleanup code before exiting gracefully. +Applications wishing to run cleanup code call p_onterminate to elect to be sent an inter-process message +in response to the p_pterminate request. + + +6-1 + + +PLIB REFERENCE + + +Finding out when other processes terminate + + +A process can request to be notified of the termination of another process by calling: +p_logona to be signalled when the specified process terminates + + +p_logon to receive an inter-process message when the specified process terminates +(convenient for server processes to keep track of their clients) + + +p_watchall to receive an inter-process message when any process terminates (normally +used by the Shell to monitor the termination of all processes) + + +See the chapter Asynchronous Requests and Semaphores for the meaning of the term "signalled". See the +chapter Processes and Inter-Process Messaging for more about inter-process messaging and servers. + + +The process termination word + + +Regardless of which one of p_logona, p_logon or p_watcha1l is used, the system delivers a single 16-bit +process termination word giving information on how the process terminated. The most significant byte of +the process termination word is one of the following (defined in epoc.h) + + +E_NORMAL_EXIT the process terminated itself by calling p_exit or it was terminated by another +process calling p_pterminate or p_pkill. The least significant byte of the +process termination word contains the nReason parameter to p_exit, +p_pterminate Or p_pkill. By convention, an nReason of zero indicates a +normal error-free graceful termination. + + +E_PANIC_EXIT the process terminated itself by calling p_panic or it was terminated by another +process calling p_ppanic. The least significant byte contains the nPanic ("panic +number") parameter to p_panic or p_ppanic. + + +E_TASK_PANIC_EXIT the process terminated because it owned a task that terminated with +E_PANIC_EXIT (tasks are lightweight processes and are described in the chapter +Processes and Inter-Process Messaging). + + +Panics + + +When the system detects a condition that it believes could only arise from a bug in a the application +program, the system terminates the process with a "panic number" in the range 0 to 255 inclusive (where +the system is said to "panic the process"). A panic is a fatal exception that causes the process to terminate +immediately. There is no way for applications to avoid being terminated when a panic has been started +(cf p_leave, described later in this chapter). + + +Panicking a process is more economical in the use of system code and application code than returning an +error, since the latter relies on application code to properly process the error return. As well as protecting +the system from defective applications, the panic system enforces a greater discipline on application code +by terminating a process as soon as the condition is detected. + + +This does not mean that the system always prefers to use panics rather than error returns. Error returns +are still used where appropriate; the system certainly never panics a process on a condition that could arise +from user action. For example, the p_alloc function to allocate a memory cell returns nutt if there is +insufficient free system memory to satisfy the request, but calls p_panic if it detects that the heap has been +corrupted. In the majority of cases, such as in the above example, it is quite clear where a panic or an +error return is appropriate, but occasionally it is not so clear. From the point of view of an application +programmer, however, it is clear that panic conditions should be avoided. In consequence the function +descriptions in this manual include any conditions that result in the caller being panicked. + + +If the panic condition is detected within the code of a system function, the function calls p_panic as in the +example above. If the condition is detected in a system process (for example, the supervisor or the file +server) the application process is terminated by the system process calling p_ppanic. + + +Application programmers can include their own calls to p_panic to catch conditions indicating a bug in +their program which might otherwise go unnoticed (until the software is used by a customer!). A common +example would be to put a call to p_panic on the default case of a switch statement, to catch an invalid +parameter. + + +6-2 + + +6 ERROR HANDLING + + +System panic numbers + + +The following lists the panic numbersthat are used by the operating system: + + +00 +01 +02 +03 +04 +05 +06 +07 +08 +09 +10 +11 +12 + + +13 +14 +15 +16 +17 +18 +19 + + +20 +21 +22 +23 +24 +25 + + +26 +27 + + +28 +29 +30 +31 +32 +33 + + +Used by test code when a test fails + +Invalid function number (semaphore manager) +Invalid semaphore handle + +Semaphore not allocated + +Initial semaphore count is negative + +Signal count is negative + +Invalid function number for process manager +Invalid process ID + +Task tried to create a task + +Invalid function number for time manager +Invalid function number for segment manager +Segment size was negative + + +Type was not one of E_SEGMENT LOW, E_SEGMENT_HIGH, E_SEGMENT_DEVICE OF +E_SEGMENT_LOCKED + + +Invalid segment handle + +Segment copy is out of range + +Invalid function number for heap manager + +Heap not initialised + +A heap cell is being reduced by more than its size +Attempt to set heap granularity greater than z_max_GRowByY + + +A heap cell address is outside the boundaries of the heap (the heap has probably been +corrupted - try calling p_alichk to catch the corruption sooner) + + +Invalid function number for inter-process message manager + +Inter-process messaging has already been initialised (ie p_minit has been called twice) +Inter-process messaging has not been initialised (ie p_minit has not been called) +Cannot initialise with zero messages in the queue + +Invalid function number for I/O manager + + +Invalid I/O channel (possibly because you did not test that the previous p_open succeeded or +you have closed the channel or you overwrote the variable containing the channel) + + +Device requested panic + + +Invalid wait handler handle (possibly nothing to do with wait handlers and just indicative of +a low address overwrite of the 4 bytes at address 2, as a result of an uninitialised pointer) + + +Key and pointing device already hooked + +Key and pointing device requesting process is not a task +Invalid function number for device manager + +Invalid device handle + +Invalid function number for file manager + + +Process already connected to file server + + +PLIB REFERENCE + + +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 + + +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 + + +61 +62 +63 +64 +65 +66 +67 +68 + + +Reserved for future use + +Invalid function number for library manager +Invalid library handle + +Invalid function number for library + +Invalid LIB file channel + +Invalid DYL index number + +Invalid message to file server + +Process has not connected to file server + +Invalid function number for conversion manager +Invalid function number for general manager +Attempt to unhook from notify when not already hooked +Invalid revector address + +Invalid function number for conversion manager + + +Leave called before a call to enter (possibly because you were unaware that the function you +were calling could call p_leave) + + +No method available to handle message (OOP) +Invalid reclass attempted (OOP) + +Unknown category in LibHandle (OOP) +Unknown class in LibCreate (OOP) + +Supersend called from outside a method (OOP) +Attempt to get a handle before being linked (OOP) +Missing external categories in LibLink (OOP) +Object does not point to a valid class (OOP) +Invalid link layer completion code + +Invalid function number for window server +Invalid function number for hardware manager +Unexpected interrupt + + +Attempted to write outside of process data segment (possibly because of an uninitialised +pointer or a corrupted data structure) + + +Interrupts have been disabled for too long +Reserved for future use + +Divide by zero interrupt + +Overflow interrupt + +Invalid function number for Dbf manager +Invalid DBF I/O channel + +Invalid parameter for DBF function + + +Address zero overwrite (possibly because of an uninitialised pointer) + + +6 ERROR HANDLING + + +69 The operating system detected less than 0x100 bytes of remaining stack (this amount is +reserved for hardware interrupts to run). You probably have declared large data structures as +automatics. Consider making them static variables or allocate them from the heap. + + +70 Environment name size > EnvMaxNameSize +71 Single step interrupt (INT 1) +72 Break point interrupt (INT 3) + + +73 A request was made while an asynchronous request of the same type and on the same +channel was already pending + + +74 Invalid function number for serial I/O manager + +75 Call to an ASIC1 function on an ASIC9 machine + +76 Attempt to find a DYL not in a visible bank + +77 Floating point emulator exception + +78 Semaphore count exceeds Ox7fff + +80. Library fatal error, preceded by a notification of the specific error +255 The function p_ailchk detected a corrupted heap + + +Some of the panics, especially those described by "Invalid function number for ...", are unlikely to indicate +a specific bug; it is almost impossible to create code that would produce such a panic by a coding error. +This type of panic could, however, easily arise from trashing a return address on the stack, with the +instruction pointer wandering into arbitrary code. In the above list, those panics that are likely to indicate +a specific coding problem are described more fully. + + +If you get a panic 79, or a panic in the range 81 to 254, it may be due to some other system component. +See the Window Server manual for panics in the range 81-110 and, when using object oriented +programming, see the OLJB manual for panics in the range 130-158. + + +p_exit Terminate this process +VOID p_exit (INT nReason) ; + +Terminate this process with reason nReason in the range -127 to 128 without returning to the caller. +Applications that exit normally should terminate with nreason equal to zero. + + +Applications that fail during their initialisation may wish to pass on the error number (in the range -127 +to -1 inclusive) that caused the initialisation to fail. + + +Programs that are run as subprocesses can use a positive nReason to pass back an exit status to their parent +process. + + +p_panic Terminate after an unrecoverable error +VOID p_panic(INT nPanic); +Terminate this process with panic number nPanic in the range 0 to 255 without returning to the caller. + + +To avoid system panic numbers, application specific panic numbers should start from 254 downwards. + + +p_pkill Unilaterally terminate a process + + +INT p_pkill (HANDLE pId, INT nReason) ; + + +Terminate process pra for reason nReason (in the range -127 to 128 inclusive) without giving the process +being terminated an opportunity to run any cleanup code before exiting. + + +It is recommended that p_pterminate (described below) is used in preference to p_pkill as it gives the +process being terminated a chance to run any cleanup code. + + +PLIB REFERENCE + + +Returns zero if successful or one of the following negative error numbers: + + +E_FILE_NXIST the process does not exist +E_GEN_FAIL pid is the null process, the supervisor or the file server +p_pterminate Terminate a process + + +INT p_pterminate (HANDLE pid, INT nReason) ; +Terminate process p1d for reason nReason in the range -127 to 128 inclusive. + + +If process prd has called p_onterminate (described next) the call to p_pterminate will simply send the +specified message number to process pid. Otherwise the effect is the same as with p_pki1l. It is +recommended that p_pterminate is used in preference to p_pkill. + + +Returns zero if successful or one of the following negative error numbers: + + +E_FILE_NXIST the process does not exist +E_GEN_FAIL pid is the null process, the supervisor or the file server +p_onterminate Elect to receive termination message + + +VOID p_onterminate (INT nMessage) ; + + +Elect to receive (non-zero) message number nMessage, rather than being summarily terminated, when +another process requests termination by calling p_pterminate. + + +On receipt of the termination message a process should execute its cleanup code and must then terminate +itself, normally by calling p_exit. + + +The process calling p_onterminate must guarantee to respond promptly when the termination message is +sent to it. It should not perform any lengthy, uninterrupted, processing. A process which calls +p_onterminate and then (presumably in error) enters an infinite loop will not be terminated by a call to +p_terminate. It is recommended that a process should not call p_onterminate unless there is an explicit +reason for it to do so. + + +The election may be cancelled by calling p_onterminate (0). + + +Messaging must have been initialised with p_minit prior to the call to p_onterminate, otherwise p_panic +will be called. + + +p_ppanic Panic a process by id + + +INT p_ppanic(HANDLE pId, INT nPanic); + + +Terminate process p1d with panic number nPanic in the range 0 to 255 (used for example by server +processes that receive a garbage message from a client process to panic the client). + + +Returns zero if successful or one of the following negative error numbers: + + +E_FILE_NXIST the process does not exist +E_GEN_FAIL pid is the null process, the supervisor or the file server +p_logona Request notification of process termination + + +INT p_logona (HANDLE pId, WORD *pStatus) ; + + +Make an asynchronous request to be notified of the termination of process pid by having this process I/O +semaphore signalled when pid terminates. See the chapter Asynchronous Requests and Semaphores for a +description of asynchronous requests and the I/O semaphore. + + +Returns zero if successful or E_FILE_NXIST if pId does not exist. + + +After a successful request and before pid has terminated, *pstatus contains E_FILE_PENDING. When pid +has terminated, *pstatus contains the (non-negative) process termination word (as described under the +heading The Process Termination Word at the beginning of this chapter). + + +The caller can cancel the asynchronous request by calling p_logoffa. + + +6-6 + + +6 ERROR HANDLING + + +A server process that responds to inter-process messages from client processes will probably find it more +convenient to use p_logon, described below. + + +For example, the following function: + + +GLDEF_C INT RunSubProcessWait (TEXT *name, BYTE *pReason) + + +{ +HANDLE pid; +WORD stat; + + +if ((pid=p_execc (name, NULL, 0) ) <0) +return (pid); + +p_logona (pid, &stat) ; + +p_presume (pid) ; + +p_waitstat (&stat); + +*pReason=(BYTE) stat; + +return (stat>>8) ; + + +} + + +loads the executable name, resumes the process, waits for it to terminate, writes the p_exit to *pReason +and returns &£_NORMAL_ExIT. It returns a negative error number if it fails to load name and £_paNIc_Ex1T if +the sub-process panics. + + +p_logoffa Cancel notification of process termination + + +INT p_logoffa(HANDLE plId)j; + + +Cancel a previously requested notification of the termination of process pra (as passed to the p_logona +being cancelled). + + +Returns zero if successful or —_FILE_NxIsT if no request is pending. + + +If the cancel gets through before pid terminates, *pstatus will contain z_F1LE_caNcEL. In either case, the +process I/O semaphore is signalled and p_1ogoffa would normally be followed by a call to +p_waitstat (pStatus). + + +p_logon Request message on process termination + + +INT p_logon(HANDLE pId, INT mType); + + +Request to be notified of the termination of process pia by receiving an inter-process message of type +mType when pid terminates. See the chapter Processes and Inter-Process Messaging for a description of +inter-process messaging. + + +Returns zero if successful or E_FILE_nxist if pra does not exist. + + +When process pid terminates the Supervisor process sends the caller a message of type mtype and whose +first word in the message buffer is the pa of the terminating process and whose second word is the +process termination word giving information on how that process terminated (as described under the +heading The Process Termination Word at the beginning of this chapter). + + +The caller can cancel the request by calling p_logoff or p_logoffx. + + +The process must have messages initialised by calling p_minit - the function calls p_ panic if messages +have not been initialised. + + +The p_logon, p_logoff and p_logoffx services were designed for server processes that respond to inter- +process messages from client processes to clean up client specific resources should a client process +terminate without disconnecting from the server. Processes that are not server process and that do not +normally respond to inter-process messages will probably find it more convenient to use p_logona, +described above. + + +PLIB REFERENCE + + +p_logoff Cancel message on process termination +INT p_logoff (HANDLE pId, INT mType); +Cancel a previous p_logon request to be sent an inter-process message when process pId terminates. + + +The value of pta should be as passed to p_logon, and mType is ignored. This form is suitable for +applications that do not make no more than one p_logon request to any particular process. + + +Applications that make two or more p_logon requests with the same value of pra (but, presumably, +different values of mtype) should cancel them by means of p_logoffx, described below. + + +Returns zero if successful or E_FILE_NXIST if pId does not exist. + + +The function calls p_panic if messages have not been initialised. + + +p_logoffx Cancel message of specific type on process termination +INT p_logoffx (HANDLE pId, INT mType); +This function is only available in EPOC version 3.18 or later. + + +Cancel a previous p_logon request to be sent an inter-process message of type mrype when pid terminates +(p1d and mType should be the values that were passed to the p_logon request that is being cancelled). + + +This function must be used in preference to p_logoff in cases where two or more p_logon requests are +made with the same value of pid. + + +Returns zero if successful or E_FILE_NXIST if pId does not exist. + + +The function calls p_panic if messages have not been initialised. + + +p_watchall Watching all exits + + +INT p_watchall(UINT mType) ; + + +Request to be notified of the termination of any process by receiving an inter-process message of type +mType when a process terminates. See the chapter Processes and Inter-Process Messaging for a +description of inter-process messaging. + + +Only one process at a time can request this service and it is usually reserved for use by a system process +(normally the Shell process) to monitor the termination of all processes. + + +The function returns zero if successful or E_GEN_FAIt if a watch is already active. +The format of the received message is as for p_logon, described above. +Calling p_watchall with an mType of zero cancels the request. + + +The process must have messages initialised by calling p_minit - the function calls p_panic if messages +have not been initialised. + + +[ce re FF +Error returns + + +System functions that can fail must somehow indicate success or failure and, where appropriate, elaborate +on the failure. + + +Where there is no elaboration of the error: + + +e Functions that return an address typically return a NULL (zero) address to indicate failure (this is +often used when a function can fail to allocate memory). + + +¢ Otherwise functions return zero or positive to indicate success and -1 to indicate failure (the +constant E_GEN_FAIL is defined as -1 although you can just test for the sign of the returned value). + + +6-8 + + +6 ERROR HANDLING + + +Where the error is elaborated, the system function returns a system error number in the range -1 to -128, +allocated as follows: + + +-1 to-31 Reserved for general errors of the form &_GEN_xxx; (defined in pp_gen.h) +-32 to -63 Reserved for I/O device errors of the form &_FILE_xxx (defined in p_file.h) +-64 to -95 Reserved for future use + +-96 to -128 Reserved for OPL run-time errors + + +The system errors include both generic error numbers (eg =_GEN_NoMEMory) and specific error numbers +(eg E_FILE_PARITY indicating a parity error in a byte received via a serial port). Application programmers +may wish to use the generic error numbers in their own code - see the contents of p_gen.h and p_file.h. + + +The system stores a language dependent description for each of the system error numbers that may be +retrieved by calling p_errs. + + +p_errs Convert error number to string + + +VOID p_errs(TEXT *str, INT errno); + + +Convert a system error number to a language dependent zero terminated text string in str. There should +be at least z_MAx_ERROR_TEXT_S1ZE (64) bytes at address str. + + +If the error is an unknown error the string "Unknown error [xx]" (or a suitable translation if not an +English ROM) is returned, where xx is the value of errno. + + +————————— SS ————>>E~— ——>E>E>>—e~—L_——_ << s +Notifier services + + +The notifier services are used to inform the user of a condition - particularly an error condition - and to +present the user with up to three options on how to proceed. There are two variants of the notify service: + + +p_notifyerr which presents the user with a system error message (converted to text from the +error number using p_errs) and a contextual message + + +p_notify which presents the user with two messages + + +These services can be used by any application and are particularly useful for processes that do not +otherwise have a user interface (for example, the file server). Investigative calls to p_notify may be +temporarily inserted into code when debugging programs. + + +At the level of the services described in this manual and except for the simple console functions such as +p_printf, the operating system does not define any user interface components and the notifier services +rely on a higher level system process! (the "notifier") taking responsibility for implementing a user +interface. The notifier "hooks" the user interface (normally at system start up) by calling p_notifyhook. +The notifier should pre-allocate any memory it requires so that the call will not fail. + + +The notifier service is used by the file server process to give the user the opportunity to rectify a problem +that would otherwise result in a file service request failing (eg to replace an SSD pack that has +inadvertently been removed). This scheme works well when the requesting process is an interactive +application but poorly if the requesting process is designed to run unattended (eg a communications +program) or is itself a server process (eg the window server trying to read a font file). Such processes can +use p_setnotify (FALSE) to stop servers such as the file server from using the notify service to give the +user the opportunity to rectify an error condition. + + +p_notify Present the user with a message and get response +INT p_notify(TEXT *pT1l, TEXT *pT2, TEXT *pOl, TEXT *pO2, TEXT *p0O3); + + +Present the two zero terminated messages pt1 and pt2 to the user, where poi, po2 and po3 are either NULL +or zero terminated strings, offering up to three options for the user to select. The function waits for the +user to select an option and returns zero if the po1 option was chosen, | if the po2 option was chosen and +2 if the po3 option was chosen. + + +'When a specialised process hooks the notifier, it is, by convention, called syssntFy. + + +6-9 + + +PLIB REFERENCE + + +The message pT1 is presented before pt2. So pt1 would typically contain a contextual message (eg "Failed +to save notes.tpd") with ptT2 containing a more detailed message (eg "Disk full"). + + +If pt2 is NULL the second message line is blank. +To offer the user 2 options rather than 3, pass po3 as NULL. + + +To offer the user no option (that is, just to wait until the user has acknowledged the message) pass both +p02 and po3 as NuLL. Alternatively, pass all 3 as NULL as in: + + +p_notify (msgl,msg2,NULL, NULL, NULL) ; +which is equivalent (on an English machine) to: +p_notify (msgl,msg2, "CONTINUE", NULL, NULL) ; + + +Each message string pT1 and pt2 can be up to E_MAX_NOTIFY_TEXT_SIZE (64) in length including the zero +terminator. Each option string po1, po2 and po3 can be up to E_MAX_OPTION_TEXT_S1ZE (16) in length +including the zero terminator. + + +This function sends an inter-process message to the process that has "hooked" the notify interface and +thereby has taken on the responsibility of presenting the error notification user interface. If no process has +hooked the notifier, or if the notifier process has terminated, p_notify returns E_GEN_FAIL. + + +The notifier process may, in some environments, take special action if any of the strings passed to +p_notify contain a leading zero. Programmers should therefore ensure that such a string is not passed as +a parameter to p_notify. Either pass an explicit NULL (as in the above examples) or intercept the string, as +in the following example, where it is assumed that only msg2 may contain a leading zero: +LOCAL_C INT NotifyError(TEXT *msgl,TEXT *msg2) +{ +if (msg2 && !*msg2) +msg2=NULL; +return (p_notify (msgl,msg2,NULL, NULL, NULL) ) ; +} + + +p_notifyerr Notify user of error and get response + + +INT p_notifyerr(INT nError, TEXT *pT2, TEXT *pO1, TEXT *pO02, TEXT *p0O3); + + +Equivalent to calling p_errs (nError) followed by calling p_notify with the resulting error string as the +second parameter and with pt2 as the first parameter (ie the first two parameters are the other way around +compared to p_not ify) with the three option parameters being passed on to p_notify. + + +The message pT2 is presented before the error text corresponding to nError and pt2 would typically +contain a contextual message. + + +Only system error numbers (which include all errors returned by the functions described in this manual) +should be notified using this service. + + +p_setnotify Set notify state +VOID p_setnotify(UINT nState) ; +Set the notify state of this process. + + +If nstate is FALSE, the system will not automatically present the notifier as a result of an error in a service +requested by this process (the error will be returned directly). + + +If nstate is TRUE (the default state after process creation) the notifier may be called. + + +p_getnotify Get notify state +INT p_getnotify (VOID) ; + + +Return the notify state for this process. + + +6-10 + + +6 ERROR HANDLING + + +p_notifyhook Hook the notifier interface + + +INT p_notifyhook (INT mType) ; + + +-Hook the notifier interface such that this process will get an inter-process message from the notifying +process of type mType as a result of the notifying process calling p_notify Of p_notifyerr. + + +Returns zero if successful or z_ceN_ratt if the notify interface has already been hooked. + + +The mtype message contains an array of 5 string pointers into the notifying process data space +corresponding to the parameters to p_notify in the order pT1, ptT2, pol, po2 and po3. A process that hooks +the notify interface should initialise messaging using p_minit with a value of at least 10 for the message +size. + + +The text strings pointed to by the 5 parameters can be fetched from the notifying process using p_pcpyfr +(say using the maximum sizes E_MAX_NOTIFY_TEXT_SIZE and E_MAX_OPTION_TEXT_SIzE). The parameter +to p_mfree gives the result of the notification. + + +A process that has hooked the notify interface should not call either p_notify of p_notifyerr as it would +then try and send itself a message, resulting in deadlock. + + +If the process that has hooked the notify interface terminates, the system automatically frees the notify +interface so that another process can hook the interface. + + +p_notifyunhook Unhook the notifier interface +VOID p_notifyunhook (VOID) ; +Release the notify interface. + + +Calls p_panic if the caller does not have the notifier interface hooked. + + +SS —————————————————————————————————————————————————————————————] +Enter and leave + + +The functions p_enter and p_leave work together. You use p_enter to call or "enter" a function. If +p_leave(err) is called before the entered function returns, the stack is unwound and the call to p_enter +returns err. By convention, a negative value of err indicates an error and a zero (or positive) value +signifies an error-free exit. + + +The call to p_leave (or to a variant such as £_leave) may occur in the entered function or in a sub- +function and so on. + + +The p_leave performs what is sometimes called a "non-local goto" where the address of the goto is +defined by the last call to p_enter. + + +The enter and leave mechanism is commonly used in medium to large interactive applications to +implement structured error recovery. When an error occurs, the application has to do the following to +recover: + + +e free any dangling resources (eg free memory cells, close open channels, close screen windows) +e inform the user of the error +¢ continue + + +Handling all this with ad hoc conditionals in the code can double the size of a program and makes the +code hard to follow. An alternative is to set error state variables, driving centralised clean-up code that is +invoked by a negative return from a call to p_enter on an error condition. + + +The call to p_enter is placed at an appropriate place to continue after the error. The return value indicates +the nature of the error (eg no system memory) and a state variable could give a contextual message (eg +"while attempting to open file xxx"). Other error state variables would give the handles of resources that +should be freed. + + +6-11 + + +PLIB REFERENCE + + +p_enter Enter a function + + +INT p_enter(VOID *pfunc,...); + +INT p_enterl(VOID *pfunc) ; + +INT p_enter2(VOID *pfunc, VOID *al); + +INT p_enter3(VOID *pfunc, VOID *al, VOID *a2); + +INT p_enter4(VOID *pfunc, VOID *al, VOID *a2, VOID *a3); + +INT p_enter5(VOID *pfunc, VOID *al, VOID *a2, VOID *a3, VOID *a4); + +INT p_enter6(VOID *pfunc, VOID *al, VOID *a2, VOID *a3, VOID *a4, VOID *a6é); + + +Call function *pfunc where the remaining (up to 5) arguments to p_enter are passed as arguments to +*pfunc. + + +You can either use p_enter, which presents the cpEct calling convention, or one of the p_enter? +variants, which use a more efficient register calling convention. + + +Once a function has been called using p_enter, that function (or any function that is called before *pfunc +returns) may call p_leave (ret) to unwind the stack and return prematurely from the call to p_enter with +the return value of ret. If p_leave is not called, p_enter returns the value returned by *pfunc. + + +Functions called with p_enter should return an INT or a UINT (since this is assumed by p_leave). A zero +or positive return value is normally taken to indicate that the function completed successfully. + + +Calls to p_enter may be nested, in which case p_leave returns from the last active p_enter on the stack. + + +When p_enter calls *pfunc, it passes parameters to it both on the stack and in registers. Neither calling +convention? is compatible with the default calling convention (which passes parameters in registers) as +specified in p_std.def. + + +Because of the above, the target of a p_enter must declare the function as using one of the following +calling conventions: + + +CDECL where the generated code will take the parameters off the stack + + +ENTER_CALL where the generated code will take the parameters from the registers (which is +more efficient) + + +If you also call the entered function directly (without a p_enter) you must ensure that the prototype for the +function declares the calling convention consistently. + + +For example, to declare the target for a p_enter using CDECL: + + +LOCAL_C INT CDECL RunTestProgram(TEXT *name) +{ + + +..return(0); + + +} +or, more efficiently, using ENTER_CALL: + + +#pragma save, ENTER_CALL + + +LOCAL_C INT RunTestProgram(TEXT *name) +{ + + +..return (0); + + +} + + +#pragma restore +where, in either case, you would enter the function using, say: +ret=p_enter((VOID *)RunTestProgram, "fred") ; +or, more efficiently: +ret=p_enter2 (RunTestProgram, "fred") ; + + +where ret contains zero if RunTest Program returned or the parameter passed to p_leave, if p_leave was +called. + + +2Note that the calling convention applied to the function called by p_enter has nothing to do with the +calling convention of p_enter (or p_enter1 etc) as discussed above. + + +6-12 + + +6 ERROR HANDLING + + +Since it is impossible to construct a general prototype to cover all cases, pfunc is prototyped as a vorpD *. +As in the above example, you have to cast the first parameter to p_enter toa (vorp *) to avoid +compilation warnings. The header files are organised in such a way that the cast is automatically done +when you use one of the fixed parameter p_enter? variants. + + +Note that the requirement for the target of a p_enter to have one of the two special calling conventions +described above means that no PLIB or WLIB function may be the direct target of a p_enter. + + +p_leave Unwind stack and return from last p_enter +VOID p_leave (INT err); + + +Unwind the processor stack and return from the most recently called p_enter, returning the value err. +The function does not return to the caller. + + +Although in practice err is often a negative error number it need not be and p_teave can legitimately be +used to unwind the stack on any kind of condition. + + +The function calls p_panic if there is no call to p_enter on the stack. + + +f_leave Unwind stack and return from last p_enter if error +INT f_leave(INT err); +Similar to p_leave except that it simply returns err if err>=0. That is, it is equivalent to: + + +GLDEF_C INT f_leave(INT err) +{ +if (err<0) +p_leave(err); +return(err); + + +} + + +Although modest in its function, using f_1eave rather than p_leave produces smaller executables and +makes code more readable. For example, compare: + + +pid=f_leave (p_execc (name, NULL, 0) ); +with: + + +pid=p_execc (name, NULL, 0) ; +if (pid<0) +p_leave (pid); + + +You cannot use £_leave on functions that return an address and fail by returning nui. However, the +more commonly used functions of this type have corresponding f_ variants. For example, p_alloc and +p_realloc have the corresponding £_alloc and £_realloc which internally call + +p_leave (E_GEN_NOMEMoRY) rather than return NULL. + + +Example + + +LOCAL_C INT RunSubProcessWait (TEXT *name) +{ +HANDLE pid; +WORD stat; + + +pid=f_leave (p_execc (name, NULL, 0) ); + +p_logona (pid, &stat) + +p_presume (pid) ; + +p_waitstat (&stat); + +if ((stat>>8) !=E_NORMAL_EXIT) +p_panic(stat); + +return ( (INT) ( (BYTE) (stat&Oxff))); + +} + + +6-13 + + +PLIB REFERENCE + + +LOCAL_C INT CDECL RunTestProgram(TEXT *name) +{ +ret=RunSubProcessWait (name) ; +if (ret) +p_printf ("Program %s failed with reason %d",name,ret); +return (0); + + +} + + +LOCAL_C VOID RunTestPrograms (TEXT *list) +{ +TEXT *p; +INT ret; +TEXT name[32]; + + +p=p_scpy (&name [32], "testx")-1; +while (*p=*list++) + + +{ +ret=p_enter((VOID *)RunTestProgram, &name[0]); + + +if (ret<0) + + +{ +p_atos(é&msg[0],"Failed to run %s",&name[0]); +ret=p_notifyerr (ret, &msg[0], "CONTINUE", "ABANDON", NULL) ; + + +if (ret==2) +p_exit (0); + + +GLDEF_C INT main(VOID) +{ + + +RunTestPrograms ("abcd"); /* runs testa.img, testb.img, ... */ + + +return (0); + + +} + + +Note the use of cbEct in the declaration of RunTestProgram. + + +There are more examples of the use of p_enter and p_leave in the Files chapter. + + +6-14 + + +CHAPTER 7 + + +MEMORY ALLOCATION + + +Overview of system memory usage + + +The EPOC operating system runs on the 8086 processor (and also the 80286, 80386 or 80486) where up +to 1Mb of memory may be addressed. On SIBO machines and depending on the model, all or part of this +address range may be used where the available memory is allocated (from address zero to oxffffFf) as +follows: + + +e 1K bytes of interrupt vectors (required by the 8086 architecture) +e the screen bit-map (small display models) +e the operating system data space + + +e allocated memory segments (including application code segments, process data segments and +device driver segments) + + +e unallocated memory + +e the internal RAM drive (LOC::M:) + +¢ environment variables (up to 4K bytes) + +e any portion of the 1Mb that is not used + +e the screen bit-map (large display models) +e the system ROM (typically 256K bytes) + + +The contents of the internal RAM drive and the environment variables survive a system reset (unless the +ESC key is held down) and most system crashes. See p_get res in the chapter General System Services for +more on system resets. + + +If we consider only that (greater) part of memory that is dynamically allocated, it is organised into four +main sections: + + +Memory segments +Unallocated memory + + +RAM drive (M:) +Environment variables + + +The system maintains all the unallocated memory in a single chunk - between the allocated memory +segments and the memory used by LOC::M:. This means that memory segments have to be moved as a +result of other segments being created, deleted or having their size changed. + + +Although application code segments and process data segments can and do move at any time while an +application process is running, the operating system automatically adjusts the 8086 segment registers +(CS, DS, SS and ES) to follow any movement without explicit support from the application - as discussed +in the first chapter of this manual. + + +7-1 + + +PLIB REFERENCE + + +As well as giving some background on memory usage, this chapter describes functions that allocate and +access: + + +¢ memory cells from the heap in the process data segment (which is a dynamic segment) +e memory segments (either device or dynamic) +¢ environment variables + +Memory segments + +The allocated memory segments contain both device and dynamic memory segments. + + +Device segments are created when an external device is installed and are deleted when the device is +removed. Once created, a device segment does not normally change its size. The first two device segments +are special and are created at system startup for the process data segments of the first two processes to be +created - the null process (SYS$NULL) and the supervisor (SYS$MANG). Neither of these two process +data segments changes size. + + +Dynamic segments are much more volatile. Code and data segments are created and deleted as processes +are created and terminated. Process data segments change their size to accommodate heap allocations. + + +Device segments are allocated with a lower address than the dynamic segments so that they are not +disturbed by any activity with respect to the more volatile dynamic segments. A device driver normally +has to stop working while its segment is moving - which could lead to loss of data (say when receiving +data via the serial port). + + +Allocated memory segments are described by: +e asegment name +e asegment handle +e asegment size +e asegment address + + +Segment names + + +Segment names are zero terminated strings of up to eight characters followed by an optional period and +up to three further characters (the same rules as for file names). Examples of valid names are as follows: + + +NOTES +NUMBERS . DAT +DATASEG.01 + + +As with file names, the segment name extension normally indicates the usage of the segment. The system +has the following conventions: + + +-LDD and .PDD indicate device segments that contain a Logical Device Driver and a Physical +Device Driver respectively. Device drivers are normally written in 8086 +assembler. See the EPOC O/S System Services reference manual for more about +device drivers. + + +$SC indicates the primary shared code segment that is associated with one or more +processes. Running say myprog.img will cause the code to be loaded into a +segment called myprog.$sc (provided that myprog.$sc isn't already loaded). + + +.DYL indicates a dynamic library code segment (DYL) that is associated with one or +more processes. See the chapter Object-Oriented Programming for more about +DYLs. + +$nn indicate process data segments where nn consists of two decimal digits + + +(O1, 02, ...) according to the process number. + + +The name of a process data segment is normally the same as the process name although they are in fact +independently held (the process name can be changed using p_prename). The process data segment is +described further below. + + +7-2 + + +7 MEMORY ALLOCATION + + +Segment handle, address and size + + +The segment handle is actually the relative address of the segment table index entry in the operating +system data space. This 16-byte entry contains the address of the segment, the segment usage count and +the segment name. + + +The usage count normally indicates the number of processes that are using the segment - for example, +when there are 2 processes of the same application, the usage count of the application code segment is 2 +whereas the usage count of each process data segment is 1. When the usage count drops to zero, the +memory segment may be (and normally is) deleted. + + +The order of the segments follows the order of the segment table index entries and the segment size is +calculated by subtracting the start addresses of adjacent segments. + + +The segment index table has a fixed total capacity with fixed sub-capacities for device and dynamic +segments (typical limits are 96 total segments as 32 device segments and 64 dynamic segments). A +segment allocation will fail if one of these limits is reached (which is unlikely unless there is a bugged +application that fails to free segments). + + +Although the allocated segments themselves are contiguous, the segment index table may have "holes" in +it as a result of segment deletion. When a new segment is allocated, it will tend to fill any holes in the +index table first and, in this case, the created segment will be inserted before other segments causing them +to be moved. + + +The address and size of memory segments is expressed in 16-byte paragraphs (as used in setting the value +of the 8086 segment registers CS, DS, ES and SS). It follows that segments start on 16-byte boundaries +and are a multiple of 16 bytes long. From the point of view of the segment allocator, the maximum +segment size is 512K which makes it possible to specify a segment size (in 16-byte paragraphs) within a +signed 16-bit word. + + +Process data segments + + +When a process is created (normally by loading an image using p_execc Of p_execcasync), a process data +segment is also created. When that process is running application code, the 8086 DS, SS and ES registers +point to the start of the data segment which can not be greater than oxffe0! bytes long (this is called the +small model on PCs). + + +The data segment contains (from low to high address): + +e the reserved static variables (0x40 bytes) + +e the floating point emulator data space (0x200 bytes from offset 0x100) +e the processor stack + +e initialised static variables + +e uninitialised static variables + +e the process heap + + +The size of the processor stack depends upon the C startup module that is being used but is typically in the +range 2K to 8K. Note that the stack size declared by the startup module includes the 64 bytes of reserved +static variables and the floating point emulator data space. + + +The word at address zero is initialised to oxpEap and is otherwise unused. If it is not oxpzap, it is probably +because of a write using an uninitialised pointer that happened to have a zero in it. + + +In the absence of any further initialisation (such as the oxpEap above), the reserved statics variables are +initialised to zero. + + +The bytes in the stack area are initialised to oxe£. The number of oxf bytes from address 0x40 in the +process data segment measures the number of spare bytes on the stack provided the program is not using +the floating point emulator. If the program is using the floating point emulator, the lowest point the stack +should legitimately reach is 0x300. + + +!The segment size is limited to 32 bytes less than the maximum 64K so that a stack underflow will always +cause an address trap. + + +PLIB REFERENCE + + +Despite their name, the uninitialised static variables are all initialised to zero. + + +The process heap contains dynamic data structures that are created and destroyed within the lifetime of +the process. The heap is placed at the end of the process data segment so that it can be expanded by +expanding the process data segment. Since the data segment is limited to 0xffe0 bytes, the maximum +heap size is somewhat smaller than 64K, depending on the size of the stack and the space taken by the +static variables. The process heap and the allocator are described in detail next + + +The heap allocator + + +The allocator is used to allocate, resize and free variable length memory cells (which typically range from +10s of bytes to a few kilobytes in length) from the process heap. Allocated cells are referenced directly by +their address; they do not move to compact free space left by freed cells. + + +The allocator functions are: + +p_alloc, f_alloc allocates a cell, returning its address. + +p_free frees a cell, which is returned to the heap. + +p_realloc, f_realloc changes the size of the cell, returning its new address. + + +p_adjust opens or closes a gap in the middle of the cell (useful for deletion and insertion +of cell content), changing the size of the cell as appropriate. + + +p_alen returns the size of the cell. + +p_hgran sets the heap granularity. + +p_allwalk walks all cells in the heap calling a supplied function (used for heap diagnosis). +p_allchk uses p_allwalk to check the integrity of the heap. + +p_allspe gets the start address and free space in the heap. + + +The functions f_alloc and f_realloc are identical to p_alloc and p_realloc respectively except that +they call p_leave (E_GEN_NOMEMoRY) if the memory could not be found rather than returning a NULL +address. See the function p_leave for more details. + + +The allocator functions are used internally by many other PLIB functions. + + +Heap structure + + +After a number of allocate and free calls the heap typically consists of ranges of adjacent allocated cells +separated by single free cells (which are linked). Each cell (whether free or allocated) is prefixed by a +hidden 16-bit word that gives the size of the cell in bytes. This leading length word is hidden since the +address returned by p_alloc, p_realloc and p_adjust skips this header and the length returned by +p_alen does not include it. + + +Writing beyond a cell's limits will corrupt a cell length word (and possibly also a free space cell pointer) +which destroys the heap's integrity. Such errors are difficult to debug because there is no immediate effect +- the corruption is a "time bomb". It will eventually be detected (resulting in a call to p_panic) bya +subsequent allocator call (such as p_free). The p_alichk function is provided as a debugging tool to force +a call to p_panic sooner rather than later when it is suspected that the heap's integrity has been damaged. + + +Growing and shrinking the heap + + +In EPOC, a process heap is not fixed in size - the system can grow and shrink the heap (and the process +data segment that contains it). The heap is grown to satisfy allocation requests that would otherwise fail, +up to the 0xffe0 process data segment limit. The heap may be shrunk to release memory to the system +when it is required. When the heap is grown, it is normally grown by 2K bytes more than is strictly +needed to satisfy the request - see p_hgran for more details. When an application is executed to create a +process, the initial size of the heap is taken from a value that is stored in the executable (by default, 2K +bytes). This same value also specifies the minimum size of the heap. + + +Allocation is based on "walking" the free space list to find a free cell that is big enough to satisfy the +request (using the "first fit" algorithm). If no free cell is big enough, the system will attempt to grow the +data segment to add more free space at the end of the heap. + + +7 MEMORY ALLOCATION + + +If there is no memory in the system to accommodate growth or if the data segment has reached its +maximum oxffeo byte value, the allocate request fails. There are few circumstances when an allocate +request can be assumed to succeed and calls to p_alloc, p_realloc and p_adjust should have recovery +code to handle a failure to allocate. + + +From the point of view of the user of an application, the two causes of an allocation failure produce quite +different situations. If there is no memory left in the system, this can normally be remedied by the user +taking some action to release memory (such as exiting a task). If the 64K limit has been reached, this is +presumably as a result of a heap-based data structure reaching its design limit (rather than a bug as in, for +example, "alloc heaven", described below). + + +Applications that contain indefinitely growing heap-based data structures (as in, say, a spreadsheet) +should not allow the data structure to grow until the allocation fails when the oxffe0 data segment limit is +reached because, at this limit, there may not be sufficient memory in the free space list to perform other +tasks (such as saving the data to file!). The growth of such data structures should be monitored by the +application and limited to leave sufficient heap capacity for tasks that the user would reasonably expect to +be able to perform. + + +The segment allocator can reclaim excess space from a heap if the last cell in the heap is a free cell, +reducing the size of the last free cell to a small value. However, the heap is never shrunk below its initial +size (as specified by the value in the executable). + + +Alloc heaven + + +There are cases in which programs allocate a sequence of cells which must either exist as a whole or not +at all. If during the allocate sequence one of the later allocations fail, the previously allocated cells must be +freed. If this is not done, the heap will contain unreferenced cells that consume memory to no purpose. At +Psion we say that these cells have gone to "alloc heaven". + + +When designing how to physically organise data structures into alloc cells you should be mindful of the +recovery code that must be written to free partially built multi-cell structures. The fewer the cells in a +structure, the easier the recovery code. + + +Internal fragmentation + + +The free space in a heap is normally fragmented where the largest cell that may be allocated is +substantially smaller than the total free space. Excessive fragmentation, where the free space is +distributed over a large number of cells (and where by implication many of the free cells are small) +should be avoided because it results in an inefficient use of memory and reduces the speed with which +cells are allocated and freed. Practical design hints for limiting internal fragmentation are: + + +e Avoid using the heap for small highly transient data structures that can be placed on the stack (as +an automatic). High frequency cycling through allocate and free pairs "churns" the heap and +leads to a long free space list. + + +e When you have a large number of variable length data structures (particularly when they are +frequently resized), "granularise" them (i.e. round the allocate up to a multiple of some +reasonable value) so that you decrease the chance of leaving small unusable free space cells. + + +e Use heap analysis tools to give you a feel for what is going on. You may find that by changing +the way you do something you get a better heap and you may even discover some alloc heaven. +Don't go too far - there are diminishing returns to heap usage tuning. + + +p_alloc (or f_alloc) Allocate a memory cell + + +VOID *p_alloc(UINT size); +VOID *f_alloc(UINT size); + + +Allocate a memory cell of at least size bytes long from the heap and return the address of the allocated +cell or nuut if there is insufficient memory. + + +You should always test the result for nuLL and take recovery action. The size actually allocated may be a +few bytes more than that requested (see p_alen). The maximum size is 64K minus the combined size of +the machine stack and the space taken by static variables. + + +2Unfortunately, the system does not distinguish between the two causes of allocation failure. + + +7-5 + + +PLIB REFERENCE + + +If the heap is corrupt, calling p_alloc may or may not detect it - but if it does it will call p_panic. Use +p_allchk to check the integrity of the heap thoroughly. + + +The function £_alloc is identical except that it calls p_leave (E_GEN_NOMEMORY) rather than return NULL. + + +Example + + +GLDEF_C TEXT *AllocString(TEXT *str) +/* +Allocate and copy in a zero terminated string. +a7 +{ +TEXT *p; + + +if (p=p_alloc(p_slen(str)+1) ) +p_scpy(p,str); /* Copy in the string */ +return (p); + + +} + + +This example assumes that any more specific error recovery is handled by the caller. + + +p_free Free an allocated cell +VOID p_free(VOID *pcell); + + +Free the allocated memory cell at address pce11, returning the cell to the free memory list. Does nothing if +pcell is zero - this is sometimes useful in error clean-up situations. + + +If pcell is non-zero, it should contain the address of a cell as returned by, for example, p_alloc. Passing a +value that is not the address of an allocated cell (eg by freeing a cell twice) will corrupt the heap. There is +a chance that p_free will detect a bad address and call p_panic. + + +p_realloc (or f_realloc) Change cell size + + +VOID *p_realloc(VOID *pcell, UINT size); +VOID *f_realloc(VOID *pcell, UINT size); + + +Change the size of the allocated cell pce11 to be size bytes and return the address of the new cell or NuLL +if there was insufficient space for the size change. + + +If nuxt is returned, the original cell is unaffected. The limits on size are as for p_alloc. Calling +p_realloc(pcell,size) when pcell is zero is equivalent to calling p_alloc(size) - this can be useful in +start up situations. + + +The cell retains its original content which is truncated if the cell size is reduced. The cell start address +does not change when the cell size is reduced or stays the same. If the cell size is increased, p_realloc +will use any trailing free space of sufficient size but, more likely, it will allocate a new cell, copy the data +across and free the old cell where, in this case, the returned address is different from pce1l. If pcell is +neither zero nor the address of an allocated cell, the heap will either be corrupted or p_panic will be +called. + + +The function £_realloc is identical except that it calls p_leave (E_GEN_NOMEMoRY) rather than return +NULL. + + +p_adjust Insert or delete data in cell +VOID *p_adjust (VOID *pcell, UINT offset, INT amount); + + +Open or close a gap at offset offset within the allocated cell pce1l, using p_realloc to make the +appropriate change to the cell size. As for p_realloc, p_adjust returns the address of the new cell or +NULL if there was insufficient memory. If amount is positive, a gap of amount bytes is opened. If amount is +negative -amount bytes are deleted. If amount is zero, the function has no effect and returns pcell. + + +Unlike p_realloc, pcell may not be passed as NULL. If pce11 is not the address of an existing allocated +cell, the heap will either be corrupted or p_panic will be called. + + +If amount is negative, -amount bytes is deleted by shifting the trailing contents left, closing the gap. + + +7 MEMORY ALLOCATION + + +old cell XXXXXXXXXXKZZZZZZZZZZYYYVYVYYVYYVYY +< offset >< amount > + + +new cell XXXXXXXXXXYYVYVVVVVVVVYYVY +< old size - amount > + + +The cell size is decreased by the same amount. There is no data deletion if the offset is greater than or +equal to the original cell size. The minimum cell size actually allocated is as for p_alloc. If the new size +would be negative, p_panic is called. + + +If amount is positive, the cell size is increased and a gap is then inserted starting from the specified offset +by shifting the trailing contents right. + + +old cell XXXXXXXXXXYYYYVVVVVYVYVYYVY +< offset >< amount > + + +new cell XXXXXXXXXXKZZZZZZZZZZYVYYVVYVYYVYY +< old size + amount > + + +If offset is greater than or equal to the original cell size, no shifting takes place. + + +A typical use is to insert or delete a record (which may be of fixed or variable length) in a contiguous +sequence of records contained in an alloc cell. + + +p_alen Get cell length +UINT p_alen(VOID *pcell); +Return the length in bytes of the allocated cell pceil. + + +The returned cell length will be equal to or slightly larger than that requested using p_alloc Of p_realloc +because (1) sizes are rounded up to an even size, (2) there is a minimum cell size and (3) the allocation +can't leave a trailing free space cell below the minimum size. + + +If the passed address is not the address of a cell, there is a chance that p_alen will detect it and call + + +p_panic. + + +p_hgran Set heap granularity + + +VOID p_hgran(UINT nparas); +Set the heap granularity to nparas (measured in paragraphs where a paragraph is 16 bytes). + + +The maximum value for nparas i$ E_MAXx_GROWByY (16K bytes) - p_hgran calls p_panic if this is violated. +Processes are created with heap granularity =_GRowBy_DEFAULT (2K bytes). z_max_GRrowBy and +E_GROWBY_DEFAULT are defined in epoc.h. + + +The heap granularity controls the increment by which the heap grows to satisfy an allocation request that +cannot be met from the existing free space list. The granularity is added to the amount that is just +sufficient to satisfy the request. Growing the heap can be computationally expensive because many other +segments may have to be shifted by the growth of the process data segment. Applications that can rapidly +create large data structures (such as when loading a large file in the text processor) can improve their +performance by setting a larger heap granularity. Setting the heap granularity has no affect on the way the +system shrinks the heap to release memory. + + +p_allwalk Visit all cells + + +VOID p_allwalk(VOID (*fptr) (VOID *fpar,INT isalloc,UINT len), VOID *fpar); + + +Walk through every cell in the heap (whether allocated or free) in sequence from low to high address and, +if fptr is not nut, call fptr for each cell. The heap is checked for consistency and p_panic is called if an +inconsistency (for example an overlap between a free cell and an allocated cell) is detected. + + +In the call to fptr, the parameter isalloc 1s TRUE if the cell is an allocated cell and ratss if it is a free +cell. The parameter 1en is the total length of the cell in bytes (1en includes the size of cell header +information and is 2 greater than that returned by p_alen). + + +7-7 + + +PLIB REFERENCE + + +Cell addresses can be calculated from the cell lengths and the heap start address. The heap start address +may be found by calling p_allspce. + + +This function is provided for heap diagnosis and is called, for example, by p_allchk. +In the following example, NumallocCel1s returns the number of cells allocated: + + +LOCAL_C VOID CountIfAlloc(UINT *pn, INT isalloc,UINT len) +{ +if (isalloc) +*pnt=1; +} + + +GLDEF_C UINT NumAllocCells () + + +‘i +UINT n; + + +n=0; +p_allwalk((VOID (*) (VOID *,INT,UINT) )CountIfAlloc, &n); +return (n); + + +} + + +The call to p_allwalk calls back count If£A1lloc (which simply increments the allocated cell count if the +cell is an allocated cell) for each cell in the heap. + + +p_allchk Check heap integrity +VOID p_allchk (INT num); + + +Walk through all the allocated cells checking for consistency with the free space list. Call p_panic (0xff) +if there is something wrong. + + +Used as a debugging aid to detect errors from freeing a cell twice or overwriting the boundaries of an +allocated cell. Otherwise, such errors can remain undetected for some time. + + +If it does discover something wrong, and before calling p_panic, it writes 3 words of diagnostic +information to reserved statics, as follows: + + +DatApp1 (0x28) a reason code, described below +DatApp2 (0x2a) the address at which the corruption was discovered +DatApp3 (0x2c) the passed parameter nun, to enable identification of the offending call + + +The reason code is one of: + + +5 a free cell pointer was probably overwritten +6 a cell length is too small or odd (possibly because it was overwritten) +7 an allocated cell length is too large (possibly because it was overwritten) + + +This information is only useful in conjunction with a debugging tool that allows the process data segment +to be examined after a call to p_panic. + + +p_allspc Get heap address and potential free space +UINT p_allspc(VOID **pheap) ; +Return the potential free space in the heap in bytes and writes the start address of the heap to *pheap. + + +The potential free space is calculated as the sum of the free cells in a process data segment that has been +expanded to its full size of 0x££e0 bytes. In practice, the amount that can be allocated will certainly be less +than this and depends upon how fragmented the heap is and on the amount of free memory in the system. +This function should not be used to predict a successful allocation but it can be used to predict an +unsuccessful one. + + +The heap start address *pheap can be used to turn the cell lengths produced by p_allwa1k into addresses. + + +7-8 + + +7 MEMORY ALLOCATION + + +a aa +System memory usage + + +p_getram Get addressable system RAM size +UINT p_getram(VOID); +Return the size of the addressable system RAM in paragraph (16 byte) units. + + +Since the memory in machines containing more than 512 kilobytes of RAM is bank-switched, this +function will never return a value larger than 32768 (corresponding to 512 kilobytes of RAM). + + +p_totalK Get total system RAM size + + +UINT p_totalK (VOID); +This function is only available in EPOC version 3.50 or later. +Return the total amount of memory in the machine in kilobytes. + + +This function reports the total amount of RAM present in the machine, irrespective of bank-switching. +Thus, on a machine containing 1 megabyte of RAM, a call to p_totaix will return the value 1024, +whereas a call to p_getram on the same machine will return 32768 (corresponding to 512 kilobytes). + + +p_sgfree Get size of available segmented memory + + +UINT p_sgfree(VOID); + + +Returns the amount of available (i.e. currently unused) addressable segmented memory in paragraph (16 +byte) units. + +Since the memory in machines containing more than 512 kilobytes of RAM is bank-switched, this +function will never return a value larger than 32768 (corresponding to 512 kilobytes of RAM). + + +The value returned should be treated with some caution as the amount of available memory in a multi- +tasking environment is a dynamic function of the memory requests of all the currently running processes. + + +p_sgramdisk Get memory used by internal RAM disk + + +UINT p_sgramdisk (VOID) ; + + +-Returns the number of 16-byte paragraphs in the addressable RAM that are currently used by the internal +RAM disk (LOC::M:). + + +On machines containing more than 512 kilobytes of RAM, the RAM disk will be created in an upper +bank. In this case, unless the RAM disk overflows into the addressable RAM, p_sgramdisk will generally +return zero. + + +On machines containing not more than 512 kilobytes of RAM, the return value will be larger than that +obtained from p_dinfo, which measures storage capacity rather than the total number of bytes used. + + +EE +Memory segments + + +Applications that need more memory to store data, can allocate one or more external memory segments. +Each segment can be up to 512K bytes long, subject to the availability of free system memory. + + +The most common use of the functions described in this section is to implement a potentially large data +structure without being constrained by the 64K (or less) limit of the heap. To create and access a data +structure in an external data segment, you would use: + + +p_sgcreate to create an external data segment of a specified initial size + +p_sgcopyto to write to the external segment + +p_sgcopyfr to read from the external segment + +p_sgadjust to adjust the size of the data segment (say to increase its size to accommodate + + +additional content) + + +p_sgdelete to delete the data segment after it is no longer required + + +7-9 + + +PLIB REFERENCE + + +Memory segments can be used to implement a data structure that is accessed by more than one process. +For example, a "pipe" in which one process creates a data segment and writes to it and where a second +process reads from it. In this case, the second process would use: + + +p_sgfind to locate the pipe by its memory segment name +p_sgopen to open the segment + +p_sgcopyfr to read from the segment + +p_sgclose after finishing with the segment + + +You would need to use an associated semaphore to synchronise access to the segment (as described in the +chapter Asynchronous Requests and Semaphores). + + +If a memory segment is locked by a process calling p_sglock, the segment will survive the demise of the +creating process + + +p_sgcreate Create memory segment +HANDLE p_sgcreate(TEXT *pName, INT nParas, INT uMode) ; + + +Creates a memory segment with the zero terminated name pName and size nParas (in 16-byte paragraphs) +and, if successful, return the positive handle to the created segment. Otherwise, it returns one of the +following negative error numbers: + + +E_GEN_NOMEMORY Not enough memory to satisfy the request +E_GEN_NOSEGMENTS No memory segment handles are available +E_FILE_EXIST A memory segment of the requested name already exists +E_FILE_NAME The requested name is invalid + + +The memory segment created is not initialized in any way and will contain random data. The returned +handle allows access to the contents of the segment using p_sgcopyto and p_sgcopyfr. + + +After being created, the memory segment is automatically opened and given a usage count of 1. It should +be closed when no longer required by calling p_sgclose. + + +When a process terminates, any open memory segment is automatically closed, decrementing the segment +usage count. If the access count become zero or negative, the segment is deleted. + + +The initial size nParas (in 16-byte paragraphs) must be positive (so the maximum segment size is 512K + + +bytes). +The parameter uMode should be one of the following: +E_SEGMENT_HIGH to create a dynamic memory segment. + + +E_SEGMENT_LOW is provided for future expansion and currently has the same effect as +E_SEGMENT_HIGH. + + +E_SEGMENT_DEVICE to create a device segment. This will result in all devices being held while +memory is moved and then resumed. All dynamic segments will be moved up +in memory to make room. This service is called, for example, by the File Server +when loading external device drivers and should not be used by applications. + + +E_SEGMENT_LOCKED is the same as E_SEGMENT_HIGH except that no process owns the created +segment. Like E_SEGMENT_DEVICE this mode is used internally by the operating +system and should not be used by applications. + + +The function calls p_panic if the requested size was negative or if uMode was not one of E_SEGMENT_LOW, +E_SEGMENT_HIGH, E_SEGMENT_DEVICE Or E_SEGMENT_LOCKED. + + +7-10 + + +7 MEMORY ALLOCATION + + +p_sgdelete Delete memory segment + + +INT p_sgdelete (TEXT *pName) ; + + +Delete the memory segment identified by the zero terminated name pName. Returns zero if successful or +one of the following negative error numbers: + + +E_GEN_INUSE the segment usage count is greater than zero (eg because it is opened by another +process) + +E_FILE_NXIST the memory segment does not exist + +E_FILE_NAME the memory segment name is invalid + +p_sgopen Open memory segment + + +HANDLE p_sgopen(TEXT *pName) ; + + +Open the memory segment identified by the zero terminated name pName and, if successful, return the +handle to the opened memory segment. Otherwise, it returns one of the following error numbers: + + +E_FILE_NXIST the memory segment does not exist +E_GEN_OPEN the memory segment is already open to this process +E_FILE_NAME the memory segment name is invalid + + +The returned handle allows access to the contents of the segment using p_sgcpto and p_sgepfr. +Opening a segment increments the segment usage count. + + +When a process terminates, any open memory segment is automatically closed, decrementing the segment +usage count. If the access count becomes zero or negative, the segment is deleted. + + +There is no limit on the number of memory segments that may be opened by a process. + + +p_sgcopyto Copy to memory segment + + +INT p_sgcopyto(HANDLE nHandle, LONG pos, VOID *source, UINT len); + + +Copy len bytes from source in the current process data segment to offset pos in the open memory +segment nHandle (as returned from p_sgcreate OF p_sgopen). + + +The system ensures that the copy is not interrupted by another process. Address trapping is automatically +switched off for the duration of the copy. + + +The return value has no significance. + + +The function calls p_ panic if pos+ien is greater than the size of the memory segment or if nHandle is not +a valid memory segment handle. + + +A program can check that the segment is still in existence before a call to p_sgcopyto by calling +p_sgopen. + + +If you want to write to a process data segment, it is more convenient to use p_pcpyto, which takes a +process ID rather than a segment handle. + + +p_sgcopyfr Copy from a memory segment + + +INT p_sgcopyfr(HANDLE nHandle, LONG pos, VOID *target, UINT len); + + +Copy len bytes from offset pos in the open memory segment nHandle (as returned from p_sgcreate or +p_sgopen) tO target in the current process data segment. + + +The system ensures that the copy is not interrupted by another process. +The return value has no significance. +The function calls p_panic if pos+1en is greater than the size of the memory segment or if nHandle is not + + +a valid memory segment handle. + + +7-11 + + +PLIB REFERENCE + + +A program can check that the segment is still in existence before a call to p_sgcopyfr by calling +p_sgopen. + + +If you want to copy from a process data segment, it is more convenient to use p_pcpyfr, which takes a +process ID rather than a segment handle. + + +p_sgsize Get size of memory segment + + +UINT p_sgsize (HANDLE nHandle) ; + + +Returns the size (in 16-byte paragraphs) of the open memory segment nHandle (as returned from +p_sgcreate Or p_sgopen). + + +The function calls p_panic if nHandle is not a valid memory segment handle. + + +p_sgadjust Adjust the size of a memory segment + + +INT p_sgadjust (HANDLE nHandle, INT nParas); + + +Adjust the size of the open memory segment nHandle (as returned from p_sgcreate or p_sgopen) to +nParas 16-byte paragraphs. Return zero if successful or the negative E_GEN_NomEmory if there is not +enough memory to satisfy the request. + + +The new segment size nParas must be positive (it follows that the maximum segment size is 512K bytes). +Setting nParas to zero discards all the memory allocated to the memory segment but does not delete the +segment. + + +The function calls p_panic if nParas is negative or if nHandle is not a valid memory segment handle. + + +p_sgfind Find segments by name + + +HANDLE p_sgfind(HANDLE fHandle, TEXT *pMatch, TEXT *pName) ; + + +Write the next segment name that matches the zero terminated match string pMatch as a zero terminated +string to pName where fHandle is NULL for the first call and is subsequently the positive return value from +the previous call. When there are no further segments matching pMatch, it returns E_FILE_NXIST. + + +Used repeatedly to find all the segments that match the wild card string pointed to by pMat ch. The buffer +at pName should be big enough to receive E_MAX_NAME+2 bytes. The wild card string pMatch should remain +the same between successive calls. + + +No memory is used by this service and it can be abandoned at any time without taking any further action. +The function calls p_panic if fHandle is not a valid memory segment handle. +Example + + +GLDEF_C VOID ListCodeSegments (VOID) + + +{ +HANDLE fH; +TEXT buf [ + + +E_MAX_NAME+2]; + + +£H=NULL; +while ((fH=p_sgfind(fH,"*.$SC", &buf[0]))>0) +p_puts (&buf[0]); + + +p_sgclose Close memory segment + + +INT p_sgclose (HANDLE nHandle); + + +Close the open memory segment nHandle (as returned from p_sgcreate or p_sgopen) decrementing the +usage count. + + +Returns zero if successful or the negative E_GEN_NOTOPEN if the memory segment is not open to this +process. + + +Should the access count become zero or negative, the segment is deleted. + + +The function calls p_panic if nHandle is not a valid memory segment handle. + + +7-12 + + +7 MEMORY ALLOCATION + + +p_sglock Increment segment usage count + + +VOID p_sglock (HANDLE nHandle); + + +Lock the open memory segment nHand1le (as returned from p_sgcreate Of p_sgopen) by incrementing the +segment usage count. + + +If p_sglock is called after creating a segment, the segment will not be deleted when the process +terminates. + + +The function calls p_panic if nHandle is not a valid memory segment handle. + + +p_sgunlock Decrement segment usage count + + +VOID p_sgunlock (HANDLE nHandle) ; + + +Unlock the open memory segment nHandle (as returned from p_sgcreate Of p_sgopen) by decrementing +the segment usage count. + + +There is no harm in unlocking a segment that is already unlocked, although if this done inadvertently the +segment could be deleted by another process. + + +The function calls p_panic if nHandle is not a valid memory segment handle. + + +Environment variables + + +The system allocates up to 4K bytes for environment variables at the high address end of the system RAM. +Environment variables are a scarce resource and should be used sparingly. + + +An environment variable consists of: +a name of up to —_MAx_ENv_s1zkE (16) bytes containing any byte except '*' or '2! +a value of up to P_ENvmax-1 (256) bytes with no restriction on the content + + +Each environment variable is stored as two successive leading byte count strings (see the example in the +description of p_findenviron, below). + + +If you are dealing with environment variables where both the names and the values are character strings +you can use: + + +p_getenv to get the value of an environment variable + +p_setenv to replace the value of an existing environment variable or to create one if +necessary + +p_delenv to delete an environment variable + +p_fndenv to get a list of environment variables and their values + + +A more general but less convenient set of environment variable functions (which can be used, for +example, when the values are binary) are: + + +p_getenviron to get the value of an environment variable + +p_setenviron to replace the value of an existing environment variable or to create one if +necessary + +p_delenviron to delete an environment variable + +p_findenviron to get a list of environment variables and their values + + +7-13 + + +PLIB REFERENCE + + +p_getenv Get environment variable value + + +INT p_getenv(TEXT *pMatch, TEXT *pValue) ; + + +Copy the value of the environment variable that matches the zero terminated name pMatch to pValue and +add a zero terminator to the end of the copied value. The name pMatch may include the wild card +characters '?' and '*' in which case the value of the first matching name is copied. + + +Returns zero if successful or the negative E_FILE_NxIst if no matching environment variable exists. + + +The maximum length of an environment variable value is P_ENvMax-1 bytes so up to P_ENvmax bytes can +be written to pvalue (including the zero terminator). + + +p_getenviron Get environment variable value + + +INT p_getenviron(TEXT *pMatch, INT mLength, VOID *pValue); + + +Copy the value of the environment variable that matches the name pMatch of length mLength to pvalue +and return the number of bytes copied. + + +Return the negative E_FILE_Nx1st if no matching environment variable exists. + + +The name pMatch may include the wild card characters '?' and '*' in which case the value of the first +matching name is copied. + + +The maximum length of an environment variable value is P_ENvmMax-1 bytes. + + +p_setenv Set environment variable value + + +INT p_setenv (TEXT *pName, TEXT *pValue) ; + + +Copy the content of the zero terminated string pvalue (excluding the terminating zero) into the value of +the environment variable with the zero terminated name pName, replacing any previous value. If the +environment variable does not exist it is created with the specified name and value. + + +The name pName may not include wild cards and must not exceed E_MAX_ENV_s12E in length. The length +of pValue should not exceed P_ENvmax-1 (255) - any non-zero value in the high byte of the length of +pValue is ignored. + + +Returns zero if successful or one of the following negative error numbers: + + +E_GEN_NOMEMORY the system was unable to allocate room to store the environment variable and +its value either because there is not enough free system memory or because of +the 4K limit on the environment variable space + + +E_GEN_FAIL if pName contains a wild card character +The function calls p_panic if the length of pName exceeds E_MAX_ENV_SIZE. + + +Note that you can't delete an environment variable by giving it a null value - use either p_delenv or + + +p_delenviron. + + +p_setenviron Set environment variable value + + +INT p_setenviron(TEXT *pName, INT nLength, VOID *pValue, INT vLength) ; + + +Copy vLength bytes from pvalue into the value of the environment variable with name pName of length +nLength, replacing any previous value. If the environment variable does not exist it is created with the +specified name and value. + + +The name pName may not include wild cards, nuength must not exceed E_MAX_ENV_SIZE and vLength +should not exceed P_ENvMax-1 (255) - any non-zero value in the high byte of vLength is ignored. + + +Returns zero if successful or one of the following negative error numbers: + + +E_GEN_NOMEMORY the system was unable to allocate room to store the environment variable and +its value either because there is not enough free system memory or because of +the 4K limit on the environment variable space + + +E_GEN_FAIL if pName contains a wild card character + + +The function calls p_panic if nLength exceeds E_MAX_ENV_SIZE. + + +7-14 + + +7 MEMORY ALLOCATION + + +p_delenv Delete environment variable + + +INT p_delenv (TEXT *pMatch) ; + + +Delete the environment variable that matches the zero terminated name pMatch. The name pMatch may +include the wild card characters '?' and '*' in which case the first matching environment variable is +deleted. + + +Returns zero if successful or the negative =_rF1LE_nxist if no matching environment variable exists. + + +p_delenviron Delete environment variable + + +INT p_delenviron(TEXT *pMatch, INT mLength) ; + + +Delete the environment variable that matches name pmatch of length mLength. The name pMatch may +include the wild card characters '?' and '*' in which case the first matching environment variable is +deleted. + + +Returns zero if successful or the negative —_FILE_nxist if no matching environment variable exists. + + +p_fndenv Find environment variables + + +INT p_fndenv (TEXT *pMatch, TEXT *pName, TEXT *pValue, HANDLE *pHandle); + + +Called repeatedly to find the name and value of all environment variables that match the zero terminated +wild card name pMatch. + + +On the first call *pHandie should contain zero and subsequent calls pass the value that is written by the +previous call. The function returns zero if a matching environment variable was found or the negative +E_FILE_EOF when there are no more matching names. The wild card match string pMatch should remain +the same on successive calls. + + +Each successful call writes the name as a zero terminated string to pName (which should have room for +E_MAX_ENV_S1ZE+1 bytes) and its value followed by a zero terminator to pvalue (which should have room +for p_ENvMax bytes). + + +A wild card name of "*" will match all the environment variables. + + +p_findenviron Find environment variables + + +INT p_findenviron(TEXT *pMatch, INT mLength, UBYTE *pBuf, HANDLE *pHandle); + + +Called repeatedly to find the name and value of all environment variables that match the wild card name +pMatch of length mLength. + + +On the first call *pHandie should contain zero and subsequent calls pass the value that is written by the +previous call. The function returns zero if a matching environment variable was found or the negative +E_FILE_EOF when there are no more matching names. The wild card match string should remain the same +on successive calls. + + +Each successful call writes the name and value to pBuf as two successive leading byte count strings giving +the environment variable name followed by its value. The maximum length of an environment variable +name is E_MAX_ENV_s1zeE and the maximum length of a value is p_ENvmax-1 bytes so pBuf should have +room for E_MAX_ENV_SIZE+P_ENVMAXx+1 bytes. + + +A wild card name of "*" will match all the environment variables. + + +7-15 + + +PLIB REFERENCE + + +In the following example, PrintaAllEnv prints the name and (potentially binary) value of all the + + +environment variables: + + +LOCAL_C VOID PrintData(TEXT *p,UINT len) + + +{ +UBYTE *pe; + + +p_print ("sd [",len); + +for (pe=ptlen;p", *p) ; + + +GLDEF_C VOID PrintAllEnv (VOID) +{ +UBYTE *p; + + +HANDLE h; +UBYTE b[E_MAX_ENV_SIZE+P_ENVMAX+1]; + + +for (h=0;p_findenviron("*",1,&b[0],&h) >=0;) + + +{ +p=é&b[0]; +PrintData(pt1,*p); /* print name */ + + +pt=*pt+1; +PrintData(pt+l,*p); /* print value */ + + +} + + +7-16 + + +CHAPTER 8 + + +ASYNCHRONOUS REQUESTS AND SEMAPHORES + + +This chapter describes asynchronous requests, semaphores, the I/O semaphore and wait handlers. + + +Semaphores + + +Semaphores are provided to synchronise cooperating processes (where, in this context, a process includes +a hardware interrupt). There are three common uses: + + +e Synchronising access to a shared resource +e —Synchronising supplier-consumer relationships +e Synchronising the completion of asynchronous requests + + +The first two are described briefly in this section. The third use is far more important and is discussed +more extensively in the following section. + + +The semaphores in EPOC are counting semaphores, having a signed value that is incremented by calling +p_signal and decremented by calling p_wait. A semaphore with a negative value implies that a process +must wait for the completion of some other event, such as the freeing of a shared resource. + + +The mechanism by which a process waits on a semaphore is part of the overall management of process +scheduling. + + +Process scheduling +In EPOC, if a process is not the currently running process, it is either suspended or in a queue. + + +A process remains suspended until it is resumed by another process (typically its creator) by that process +calling p_presume. + + +If a process is not suspended, it is in one of the following three types of queues: + + +The ready queue The ready queue contains processes ordered by process priority. On a +reschedule, the process at the high priority end of the ready queue runs. If there +is more than one ready process at the highest priority, they take it in turns to +run every 4 system ticks. + + +The time delta queue There is a single (possibly empty) time delta queue, effectively containing both +processes and timer device entries. The processes are waiting for a relative or +an absolute time as a result of calling p_sleep, p_sleept or p_sleepa. The +timer device entries are associated with processes that have requested an +asynchronous timer. The head of the queue has its delta time decremented +every system tick and is removed when it reaches zero or negative. If it is a +process, it is inserted into the ready queue. If it is a timer device entry, the +associated process I/O semaphore is signalled. + + +The semaphore queues _ There is a (possibly empty) queue of processes for each created semaphore in +the system. If, on calling p_wait, the decremented semaphore is negative, the +calling process is placed at the end of the appropriate semaphore queue. When +that semaphore is subsequently incremented by a call to p_signal, the process +at the head of the semaphore queue is either made current (if it has the highest +priority) or it is inserted into the ready queue (after any processes of equal +priority). + + +8-1 + + +PLIB REFERENCE + + +See also the description of Preemptive scheduling in the chapter Processes and Inter-process Messaging. +Shared access + + +A mutual exclusion semaphore may be used to serialise access to a shared resource (for example, a shared +memory segment). + + +The creator of the shared resource uses p_semcrt to create an associated mutual exclusion semaphore with +an initial value of one. Any process wishing to access the resource first calls p_wait on the resource +semaphore and then calls p_signa1 after completing its access. Because the semaphore was created with +an initial value of one, the first process to call p_wait will return immediately but any other processes that +call p_wait will wait in the semaphore queue. Waiting processes are released on a first-in first-out basis +when the process currently accessing the resource calls p_signal. + + +The nature of the shared resource should be such that any access completes in a relatively short time so +that processes do not wait for extended periods on the mutual exclusion semaphore. Another consideration +is that whereas the resource may survive the demise of its creating process, semaphores are automatically +deleted when the creating process terminates. In many cases, you may find that EPOC is better suited to +supporting the use of server processes for serialising access to a shared resource (as in, for example, the +file server and the window server) rather than using a mutual exclusion semaphore. The design of EPOC's +inter process messaging was largely driven by the requirements of server processes and their clients. + + +Supplier-consumer + + +In this usage, the semaphore is associated with a pool of data (say a circular list in a shared data segment) +and is created with an initial value equal to the number of elements in the pool. The consumer calls +p_wait when it is ready to extract an item from the pool and the supplier calls p_signa1 after it inserted +an item into the pool. If there are one or more elements in the pool, the consumer's call to p_wait returns +immediately. Otherwise, the call to p_wait returns when the supplier inserts an element and calls +p_signal. + + +Asynchronous requests + + +Many system services are implemented in two steps: +e make the service request +e wait for the requested operation to complete + + +In most cases, as well as providing functions for each step, the system provides a function containing both +the above steps. Such functions are called synchronous because they automatically synchronise the +requesting process by waiting until the operation has completed. The internal function that makes the +request without waiting for completion is called an asynchronous function. + + +Examples of asynchronous request functions are: + + +p_ioa, p_ioc for requests on an open I/O channel +p_mreceive to receive an inter process message +p_execcasync for loading images + +p_logona for being informed of a process termination + + +There are also synchronous versions of all the above functions except p_logona (but see the example +below). + + +Applications use asynchronous requests in situations like the following: +e make request A +e make request B +e wait for either of the requested operations to complete + + +Processes wait for the completion of asynchronous requests by waiting on their //O semaphore where each +request is associated with a status word. + + +8-2 + + +8 ASYNCHRONOUS REQUESTS AND SEMAPHORES + + +The I/O semaphore + + +When a process is created, the system automatically creates an I/O semaphore on its behalf (a more +accurately descriptive name would have been the asynchronous request semaphore). After making one or +more asynchronous requests, a process calls p_iowait to wait on the I/O semaphore for one of the requests +to complete. A typical application process spends most of its time waiting on its I/O semaphore. For +example, an interactive application process that is waiting for user input from the window server is +waiting on the I/O semaphore. + + +The process or the hardware interrupt handler that implements the requested operation typically uses +p_iosignalbypid to indicate that the operation has completed. If one or more wait handlers have been +installed (wait handlers are described below), they may process the signal and re-signal using p_iosignal. +In some cases, it is convenient for the requestor to use p_iosignal to signal itself and to subsequently +process that signal in a central call to p_iowait. + + +Status words + + +Although the parameters to asynchronous request functions vary, they all take the address of a signed +16-bit status word which subsequently contains the status of the requested operation. + + +All asynchronous requests exhibit the following behaviour: + + +e While the request is pending, the status word contains the negative E_FILE_PENDING (defined +in p_file.h) + + +e When the operation has completed, a value other than =_rFILE_PENDING Is written to the status +word. This value should be zero or positive to indicate success or a negative error number to +indicate failure. + + +e The requesting process's I/O semaphore is signalled (after the status word has been written). + + +Making a request while a previous request on the same status word is still pending will normally result in +a call to p_panic. + + +When there are multiple requests, each request is associated with a different status word. After returning +from p_iowait, the caller typically polls each status word until one is found that contains other than +E_FILE_PENDING. That completion is then processed (which might include renewing the asynchronous +request) and p_iowait is called again to process the next completion. + + +Every p_iosignai should be matched by a call to p_iowait (or a function that calls p_iowait). The status +word associated with the p_iowait must have completed (ie must contain a value other than +E_FILE_PENDING) at the time that p_iosignal is called. A common programming error is to introduce a +p_iosignal without correctly associating it with a status word, such that the poll after the p_iowait +cannot find a completed status word. + + +At Psion this is known as a "stray signal" and programmers should detect this as early as possible by (say) +calling p_panic when the poll is unable to find a completed status word. + + +For Series 3, Series 3a and Workabout developers, using the Spy application supplied with this SDK may +help identify an accumulation of such unused signals. + + +In the following example, the opened asynchronous timer TimerChannel is used to construct a +synchronous function which attempts to write the passed string to the opened serial channel +SerialChannel. If it takes more that 5 seconds to complete the write, the function calls + +p_leave (SERIAL_TIMEOUT) . For simplicity it is assumed that there are no other outstanding events which +could complete. Thus it is certain that on return from the call to p_iowait, one of the two asynchronous +requests has completed. + + +8-3 + + +PLIB REFERENCE + + +LOCAL_C VOID StringToSerial (TEXT *str) +{ +UWORD len; +WORD TimerStatus; +WORD SerialStatus; +ULONG timeout; + + +len=p_slen(str); +p_ioc(SerialChannel, P_FWRITE, &éSerialStatus, str, &len) ; +timeout=50; /* 5 second timeout */ +p_ioc(TimerChannel, P_FRELATIVE, &TimerStatus, &timeout) ; +p_iowait (); +if (SerialStatus==E_FILE_PENDING) +{ /* must have timed out */ +p_iow(SerialChannel,P_FCANCEL) ; +p_waitstat (&SerialStatus) ; +p_leave (SERIAL_TIMEOUT); /* never returns */ +} +p_iow(TimerChannel, P_FCANCEL) ; +p_waitstat (&TimerStatus) ; +} + + +The functions p_ioc and p_iow are described in the next chapter: /O System. +Cancelling an asynchronous request + + +In the above example, the asynchronous request which does not complete is cancelled by making a +P_FCANCEL request using p_iow (the synchronous version of p_ioc or p_ioa). Most asynchronous request +functions have an associated cancel function; the P_FCcANCEL, to cancel I/O requests on a device channel, +is one example. Other examples are: + + +p_mcancel to cancel a call to p_mreceive to receive an inter process message +p_logoffa to cancel a call to p_logona for being informed of a process termination +The following general principles apply to all functions that cancel an asynchronous request: + + +e the cancel precipitates the completion of the operation (it does not stop the operation from +completing) + + +e the cancel may or not be effective (that is, the operation may complete naturally before the cancel +is processed) + + +e after a cancel, you must still process the completion of the asynchronous request (typically by +immediately calling p_waitstat to "use up" the signal) + + +Waiting for a particular completion + + +When waiting for the completion of a particular asynchronous request, the wait on the I/O semaphore +must be sure that it is not fooled into a premature return by the completion of any other pending +asynchronous request. This is done by calling p_waitstat which behaves in a similar way to p_iowait +except that it only returns when the associated status word is other than E_FILE_PENDING. + + +In general, p_waitstat is a safer option than p_iowait to "use up" the signal resulting from the cancelled +operation. If the cancel is not immediately effective and another completion causes p_iowait to return, the +program could continue and make another request before the cancelled operation completes (which would +result in p_panic being called). The above example illustrates the technique although, in this case, it is +not strictly necessary since there can be no confusion as to which event has completed. + + +8-4 + + +8 ASYNCHRONOUS REQUESTS AND SEMAPHORES + + +Constructing synchronous functions + + +General purpose functions that provide a synchronous interface must use p_waitstat rather than +p_iowait since they can not assume that there are no other pending asynchronous requests. + + +The use of p_waitstat Is illustrated by the following example of a synchronous function: + + +GLDEF_C INT ResumeWait (HANDLE pid) + + +{ +WORD stat; +INT ret; + + +if (!(ret=p_logona (pid, &stat) ) ) +{ +p_presume (pid) ; +p_waitstat (&stat); +ret=stat; +} + + +return (ret); + + +} + + +This is intended to be used in place of p_presume and behaves like p_presume except that it returns only +when the resumed process has terminated. It effectively implements a synchronous version of p_logona. + + +Wait handlers + + +Wait handlers are functions that handle the completion of asynchronous requests from within p_iowait +(or p_waitstat). Active wait handler functions are called just before p_iowait would have otherwise +returned. + + +Many I/O devices install a device wait handler when the device is opened (see the System Services +reference manual for information on writing device drivers and I/O device wait handlers). An application +can install any number of application wait handlers using p_svecadd (p_svecrem removes an application +wait handler). Before p_iowait will call an installed wait handler, it has to be activated using p_sveccall +(p_sveccali can also be used to deactivate a wait handler). An installed wait handler is automatically +deactivated when called (which stops it being called recursively since a wait handler often itself calls +p_iowait, directly or indirectly). + + +In the following example (which does not check for errors), setupHeapChecker installs the wait handler +CheckHeap which then calls p_alichk every 2 seconds or so without any cooperation from the rest of the +program. + + +typedef struct +{ +UBYTE *Channel; +WORD Status; +ULONG Timeout; +} HEAP_TIMER; + + +LOCAL_C INT CheckHeap(HEAP_TIMER *pTimer) +{ +if (pTimer->Status==E_FILE_PENDING) +return (P_SIGNAL_UNUSED) ; +p_allchk (0); +p_ioc(pTimer-—>Channel, P_FREAD, &épTimer->Status, &pTimer-—>Timeout) ; +return (P_SIGNAL_ENABLE) +} + + +GLDEF_C VOID SetupHeapChecker (VOID) + + +{ +HEAP_TIMER *pHeapTimer; + + +pHeapTimer=p_alloc(sizeof (HEAP_TIMER) ); + +p_open (&pHeapTimer->Channel,"TIM:",-1); +pHeapTimer->Status=0; + +pHeapTimer->Timeout=20; /* 2 second tick */ +p_sveccall (p_svecadd (CheckHeap, pHeapTimer) , TRUE) ; +} + + +Wait handlers are only called when the process calls p_iowait (or a function such as p_waitstat that +calls p_iowait). While an application performs a computationally intensive task that takes an extended +time, it should consider calling p_ioyieid (which effectively calls p_iosignal1 followed by p_iowait) to +allow any installed wait handlers to be called. Application programs must never assume that no wait +handlers have been installed. + + +PLIB REFERENCE + + +Installed device wait handlers and application wait handlers are represented as a doubly linked queue of +data structures allocated out of the process heap. The queue is built from a 4-byte queue header in a +reserved static at address 2 in the process data segment. If this reserved static is corrupted (say because of +a write using an uninitialised pointer that happens to have a low value), p_iowait will almost certainly +detect an invalid wait handler and call p_panic (27) although the cause of the panic may have nothing to +do with wait handlers. + + +Polling rather than waiting + + +In a multi-tasking operating system it is extremely anti-social to wait for an operation to complete by +polling the status word in a tight loop rather than call p_iowait (because the polling will "hog" the +processor to no benefit). However, when there is useful work to be done between each poll, it can be +appropriate to poll - for example, to check periodically for user input while performing an extended +calculation. + + +If this approach is used, you should be aware that in some cases asynchronous requests are completed by +a wait handler and it is necessary to call p_ioyield before each poll to give any wait handlers a chance +to run. + + +This case occurs when making requests on a device driver that services hardware interrupts. For example, +the serial port driver services the hardware interrupt generated by the receipt of a serial frame. A +hardware interrupt handler cannot write directly to the data segment of the requesting process because +that data segment may be moving when the interrupt occurs. Instead, the interrupt handler must write first +to a fixed memory location (either in the operating system variables if it is an in-built driver or in a device +segment if it is an external driver) and then signal the I/O semaphore of the requesting process. When the +requesting process next calls p_iowait (directly or indirectly through say p_ioyield), the device driver's +wait handler is called to copy the data safely to the process data segment. + + +Device drivers that are implemented by a server process (for example, the window server) do not require a +wait handler to complete operations. + + +When a poll detects a completed status word it is still obligatory to "use up" the signal by calling p_iowait +(otherwise you will get a "stray signal" later). + + +Attached I/O devices + + +Wait handlers are often used in attached I/O drivers that layer over an existing driver (which may be +another attached driver or a hardware device driver) to extend or modify its services. The attached driver +typically installs a wait handler to handle the completion of requests on the underlying driver. Although +attached drivers can be written in C, the interface between the I/O system and the functions that are called +requires some assembly language programming. See the //O System chapter for more information on +attached drivers. + + +EEE +Primitive semaphore functions + + +p_semcrt Create a semaphore +HANDLE p_semcrt (INT nCount) ; + + +Create a semaphore with an initial positive count ncount. Returns the handle of the semaphore if +successful, or E_GEN_NosEM if no semaphores are available. + + +The created semaphore is owned by the calling process and, in version 3 and later of EPOC, may be +deleted using p_semde1 before exiting. However, the semaphore will always be automatically deleted on +termination of the process. + + +Calls p_panic if ncount is negative. + + +p_semdel Delete a semaphore +VOID p_semdel (HANDLE sHandle); +Delete semaphore sHandle. Any processes waiting on the semaphore are automatically signalled. + + +Calls p_panic if sHand1e is not the handle of a previously created semaphore. + + +8-6 + + +8 ASYNCHRONOUS REQUESTS AND SEMAPHORES + + +Prior to version 3 of EPOC the recommended action is not to delete a semaphore, but to let the operating +system perform any necessary clean-up actions on termination of the application. This is an acceptable +solution for all versions of EPOC. Except in extreme cases, where large numbers of semaphores are +created, there is no need for an application ever to call p_semdel. + + +p_wait Wait on a semaphore + + +VOID p_wait (HANDLE sHandle) ; + + +Decrement semaphore sHand1e by one and return immediately if it is zero or positive. If sHandle is +negative after being decremented, it waits for semaphore sHandl1e to be signalled by another process or by +an interrupt handler (or for sHand1e to be deleted). + + +More than one process can be waiting on a particular semaphore at a time. When there are multiple +processes waiting on a semaphore, they are released on a first-in first-out basis. If a semaphore is deleted, +all processes waiting on that semaphore are released. + + +Calls p_panic if sHandle is not the handle of a previously created semaphore. + + +p_signal Signal a semaphore + + +VOID p_signal (HANDLE sHandle) ; + + +Signal semaphore sHandle, incrementing it by one. If sHandie was less than zero, the first process waiting +on it is released and a reschedule takes place (before p_signal returns). + + +Calls p_panic if sHandle is not the handle of a previously created semaphore. + + +p_signaln Signal a semaphore n times +VOID p_signaln(HANDLE sHandle, INT nTimes); +Equivalent to calling p_signal(sHandle) nTimes times. + + +Calls p_panic if sHand1e is not the handle of a previously created semaphore or if nTimes is not greater +than or equal to 1. + + +p_signalnr Signal a semaphore with no re-schedule +VOID p_signalnr (HANDLE sHandle) ; +Behaves as for p_signa1 except that the re-schedule does not take place. + + +In the absence of any other cause, a re-schedule will not occur until the next system tick. A re-schedule +can always be forced by calling p_sieept (OL). + + +Calls p_panic if sHand1e is not the handle of a previously created semaphore. + + +The I/O semaphore + + +Although the I/O semaphore is indeed associated with I/O operations, it is not used exclusively for I/O +operations. In retrospect, a more accurate name would have been the "asynchronous request semaphore". + + +p_iosignal Signal the 1|O semaphore +VOID p_iosignal (VOID) ; +Increment the process I/O semaphore. + + +Used in wait handlers to signal the completion of an asynchronous request after writing the completion +status to the associated status word. + + +It can also be used outside wait handlers to generate "internal events" where the call to p_iosignal +necessarily precedes the call to p_iowait. + + +8-7 + + +PLIB REFERENCE + + +p_iosignalbypid Signal the 1O semaphore of another process +VOID p_iosignalbypid (HANDLE pid); +Signal the I/O semaphore of process pid. + + +Used to signal the completion of a request from process pid (normally a different process but it still works +if it is the same process). Before calling p_iosignalbypid, the process should already have set the pia's +status word using say p_pepyto. + + +p_iowait Wait on the lO semaphore +VOID p_iowait (VOID) ; + + +Wait for the I/O semaphore to be signalled (of course, it returns immediately if the I/O semaphore has +already been signalled). + + +When the I/O semaphore is signalled, any active wait handlers are called. Only when all the active wait +handlers indicate that the signal has nothing to do with them (ie they all return P_stGNAL_uNUSED) will the +p_iowait call return. When it does return, the signal must be associated with an external (ie outside any +wait handler) status word. + + +The application should then poll the request status words to determine which operation has completed. + + +p_ioyield Allow any wait handlers to run +VOID p_ioyield(VOID) ; + + +Give an opportunity for any active wait handler to run. Equivalent to calling p_iosigna1 followed by a + + +p_iowait. + + +Any application that polls a status word for the completion of an I/O operation (presumably in between +performing chunks of a computationally intensive task) should call p_ioyieid before polling to give any +wait handlers (which are commonly required to complete an asynchronous request) a chance to run. + + +p_waitstat Wait for a particular request to complete +VOID p_waitstat (WORD *pstat); +Wait for the particular asynchronous request associated with *pstat to complete. + + +It is similar to p_iowait except that rather than just wait for the I/O semaphore to be signalled, it also +waits until *pstat is not E_FILE_PENDING. It correctly adjusts the I/O semaphore if any other I/O requests +completes in the meantime, as illustrated in the following code: + + +GLDEF_C VOID p_waitstat (WORD *pstat) + + +/* +Wait for *pstat!=E_FILE_PENDING +*/ + +{ + +INT i; + +i=(-1); + +do + + +p_iowait (); + +itt; + +} while (*pstat==E_FILE_PENDING) ; +while (i--) + +p_iosignal(); + + +} + + +8 ASYNCHRONOUS REQUESTS AND SEMAPHORES + + +The principle may be extended to wait for the completion of more than one asynchronous event. This is +illustrated in the following code, which waits until both of two status words are not equal to +E_FILE_PENDING: + + +GLDEF_C VOID waitstat2(WORD *pstat1,WORD *pstat2) + + +/* +Wait until both *pstat1l and *pstat2 are not E_FILE_PENDING +xf + +{ + +INT i; + +i=(-1); + +do + + +p_iowait (); + +Ltt; + +} while ((*pstat1==E_FILE_PENDING) && (*pstat2==E_FILE_PENDING) ); +if (*pstat2==E_FILE_PENDING) + +pstatl=pstat2; +p_waitstat (pstat1); +while (i--) + +p_iosignal(); + + +Wait handlers + + +p_svecadd Add a wait handler function + + +HANDLE p_svecadd(INT (*vec) (VOID *), VOID *pcb); + + +Add function vec to the I/O semaphore wait handler list and return the non-zero handle of the wait +handler if successful or zero if there is insufficient memory. + + +The returned handle is subsequently used to activate (by calling p_sveccaii) and remove the wait handler +(by calling p_svecrem). + + +Initially the wait handler is inactive. The installed wait handler is normally activated to process the +completion of one or more asynchronous requests. + + +When the wait handler is active, the wait handler function is called from within p_iowait when the I/O +semaphore is signalled. In the interests of efficiency, a wait handler should only be active while there is an +associated pending request. + + +The wait handler function should poll the one or more status words associated with the one or more +requests it is monitoring and return one of the following values: + + +P_SIGNAL_DISABLE the status word was other than &_FILE_PENDING and the completion has been +processed. There are no more requests to process and the wait handler can now +be deactivated. + + +P_SIGNAL_ENABLE a status word was other than &_FILE_PENDING and the completion has been +processed. However, there are still pending requests (either because the wait +handler is associated with more than one request or because another request +was queued) and the wait handler should remain active. + + +P_SIGNAL_UNUSED all status words contained &_FILE_PENDING and no processing took place. The +wait handler remains active. + + +In the first two cases, where the signal is consumed, p_iowait loops back and waits on the I/O semaphore +again. + + +If the wait handler does not detect the completion of an internal request and returns p_sIGNAL_UNUSED, +p_iowait will call any other active wait handlers and will only return to the caller when there are no +active wait handlers or when all the active wait handlers return p_s1GNAL_UNUSED. + + +If in the processing of the completion of one request the wait handler cancels another request, the wait +handler would normally use up the signal from the cancelled requests by calling p_waitstat. + + +8-9 + + +PLIB REFERENCE + + +An active wait handler is deactivated before being called and is only reactivated when it returns with the +value P_SIGNAL_ENABLE Or P_SIGNAL_UNUSED. This normally works such that any calls to p_iowait within +a wait handler will not cause the same wait handler to be called recursively. Other active wait handlers +may still be called within a p_iowait within the wait handler. + + +The wait handler function vec is called with pcb as its single parameter. Where re-entrant code is +required, pcb would normally be an address leading to the status word (or words) associated with the +requests the wait handler is interested in. In non re-entrant code, where static data is used, it may not be +necessary to use pcb. + + +p_sveccall Activate/deactivate a wait handler + + +VOID p_sveccall (HANDLE hand, INT isactive); + + +If isactive is TRUE activate wait handler hand (where hand was returned by p_svecada). If isactive is +FALSE deactivate wait handler nana. + + +In the interests of efficiency, wait handlers should be deactivated when they have no pending requests to +process. As well as being externally deactivated by calling p_svecca11, a wait handler can deactivate itself +by returning P_SIGNAL_DISABLE. + + +p_svecrem Remove a wait handler + + +VOID p_svecrem(HANDLE hand) ; + + +Remove wait handler hand (where hand was returned by p_svecadd) from the I/O semaphore wait handler +list. + + +8-10 + + +CHAPTER 9 + + +/O SYSTEM + + +This chapter describes the EPOC I/O system in general and the C functions used to access I/O devices. To +use a particular device you need (also) to read a description of the device driver. + + +The files device driver and the asynchronous timer device driver are described in this manual - in the +chapters Files and Time, Timers and Dates respectively. Other device drivers are described in the J/O +Devices manual. + + +The last section of this chapter describes a set of console services for constructing rudimentary user +interfaces with the minimum of effort. Worthier user interfaces may be implemented using the services +described in the Window Server reference manual. + + +I/O Device Drivers + + +The principal purpose of device drivers is to provide convenient software interfaces that hide the internal +details of the underlying hardware. For example, the software interface to the RS232 driver is independent +of the interface to the underlying hardware. The fact that the RS232 hardware is different between SIBO +machines and PCs is not apparent to the user of the RS232 driver. + + +Many device drivers do not themselves interface to hardware but layer over one or more other device +drivers that ultimately access the hardware. For example, the majority of the code in the RS232 driver is +independent of the hardware interface and the driver is implemented in 2 layers - an upper hardware- +independent layer and a lower hardware-dependent layer. + + +Some device drivers do not access hardware at all - even indirectly. In such cases, the device driver +mechanism is used to extend the services available to applications. For example, the C standard floating +point library is implemented as a device driver. + + +LDDs and PDDs + +In EPOC there are two types of device driver: +e physical device drivers (PDDs) which are hardware dependent +e logical device drivers (LDDs) which are hardware independent + + +Applications normally interface to LDDs only. An LDD may use one or more PDDs in its +implementation. For example, the RS232 driver is an LDD (the upper layer) using an appropriate PDD +(the lower layer) depending on the underlying hardware. PDDs are also used by the file server system +process to access different types of SSDs. + + +Some device drivers are built into the operating system where their code is in the ROM. For example, the +RS232 LDD and its PDD are normally built into the operating system whereas a bar code reader device +driver is normally external and has to be loaded. + + +PLIB REFERENCE + + +External device drivers + + +External device drivers are loaded from a device driver file into a device memory segment. The device +driver file has the file name extension .LDD or .PDD depending on whether it is an LDD or PDD +respectively. The device memory segment is allocated by the segment allocator as described in the chapter +Memory Allocation. + + +The ability to load and remove external device drivers without a system reset is a key feature of the EPOC +I/O system and contrasts with most other operating systems, which require a system reset to install a +device driver. On a SIBO machine you can physically attach a peripheral device (for example, a bar code +wand) and load a device driver without having to exit any application processes. The I/O system also +notifies devices when the machine switches off and on so that the driver can take appropriate device +specific action before losing power and to recover when the power is resumed. + + +The interface between the operating system and an LDD does not conform to a C calling convention. An +LDD may be written in C but some 8086 assembly language is required to provide the LDD interface. See +the System Services reference manual for more about device drivers. + + +Opening a channel to a device + + +The I/O device driver functions are accessed by opening a channel to the device by calling p_open and +passing it a name consisting of a 3 character device name and a terminating colon. Examples of device +names are: + + +FIL: for opening a file + +PAR: for opening a parallel port + +TTY: for opening an RS232 port + +TIM: for opening an asynchronous timer + + +Note that device names of external LDDs bear no relation to the file name from which they were loaded. + + +Depending on the nature of the device, the ':' may be followed by further text. Where the device driver +supports more than one unit, the device name may be followed by a unit letter. For example, "Try:a" is +used to open a channel to serial port A and "Par:B" is used to open a channel to parallel port B. + + +In the file system device r1u:, the qualifying text is normally a file name or full path name. Because the +file system has more p_open calls made to it than any other device, the p_open function effectively inserts +a "FIL:" before a device name if it fails to recognise a valid device name - making the leading "FIL:" +optional. For example, calling p_open with the name "c:\NOTES\NEW.TxT" has the same effect as the +name "FIL:C:\NOTES\NEW. TXT". Keeping the FIL: prefix removes any possibility of mistaking the file +specification for a device name - for example to open a file on the default directory with file name "TTv:". + + +The p_open function works such that a loaded device driver supersedes any existing device of the same +device name. + + +Operations on an open I/O channel + + +Once a channel has been opened on a device, the primitive p_ioa function is used (directly or indirectly) +to make an asynchronous I/O function request on the channel. Asynchronous requests are described in the +chapter Asynchronous Requests and Semaphores. + + +All I/O function requests are asynchronous in principle and the process I/O semaphore is always signalled +as a result of an I/O function request. In practice, many I/O functions are implemented synchronously, +which means that the I/O operation will have completed before p_ioa returns. A typical I/O device will +provide zero, one, two or three truly asynchronous functions (where the request will probably not have +completed before p_ioa returns) with the remaining functions provided synchronously. For example, the +I/O function that closes an I/O channel is always implemented synchronously, whereas the I/O function +that reads input from a device is commonly implemented asynchronously. + + +In practice, p_ioa is often called indirectly by: + + +p_ioc which makes an asynchronous I/O request in a way that simplifies the handling +of error returns - this should generally be used in preference to p_ioa + + +p_iow which makes the I/O request and then waits for the request to complete (by +calling p_waitstat) + + +9-2 + + +9 /O SYSTEM + + +The particular I/O function requested by a call to p_ioa, p_ioc Or p_iow is specified by a function number +parameter of the form p_Fxxx, defined in p_file.h. Some I/O functions are specific to a particular device +(for example p_rsEtTEor, which sets the end of file position on an open file channel). Some I/O functions +apply to more than one device, including: + + +P_FREAD to read data from a channel + +P_FWRITE to write data to a channel + +P_FCLOSE to close a channel + +P_FCANCEL to cancel outstanding asynchronous requests on a channel +P_FSENSE to sense channel characteristics + +P_FSET to set channel characteristics + +P_FFLUSH to flush out data held in buffers + + +This manual uses the notation p_ioa(P_Fxxx), p_ioc(P_Fxxx) and especially p_iow(P_Fxxx) to refer to +the corresponding function call with p_rxxx passed as the I/O function number. (In the descriptions of +p_ioa, p_ioc and p_iow later in this chapter the I/O function number has the parameter name func.) + + +The most commonly used I/O functions are supported by their own synchronous convenience functions as +follows: + + +p_close which calls p_iow (P_FCLOSE) +p_read which calls p_iow (P_FREAD) +p_write which calls p_iow(P_FWRITE) +p_seek which calls p_iow (P_FSEEK) + + +The functions p_close, p_read and p_write are used across many devices (p_close is applicable to all +devices) and are described in this chapter. The function p_seek applies to an open file channel only and is +described in the Files chapter. + + +The file server + + +The file server is a high priority system process (with process name SYS$FSRV) that performs all file +related operations. These include those that are accessed using the I/O channel services (the r1L: device) +and those that do not require a channel to be opened (eg deleting a file, making a directory). The file +server is also responsible for loading executables (see the chapter Processes and Inter-Process Messages) +and for loading external device drivers (described in this chapter). + + +The file server serialises access to shared file storage devices (eg SSD drives on a SIBO machine) which +may be local or remote. On SIBO machines, the file server uses PDDs extensively to access the many +different types of SSD (different configurations of FLASH, RAM, ROM). The file server also uses an +installable PDD to connect to remote devices via a remote file server. The file server is a process rather +than an LDD because, in a multi-tasking system, more than one process can be accessing a particular file +storage device at a time (at a lower level only the file server owns an SSD drive where it performs all +operations on the SSD on behalf of requesting processes). + + +Application processes that use the file server are called "clients". To become a client of the file server, a +process must connect to it. Because most applications need the file server, the normal code that precedes +main connects to the file server. + + +The client processes send the file server an inter-process message to request a file server service. If the +service accesses local devices, it is implemented synchronously since the file server runs at a higher +priority than any application process. If the service accesses remote devices, it may be implemented +asynchronously. + + +The application programmer does not program at the message passing level but uses the interfaces +provided by the ri: device and a number of ROM resident functions (most of which are described in the +Files chapter). Whether provided by a function or via the r1L: device, all access to the file server +ultimately involves the sending of an appropriate inter-process message. + + +9-3 + + +PLIB REFERENCE + + +Attached drivers + + +An attached driver is an LDD using the services of an another LDD to provide a different set of services to +its user. Some of the devices described in the J/O Devices manual are attached drivers. + + +For example, the PRD: device is an attached driver, layered over a suitable print output device to provide +primitive printer driver services (involving translates, preambles and postambles as driven from a .PRD +file). In this case a suitable print output device is any device that supports the normal P_rwRITE operation +as provided by the par:, TTY: and FIL: devices. + + +The user of the PRD: device does the following: +¢ open the print output device using p_open (eg PAR: Or TTY:) +e perform any initialisation on the channel (eg to set the Baud rate on a tty: channel) +¢ open the prp: device using p_open, attaching it to the opened print output device + + +Once the prp: device has been opened, it replaces the P_FWRITE, P_FCANCEL and P_FCLOSE functions of the +underlying device. + + +In general, an attached driver may completely replace the original driver's functions or it may augment +them (possibly also replacing or disabling some functions). It may also allow some functions through to +the underlying driver or beyond. + + +Like any other LDD, an attached driver may be written in C but some assembly language code is required +to provide the LDD vector interface. See the System Services reference manual for more about writing +attached device drivers. + + +Attached drivers that provide one or more of their services asynchronously make internal asynchronous +requests on the device they are attached to. Where this is the case, the attached driver processes the +completion of its internal requests in code that is entered via its wait handler vector. The attached device +installs its device wait handler when the channel is opened and the wait handler vector is subsequently +called from within the p_iowait of the process which opened the device whenever the process I/O +semaphore is signalled. Except for the way in which they are called, device wait handlers are the same as +application wait handlers as described in the chapter Asynchronous Requests and Semaphores. + + +Channel-based I/O functions + + +p_open (or f_open) Open a channel to a device + + +INT p_open(VOID **ppfcb, TEXT *name, UINT mode); +INT f_open(VOID **ppfcb, TEXT *name, UINT mode); + + +Open a channel to the device with the zero terminated device name name or attach driver name to an +existing channel. + + +The parameter name consists of a 3 character device name terminated by a':’ and optionally followed by +further data, depending on the device. + + +The interpretation of the mode parameter depends upon the device and some devices ignore mode. When a +device ignores mode, the caller should pass a mode of -1. + + +The files device (device name "F1L:") and the asynchronous timer device (device name "TIM:") are +described in the chapters Files and Time, Timers and Dates in this manual. These devices are also +described in the //O Devices manual along with many other devices. + + +If the device name is not an attached device and it is opened successfully, the address of the channel +control block is written to *ppfcb. If the open fails, *ppfcb is not written to - setting *ppfcb to zero before +calling p_open can simplify clean-up code since p_close(0) has no effect and p_close can subsequently +be called regardless of whether the open call was successful. + + +If device name is an attached device, the driver control block is attached to *ppfcb - the value in *ppfcb is +not changed. + + +9-4 + + +9 VO SYSTEM + + +Returns zero if successful or a negative error number if it failed. As well as device specific errors (as +described in the description of each device) the following error numbers may be returned: + + +E_FILE_ALLOC failed to allocate memory for the control block +E_FILE_DEVICE the device does not exist +E_GEN_ARG the value of the mode parameter was invalid (possibly as a result of falling + + +through to the rr: device, as described next) + + +The function £_open is identical to p_open except that it calls p_leave (passing the error number) rather +than return a negative error number. + + +If p_open fails to locate a device that matches name, then name is passed to the r1L: device driver (in +which case the process must be connected to the file server). To put it another way, the leading FrL: +device name is optional when opening files and, for example, calling p_open with a name of + +"LOC: :A:\DEF.EXT" is equivalent to a name Of "FIL: LOC: :A:\DEF.EXT" (the FIL: device is described in +more detail in the Files chapter). + + +This behaviour has an undesirable side effect: an attempt to open a device that does not exist does not give +the expected &_FILE_DEVICE error since name is passed on to the Fru: device with a result that depends +upon mode (with some values of mode the open might even be successful). Passing a mode of -1 is +guaranteed to cause the Fru: device driver open to fail - albeit with a misleading error number +(&_GEN_ARG). + + +p_ioa Start an I/O operation + + +INT p_ioa(VOID *pcb, INT func, WORD *pstat, ...); + +INT p_ioa3(VOID *pcb, INT func, WORD *pstat); + +INT p_ioa4(VOID *pcb, INT func, WORD *pstat, VOID *al); + +INT p_ioa5(VOID *pcb, INT func, WORD *pstat, VOID *al, VOID *a2); + + +Start the I/O operation func with zero, one or two parameters on the opened channel pcb and return +without waiting for the operation to complete. + + +You can either use p_ioa, which presents the cpzct calling convention, or one of the p_ioa? variants, +which uses a more efficient register calling convention. + + +Note that it is almost always preferable to use p_ioc in preference to p_ioa. + + +The legitimate values of func depends upon the device. The number of function parameters (zero to two) +and the interpretation of the function parameters (if any) depends on the function and the device. If a +function parameter exists, it is normally an address that may be used as input, output or both input and +output. + + +The function returns zero if the I/O request was started successfully or a negative error number. Returns +E_FILE_INv if func is not valid for this device. Other device specific errors may be returned. + + +When the successfully started operation completes, the process I/O semaphore is signalled and *pstat +contains the completion status. While the operation is pending (ie before the I/O semaphore has been +signalled), *pstat contains E_FILE_PENDING. Asynchronous requests in general are described in the +chapter Asynchronous Requests and Semaphores. + + +After the operation has completed, *pstat contains zero if the operation completed successfully or a +negative error number if the operation completed with an error. The possible error numbers depend upon +the device but any asynchronous operation that is successfully cancelled completes with *pstat containing +E_FILE_CANCEL. + + +Drivers normally only support one pending request per I/O operation per channel. For example, on the +TTy: (serial port) device you must wait for an asynchronous write request to complete before you can make +another write request on the same channel (the driver will call p_panic if this is attempted). However, it is +legitimate to have one read request and one write request simultaneously pending. + + +9-5 + + +PLIB REFERENCE + + +The storage pointed to by pstat must be retained for the duration of the operation. A common error, +which has disastrous results, is to allocate the status word on the stack and then to return from the +function before the operation has completed - as in the following example: + + +GLDEF_C INT DisastrousWrite(VOID *pcb, TEXT *buf) +{ +WORD stat; +UWORD len; + + +len=p_slen (buf) ; +return (p_ioa(pcb, P_FWRITE, &stat,buf, &len) ); +} + + +The following generic I/O functions (where a1 and a2 are further parameters to p_ioa) are commonly +(but not always) implemented asynchronously by device drivers: + + +P_FREAD request a read operation where a1 is the address of the buffer to take the data +and a2 is the address of a worp length to read (or the maximum length to read if +the device is record oriented). When the read completes, *pstat contains zero +if the read was successful or a negative error number if the read failed and «a2 +contains the number of bytes written to a1. + + +P_FWRITE request a write operation where a1 is the address of the data to write and a2 is +the address of a worp length to write. When the write completes, *pstat +contains zero if the write was successful or a negative error number if the write + + +failed. +p_ioc Start an I/O operation with guaranteed completion +VOID p_ioc(VOID *pcb, INT func, WORD *pstat, ...); + + +VOID p_ioc3(VOID *pcb, INT func, WORD *pstat); +VOID p_ioc4(VOID *pcb, INT func, WORD *pstat, VOID *al); +VOID p_ioc5(VOID *pcb, INT func, WORD *pstat, VOID *al, VOID *a2); + + +Behaves as for p_ioa except that if the I/O request func fails to start, the failure is reported as if it had +started successfully but completed with that error. + + +You can either use p_ioc, which presents the cbEct calling convention, or one of the p_ioc? variants, +which uses a more efficient register calling convention. + + +The implementation of p_ioc is effectively as follows: + + +GLDEF_C VOID p_ioc(VOID *pcb, INT func,WORD *pstat,VOID *al,VOID *a2) +{ +INT ret; + + +if (ret=p_ioa(pcb, func, pstat,al,a2) ) +{ +*pstat=ret; +p_iosignal(); +} +} + + +In most cases, p_ioc is preferred to p_ioa because there is only one place (*pstat) to check for an error +rather than two (the return from p_ioa and *pstat). It is rarely necessary to differentiate between a failure +to start the I/O operation and a failure in its completion. + + +In the following example, WriteTimeout writes the len bytes at buf to channel pcb and returns as for +p_write. However, if the write does not complete within secs seconds, the write operation is cancelled +and £_FILE_CANCEL is returned. + + +For simplicity, it assumes that completion of the write or expiry of the timer are the only two events that +are expected to cause a return from the call to p_iowait. This will be true if there is no other +asynchronous activity. + + +9-6 + + +LOCAL_C INT WriteTimeout (VOID *pcb, UBYTE *buf, UWORD len, + + +{ + +WORD tstat; +WORD wstat; +ULONG tval; + + +p_ioc (pcb, P_FWRITE, &wstat, buf, &len) ; +tval=10L*secs; +p_ioc(tcb,P_FRELATIVE, étstat, &tval) ; +p_iowait (); + +if (tstat!=E_FILE_PENDING) + +/* the timer expired */ +p_iow(pcb,P_FCANCEL); /* cancel write */ +p_waitstat (&wstat); + + +else if (wstat!=E_FILE_PENDING) + +/* the write completed */ +p_iow(tcb,P_FCANCEL); /* cancel timer */ +p_waitstat (&tstat); + + +else +p_panic(254); /* unexpected, unrecognised signal */ +return (wstat) ; + + +} + + +UINT secs) + + +9 VO SYSTEM + + +The call to p_iowait returns when either request completes. If the timer has completed, the write request +is cancelled. Otherwise, the timer request is cancelled. If both requests have completed by the time +p_iowait returns (quite possible if a higher priority process "hogged" the CPU), the cancel of the write +request will have no effect and wstat will contain the completion code of the write. + + +In the example, the static variable tcb is the channel of a previously opened asynchronous timer, as in: + + +p_open (&tcb, "TIM:",-1); + + +The following version of writeTimeout is more general, and caters for the presence of other asynchronous + + +activity. + + +LOCAL_C INT WriteTimeout (VOID *pcb, UBYTE *buf, UWORD len, + + +{ + +WORD tstat; +WORD wstat; +WORD count; +ULONG tval; + + +p_ioc (pcb, P_FWRITE, &wstat, buf, &len) ; +tval=10L*secs; +p_ioc(tcb, P_FRELATIVE, étstat, &tval) ; +count=0; +FOREVER +{ +p_iowait (); +if (tstat!=E_FILE_PENDING) +{ /* the timer expired */ +p_iow(pcb,P_FCANCEL); /* cancel write */ +p_waitstat (&wstat); +break; +} +else if (wstat!=E_FILE_PENDING) +{ /* the write completed */ +p_iow(tcb,P_FCANCEL); /* cancel timer */ +p_waitstat (&tstat); +break; +} +else +count+=1; /* count unrecognised signals */ +} +while (count--) +p_iosignal(); /* replace unrecognised signals */ +return (wstat) ; + + +} + + +UINT secs) + + +PLIB REFERENCE + + +In such a situation, with other asynchronous activity, it may be better to handle the expiry of the timer in +the main p_iowait loop. The wait for the write to complete could then be handled by: + + +p_waitstat (&wstat) ; +p_iow(tcb,P_FCANCEL); /* cancel timer */ +p_waitstat (&tstat); + + +p_iow Start an I/O operation and wait for completion + + +INT p_iow(VOID *pcb, INT func, ...); + +INT p_iow2(VOID *pcb, INT func); + +INT p_iow3(VOID *pcb, INT func, VOID *al); + +INT p_iow4(VOID *pcb, INT func, VOID *al, VOID *a2); + + +Behaves as for p_ioa except that it waits for operation func to complete and returns the completion status, +providing a synchronous (as opposed to an asynchronous) interface. + + +You can either use p_iow, which presents the cbEct calling convention, or one of the p_iow? variants, +which uses a more efficient register calling convention. + + +The code for p_iow is effectively: + + +GLDEF_C INT p_iow(VOID *pcb, INT func,VOID *al,VOID *a2) +{ +WORD stat; +INT ret; + + +if (!(ret=p_ioa (pcb, func, &stat,al,a2))) +{ +p_waitstat (&stat); +ret=stat; +} +return (ret); + + +} + + +Calling p_iow is simpler and requires one less parameter (since the status word is returned) than p_ioa or +p_ioc and should be used in preference to p_ioa or p_ioc unless there is a need for an asynchronous +request. + + +The following generic I/O functions are essentially synchronous and are normally requested using p_iow: + + +P_FCANCEL to cancel outstanding requests on a channel + +P_FSENSE to sense channel characteristics + +P_FSET to set channel characteristics + +P_FFLUSH to flush out data held in buffers + +p_close Close an I/O channel + + +INT p_close(VOID *pcb); +Close I/O channel pcb and return zero if successful. If pcb is NULL, just return zero. +The code for p_close is effectively: + + +GLDEF_C INT p_close(VOID *pcb) +{ +if (!pcb) +return (0); +return (p_iow(pcb, P_FCLOSE) ) ; +} + + +Although p_close can return an error, it will always succeed in closing the channel (and pcb should not +be used subsequently). + + +If the device buffers written data, the close operation may need to perform one or more write operations on +closing, in which case P_FCLOSE can return similar errors to P_FWRITE. However, the failure to flush the +data will not (assuming a competently written device driver) cause the close operation to be aborted +although the failure to flush will be reported. + + +Carefully written applications avoid this problem by using p_FFr1uss to flush the data (and taking +appropriate action if this fails) before closing the channel without risk of failure. + + +9-8 + + +9 1/0 SYSTEM + + +p_read (or f_read); Read from an I/O channel + + +INT p_read(VOID *pcb, VOID *buf, UINT len); +INT f_read(VOID *pcb, VOID *buf, UINT len); + + +Request a P_FREAD Of up to 1en bytes of data into bur from channel pcb, wait for the request to complete +and, if successful, return the number of bytes written to buf or a negative error number if the read failed. + + +The code for p_read is effectively: + + +GLDEF_C INT p_read(VOID *pcb, UBYTE *buf, UINT len) + + +{ +INT ret; +UWORD 1; + + +l=len; +ret=p_iow (pcb, P_FREAD, buf, &1); +if (!ret) + +ret=1; +return (ret); + + +} + + +The function £_read is identical to p_read except that, if there is an error, it calls p_leave (err) rather +than return the negative error number err. + + +p_write (or f_write); Write to an I/O channel + + +INT p_write(VOID *pcb, VOID *buf, UINT len); +INT f_write(VOID *pcb, VOID *buf, UINT len); + + +Request a P_FWRITE Of len bytes of data from buf to channel pcb, wait for the request to complete and, if +successful, return zero or a negative error number if the write failed. + + +The code for p_write is effectively: + + +GLDEF_C INT p_write(VOID *pcb, UBYTE *buf, UINT len) + + +{ +UWORD 1; + + +l=len; +return (p_iow(pcb, P_FWRITE, buf, &1)); +} + + +The function £_write is identical to p_write except that, if there is an error, it calls p_leave (err) rather +than return the negative error number err. + + +p_iow(P_FCANCEL) Cancel requests on an I/O channel + + +INT p_iow(VOID *pcb, P_FCANCEL) ; + + +Cancel any outstanding asynchronous requests on channel pcb and return zero. Harmless if there are no +pending requests. + + +Device drivers that support truly asynchronous services provide a cancel service. The detailed effect of +the cancel depends upon the device driver. However, the following general principles apply: + + +e the cancel precipitates the completion of the request (it does not stop the request from +completing) + + +e the cancel may or not be effective (that is, the request may complete naturally before the cancel is +processed) + + +e after a cancel, you must still process the completion of the asynchronous request (typically by +immediately calling p_waitstat to "use up" the signal) + + +The above principles actually apply to cancelling any asynchronous request (not just an asynchronous I/O +request). + + +Although legitimate, using p_ioa(P_FCANCEL) Of p_ioc(P_FCANCEL) (rather than p_iow(P_FCANCEL) ) is +somewhat perverse since you then have two signals to use up - one for the request being cancelled and one +for the cancel itself. + + +9-9 + + +PLIB REFERENCE + + +Device driver functions + + +p_loadidd Load a logical device driver +INT p_loadldd(TEXT *pName) ; + + +Load the logical device driver (LDD) from the zero terminated file name pName. If pName contains no +extension an extension of .LDD is assumed (an LDD file would normally have the extension .LDD). If +pName is not a full path name the current path is assumed. + + +Returns zero if successful or one of the following negative error numbers: + + +E_FILE_EXIST an LDD of the same file name has already been loaded +E_FILE_NXIST the LDD file does not exist + +E_FILE_DEVICE the supplied file name is that of a PDD + +E_GEN_IMAGE the LDD file does not have the correct format or has been corrupted +E_GEN_NOMEMORY Not enough memory to satisfy the request + +E_GEN_NOSEGMENTS No memory segment handles are available + + +After the LDD has been loaded, a channel may be opened to it by calling p_open. + + +Applications that rely on an external LDD should use p_1oadidd and not care if it fails with +E_FILE_EXIST. + + +p_loadpdd Load a physical device driver +INT p_loadpdd(TEXT *pName) ; + + +Load the physical device driver (PDD) from the zero terminated file name pName. If pName contains no +extension an extension of .PDD is assumed (an PDD file would normally have the extension .PDD). If +pName is not a full path name the current path is assumed. + + +Returns zero if successful or any of the same negative error numbers as for p_1oadidd above except that, +in this case, the error E_FILE_DEVICE is returned if the specified file name is that of an LDD. + + +p_devdel Delete a device driver +INT p_devdel (TEXT *pName, INT devType) ; + + +Delete the logical (devType is E_LDD) or physical (devType is E_PDD) device driver with the zero +terminated device name pName (as used in p_open but without a trailing ':'). + + +Only device drivers that have been loaded into RAM (and not those devices that are built into the ROM) +can be deleted by this service. + + +Returns zero if successful or one of the following negative error numbers: + + +E_FILE_DEVICE The device driver is not currently loaded. + +E_GEN_NSUP The device driver is a ROM device driver and cannot be deleted. +E_GEN_INUSE The device driver is currently open and cannot be deleted. + +A device dependent Returned by the device driver code. + + +error number + + +If you have loaded an external device driver and finished with it, it is good practice to attempt to delete it +by calling p_devdel and to ignore the return value. The call is harmless if the device is loaded by another +process or if the device is built into the ROM. + + +WARNING: If pname points to a null string, the first located unloadable device driver of the type specified +by devType will be deleted. + + +9-10 + + +9 1/0 SYSTEM + + +p_devqu Query the number of units supported by a device + + +INT p_devqu (TEXT *pName) ; + + +Returns the number of units supported by logical device driver with the zero terminated device name +pName (as used in p_open but without a trailing ':'). The function is not applicable to PDDs. + + +Returns a positive number if successful or one of the following negative error numbers: + + +E_GEN_FAIL Unlimited units (as returned by the r1L: device driver as it can support a large +number of files). + + +E_FILE_DEVICE Device driver not found. +For example: +p_devqu ("TTY"); + + +returns 2 if there are two serial expansion boards fitted. + + +p_devfnd Find all devices + + +HANDLE p_devfnd(HANDLE fHandle, TEXT *pMatch, INT devType, TEXT *pName) ; + + +Write the next device name (as used in p_open but without a trailing ':') of type devType (either z_ppp to +find PDD devices or z_upp to find LDD devices) that matches the zero terminated match string pMatch as +a zero terminated string to pName where fHand1e is zero for the first call and is subsequently the positive +return value from the previous call. When there are no further devices of type devType that match pmatch, +p_devfnd returns E_FILE_DEVICE. + + +Used repeatedly to find all the PDD or LDD devices that match the wild card string pointed to by pmatch. +The buffer at pName should be big enough to receive &_max_NamE+2 bytes. The wild card string pMatch +should remain the same between successive calls. + + +No memory is used by this service and it can be abandoned at any time without taking any further action. +Calls p_panic if fHandle is invalid. +Example + + +LOCAL_C VOID PrintDevices (VOID) +{ +HANDLE fh; +TEXT bb[E_MAX_NAME+2]; + + +fh=0; +FOREVER +{ +fh=p_devfnd(fh,"*",E_LDD, &bb[0]); +if (fh<0) +break; +p_puts (&bb[0]); +} + + +Simple console I/O + + +The simple console functions are provided for "quick and dirty" applications - for example test programs +and software tools. They are not suitable for constructing quality user interfaces. + + +The console functions use the services of the con: device driver to implement the following screen output +and keyboard input functions: + + +p_putch to write a character to the screen +p_puts to write a line of text to the screen and move to the beginning of the next line +p_printf£ to convert numbers to printable form and write them as a line of text to the + + +screen and then move to the beginning of the next line + + +p_print to convert numbers to printable form and write them to the screen + + +9-11 + + +PLIB REFERENCE + + +p_getch to get (without echo) a single character from the keyboard + +p_gets to input (with simple backspace editing) a line of text from the keyboard + +p_getl to display a prompt and then input (with simple backspace editing) text from +the keyboard + + +Redirecting console writes + + +These functions automatically open con: when they are first used. The open channel is stored in the +global static: + + +GLREF_D VOID *winHandle; + + +which is initialised to nuLL. You can open a suitable alternative device (eg a file or Try: ) before the first +usage of a console function to redirect the output functions p_putch, p_print and p_printf. For +example, to redirect to the file a.Jis in the current path, use: + + +p_open (&winHandle, "a.lis",P_FREPLACE |P_FUPDATE) ; +Note that if you do redirect the console to such a device, you should not use p_getch, p_gets or p_getl. +Changing the size of the console window + + +If you want to change the size of the console window, you can do this by declaring the global P_REcT +structure _DefScreenRect and initialising it to the required size before the first usage of a console +function. The P_REcT struct is defined in p_graf-h as: + + +typedef struct +{ +WORD x; /* Horizontal coordinate */ +WORD y; /* Vertical coordinate */ +} P_POINT;. + + +typedef struct +{ +P_POINT tl; /* Top left point */ +P_POINT br; /* Bottom right point */ +} P_RECT;. + + +where the top left coordinates should be (0,0) and the bottom right coordinates should reflect the required +dimensions in character columns and rows as in, for example: + + +GLDEF_D P_RECT _DefScreenRect={{0,0},{10,20}}; +for 10 columns by 20 rows, or: + + +GLDEF_D P_RECT _DefScreenRect; + + +_DefScreenRect.t1l.x=0; +_DefScreenRect.tl.y=0; +_DefScreenRect.br.x=columns; +_DefScreenRect.br.y=rows; + + +Changing the console window mode + + +By default the console starts up in the native mode of the machine. At the time of writing, all SIBO +machines default to single pixel (non-compatibility) mode, with no access to grey. If you want to change +the mode, you can do this by declaring the global variable _DefscreenMode and initialising it to the +required value before the first usage of a console function. The possible modes are: + + +use the native mode of the machine - this is the default value +compatibility mode, allowing Series 3 software to run on the Series 3a +non-compatibility mode, with grey enabled + +compatibility mode, but with grey enabled + + +WN FO + + +Thus, compatibility mode may be set on the Series 3a as follows: + + +GLDEF_D INT _DefScreenMode; + + +_DefScreenMode=1; + + +Values that are not relevant to a particular type of machine are simply ignored. + + +9-12 + + +9 1/0 SYSTEM + + +p_putch Write a character to the console + + +VOID p_putch(UINT c); + + +Write character c to the console, opening the console if necessary. + + +p_puts Write a string to the console + + +VOID p_puts(TEXT *str); + + +Write the zero terminated string str to the console and start a new line. The console is opened if +necessary. + + +p_printf Convert arguments and write line to console + + +VOID p-printé#(TEAT *fstry +44 )¥ + + +Converts multiple arguments to an internal buffer under control of the format string fstr, writes the +complete string to the console screen and then moves the print position to the beginning of the next line. +The console is opened if necessary. + + +The internal buffer is p_maxsysto (258) bytes long and the length of the output (which depends on the +arguments) must be limited to p_maxsys1o-2 (256) bytes per call of p_print£. + + +The format of ¢str is exactly the same as for p_atob, which is described in the chapter Integer +Conversion and Rectangle functions. + + +p_print Convert arguments and write to console + + +VOID p_print (TEXT *fstr, ...); + + +Behaves as for p_printf above except that the print position is not automatically moved to the beginning +of the next line after the write. + + +You can embed \r and \n characters in fstr to move to the beginning of the line and to move down a line +respectively. + + +p_getch Get a character from the console + + +INT p_getch(VOID); + + +Wait for a key to be pressed and return its character code. The console is opened if necessary. + + +p_gets Get a string from the console + + +INT p_gets(TEXT *str); + + +Input (with simple backspace editing) a line of up to p_maxsys1o-1 characters from the keyboard, creating +a zero terminated string at str. The input is terminated by the user pressing the Enter key. + + +Returns the length of the string at str. + + +There should be at least p_maxsyszio bytes at str. The console is opened if necessary. + + +p_getl Get a string with prompt from the console + + +INT p_get1l(TEXT *pmt, TEXT *str, INT len); + + +Write the zero terminated string pmt to the console and input (with simple backspace editing) up to 1en +characters from the keyboard, creating a zero terminated string at str. The input is terminated by the user +pressing the Enter key. + + +Returns the length of the string at str. + + +There should be at least 1en+1 bytes at str. The console is opened if necessary. + + +CHAPTER 10 + + +TIME, TIMERS AND DATES + + +System time + + +The system time is set and sensed as a ULONG, counting the number of seconds since 00:00:00, January 1, +1970 (compatible with UNIX system time). + + +The system time overflows approximately 136 years after 1970 (which is sometime in the year 2106). + + +p_date Return the system time +ULONG p_date (VOID) + + +Return the system time as the number of seconds since 00:00:00, January 1, 1970. + + +p_sdate Set the system time +VOID p_sdate(ULONG newTime) ; +Set the system time to newTime (the number of seconds since 00:00:00, January 1, 1970). + + +Note that setting the system time forward by an interval will cause any absolute timers due in that interval +to expire. + + +Absolute and relative timers + + +In the EPOC operating system a process can be waiting on a timer in two ways: +e The process is in the time delta queue as a result of calling p_sleep, p_sleept Of p_sleepa. + + +e The process is waiting for its I/O semaphore to be signalled by a timer device entry in the time +delta queue after making an asynchronous timer request by calling p_ioc(P_FRELATIVE) or +p_ioc(P_FABSOLUTE) on an open timer channel. + + +Each entry in the time delta queue contains the signed long delta time in system ticks relative to its +predecessor while the head of the queue contains the delta time relative the current system time (for more +on delta queues see the chapter Characters, Strings, Buffers and Queues). The head of the time delta +queue is decremented every system tick and the corresponding timer expires (and is removed from the +queue) when its delta time is zero or negative. If the entry is a process, the process will either run (if it has +the highest priority) or it will wait in the ready queue. If the entry is a timer device entry, the associated +process I/O semaphore is signalled. See the chapter Asynchronous Requests and Semaphores for +information on the I/O semaphore, asynchronous requests and the ready queue. + + +As well as being marked as processes or timer device entries, entries in the time delta queue are also +marked as being absolute or relative. + + +PLIB REFERENCE + + +Absolute timers + + +An absolute timer is characterised by the following: + + +e the timer expiry is set in terms of an absolute time (the number of seconds since 00:00:00, +January 1, 1970) + + +e SIBO machines (as opposed to a PC running EPOC) that have switched off will automatically +switch on when an absolute timer is due to expire + + +e setting the system time forward by an interval will cause any absolute timers due in that interval +to expire + + +Absolute timers are used to implement, for example, alarms for the Diary and Alarms applications on the +MC GI machines. You can set absolute timers to expire after a relative time interval (expressed in +seconds) by adding the required interval to the time returned by p_date. + + +Although absolute timers are converted to relative signed long delta time in the time delta queue, absolute +timer entries can re-launch themselves to cover ranges in excess of 0x7£ffffFfF ticks. + + +Relative timers +A relative timer is characterised by the following: + + +e the timer expiry is set as a time interval relative to the current system time (either as a number of +1/10ths of a second or as a number of system ticks) + + +e the timer stops running while SIBO machines are switched off and it follows that relative timers +do not wake up the operating system up + + +e changing the system time has no effect on relative timers + + +If a relative timer is set to expire after 5 seconds when the system time is advanced by | hour the timer +still expires after 5 seconds (provided the machine is not switched off). + + +If a relative timer is due to expire in 5 seconds when the machine switches off for | hour, the relative +timer actually expires after 1 hour plus 5 seconds. + + +SIBO machines are normally configured to switch off automatically after a period of inactivity (typically +5 minutes). A process that repeatedly waits on a relative timer with an interval shorter than the switch off +inactivity period (for example to implement a clock or a flashing cursor) would by default stop the +machine from ever switching off. Keeping a battery powered machine on indefinitely is normally +undesirable and, in this situation, the application should call p_unmarka (described in the chapter +Processes and Inter-Process Messaging) to stop such activity from keeping the machine on. + + +Relative timers are ultimately converted to system ticks in a signed long - giving them a range of +Ox7f£f£ffFFE ticks, or approximately 2.1 years, on a SIBO machine (which ticks 32 times a second). + + +p_sleep Suspend process for n tenths of a second +INT p_sleep(ULONG n); +Return zero after n 1/10ths of a second has elapsed. + + +Returns E_GEN_OVER immediately if the conversion from 1/10ths to ticks overflows (ie the number of ticks +is greater than 0x7fffffff). + + +This function uses a relative timer. If the machine switches off before the function returns, it will take +indefinitely longer than n tenths of a second to return. + + +p_sleept Suspend process for n system ticks +INT p_sleept (LONG nTicks) ; +Returns zero after ntTicks system ticks if successful or E_GEN_aRc if nTicks is negative. + + +On the SIBO hardware the system ticks 32 times a second. On IBM PCs and compatibles the system ticks +18.2 times a second. The constant E_TICKS_PER_SECOND in epoc.h contains the number of ticks per +second, to the nearest integer. + + +10-2 + + +10 TIME, TIMERS AND DATES + + +A request to sleep for zero ticks is valid and will just force a re-schedule, with the process calling this +service losing the remainder of its time slice if there are other processes at the same priority. + + +This function uses a relative timer. If the machine switches off while the process is suspended, it will take +indefinitely longer than nticks system ticks to return. In the absence of any switching off, the actual time +the process is suspended is greater than or equal to nticks and less than nTicks+1. + + +p_sleepa Suspend process until absolute time + + +INT p_sleepa(ULONG time) ; + + +Return when the system time is time (the number of seconds since 00:00:00, January 1, 1970). Returns +zero 1f successful or E_GEN_aRG if time is earlier than the current system time. + + +This uses an absolute timer which will wake the machine up if necessary when the timer expires. Another +process setting the system time past the expiry time (using p_sdate) will cause p_sleepa to return. + + +eee eee ——————EEEEEEEEeeeEeEeeseeee— +Asynchronous timers + + +The functions p_sleepa, p_sleep and p_sleept are synchronous functions in the sense that they return +only when the requested operation (in this case the expiry of a timer) has completed. With asynchronous +timers, the function call to start the timer returns immediately. This allows other processing to take place +before waiting for any one of a number of events (including the expiry of the timer) by calling p_iowait. +See the chapter Asynchronous Requests and Semaphores for an explanation of asynchronous requests in +general. + + +In EPOC, asynchronous timers are implemented as an I/O device with the device name "TIM:". To use an +asynchronous timer, you open a channel to "TIM:" and use: + + +p_ioc (P_FRELATIVE) to start a relative timer +p_ioc (P_FABSOLUTE) to start an absolute timer +p_iow (P_FCANCEL) to cancel a timer +p_close to close a timer channel + + +The constants p_FRELATIVE, P_FABSOLUTE and p_FcaANCcEL are defined in p_file.h. See the chapter //O +System for a description of the I/O system in general. + + +If you want to run multiple timers in parallel, you open a channel for each timer needed. + + +Although you can open a timer channel and use p_iow(P_FRELATIVE) Of p_iow(P_FABSOLUTE) (rather +than p_ioc) to the same effect as p_sleep Or p_sleepa respectively, the latter should be preferred for their +simplicity and efficiency. + + +p_open(“TIM:”) Open a timer channel + + +INT p_open(VOID **pptcb,TIM:,-1); + + +Open a timer channel and write the address of the timer control block to *ppt cb. Returns zero if +successful or the negative error number &_cEN_Nomemory if, for example, it failed to allocate memory for +the control block. + + +p_ioc(P_FRELATIVE) Start a relative timer + + +VOID p_ioc(VOID *ptcb, P_FRELATIVE, WORD *pstat, ULONG *pn); +Start a relative timer to expire after *pn tenths of a second. +Calls p_panic if a timer is already pending on channel ptcb. + + +While the timer is pending, *pstat contains E_FILE_PENDING. When the timer expires successfully, +*pstat is set to zero and the I/O semaphore is signalled. + + +The timer is not started and *pstat is set to E_GEN_OVER if the conversion from tenths of a second to ticks +overflows (ie the number of ticks is greater than ox7£f£ffFfF). + + +10-3 + + +PLIB REFERENCE + + +p_ioc(P_FABSOLUTE) Start an absolute timer + + +VOID p_ioc(VOID *ptcb, P_FABSOLUTE, WORD *pstat, ULONG *ptime) ; + + +Start an absolute timer to expire when the system time is *pt ime (the number of seconds since 00:00:00, +January 1, 1970). + + +Calls p_panic if a timer is already pending on channel pt cb. + + +While the timer is pending, *pstat contains E_FILE_PENDING. When the timer successfully expires, +*pstat is set to zero and the I/O semaphore is signalled. + + +The timer is not started and *pstat is set to E_GEN_aRG if *ptime is earlier than the current system time. + + +p_iow(P_FCANCEL) Cancel a timer + + +INT p_iow(VOID *ptcb, P_FCANCEL) ; +Cancel a timer on channel ptcb and return zero. + + +The operation is harmless if no timer is pending. This is important because there is always a chance that a +timer will expire before the cancel gets to it. If the cancel does get to the timer before it expires, the I/O +semaphore is still signalled but *pstat is set to E_FILE_CANCEL rather than zero. However, when +cancelling a timer, you don't normally care how the timer actually completed. It is common to call +p_waitstat immediately after the cancel to "use up" the signal. + + +To reset a timer, you first cancel the timer using p_iow(P_FCANCEL) followed by a call to p_waitstat and +then call p_ioc (P_FRELATIVE) to start the timer again. + + +p_close Close a timer channel +INT p_close(VOID *ptcb); +Close the timer channel ptcb and return zero. + + +You should close a timer channel when you no longer need it. + + +Converting between binary representations of time + + +The system time format sacrifices range to obtain high compression and is the most convenient and +efficient representation for adding and subtracting small time intervals such as seconds, minutes, hours +and days. + + +There are 86,400 seconds in a day (P_NseEcpay is defined as 86400L in p_date.h). +There are three different binary representations for time in PLIB: +e The number of seconds since 00:00:00, January 1, 1970 (system time format) +e Days since January 1, 1900 and seconds in day +e (Year since 1900,Month,Day) and (Hour, Minute,Second) + + +Note that the first representation works from a base year of 1970 while the second two representations +work from a base year of 1900. + + +PLIB contains conversion routines that convert both ways between adjacent representations in the above +list. By combining conversion functions, you can convert between the first and third representation. + + +The second format measures the days since January | 1900 (day=0 for Jan 1) and the seconds since +00:00:00 and is stored in a p_payszc struct, defined in p_date.h as follows: + + +typedef struct +{ +ULONG day; /* day number since Jan 1 1900 */ +ULONG sec; /* seconds in day, 0 to 86399 */ +} P_DAYSEC;. + + +10-4 + + +10 TIME, TIMERS AND DATES + + +The day number is useful for date calculations not involving time. Examples are to count the number of +days between two dates, or to calculate a new date from a base date and a number of days (positive or +negative). + + +The third format is closest to a human understandable representation of the date and time and is defined +by the p_pate struct in p_date.h: + + +typedef struct +{ +UBYTE year; /* Year since 1900 (0 is 1900) */ +UBYTE month; /* Month number in year, 0 to 11 */ +UBYTE day; /* Day number in month, 0 to 30 */ +UBYTE hour; /* Hour in day, 0 to 23 */ + +UBYTE minute; /* Minute in hour, 0 to 59 */ + +UBYTE second; /* Second in minute, 0 to 59 */ +UWORD yrday; /* Day in year */ + +} P_DATE;. + + +The last member, yrday is a function of year, month and day. It is provided when p_parte is generated +from p_pays«c but is ignored when converting from P_paTE. + + +p_sttods Convert system time to P_DAYSEC time + + +VOID p_sttods(ULONG *pstim, P_DAYSEC *pds) + + +Convert *pstim from system time format (the number of seconds since 00:00:00, January 1, 1970) to the +number of days since 1900 and the number of seconds in the day, both being written to pas. + + +p_dstost Convert P_DAYSEC time to system time + + +INT p_dstost (P_DAYSEC *pds, ULONG *pstim) ; + + +Convert pds from the number of days since 1900 and the number of seconds in the day to system time +format (the number of seconds since 00:00:00, January 1, 1970). The result is written to *pstim. + + +Returns zero if successful, or one of the following negative error numbers: + + +E_GEN_OVER date in pds is too late for system time +E_GEN_UNDER date in pds is too early for system time (ie before 1970) +E_GEN_ARG seconds is greater than seconds in day + + +p_dstodt Convert P_DAYSEC time to P_DATE time + + +INT p_dstodt (P_DAYSEC *pds, P_DATE *pdt); + + +Convert p_paysec time pds (days since 1900, seconds in day) to p_paTE time pdt (year, month, day, +hour, minute, second and day in year) and return zero if successful or one of the following negative error +numbers: + + +E_GEN_OVER the year is greater than 255 (year 2155) +E_GEN_ARG seconds is greater than seconds in day + + +As well as the date and time, this function calculates pdt->yrday (the day number of the year, where day +zero 1s January 1). Although you could calculate this yourself from the year, month and day it is not a +simple calculation since it involves adding the number of days in preceding months and thus depends on +leap years. + + +This function actually performs two independent calculations: +¢ converting the number of days since 1900 to year, month, day and day in year (date calculation) + + +¢ converting the number of seconds since 00:00:00 to hours, minutes and seconds (time of day +calculation) + + +Both calculations may be abandoned if either calculation fails. If you are only interested in one of the +calculations, set the other member of p_paysEc to zero (which is a legal input for both calculations). + + +10-5 + + +PLIB REFERENCE + + +p_dttods Convert P_DATE time to P_DAYSEC time + + +INT p_dttods(P_DATE *pdt, P_DAYSEC *pds); + + +Validate the p_DaTE format pdt and convert it to the p_payszEc format pds and return zero if successful or +the negative E_GEN_arc if the content of pdt is invalid (ie no such date or time exists). The value of +pdt->yrday is ignored. + + +The validation can fail for one or more of the following reasons: +@ pdt ->month is outside the range 0 to 11 + + +¢ pdt ->day is outside the range for the particular month taking into account leap years for +February + + +@ pdt ->hour is outside the range 0 to 23 +@ pdt->minute is outside the range 0 to 59 +@ pdt->second is outside the range 0 to 59 +This function actually performs two independent calculations: +e converting the year, month and day to the number of days since January 1 1900 (date calculation) + + +e converting the hours, minutes and seconds to the number of seconds since 00:00:00 (time of day +calculation) + + +Both calculations may be abandoned if either calculation fails. If you are only interested in one of the +calculations, set the members of P_DATE corresponding to the other calculation to zero (zero is a legal +input for all members in both calculations). + + +p_dayinm Find the number of days in the specified month +INT p_dayinm(INT year, INT month); + + +Return the number of days in month month of year year where year is the number of years since 1900 +(zero is 1900) and month is 0 to 11 inclusive. (Returns the negative E_GEN_aRc if month is greater than 11.) + + +The year is required because it affects the number of days in February. This may be used to test for a leap +year, for example: + + +if (p_dayinm(year,1)==29) + + +p_wkday Convert day since 1900 to day in week +INT p_wkday(ULONG nDay) ; + + +Returns the week day number given the number of days nDay since January 1 1900. The value returned is +in the range 0 to 6, with 0 being Monday and 6 being Sunday. + + +The day number since 1900 would normally come from a structuresP_DAYSECc struct. + + +p_weekno Calculate week number in year + + +INT p_weekno(ULONG nDay) ; + + +Return the week number, in the range | to 53 inclusive, of the week containing day nDay (the number of +days since January 1 1900). Returns zero if successful or E_GEN_aRG if nDay exceeds the year 2155. + + +The value returned is dependent on the value of the system structuresE_conrte structure field +startOfWeek (see p_getctd in this chapter). + + +10-6 + + +10 TIME, TIMERS AND DATES + + +Time and date components in text form + + +The functions in this section get a range of date and time components in text form. They constitute a +more primitive set of functions than those, described in the following section, that generate strings +containing full date and/or time representations. + + +These functions are based on language-dependent information that is built into the ROM. If you use these +functions, your code should automatically work on, for example, English, French and German machines. + + +The functions are: + + +p_nmday to get the day names (eg Monday, Tuesday) + +p_nmmon to get the month names (eg January, February) + +p_nmdaya to get the day name abbreviations (eg Mon, Tue) + +p_nmmona to get the month name abbreviations (eg Jan, Feb) + +p_getsuffixes to get the 31 day in month number suffixes (eg st, nd) + +p_getampmtext to get the am and pm suffixes + +p_getctd to get a copy of the setable country-dependent data and time preferences (such + + +as whether to use a 12 or 24 hour clock) +The following example displays the system time in the form: +Monday, 11th April 1988 11:03 +and uses many of the functions described in this chapter. + + +#include + + +GLDEF_C VOID PrintDateTime() +{ +ULONG st; +P_DAYSEC ds; +P_DATE dt; +E_CONFIG cfg; +TEXT DayName [32]; +TEXT MonthName [32]; +TEXT Suffix[31] [3]; + + +st=p_date(); +p_sttods (&st, &ds) ; +p_dstodt (&ds, &dt) ; +p_nmday (&DayName[0],p_wkday (ds.day) ); +p_nmmon (&MonthName[0],dt.month) ; +p_getsuffixes (&Suffix[0][0]); +p_getctd(&cfg) ; +p_printf("%s, Suss Ss Su SO2uscs02u", +&DayName[0],dt.day+1, &Suffix[dt.day] [0], +&MonthName[0],dt.year+1900, +dt .hour,cfg.timeSeparator,dt.minute) ; + + +} + + +This example is somewhat artificial since the same action can be performed more simply by the use of +p_nowtostr, described in the following section. + + +Object-oriented programmers may prefer to use the time class in OLIB (described in the OLIB Reference +manual of the SIBO SDK Object Oriented Extension) to produce textual representations of the date and +time. + + +10-7 + + +PLIB REFERENCE + + +p_nmday Get the day name + + +VOID p_nmday (TEXT *buf, INT daynum) ; + + +Write the language dependent name of day daynum as a zero terminated string to buf where daynum should +be in the range 0 to 6 inclusive and day 0 is Monday. + + +If you are working in a fixed language, you will know how long the longest day name is. If you are writing +a program that has to work with different language ROMs, you can use the fact that the tool that builds +the day name list for the ROM limits a particular day name to E_MAX_DAY_NAME (32), including the zero +terminator. + + +p_nmdaya Get the day name abbreviation +VOID p_nmdaya(TEXT *buf, INT daynum) ; +This function is only available in EPOC version 3.18 or later. + + +Write the language dependent abbreviation for the name of day daynum as a zero terminated string to buf +where daynum should be in the range 0 to 6 inclusive and day 0 is Monday + + +All day name abbreviations for a particular language are of the same length and could be one, two or three +characters. In no language will day name abbreviations exceed three characters. + + +p_nmmon Get the month name +VOID p_nmmon(TEXT *buf, INT monthnum) ; + + +Write the language dependent name of month monthnum as a zero terminated string to buf where +monthnum should be in the range 0 to 11 inclusive and month 0 is January. + + +If you are working in a fixed language, you will know how long the longest month name is. If you are +writing a program that has to work with different language ROMs, you can use the fact that the tool that +builds the month name list for the ROM limits a particular month name to E_Max_MONTH_NAME (32), +including the zero terminator. + + +p_nmmona Get the month name abbreviation +VOID p_nmmona(TEXT *buf, INT monthnum) ; +This function is only available in EPOC version 3.18 or later. + + +Write the language dependent abbreviation of the name of month monthnun as a zero terminated string to +buf where monthnum should be in the range 0 to 11 inclusive and month 0 is January. + + +All month name abbreviations for a particular language are of the same length and could be one, two or +three characters. In no language will month name abbreviations exceed three characters. + + +p_getsuffixes Get the day-in-month suffixes +VOID p_getsuffixes (TEXT *buf); +Write the language dependent array of the 31 day-in-month number suffixes to buf. + + +The suffixes are written as an array of 31 3-byte fixed length elements where each element contains 0, 1 +or 2 characters followed by a zero terminator (suffixes contain at most 2 characters in any language). +There must be at least 31*3 bytes of memory at buf. + + +Each element in the array contains the suffix for the corresponding day of the month. For example, in +English, the first element contains "st" and the second element contains "nd". + + +p_getampmtext Get the am and pm suffixes +VOID p_getampmtext (TEXT *buf, INT n); + + +Write the language dependent am or pm time suffix as a zero terminated string to buf. If n is 0, write the +am suffix. If n is 1, write the pm suffix. + + +The am and pm suffixes are limited to 2 characters in any language. + + +10-8 + + +p_getctd + + +VOID p_getctd(E_CONFIG *pcfg); + + +10 TIME, TIMERS AND DATES + + +Get time representation preferences + + +.Write a copy of the system structuresz_conFiIe struct to pcfg where the &_conFice struct is defined, in +p_config.h, as: + + +typedef struct + + +{ + + +UWORD countryCode; + +WORD gmtOffset; + +UBYTE dateType; + +UBYTE timeType; + +UBYTE currencySymbolPosition; +UBYTE currencySpaceRequired; +UBYTE currencyDecimalPlaces; +UBYTE currencyNegativelInBrackets; +UBYTE currencyTriadsAllowed; +UBYTE thousandsSeparator; +UBYTE decimalSeparator; +UBYTE dateSeparator; + +UBYTE timeSeparator; + +UBYTE currencySymbol [9]; +UBYTE startOfWeek; + +UBYTE summerTime; + +UBYTE clockType; + +UBYTE dayAbbreviation; + +UBYTE monthAbbreviation; +UBYTE workDays; + +UBYTE units; + +UBYTE spare[9]; + + +} E_CONFIG; + + +In the context of this chapter we are interested in the following items: + + +gmtOffset + + +dateType + + +timeType + + +dateSeparator + + +timeSeparator + + +startOfWeek + + +summerTime + + +cloc + + +dayA + + +mont + + +work + + +kType + + +bbreviation + + +hAbbreviation + + +Days + + +the offset in minutes of the local system time from Greenwich Mean Time. + + +one of &_pate_usa for MM/DD/YY, £_pate_euRopE for DD/MM/YY or +E_DATE_gapan for YY/MM/DD. + + +either =_Trme_12 for a 12 hour clock or E_tT1ime_24 for a 24 hour clock. +the character code of the date separator. For example, the character '/’. +the character code of the time separator. For example, the character ':'. + + +the day number (in the range 0 to 6 inclusive where day 0 is Monday) of the +first day in the week - as used by p_weekno. This is normally either Sunday +(day 6) or Monday (day 0). For example, it is normally Sunday for USA +machines and Monday for UK machines. + + +a bit pattern indicating summer time-zones as follows: E_pst_Home if the +system time should be adjusted for summer time; E_DsT_EUROPEAN if a +European time-zone should be adjusted for summer time; z_DsST_NORTHERN if a +non-European time-zone in the Northern hemisphere should be adjusted for +summer time; E_DST_SOUTHERN if a time-zone in the Southern hemisphere +should be adjusted for summer time. + + +either E_ANALOGUE_CLOCK to indicate a preference for an analogue clock +display or =_p1G1ITAL_cLock to indicate a preference for a digital clock display + + +how many leading characters to take from the day name (as returned by +p_nmday) to abbreviate the day name + + +how many leading characters to take from the month name (as returned by +p_nmmon) to abbreviate the month name + + +a bit mask of 7 bits indicating (by being set) which days are to be considered +work days where the least significant bit corresponds to Monday + + +The data may be set using p_setctd - as described in the chapter General System Services. + + +10-9 + + +PLIB REFERENCE + + +Generating time and/or date strings + + +The functions in this section construct text strings that represent the date and time in a range of formats. + + +The functions are based on language-dependent information that is built into the ROM, in particular, the +system E_CONFIG struct (see the description of p_getctd in the Language and country section of the +General System Services chapter). If you use these functions, your code should automatically work on, for +example, English, French and German machines. + + +Note that the implementation of these functions uses static data. In consequence they may not be used in +the code of a dynamic library (DYL). + + +Date and time format strings + + +The form of the output of the date and time conversion functions described below is controlled by a +format string, in a similar way to the format strings used by p_printf, p_atob and p_atos. + + +The format string consists of literal text intermixed with embedded commands. The literal text is simply +copied to the output and the embedded commands are replaced by the corresponding time or date element. + + +An embedded command is of the form %c or %*c, where c is one of the characters listed below, and * +indicates that the output should be in an abbreviated form. The abbreviated form can be specified for all +commands, but in some cases there is no difference between the full and abbreviated forms. + + +The available commands are as follows: +%% replaced by a single '%' character. Abbreviation has no effect. + + +%: replaced by the time separator character as specified by the timeSeparator +field of the system E_conFie struct. Abbreviation has no effect. + + +%/ replaced by the date separator character as specified by the dateSeparator field +of the system E_conrié struct. Abbreviation has no effect. + + +aN depending on the supplied time of day, this is replaced by the appropriate am or +pm text (as obtained by use of p_getampmt ext). Abbreviation supplies just the +first character of this text. Note that abbreviation may not be appropriate in +some languages. + + +&D replaced by the day-in-month number, in the range 01 to 31, as two digits with +a leading zero as necessary. Abbreviation suppresses any leading zero. + + +%E replaced by the day name, as supplied by p_nmday. Abbreviation causes the +name to be truncated to the number of characters specified in the +dayAbbreviation element of the system E_CONFIG struct. + + +3H replaced by two digits in the range 00 to 23 (24-hour format) corresponding to +the hours component of the supplied time of day. Abbreviation suppresses any +leading zero. + + +SI replaced by two digits in the range 01 to 12 (12-hour format) corresponding to +the hours component of the supplied time of day. Abbreviation suppresses any +leading zero. + + +oM replaced by two digits in the range 01 to 12 corresponding to the month number +for the supplied date. Abbreviation suppresses any leading zero. + + +3N replaced by the month name for the supplied date. Abbreviation causes the +name to be truncated to the number of characters specified in the +monthAbbreviation element of the system E_CONFIG struct. + + +%S replaced by two digits in the range 00 to 59 corresponding to the seconds +component of the supplied time of day. Abbreviation suppresses any leading +Zero. + + +ST replaced by two digits in the range 00 to 59 corresponding to the minutes +component of the supplied time of day. Abbreviation suppresses any leading +Zero. + + +ow replaced by two digits in the range 01 to 53 corresponding to the week number +for the supplied date, as provided by p_weekno. Abbreviation suppresses any +leading zero. + + +10-10 + + +ole +x + + +ole +iS) + + +ole +Ww + + +ole +& + + +oe +uo + + +\ +oO) + + +ole +a + + +10 TIME, TIMERS AND DATES + + +replaced by the suffix text corresponding to the (p) day number for the +supplied date. Abbreviation has no effect. + + +replaced by four digits, in the range 1900 to 2155, corresponding to the year +number for the supplied date. Abbreviation discards the first two digits (note +that, for example, both 1900 and 2000 will appear as 00). + + +replaced by three digits, in the range 001 to 366, corresponding to the day-of- +year number for the supplied date. Abbreviation discards any leading zeros. + + +replaced by the first component of a three-component (day, month and year) +date, where the order of the components is determined by the value of the +dateType component of the system &_conrie struct. Abbreviation has no effect, +but the form of the generated text is conditioned by the toggle commands +described below. In the absence of any toggles, %1 is equivalent to: + +sp if dateType 1S E_DATE_EUROPE + +gm if dateType iS E_DATE_USA + +sy if dateType iS E_DATE_JAPAN + + +replaced by the second component of a three-component (day, month and year) +date, where the order of the components is determined by the value of the +dateType component of the system &_conrie struct. Abbreviation has no effect, +but the form of the generated text is conditioned by the toggle commands +described below. In the absence of any toggles, ¢2 is equivalent to: + +gm if dateType 1S E_DATE_EUROPE + +zp if dateType iS E_DATE_USA + +gm if dateType iS E_DATE_JAPAN + + +replaced by the third component of a three-component (day, month and year) +date, where the order of the components is determined by the value of the +dateType component of the system &_conrie struct. Abbreviation has no effect, +but the form of the generated text is conditioned by the toggle commands +described below. In the absence of any toggles, s3 is equivalent to: + +sy if dateType iS E_DATE_EUROPE + +sy if dateType iS E_DATE_USA + +sp if dateType iS E_DATE_JAPAN + + +replaced by the first component of a two-component (day and month) date, +where the order of the components is determined by the value of the dateType +component of the system &_conFie struct. Abbreviation has no effect, but the +form of the generated text is conditioned by the toggle commands described +below. In the absence of any toggles, %4 is equivalent to: + +sp if dateType 1S E_DATE_EUROPE + +zm if dateType iS E_DATE_USA Of E_DATE_JAPAN + + +replaced by the second component of a two-component (day and month) date, +where the order of the components is determined by the value of the dateType +component of the system E_conFie struct. Abbreviation has no effect, but the +form of the generated text is conditioned by the toggle commands described +below. In the absence of any toggles, %5 is equivalent to: + +gm if dateType 1S E_DATE_EUROPE + +sp if dateType iS E_DATE_USA OF E_DATE_JAPAN + + +replaced by the hour in the format determined by the value of the timeType +component of the system &_conrte struct. Abbreviation discards any leading +zero. The action of 6 is equivalent to: + +3H if timeType 1S E_TIME_24 + +%1 if timeType 1S E_TIME_12 + + +replaced by the am/pm text (as for sa) if the timeType component of the system +E_CONFIG Struct has the value z_t1mz_12, otherwise produces no output. If +output is produced, abbreviation reduces the output to just the first character of +the text, as for za. + + +Note that format strings of the form "s1%/%2%/%3" and "4%/%5" respectively generate three- and two- +component dates that automatically conform to the system configuration dateType setting, and that a +format string of the form "%63:%T%:%s%7" generates a time that automatically conforms to the system +configuration timeType setting. + + +10-11 + + +PLIB REFERENCE + + +The commands 31, %2, %3, 4 and %5 are conditioned by the following toggles: + + +ole + + +F produces no output, but toggles the behaviour of subsequent day items between + +numeric (the default) and name generation. For example, if dateType is +E_DATE_EUROPE and the supplied date is 09/03/1993, the format string +"$1 %F%1 %F%1" will generate the (English) string "09 Tuesday 09". +Abbreviation has no meaning, and is ignored. The items conditioned by this +toggle depend on dateType as follows: + +%1 and %4 for E_LDATE EUROPE + +%2 and %5 for E_LDATE_USA + +%3 and %5 for E_DATE_JAPAN + + +ole +[e) + + +produces no output, but toggles the behaviour of subsequent month items +between numeric (the default) and name generation. For example, if dateType +iS E_LDATE_EUROPE and the supplied date is 09/03/1993, the format string +"$2 %0%2 %0%2" will generate the (English) string "03 March 03". +Abbreviation has no meaning, and is ignored. The items conditioned by this +toggle depend on dateType as follows: + +32 and %5 for E_DATE EUROPE + +%1 and 34 for E_LDATE_USA + +%2 and %4 for E_DATE_JAPAN + + +ole +(9) + + +produces no output, but toggles the behaviour of subsequent day items between +their full (the default) and their abbreviated forms. For example, if dateType is +E_DATE_EUROPE and the supplied date is 09/03/1993, the format string +"SF%1 %G%1 %G%1" will generate the (English) string "Tuesday Tue Tuesday". +Abbreviation has no meaning, and is ignored. The items conditioned by this +toggle depend on datetype as follows: + +%1 and %4 for E_LDATE EUROPE + +%2 and %5 for E_LDATE_USA + +%3 and %5 for E_DATE_JAPAN + + +ole +ae] + + +produces no output, but toggles the behaviour of subsequent month items +between their full (the default) and their abbreviated forms. For example, if +dateType 18 E_LDATE_EUROPE and the supplied date is 09/03/1993, the format +string "80%2 %P%2 %Pp%2" will generate the (English) string +"March Mar March". Abbreviation has no meaning, and is ignored. The items +conditioned by this toggle depend on dateType as follows: + +32 and %5 for E_DATE EUROPE + +%1 and %4 for E_LDATE_USA + +%2 and %4 for E_DATE_JAPAN + + +ole +aq + + +produces no output, but toggles the behaviour of subsequent year items between +their full (the default) and their abbreviated forms. For example, if dateType is +E_DATE_EUROPE and the supplied date is 09/03/1993, the format string +"$3 %U%3 %U%3" will generate the string "1993 93 1993". Abbreviation has no +meaning, and is ignored. The items conditioned by this toggle depend on +dateType as follows: + +33 for E_LDATE EUROPE + +%3 for E_DATE_USA + +%1 for E_DATE_JAPAN + + +ld +fed! + + +produces no output, but toggles between the absence (the default) and the +presence of a day number suffix following a day-in-month number (but not a +day name) generated by 1, 2 or 33. For example, if dateType is +E_DATE_EUROPE and the supplied date is 09/03/1993, the format string + +"$G%1 %L%1 %L%1" will generate the (English) string "9 9th 9", but +"SF%G%1 %L%1 %L%1" will generate the (English) string "Tue Tue Tue". +Abbreviation has no meaning, and is ignored. + + +10-12 + + +10 TIME, TIMERS AND DATES + + +Function return values + + +The Window Server animates time displays either by flashing the last time separator character in the text +or, if the text contains a seconds display, by updating the time every second. + + +All the functions described below return a value that indicates the form of animation required. The +possible return values are: + + +-2 The display does not show seconds and contains no time separators. The +display is not animated. + + +-1 The display shows seconds. Animation updates the display every second. + + +any other value The return value is the offset in the string to the last time separator character. +Animation flashes this character. + + +p_dt2str Convert a P_DATE time to a string +INT p_dt2str(TEXT *buf, TEXT *fstr, P_DATE *pdt); + + +Write a zero terminated string containing formatted date and time text to buf, controlled by the zero +terminated format string pointed to by fstr and the content of the p_paTE struct pointed to by pat. + + +The format string fstr contains literal text, embedded with commands, as described above. + + +p_ds2str Convert a P_DAYSEC time to a string + + +INT p_ds2str(TEXT *buf, TEXT *fstr,P_DAYSEC *pds); + + +Write a zero terminated string containing formatted date and time text to buf, controlled by the zero +terminated format string pointed to by fstr and the content of the p_payszc struct pointed to by pas. + + +The format string fstr contains literal text, embedded with commands, as described above. + + +p_st2str Convert a system time to a string + + +INT p_st2str(TEXT *buf, TEXT *fstr, ULONG *pst); + + +Write a zero terminated string containing formatted date and time text to buf, controlled by the zero +terminated format string pointed to by fstr and the system time (seconds since 00:00:00, January 1, +1970) pointed to by pst. + + +The format string fstr contains literal text, embedded with commands, as described above. + + +p_now2str Convert the current time to a string + + +INT p_now2str(TEXT *buf, TEXT *fmt); + + +Write a zero terminated string containing formatted date and time text to buf, controlled by the zero +terminated format string pointed to by fstr and the currently set time. + + +The format string fstr contains literal text, embedded with commands, as described above. + + +10-13 + + +CHAPTER 11 + + +FILES + + +Files in EPOC + + +The file server + + +The file server is a high priority system process (with process name SYS$FSRV) performing all file +related operations on behalf of "client" processes. + + +An application process must connect to the file server before using its services. However, this is normally +taken care of by the C startup module (the code that precedes main) and supplied as standard for use with +the PLIB library. (Most applications need the services of the file server and the overhead of connecting to +the file server is modest.) + + +A client process sends the file server an inter-process message to request a file server service. However, +the application programmer does not program at the message passing level but uses the interface provided +by the r1L: device (ie using p_open) together with the interface provided by a number of ROM resident +functions (eg p_delete to delete a file) as described in this chapter. + + +Any process that attempts to send a message to the file server without having connected is panicked with +panic number 41. + + +File systems + + +The file server supports multiple file systems (also called nodes). In principle, the file server supports any +number of file systems (p_open may be used to get a list of the file systems as described later in this +chapter). At the time of writing, three file systems have been implemented: + + +LOC: : The local filing system with devices M: (the RAM drive) and SSD drives A:, +B:, ...(where the quantity depends upon the hardware). + + +REM: : The remote filing system, available while the file server is connected to a +remote file server. The structure of the filing system depends upon what the +remote system is. If the remote system is a PC or another SIBO machine, the +structure is the same as for Loc: :. + + +ROM: : The ROM filing system, used to access ROM-based files. This filing system is +not normally visible to the user. The Rom: : file system does not support devices +or directories. + + +Within the toc: : file system (and where REM: : is connected to a PC or another SIBO machine), the +devices and directories structure is compatible with the MSDOS filing system. + + +File systems are implemented as PDDs (Physical Device Drivers) which are normally resident in the +ROM (PDDs are described in the chapter //O System). If you use (as described in I/O System): + + +GLDEF_C VOID PrintPDDs (VOID) +{ +HANDLE h; +TEXT b[E_MAX_NAME+2]; + + +for (h=0; (h=p_devfnd(h,"*",E_PDD, &b[0]))>=0;) + + +p_printf(" %s",&b[0]); +} + + +11-1 + + +PLIB REFERENCE + + +to get a list of PDDs, the list would include: + + +FSY.LOC the toc:: PDD +FSY.ROM the Rom:: PDD +FSY.REM the REM:: PDD +SSD drives + + +SIBO machines have 2 to 4 (depending on the machine) Solid State Disk (SSD) drives, taking SSDs of +various type and capacity (from 32K bytes to 8Mb and beyond). SSDs are so called because they are +based on silicon memory with no moving parts. The different types of SSD (in order of decreasing unit +cost) include: + + +e static RAM with integral Lithium battery +e Flash EPROM +¢ one-time-programmable ROM +e masked ROM +An SSD drive can physically and logically mount any type of SSD. + + +The physical interface between an SSD and the drive has only 6 connectors (4 for power, and 2 for data). +The 2 data connections are an instance of a high speed serial channel. This is a fundamental part of the +SIBO hardware architecture, implemented in custom chips. It can be used to communicate with other +peripherals. + + +The high speed serial channel is driven synchronously by a clock which normally runs at 3.84 MHz, +giving a data transfer speed comparable to the more expensive hard disks on PCs but, without any latency +for the drive head to position to the required track. Writing to a Flash SSD is slower because of the time +taken to program the EPROM and, in this case, the speed of writing is twice as fast as writing to a typical +floppy disk on a PC. + + +SSDs are driven by the Loc: : file system using a number of subsidiary PDDs (Physical Device Drivers) +handling the different SSD types and the internal m: device. The list of PDDs produced by calling +PrintPDDs (described above) would include: + + +LOC. TYO the RAM SSD PDD +LOC. TY1 the Flash SSD PDD +LOC.TYM the internal RAM (“:) PDD + + +Files are stored in a completely different way on RAM SSDs from Flash SSDs. + + +SSD drive doors have a switch that keeps the file server informed of possible SSD removals and +insertions. After an SSD drive door has been opened the file server checks each drive to see if it contains a +new SSD. When the file server detects a new SSD it automatically mounts the new SSD. + + +If a previous occupant of the SSD drive had one or more files open on it, the file server keeps a record of +the SSD. When access is subsequently attempted on a file channel on that SSD, the file server uses +p_notify (described in the chapter Error Handling) to request the user to replace the SSD and to retry or +to abandon the channel. If the user replaces the SSD and selects retry such that the operation completes +successfully, the application process is not made aware of any problem. If the user chooses to abandon the +channel, the operation completes with the error E_FILE_ABoRT. When this occurs, the channel is +disconnected from the file and put into an abort state where the only possible operation is to close the +channel (any operation other than p_close fails with the error E_FILE_ABORT). + + +An application that receives an E_FILE_ABORT error can either make do without the file (which probably +means having to exit) or to appeal yet again to the user to put the SSD back in the drive and, if the user +does put the SSD back, to locate and re-open the file and recover. The latter takes more code but is kinder +to the user. + + +11 FILES + + +Unattended applications + + +The file server will also normally call p_notify to give the user a chance to retry any file operation that +fails on a mounted medium. This kind of failure is rare on SSDs but is more common on magnetic media - +especially floppy disks. In some cases, the user may be able to correct the error (eg to close the door on a +floppy disk drive) and successfully retry. If the user abandons, the file operation completes with an error +other than £_FILE_ABORT (eg E_FILE_READ if a floppy disk read fails). + + +This scheme whereby the file server uses p_notify to give the user a chance to correct the problem and +retry works well when the client process is an interactive application but poorly if the requesting process is +designed to run unattended (eg a communications program) or is itself a server process (eg the window +server trying to read a font file). Such processes can use p_setnotify (FALSE), described in the chapter +Error Handling, to stop the file server from using the notify service. In this case all errors are returned +directly. + + +RAM SSDs + + +RAM SSDs use static RAM backed up by an integral Lithium battery. While the RAM SSD is inserted in +an SSD drive, it draws current from the SIBO machine. When the SSD is removed, it relies on its internal +battery to maintain its data. + + +The allocation of the space for directories and files on a RAM SSD is block structured - identical to that +which is used on PC hard disks and floppy disks. Just like floppy disks on a PC, there is a limit to the +number of files that may appear in the root directory (where this limit includes directory files). This root +directory limit does not limit the number of files that can be stored on a RAM SSD since any number of +files may be stored in subdirectories. + + +The format function (described below in this chapter) automatically allocates the capacity of the root +directory as a function of the capacity of the SSD. The dependence of the number of files that may appear +in the root directory on SSD size is as follows: + + +less than 128K +128K or greater but less than + + +256K or greater but less than + + +512K or greater but less than 1M +1M or greater but less than 2M +2M or greater but less than 4M +4M + +6M + +8M + + +The RAM SSD PDD on the toc: : file system on SIBO machines does not buffer written data. This +protects the integrity of the SSD contents from being corrupted by application process or system crashes +occurring while files are open, or by the removal of the SSD while files are open on it. + + +Flash SSDs + + +Flash SSDs use Flash EPROM chips in which all the data bits are initially set. A particular bit may be +cleared by programming but it can not be set again unless all the bits on the chip are set (by erasing the +chip). Unlike older generation EPROMs, Flash EPROMs are erased electrically (rather than by exposure +to UV light). The speed with which Flash can be programmed is also substantially faster than the old UV +erasable EPROMS. + + +A Flash SSDs may be erased in its SSD drive by formatting (formatting is described later in this chapter). + + +Since Flash memory does not require a battery to maintain it, the data on a Flash SSD is very secure - +more so than on RAM SSDs or magnetic media. Flash memory is also cheaper than RAM. + + +The Flash filing system is designed such that the logical interface to files on a Flash SSD (whether +reading or writing) is entirely equivalent to that on other devices (RAM SSD, hard disk etc). However, +when overwriting or when deleting a file, space is consumed and is not recovered until the SSD is next +formatted. Note also that renaming a file, setting the date and time or setting the file attributes all use up +additional space and can therefore fail through lack of remaining capacity (the function returns +E_FILE_FULL). However, deleting a file does not consume any further space. + + +11-3 + + +PLIB REFERENCE + + +You can randomly access a Flash file and overwrite sections of it in exactly the same way as for any +other file. However, in contrast to read/write block storage devices, overwriting incurs a storage +overhead. For example, the following code: + + +pos=0L; + + +do +{ +p_seek (chan, F_FABS, pos) ; +} while (!p_write(chan,"Pointless", 8) ); + + +continuously overwrites the first 8 bytes of the file on channel chan. On a RAM file, this would work +indefinitely and just exercise the hardware. On a Flash file, the code would work but each iteration would +use up space on the Flash SSD and the p_write would eventually fail and return E_FILE_FULL. + + +In practice, you should not worry about limited overwriting of file data - for example, to patch a program +file or to update a header. However, you cannot reasonably repeatedly and indefinitely overwrite a Flash +file and, for example, Flash SSDs are unsuitable for B-tree index files. + + +See the chapter Database Files for a description of a Flash-friendly set of functions allowing random +access to, and the deleting and updating of, variable length records. These functions take advantage of the +fact that a byte can be physically overwritten (with no storage penalty) provided that the overwrite is such +that each bit in the byte either stays the same or is cleared. + + +Flash SSDs are particularly attractive for storing program files, read-only data (say for data-referral +applications), for securely storing logged data in the field and for archiving data. + + +The storage of files on a Flash SSD is very different from that used on RAM SSDs. The scheme is not at +all block structured but is based on linked variable length records. All this is hidden from the caller and +the logical interface to a file on a Flash SSD is the same as for a file on a RAM SSD (or any other +medium). + + +The data in each write to a file on a Flash SSD is written straight to the SSD (ie it is not buffered)!. +However, in the interests of efficient storage, the record just written is kept open (with a oxtf££ length) +for as long as possible - until the file channel is closed or flushed using P_FFLus# or until a write to +another file on the same SSD occurs. The date and time stamp is also not written until the file channel is +flushed or closed. + + +If the SSD is removed or the machine resets while there is an open file channel with an outstanding write, +the record is closed when the file is next accessed (the file is then also stamped with the current date and +time). + + +On a Flash SSD, there is no limit on the number of files or directories in the root directory. You will also +find that it is possible to fit slightly more data on a freshly formatted Flash SSD than on a RAM SSD of +the same nominal capacity. This is due to the fact that files are allocated space in multiples of whole +blocks on a RAM SSD whereas Flash files are stored in exactly sized variable length records. + + +File specifications +A full file specification has the form: + + + +where the components are: + + + the file system node (eg Loc: :) + the device name (eg B:) + + the directory name (eg \NOTES\OLD\) + the file name (eg PLaNs). + + the extension name (eg .TPD) + + +!This may not be the case for text files, which are handled by a layer over the FL: device. The buffering +of such files is thus outside the file server's control. + + +11 FILES + + +An example of a full file specification is: +LOC: :B: \NOTES\OLD\PLANS . TPD + + +Although the file server assumes that a file specification may be decomposed into a , , +, and , it avoids any assumption of the detailed syntax of the , , +and components. This is left to the file system code that implements the file specification +manipulation functions p_fparse and p_chdir. + + +Leaving such detailed considerations to the file system is designed to allow the file stores of remote +foreign file systems to be mapped transparently to the file server model (which is compatible with the +MSDOS filing system). For example, in the VMS operating system, the above example of a file +specification might translate to: + + +REM: : USER: [NOTES.OLD]PLANS.TPD +and on an Apple Macintosh, it might be: +REM: :HD40:NOTES:OLD:PLANS.TPD + + +and on Unix, it might be: + + +REM: : USER: :NOTES/OLD/PLANS.TPD + + +To prepare for such foreign systems, applications should follow the example of the file server and avoid +making assumptions about the syntax of file specifications and use functions such as p_fparse and +p_chdir to manipulate file specifications. + + +File specifications satisfy the following rules: + + +e a file specification will not require more than p_FNamEs1zE (128) bytes, including a zero +terminator + + +e the component is always p_FsySNAMESIzE bytes long (excluding any zero terminator) + + +where P_FNaMESIzE and p_FsysNameEsi1zeE are defined in p_file.h. Except for and the p_FNAMESIZE +total, you should not make any assumptions about the maximum size of the components of a file +specification. + + +Default path + + +The file server stores a default node, device and directory, also called the default path, for each of its +clients. In addition, the file server stores a lower level default path, the system-wide default path. This is +the default path assigned to new clients when they connect to the file server. + + +A process that is a client of the file server uses: +p_setpth to set its default path +p_getpth to get a copy of its default path + + +A process (normally a system process such as the shell) can change the system-wide default path - the +path subsequently assigned to connecting clients - by calling p_setdefaultpath. + + +Channel-based services + + +A client of the file server can use p_open on the Fru: device with different values of mode to do the +following: + + +P_F STREAM, to open a file and manipulate it as a flat binary file +P_FSTREAM_TEXT + +P_FTEXT to open a file and manipulate it as a record-oriented text file +P_FDIR to get a list of the files and subdirectories in a directory +P_FDEVICE to get a list of the available devices + +P_FNODE to get a list of the available file systems + +P_F FORMAT to format a Loc: : device + + +11-5 + + +PLIB REFERENCE + + +Once a channel has been opened, one or more I/O functions (depending on mode) may be requested +synchronously using p_iow (or a convenience function such as p_read) or asynchronously using p_ioc or +p_ioa. + + +There is no practical limit to the number of file channels that may be opened in the system or by a +particular process. + + +Non-channel-based services + + +These are file operations not involving the F1L: device driver. They are requested by the following +function calls: + + +p_fparse, to parse a file specification +p_fparseasync + + +p_chdir, to change the directory component of a file specification +p_chdirasync + + +p_ninfo, to get file system node information +p_ninfoasync + + +p_dinfo, to get information on the medium in a device +p_dinfoasync + + +p_finfo, to get information on a file or a directory +p_finfoasync + + +p_rename, to rename a file or a directory + + +p_renameasync + + +p_delete, to delete a file or a directory +p_deleteasync + + +p_mkdir, to make a new directory +p_mkdirasync + + +p_sfstat, to set the attributes of a file (and to set the volume label of a medium) +p_sfstatasync + + +p_fdate, set the modification date and time of a file +p_fdateasync + + +The name of asynchronous equivalents are generated by appending async to the name of the +corresponding synchronous function. The asynchronous function takes the same parameters as the +synchronous function but with the addition of a status word parameter at the end of the parameter list. + + +Asynchronous file operations + + +The file server is essentially asynchronous in its operation and most functions are provided in both +asynchronous and synchronous forms. + + +Because the file server has a higher priority than any of its clients, any operation that does not wait for a +slow external device will have completed by the time an asynchronous request has returned. This includes +any operation on the Rom: : file system or where the toc: : file system accesses SSDs or the internal RAM +drive (M:). However, when accessing the REM: : file system where the connection is via an RS232 cable, +any asynchronous request is almost certain to return before the operation is complete. + + +Although, in practice, most file operations complete in a fraction of a second, a particular file request may +take an extended time. For example, a read of 8K bytes from a Rem: : file, connected over a 1200 baud +modem link, would take well over a minute. However, a request will never take an indefinite time to +complete (as, for example, a write to the parallel port can do when the printer is off line). + + +For these reasons, the file server does not actively support a cancel service. (Incidentally, it is also worth +considering the state in which a file would be left if a partially completed write operation were cancelled.) + + +A request on an open file channel may be cancelled using p_iow(P_FCANCEL) but the cancel will not cause +the operation to complete any sooner (and it will not complete with E_FILE_CANCEL). + + +In general, it is preferable to simulate a cancel by waiting for current service to complete and forcing the +status word to E_FILE_CANCEL, as illustrated below. + + +11-6 + + +11 FILES + + +The cancelling of an asynchronous request such as: +p_ioc (pcb, P_FREAD, &stat,buf,1len); +may be simulated by: + + +if (stat==E_FILE_PENDING) +{ +p_waitstat (&stat); /* wait for completion */ +stat=E_FILE_CANCEL; /* report a cancel */ +} + + +This will normally complete almost immediately. You should, however, be aware that in rare cases when +using the remote filing system (say, when the remote computer is re-booted and the communications link +is set up to have a long timeout period) it may take an extended time to complete. + + +Manipulating file specifications + + +p_fparse (or f_fparse) Parse a file specification + + +INT p_fparse(TEXT *name, TEXT *related, TEXT *full, P_FPARSE *pcrk); +INT f_fparse(TEXT *name, TEXT *related, TEXT *full, P_FPARSE *pcrk); +INT p_fparseasync(TEXT *name, TEXT *related, TEXT *full, P_FPARSE *pcrk, WORD *stat); + + +Builds a full file specification of the form: + + + +as a zero terminated string in fu11, where the components are: + + + the file system node (eg Loc: :) + the device name (eg B:) + + the directory name (eg \NoTES\OLD\) + the file name (eg PLans). + + the extension name (eg . TPD) + + +The parameters name and full may point to the same address, but related and ful should not have the +same address. + + +There should be at least p_rNamestze (128) bytes of memory reserved at fu11. Note that p_rNamEs1zE +bytes are always written to fu11 even when the generated file specification is shorter. If you have a name +produced by a previous call to p_fparse and you are calling p_fparse again to fill in the struct at pcrk, +you still need p_rnames1ze bytes at full. + + +Subject to the restrictions described below, under the heading Using p_fparse across filing systems, the +components making up the full file specification are taken from the following (in order of precedence): + + +e the zero terminated file specification name + + +e the zero terminated related file specification re1atea (the related file specification may be +omitted by passing nuLL). + + +e the default path (the node, device and directory as set by p_setpth) + + +Thus components are only taken from related if they are missing from name. If there are still missing +components, they are taken from the default path. Note that the and fields in name and +related may contain wildcard characters. + + +The output file specification in fu11 is converted to upper case characters. Prior to EPOC version 2.31, +conversion to upper case was performed by folding (as by using p_tofoid). From EPOC version 2.31 +onwards the conversion is by converting to upper case (as by using p_toupper). This has no significant +effect on UK applications, but improves the handling of file names containing, for example, accented +characters. + + +11-7 + + +PLIB REFERENCE + + +Further information on the content of £u11 is written to the P_FPARSE struct pcrk. If this information is +not required, pcrk may be passed as NULL. If perk is not NULL, it should be the address of a P_FPARSE +struct, defined in p_file.h as follows: + + +typedef struct +{ +UBYTE system; /* file system name length */ +UBYTE device; /* device name length */ + + +UBYTE path; /* path name length */ + +UBYTE name; /* name length */ + +UBYTE ext; /* extension length */ + +UBYTE flags; /* information on the presence of wildcards */ +} P_FPARSE;. + + +The members system, device, path, name and ext are set to the lengths of their corresponding fields in +full, including delimiters. The flags field contains information on the occurrence of wild card characters +in the extended specification according to the following masks: + + +P_PWILD_ANY if set, the file specification contains one or more wild card characters and at +least one of the following bits are set + + +P_PWILD_NAME if set, the name field contains one or more wild card characters +P_PWILD_EXT if set, the extension contains one or more wild card characters + + +The function returns zero if successful or one of the following negative error numbers: + + +E_FILE_NAME either name or related contains an invalid name + +E_FILE_DEVICE either name or related contains an invalid device name + +E_FILE_DIR either name or related contains an invalid directory name + +E_GEN_FSYS either name or related contains an invalid file system name or the file system + + +does not exist + + +The function f_fparse is identical to p_fparse except that it calls p_leave (passing the error number) +rather than return a negative error number. + + +As an example, if the current default path is "Loc: :a:\", then + +p_fparse ("FRED", "\\FILES\\DOCS\\JOE.DOC", buf, &crk) ; +writes the zero terminated string Loc: :A: \FILES\DOCS\FRED.DOC to buf and {5,2,12,4,4,0} tocrk. +The function is often used to change the extension of a file as, for example, in: + +p_fparse (".BCK", "\\FILES\\DOCS\\JOE.DOC", buf, &crk) ; + + +Using p_fparse across filing systems + + +Since the syntax of a file specification may differ between filing systems (see File specifications, earlier in +this chapter) the functions p_fparse and p_chdir are implemented in the code of each file system. The +function p_fparse builds a full file specification from up to three sources, which may therefore specify +two or more different filing system nodes. + + +This section describes the rules that determine which implementation performs the function p_fparse in +any particular case, and which of the three sources contribute towards the full file specification. The three +sources will be referred to as name, related and the default path, as in the description of p_fparse. + + +The node which performs the p_fparse is determined from name, related and the default path, according +to the following rules: + + +e If neither name nor related contain an explicit component, the node specified by the +default path is assumed (the default path always has an explicit component). + + +e If either name or related (but not both) contain an explicit component, this is taken to be +the node which performs the p_fparse. + + +e If both name and related contain explicit components, the specified in name is +taken to be the node which performs the p_fparse. + + +11-8 + + +11 FILES + + +If an explicit in related differs from that determined from the above rules, related is assumed +not to be valid for the specified node and is ignored by p_fparse. + + +If the in the default path differs from that determined from the above rules, the default path is +assumed not to be valid for the specified node and is ignored by p_fparse. + + +Thus, assuming that the default path is "Loc: :a:\", then +p_fparse ("PLIB.MAK", "REM: :HD40:SOURCE:",buf,NULL) ; + +is handled by the remote filing system and writes the string REM: :HD40:SOURCE:PLIB.MAK to buf, but +p_fparse ("LOC: : PLIB.MAK", "REM: : HD40: SOURCE: PLIB.MAKE", buf, NULL) ; + +is handled by the local filing system and writes the string Loc: :A:\PLIB.MAK tO buf (related is ignored). + + +All sources that are not ignored by p_fparse are checked as being valid for the specified node, even if +they do not contribute to final full file specification. Thus + + +p_fparse ("LOC::C:\\PLIB.MAK", "PLIB.MAKE", buf, NULL) ; + + +will fail with error =_F1LE_NamE because the in related is not valid for the Loc: : filing system, +even though all the components of a full file specification are present in name. This type of situation is +typically likely to occur when copying files between the rem:: and toc: : filing systems. + + +p_chdir Change the directory in a file specification + + +INT p_chdir (TEXT *src, TEXT *outp, INT mode, TEXT *subdir) ; +INT p_chdirasync(TEXT *src, TEXT *outp, INT mode, TEXT *subdir, WORD *stat); + + +Parse src with a nut related name and change its directory to produce a new file specification outp +according to mode, which should be one of: + + +P_CD_ROOT to move to the root directory +P_CD_PARENT to move to the parent directory +P_CD_SUBDIR to move to the zero terminated subdirectory subdir + + +The parameter subdir is ignored if mode is not P_CD_SUBDIR. + + +If src contains a file name then this name is retained and appended to the new directory specification +outp. + + +There should be at least p_rnames1zz (128) bytes of memory reserved at outp. Note that p_rNAMESIZE +bytes are always written to outp even when the generated file specification is shorter. + + +The parameters src and outp may point to the same address. + + +Note that p_chdir is just a means of setting up outp from mode, src and subdir with no consideration to +the existence of the directories in src and subdir. The operation is performed by the appropriate file +system (as specified by the component of the full file specification) allowing a file specification to +be manipulated without knowledge of the detailed structure (eg the delimiters used) of file specifications +on that . + + +When mode is P_cD_SUBDIR, subdir is just inserted into the full file specification at the appropriate +position. Except for checking that the resultant full file specification length does not exceed p_FNAMESIZE +bytes, the validity of outp is not checked. + + +The function returns zero if successful or a negative error number if it fails. As well as the errors that can +be returned by the internal parse of src, p_chdir can return: + + +E_FILE_NXIST mode Was P_CD_PARENT and src was already at the root directory + +E_FILE_DIR subdir contains an invalid directory name + +E_FILE_NAME inserting subdir would make the file specification length exceed p_FNAMESIZE +bytes + + +11-9 + + +PLIB REFERENCE + + +For example, if the current default path is "Loc: :a:\", then +p_chdir("\\fred\\*.c", buf, P_CD_SUBDIR, "bill") writes LOC: :A:\FRED\bill\*.C to buf +p_chdir ("\\fred\\aa.c",buf,P_CD_SUBDIR, "jim") writes LOC: :A:\FRED\jim\AA.C to buf + + +p_chdir("\\fred\\aa.c", buf, P_CD_SUBDIR, "bill\\jim") writes LOC: :A:\FRED\bill\jim\AA.C to buf +(although, depending on where bi11\4jim came from, this breaks the spirit of p_chdir by including a +delimiter in subdir) + + +p_chdir ("\\fred\\jim\\*", buf, P_CD_PARENT, NULL) writes LOC: :A:\FRED\* to buf +p_chdir("\\fred\\jim\\*", buf, P_CD_ROOT, NULL) writes LOC: :A:\* tO buf + + +p_chdir ("rem: :hd40:fred:aa.c",buf,P_CD_SUBDIR, "jim") writes REM: :HD40:FRED: jim:AA.C to buf + + +The default node, device and directory + + +p_setdefaultpath Set the system-wide default path +INT p_setdefaultpath(TEXT *name) ; + + +Set the file server system-wide default path to name. This is the default path that is assigned to a process +when it connects to the file server. + + +The parameter name is a zero terminated string of the form: + + + + + +where + + is the file system node (eg Loc: :) + is the device name (eg B:) + + is the directory name (eg \NOTES\OLD\) + + +The parameter name is parsed with a nut related file name and any file name and extension component is +discarded. + + +The function returns zero if successful or the same error numbers as for p_fparse if name failed to parse. + + +A successful call implies that file system exists at the time of the call (note that some file systems +such as REM: : are not permanently installed) and that and are valid for the file system. It +does not mean that contains a medium, or that exists. + + +For example, after: +p_setdefaultpath ("LOC::B:\\"); + + +all new file server clients will initially have the default path of Loc: :B:\. + + +p_setpth Set the default path of this process + + +INT p_setpth(TEXT *name) ; +INT p_setpthasync(TEXT *name, WORD *stat); + + +Set the default node, device and directory for this process to name where name is a zero terminated string +of the form: + + + + + +where + + is the file system node (eg Loc: :) + is the device name (eg B:) + + is the directory name (eg \NOTES\OLD\) + + +The parameter name is parsed with a nut related file name and any file name and extension component is +discarded. The specified directory must exist. + + +11-10 + + +11 FILES + + +The function returns zero if successful or a negative error from p_fparse if name failed to parse or: + + +E_FILE_DEVICE if the device does not exist +E_FILE_NOTREADY if the device does not contain a medium +E_FILE_DIR if the directory does not exist + + +When a process connects to the file server, it is assigned the file server system-wide default path, set by +the last call to p_setdefaultpath. + + +For example, if the current default path is Loc: :m:\, then: +p_setpth("B:"); + + +sets the default path to Loc: :B:\. + + +p_getpth Get the default path of this process +VOID p_getpth(TEXT *name) ; + + +Write the default node, device and directory for this process as a zero terminated string to name of the +form: + + + + + +where + + is the file system node (eg Loc: :) + is the device name (eg B:) + + is the directory name (eg \NOTES\OLD\) + + +There should be p_rnames1zeE bytes of memory reserved at name. + + +There is no asynchronous version of p_getpth because the process default node, device and directory is +stored by the file server without recourse to the appropriate file system (although the interpretation of + and may depend on ). + + +p_getpthbyid Get the default path by process id + + +INT p_getpthbyid(HANDLE pid, TEXT *name); + + +Write the default node, device and directory of process pia as a zero terminated string to name. The +content of name is as for p_getpth, described above. + + +Returns zero if successful or E_FILE_Nxist if pia is not a client of the file server. + + +Operations on nodes and devices + + +p_open(P_FNODE) Get a list of nodes + + +INT p_open(VOID **ppfcb, TEXT *name, UINT mode); + +INT p_iow(VOID *pfcb, INT func, TEXT *buf, P_NINFO *pinfo); +INT p_close(VOID *pfcb) ; + +To get a list of file system node names, you: + + +e = call p_open with a mode of P_FNoDE to open a node list channel + + +e repeatedly call p_iow with a func of p_rREap to read each node name (until it returns +E_FILE_EOF) + + +e = call p_close to close the node list channel + + +11-11 + + +PLIB REFERENCE + + +The name parameter to p_open may be "FIL:" or NULL. The mode parameter must be P_FNODE. + + +Each successful call to p_iow(P_FREAD) writes the next file system node name as a zero terminated string +to buf (buf should have a capacity of P_FSYSNAMESIZE+1 (6) bytes). The call to p_iow(P_FREAD) returns +E_FILE_EOF after all the node names have been read. + + +If the parameter pinfo is not NULL it is taken as the address of a P_NINFo struct which is filled with the +same node information as would be obtained by calling p_ninfo, described below. + + +For example: + + +LOCAL_C VOID ListNodes (VOID) + + +{ +VOID *ncb; +TEXT buf [P_FSYSNAMESIZE+1]; + + +p_open(&ncb, "FIL:",P_FNODE) ; + +while (!p_iow(ncb,P_FREAD, &buf[0],NULL) ) +p_puts (&buf[0]); + +p_close(ncb); + + +} + + +lists the current node names. + + +p_ninfo Get node information + + +INT p_ninfo(TEXT *node, P_NINFO *pninfo); +INT p_ninfoasync(TEXT *node, P_NINFO *pninfo, WORD *stat); + + +Write information on the zero terminated file system node to the P_NINFo structure at pninfo and return +zero if successful or the negative E_GEN_Fsys if node is invalid or does not exist. + + +The P_NrnFo struct is defined in p_file.h as: + + +typedef struct { +UWORD version; +UWORD type; +UWORD formattable; +UBYTE spare[26]; +} P_NINFO;. + + +where pninfo->type contains: +P_FSYSTYPE_FLAT if file system node does not support hierarchical directories +P_FSYSTYPE_HIER if file system node does support hierarchical directories + + +and pninfo->formattable is TRUE if file system node supports the formatting of its devices and FALSE +otherwise. + + +The version field pninfo->version is designed to allow future versions of p_ninfo (which would write +further information to pninfo->spare[]) to be identified by the caller. At the time of writing, +pninfo->version is Set to 2. + + +p_locchg Check if LOC:: has changed +INT p_locchg(INT mask) ; +This function is only available in EPOC version 2.16 or later. + + +Check if Loc: : has changed (for example, if the SSD door has been opened) since the last call to +p_locchg. The return value has the bits that were set in mask either set or cleared, depending on whether +or not LOC:: has changed. + + +The use of a mask allows multiple independent calls from within one application, with each caller +consistently using one specific bit of mask. Bit 15 is ignored, so as never to return a negative value (even +though the call can never fail). Bits 8 to 14 inclusive are reserved for system use. An application may +therefore make up to eight independent calls, using bits 0 to 7. + + +Typical calling code would make an initial call to p_locchg, to ensure that only subsequent changes are +detected. It would then poll for changes by calling p_locchg, say, every two seconds. + + +11-12 + + +11 FILES + + +p_open(P_FDEVICE) Get a list of devices + + +INT p_open(VOID **ppfcb, TEXT *name, UINT mode) ; +INT p_iow(VOID *pfcb, VOID *buf, NULL); +INT p_close(VOID *pfcb) ; + + +To get a list of device names for a particular file system you: +e call p_open with a mode of P_FDEVICE to open a device list channel + + +e repeatedly call p_iow with a func of p_FReEap to read each device name (until it returns +E_FILE_EOF) + + +e call p_close to close the device list channel + + +The name parameter to p_open should be a zero terminated node name (with or without a leading F1L:). +The parameter mode must be p_rpevice. If the node name is illegal or does not exists, p_open fails and +returns E_GEN_Fsys. If the node does not support devices (as is the case for Rom: :), p_open fails and +returns E_GEN_NSUP. + + +Each successful call to p_iow(P_FREAD) Writes the next device name as a zero terminated string to buf +(buf should have a capacity of p_rNames1zeE (128) bytes). The call to p_iow(P_FREAD) returns E_FILE_EOF +after all the device names have been read. The parameter following but in the call to p_iow (P_FREAD) +should be nut. + + +For example: + + +LOCAL_C VOID ListDevices (VOID) +{ +VOID *ncb, *dcb; +INT ret; +TEXT node[P_FSYSNAMESIZE+1]; +TEXT device [P_FNAMESIZE]; + + +p_open(&ncb, "FIL:",P_FNODE) ; +while (!p_iow(ncb,P_FREAD, &énode[0],NULL) ) +{ +p_puts (&node[0]); +if ((ret=p_open (&dcb, &node[0],P_FDEVICE) ) <0) +{ +p_puts("\tDevices not supported"); +continue; +} +while (!p_iow(dcb,P_FREAD, &édevice[0],NULL) ) +p_printf("\t%s",&device[0]); +p_close(dcb); +} +p_close(ncb); +} + + +lists the current node names with their devices. + + +p_dinfo Get device information + + +INT p_dinfo(TEXT *dname, P_DINFO *pdinfo) ; +INT p_dinfoasync(TEXT *dname, P_DINFO *pdinfo, WORD *stat); + + +Write information on the device with zero terminated name dname and on the medium (eg SSD or +diskette) that is mounted on device dname to the p_DINFo struct at pdinfo. Returns zero if successful or +one of the following negative error numbers: + + +E_FILE_DEVICE if an invalid or non-existent device is specified + +E_FILE_NOTREADY if the device does not contain a medium + +E_FILE_CORRUPT the Loc: : sub file system on a SIBO machine has recognised a RAM or Flash +SSD without a valid boot record (probably because the SSD is not formatted) + +E_FILE_UNKNOWN none of the file systems recognise this medium and formatting is unlikely to + + +make it readable + + +11-13 + + +PLIB REFERENCE + + +The P_p1nFo struct is defined in p_file.h as: + + +typedef struct { + +UWORD version; + +UWORD mediatype; + +UWORD removable; + +ULONG size; + +ULONG free; + +UBYTE name [P_VOLUMENAME] ; +WORD batterystate; + +UBYTE spare[16]; + +} P_DINFO;. + + +Except for pdinfo->removable, which is TRUE if the device has removable media, all information +describes the medium mounted on device dname. + + +The least significant byte of pdinfo->mediatype takes one of the following values: + + +P_FMEDIA_UNKNOWN unknown media type + +P_FMEDIA_FLOPPY drive takes 3.5 inch or 5.25 inch diskettes + +P_FMEDIA_HARDDISK drive contains a hard disk + +P_FMEDIA_RAM drive contains a RAM disk (read/write) + +P_FMEDIA_FLASH drive contains a Flash disk + +P_FMEDIA_ROM drive contains a ROM disk (read only) + +P_FMEDIA_WRITEPROTECTED drive contains a write protected medium + +The most significant byte of pdinfo->mediatype takes a combination of the following bit flags: +P_FMEDIA_COMPRESSIBLE it is worth compressing out logically deleted records from a file on this + + +medium to reduce both the file size and the storage consumed by the file +(not set for Flash SSDs) + + +P_FMEDIA_DYNAMIC the media capacity pdinfo->size can change over time + +P_FMEDIA_INTERNAL media is internal (implicitly not removable) + +P_FMEDIA_DUAL_DENSITY device drive is dual density (if this is set then p_open (P_FFORMAT) can take +the optional p_FLowpENsiTy for a low density format) + +P_FMEDIA_FORMATTABLE media is formattable + + +The members pdinfo->size and pdinfo->free give the total capacity of the medium in bytes and how +much of that capacity is free (also in bytes) respectively. If p_rMzDIA_DYNAMIC is set in +pdinfo->mediatype (as it is for the internal RAM device m:), pdinfo->size and pdinfo->free may +change over time. + + +The volume name, with a maximum of 12 characters (for example, "DISKNAME.DSK"), 1s written as a zero +terminated string to spdinfo->name [0]. + + +The system is designed to be able to take advantage of hardware which can detect a low battery voltage in +a RAM SSD. When this is not possible (either because the medium is not a RAM SSD or because the +hardware does not support it), pdinfo->batterystate contains E_GEN_NsupP. If the SSD does contain a +battery and the hardware to detect a low voltage, pdinfo->batterystate contains FALSE if the battery is +low or TRUE (more precisely, a non-zero value other than E_cEN_NsupP) if the battery voltage is acceptable. +The content of this field is undefined for values of pdinfo->version less than 3. + + +The version field pdinfo->version is designed to allow future versions of p_dinfo (which would write +further information to pdinfo->spare[] to be identified by the caller. + + +In the following example, ListDevices produces a device list with some device information, including the +devices on REM:: (if the file server is connected to a remote file server) as well as Loc: :. + + +11-14 + + +LOCAL_C TEXT *GetTypeText (UINT type) + + +{ + + +switch (type) + + +{ + + +case P_FMEDIA_FLOPPY: + + +return + + +"Floppy"; + + +case P_FMEDIA_HARDDISK: + + +return + + +"Hard"; + + +case P_FMEDIA_FLASH: + + +return + + +"Flash"; + + +case P_FMEDIA_RAM: + + +return + + +"RAM"; + + +case P_FMEDIA_ROM: + + +return + + +"ROM"; + + +case P_FMEDIA_WRITEPROTECTED: + + +return + + +"Protected"; + + +} + + +return "Unknown"; + + +LOCAL_C VOID ListDevices (VOID) + + +VOID *ncb, *dcb; + +INT ret; + +TEXT device [P_FNAMESIZE]; + +TEXT bb[E_MAX_ERROR_TEXT_SIZE]; +P_DINFO dinfo; + + +p_printf(" Device Name Type Size + + +p_printf ("====s======= =S==S=S=S=S==== S=S=SSS==5== SSS 555 + + +p_open(&ncb, "FIL:",P_FNODE) ; +while (!p_iow(ncb,P_FREAD, &device[0],NULL) ) +{ +if (p_open(&dcb, &device[0],P_FDEVICE) ) +continue; + + +while (!p_iow(dcb,P_FREAD, &édevice [P_FSYSNAMESIZE],NULL) ) + + +{ +if ((ret=p_dinfo(&device[0],&dinfo) ) <0) + + +{ +p_errs (&bb[0],ret + + +i +p_printf("%- 12s %- 12s<%s>", &device[0],"**Failed**", sbb[0]); + + +continue; + + +} +p printf ("S- 12s 4- 12sS- lis S7IdK >10, (dinfo.free+512)>>10); + + +} +p_close(dcb); +} +p_close(ncb); + + +} + + +p_open(P_FFORMAT) + + +INT p_open(VOID **ppfcb, TEXT *name, UINT mode) ; +INT p_read(VOID *pfcb, VOID *buf, UINT len); +INT p_close(VOID *pfcb); + + +To format a medium in a device you: + + +11 FILES + + +Format a device + + +e call p_open with a mode of p_FrormatT to open a device format channel + + +e call p_read to get the total format count (optional) +e repeatedly call p_reaa until it returns E_FILE_EOF + + +e call p_close to close the device format channel + + +11-15 + + +PLIB REFERENCE + + +The name parameter to p_open should be a zero terminated file specification with a root directory (name is +parsed with a nuut related name) of the form: + + +LOC: :\ + + +to format the medium in , giving it the volume name . The volume name may +subsequently be changed using p_sfstat, described later in this chapter. + + +The mode parameter to p_open must be Pp_Frormat. If the device supports dual density formatting (as may +be established by calling p_dinfo), P_LFLOWDENSITY may be or'ed into mode to format at the lower density. + + +The call to p_open returns zero if successful. As well as the error numbers that can be returned by +p_fparse, p_open(P_FFORMAT) can also return one of the following negative error numbers: + + +E_GEN_NSUP the file system, device or medium does not support formatting +E_FILE_PROTECT the medium is write protected or is read-only (eg a ROM SSD) + + +At the time of writing, formatting is only supported on the Loc: : system on a SIBO machine. You can tell +in advance if a file system supports formatting by calling p_ninfo (described above). If the file system +does support formatting, you can tell if a device contains a formattable medium by calling p_dinfo (also +described above). + + +The first call to p_read writes a uworD total count to buf and returns zero. This count represents the +number of subsequent p_read calls required to complete the format. The 1en parameter to p_read is +ignored in all cases. + + +A call count can be combined with the total format count to present a percentage done indication. When +the format is complete, p_read returns E_FILE_EoF; you should then call p_close. Abandoning the +format, by calling p_close prematurely, will leave the medium in a corrupted state. + + +For example, the following function: + + +LOCAL_C VOID FormatDevice (TEXT *name) +{ +INT err,i; +UWORD count; +VOID *chan; +TEXT bb[E_MAX_ERROR_TEXT_SIZE]; + + +chan=NULL; + +if ((err=p_open(&chan, name, P_FFORMAT) ) <0) +goto exit; + +if ((err=p_read(chan, &count, 0) ) <0) +goto exit; + +p_printf ("Formatting %s count=%d",name, count) ; + +i=1; + +while ((err=p_read (chan, &val,0) ) >=0) +ploprint ( \rse05u", 2 ++); + +if (err==E_FILE_EOF) +err=0; + +exit: + +p_close(chan); + +if (err<0) +{ +p_errs (&bb[0],err); +p_printf("\r\nFormat failed: %s",&bb[0]); +} + +else +p_printf("\r\nFormat complete") ; + +} + + +could be called with: +FormatDevice ("LOC: :A:\\BACKUP") ; + + +to format the SSD in drive a:, giving it the volume name BACKUP. + + +11-16 + + +11 FILES + + +p_locdevice Read media information of a local device +INT p_locdevice (INT aDevice, UWORD *pMedia) ; +This function is only available in EPOC version 3.18 or later. + + +Write, to *pMedia, the media type of the local device (that is, a device on the toc: : file system) specified +by aDevice. The value of aDevice must be one of: + + +@ = 'M' (0x4d) + +e ='T (0x49) + +e ='A' (0x41) to 'H' (0x48) inclusive. +where 'T' (Internal) is an alias for 'M'. + + +Apart from two additional flags, the value written to *pmedia is the same as the value written to the +mediatype of a p_DINFo struct by p_dinfo. The call is more efficient than a call to p_dinfo, provided that +the media type is the only information that is required. + + +The two extra flags that may be written to *pMedia are &_FMEDIA_BATTERY_VALID and +E_FMEDIA_BATTERY_GooD, defined in epoc.h. If —_FMEDIA_BATTERY_VALID is not set then the device does +not support battery measurement. If it is set then E_FMEDIA_BATTERY_Goop Will be clear if the battery +voltage is too low, otherwise it will be set. + + +Returns zero or a negative error number. Errors that may be returned are: + + +E_FILE_NOTREADY no device is available +E_FILE_DEVICE the device specified by aDevice is not in the valid range of devices +E_GEN_NSUP no PDD exists which can handle the device + + +E_GEN_UNKNOWN + + +Note that the media does not have to be mountable for this service to work. + + +p_locreadpdd Direct read of local SSD +INT p_locreadpdd(INT aDevice, LONG *aPos, VOID *aPtr, UINT aLen); +This function is only available in EPOC version 3.18 or later. + + +Read, to the buffer pointed to by apt r, aLen bytes starting at an offset of *apos bytes into the SSD from +the local SSD (that is, an SSD on the toc: : file system) specified by aDevice. The data is read by means +of direct access to the physical device driver (PDD) and the reading is therefore very efficient. + + +The value of aDevice must be one of: + +e = 'M' (0x4d) + +e =6'T (0x49) + +e ='A' (0x41) to 'H' (0x48) inclusive. +where 'T' (Internal) is an alias for 'M'. + + +The medium must have been mounted prior to using this service. (To ensure the medium is mounted, just +make any normal device access.) + + +The service returns zero or one of the following negative error numbers: +E_GEN_OS the medium is not mounted + + +E_FILE_CORRUPT the specified offset is greater than the size of the SSD + + +11-17 + + +PLIB REFERENCE + + +Operations on directories and files + + +p_open(P_FDIR) Get a directory list + + +INT p_open(VOID **ppfcb, TEXT *name, UINT mode) ; +INT p_iow(VOID *pfcb, INT func, TEXT *buf, P_INFO *pinfo); +INT p_close(VOID *pfcb) ; + + +To get a list of files in a directory you: +e call p_open with a mode of P_FD1R to open a directory list channel + + +e repeatedly call p_iow with a func of P_FREAD to read each directory entry (until it returns +E_FILE_EOF) + + +e call p_close to close the directory list channel + + +The name parameter to p_open is a zero terminated file specification. Internally to the call to p_open, this +is parsed with a wild card related name (such as "*.*") that will find all files in the directory. It is +therefore not necessary to include a file name or file name extension in name unless you wish to restrict the +directory search to files with that name and/or extension. If present, the file name and the file name +extension in name would normally contain wildcards. Passing a name of "" produces the names of all the +files in the current directory. The parameter mode must be P_FDIR. + + +Each successful call to p_iow (P_FREAD) writes the next matching file name (excluding the node, device +and directory component) as a zero terminated string to buf (buf should have a capacity of P_FNAMESIZE +(128) bytes). The call to p_iow(P_FREAD) returns E_FILE_EOF after all the file names have been read. + + +If the parameter pinfo is not NULL it is taken as the address of a P_INFo struct where p_1nro is defined in +p_file.h as: + + +typedef struct { +UWORD version; +UWORD status; /* status bits */ + + +ULONG size; /* size of the file in bytes */ + +ULONG modst; /* system time of last modification */ +UBYTE spare[4]; + +} P_INFO;. + + +The file status pinfo->status has the following bit fields: + + +P_FAWRITE set if file is not read-only + +P_FAMOD set if the file has been modified + +P_FAHIDDEN set if file is hidden + +P_FASYSTEM set if file is a system file + +P_FADIR set if the file is a directory file + +P_FAVOLUME set if the file is a volume name directory + +P_FATEXT set if file is a text file + +Note that a directory read may return with a volume name written to buf and p_FAVOLUME set in + + +pinfo->status. This will only occur if the directory is a root directory of a PC-based device that has a +volume name. + + +A directory read only returns with P_FaTEXT set in pinfo->status when the file system can recognise a +text file. The toc: : file system cannot recognise text files but a remote file server, running on an +operating system (eg VMS) which can recognise text files, will set the p_raTExt bit as appropriate. + + +The field pinfo->size gives the logical file length (the end-of-file position). + + +The field pinfo->modst gives the time the file was last modified, expressed in system time format (the +number of seconds since 00:00:00 January 1 1970). See the chapter Time, Timers and Dates for details on +how to convert to and from the system time. + + +The p_inro file information may also be obtained when using p_finfo, described below. + + +11-18 + + +11 FILES + + +Example +#include +LOCAL_D VOID *dcb=NULL; +LOCAL_C VOID panic(TEXT *msg, INT errno) + + +{ +TEXT bb[E_MAX_ERROR_TEXT_SIZE]; + + +p_close(dcb); dcb=NULL; + +p_errs (&bb[0],errno) ; +p_printf("%Ss: %s",msg,&bb[0]); +p_leave (errno) ; + + +} + + +LOCAL_C VOID PrintDirLine (TEXT *name, P_INFO *pinfo) +{ +P_DAYSEC ds; +P_DATE dt; +TEXT *p,b[40]; + + +p=&b[0]; +if (pinfo->status&P_FAVOLUME) +p=p_scpy(p,"Vol,"); +if (pinfo->status&P_FADIR) +p=p_scpy(p,"Dir,"); +if (pinfo->status&P_FAMOD) +p=p_scpy (p, "Mod, "); +if (! (pinfo->status&P_FAWRITE) ) +p=p_scpy (p, "Read,"); +if (pinfo->status&P_FASYSTEM) +p=p_scpy (p,"Sys,"); +if (pinfo->status&P_FAHIDDEN) +p=p_scpy(p,"Hid,"); +if (*(p-1)==',') +*-—p=0; +p_sttods (&pinfo->modst, &ds) ; +p_dstodt (&ds, &dt) ; +p_printf("S- 12s S8lu %02u-%02u-%02u %02u:%02u Zs", +name, pinfo->size,dt.day+1,dt.month+1,dt.year,dt-.hour,dt.minute, &b[0]); +} + + +LOCAL_C VOID CDECL PrintDirList (TEXT *dir) +{ +INT err,NoFiles; +P_INFO info; +TEXT name [P_FNAMESIZE]; + + +if ((err=p_open (&dcb, dir, P_FDIR) ) !=0) +panic("Failed to open directory file",err); +NoFiles=TRUE; +while (! (err=p_iow(dcb, P_FREAD, &name[0],é&info) ) ) +{ +NoFiles=FALSE; +PrintDirLine(&name[0],&info); +} +p_close(dcb); dcb=NULL; +if (err!=E_FILE_EOF) +panic("Failed to read directory",ret); +if (NoFiles) +p_printf("No files found"); +} + + +GLDEF_C INT main(VOID) + + +{ +TEXT name [P_FNAMESIZE] ; + + +while (p_get1l(">", &name[0],P_FNAMESIZE) ) +p_enter((VOID *)PrintDirList, éname[0]); +return (0); + + +} + + +11-19 + + +PLIB REFERENCE + + +p_finfo Return file information + + +INT p_finfo(TEXT *name, P_INFO *pinfo); +INT p_finfoasync(TEXT *name, P_INFO *pinfo, WORD *stat); + + +Parse name with a NULL related name and write information about the specified file (which may be a +directory file) to the p_1NnFo struct at pinfo. The same file information is written to pinfo as is obtained +when using p_iow(P_FREAD) on a directory list channel that was opened with p_open(P_FDIR), as +described above. + + +The version field pinfo->version is designed to allow future versions of p_finfo (which would write +further information to pinfo->spare[]) to be identified by the caller. At the time of writing, +pinfo->version Is set to 2. + + +Returns zero if successful or a negative error number. As well as the p_fparse error numbers if the parse +fails, p_finfo can return: + + +E_FILE_DEVICE if the device does not exist +E_FILE_NOTREADY if the device does not contain a medium +E_FILE_DIR if the directory does not exist +E_FILE_NXIST if the file does not exist + + +The atomic nature of the p_finfo (unlike p_open) makes it a good choice for checking whether a file +exists (it returns E_FILE_NxtsT if the file does not exist). To test for the existence of a directory, you can +also use p_testpth, described below. + + +p_testpth Test for the existence of a directory + + +INT p_testpth(TEXT *dname) ; +INT p_testpthasync(TEXT *dname, WORD *stat); + + +Return zero if the directory component of the zero terminated file specification dname exists. + + +The file specification dname is parsed with a nuLt related name and any file name component is +discarded. + + +If the parse fails, p_testpth returns the error return from p_fparse. It can also fail with: + + +E_FILE_DEVICE if the device does not exist +E_FILE_NOTREADY if the device does not contain a medium +E_FILE_DIR if the directory does not exist + + +For example, if the current path is Loc: :a:\, then: +p_testpth("\\dirl\\dir2\\fred.c"); + + +returns zero if the directory Loc: :A:\DIR1\DIR2\ exists. + + +p_rename Rename a file or directory + + +INT p_rename (TEXT *oldname, TEXT *newname) ; +INT p_renameasync(TEXT *oldname, TEXT *newname, WORD *stat); + + +Parse each of newname and oldname with a NULL related name and, if successful, rename oldname to +newname. Both buffers should be at least P_rNames1zE bytes in length. + + +The file specified by oldname must exist and newname must not already exist. +Neither file name may include wild cards. + + +Both files should be on the same node and device. On Loc: :, files may be renamed across directories (but +this may not be supported by some remote systems). Prior to version 3.5 of EPOC, renaming across +directories can fail when the target directory is the root of Loc: :m:. + + +Directory files (which do not need to be empty) may be renamed, but not across different directories. + + +11-20 + + +11 FILES + + +The function returns zero if successful or a negative error number if it fails. As well as a p_fparse error +number if either oldname Or newnane fails to parse, p_rename can return the following error numbers: + + +E_FILE_DEVICE oldname and newname are on different devices or the device does not exist +E_FILE_NOTREADY the device does not contain a medium + +E_FILE_DIR the directory does not exist + +E_FILE_EXIST newname already exists + +E_FILE_NXIST oldname does not exist + +E_FILE_LOCKED oldname exists but a process has the file open + +E_FILE_PROTECT the medium is write protected or is read-only (eg a ROM SSD) +E_FILE_FULL not enough room on the medium for the rename (possible on Flash SSDs) + + +For example, if the current path is toc: :a:\, then: +p_rename ("\\dirl\\dir2\\fred.c", "\\dirl\\dir2\\jim.c"); +renames FRED.C iN LOC::A:\DIR1\DIR2\ to giIm.c while: +p_rename ("\\dirl\\dir2\\fred.c","fred.c"); +effectively moves FRED.c iN LOC: :A:\DIR1\DIR2\ to the root directory. +It is sometimes useful to parse newname With oldname as a related name before calling p_rename as in: + + +GLDEF_C INT RenameFile(TEXT *oldname, TEXT *newname) + + +{ +TEXT buf [P_FNAMESIZE]; + + +if (ret=p_fparse (newname, oldname, &buf[0],NULL) ) +return (ret); +return (p_rename (oldname, &buf[0])); + + +} +Then, for example, calling: +RenameFile("\\dir1l\\dir2\\fred.c","jim.c"); +renames FRED.C iN LOC: :A:\DIR1\DIR2\ to gim.c while: +RenameFile("\\dir1l\\dir2\\fred.c","\\jim.c"); + + +renames FRED.C IN LOC: :A:\DIR1\DIR2\ to gIm.c and moves Jim.c to the root directory. + + +p_delete Delete a file or directory + + +INT p_delete (TEXT *name) ; +INT p_deleteasync(TEXT *name, WORD *stat); + + +Parse name with a nui related name and, if successful, delete the specified file (which may be a directory +file). + + +A directory can not be deleted unless it is empty. + + +The function returns zero if successful or a negative error number if it fails. As well as a p_fparse error +number if name fails to parse, p_delete can return the following negative error numbers: + + +E_FILE_DEVICE the device does not exist + +E_FILE_NOTREADY the device does not contain a medium + +E_FILE_DIR the directory does not exist + +E_FILE_NXIST the file does not exist + +E_FILE_LOCKED a process has name open + +E_FILE_ACCESS name is a read-only file + +E_FILE_PROTECT the medium is write protected or is read-only (eg a ROM SSD) +E_FILE_EXIST name is a directory that contains files + + +11-21 + + +PLIB REFERENCE + + +For example, if the current path is Loc: :a:\, then: +p_delete("\\dir1l\\dir2\\fred.c"); + + +deletes Loc: :A:\DIR1\DIR2\FRED.C. + + +p_mkdir Make a new directory + + +INT p_mkdir (TEXT *name) ; +INT p_mkdirasync(TEXT *name, WORD *stat); + + +Parse name with a NULL related name and create the specified directory. The name of the directory to be +created is specified by the file name component of name if name contains a file name component. +Otherwise it is specified by the directory component of the parsed file specification. + + +Intermediate directories are also created if necessary. + + +Although unusual, there is no reason why a directory should not have an extension, and any extension in +name is significant. + + +The function returns zero if successful or a negative error number if it fails. As well as the p_fparse error +numbers returned if name fails to parse, p_mkdir can return the following negative error numbers: + + +E_FILE_DEVICE the device does not exist + +E_FILE_NOTREADY the device does not contain a medium + +E_FILE_EXIST the directory already exists + +E_FILE_PROTECT the medium is write protected or is read-only (eg a ROM SSD) +E_FILE_FULL there is no more room on the medium + +E_FILE_DIRFULL there is no more room in the root directory + + +For example, if the current path is Loc: :a:\, then either: +p_mkdir("\\dirl\\dir2\\"); + +or +p_mkdir("\\dirl\\dir2") ; + + +makes the directory Loc: :A:\DIR1\DIR2\ and also makes Loc: :A:\DIR1\ if it does not already exist. + + +p_sfstat Set file attributes or label medium + + +INT p_sfstat (TEXT *name, UINT status, UINT mask); +INT p_sfstatasync(TEXT *name, UINT status, UINT mask, WORD *stat); + + +Set or clear the attributes of the file specified by the zero terminated file name name (but see also Setting +the volume name below). Both status and mask contain a bit field made up of the following bit masks: + + +P_FAWRITE set if file may be written to +P_FAMOD set if the file has been modified +P_FAHIDDEN set if file is hidden + +P_FASYSTEM set if file is a system file + + +The function only modifies those bits that are set in mask where attribute is set or cleared depending on +the value of the corresponding bit in status. + + +11-22 + + +11 FILES + + +The function returns zero if successful or a negative error number if it fails. As well as a p_fparse error +number if name fails to parse, p_sfstat can return the following negative error numbers: + + +E_FILE_DEVICE the device does not exist + +E_FILE_NOTREADY the device does not contain a medium + +E_FILE_DIR the directory does not exist + +E_FILE_NXIST the file does not exist + +E_FILE_LOCKED a process has name open + +E_FILE_PROTECT the medium is write protected or is read-only (eg a ROM SSD) + + +For example: +p_sfstat ("joe.doc",0,P_FAWRITE) ; +makes the file joe.doc read-only. + + +Setting the volume label + + +If mask has the p_ravouume bit set, status 1s ignored p_sfstat and p_sfstat sets or deletes the volume +name. + + +At the time of writing, only the toc: : file system supports setting the volume label (the function returns +E_GEN_Nsup if it is not supported). + + +The name parameter should be a zero terminated file specification with a root directory (name is parsed +with a nuuu related name) of the form: + + +LOC: :\ + + +to label the medium in , giving it the volume name . If name does not contain a + component, the volume label is deleted. + + +The function returns zero if successful or a negative error number if it fails. As well as a p_fparse error +number if name fails to parse, p_sfstat can return the following negative error numbers: + + +E_FILE_DEVICE the device does not exist +E_FILE_NOTREADY the device does not contain a medium +E_FILE_PROTECT the medium is write protected or is read-only (eg a ROM SSD) + + +For example, if the current path is toc: :a:\, then: +p_sfstat ("d:\mydisk",0,P_FAVOLUME) ; +gives the medium in device Loc: :p: the label myprskx, +p_sfstat ("d:\diskname.dsk", 0,P_FAVOLUME) ; +gives the medium in device toc: :p: the label prsKName.psx and: +p_sfstat ("d:\",0,P_FAVOLUME) ; + + +deletes any volume name from device Loc: :D:. + + +p_fdate Set file creation date + + +INT p_fdate(TEXT *name, ULONG date); +INT p_fdateasync(TEXT *name, ULONG date, WORD *stat); + + +Set the file creation date to date where date is in the form of the system time - that is, the number of +seconds since January Ist 1970. + + +The date may not be set earlier than January Ist 1980. If p_fdate is called with any earlier system time, +the date is forced (without error) to January Ist 1980. + + +The system time used for the creation date is always converted to an even number of seconds (i.e. the least +significant bit of date is discarded). + + +11-23 + + +PLIB REFERENCE + + +The function returns zero if successful or a negative error number if it fails. As well as a p_fparse error +number if name fails to parse, p_fdate can return the following negative error numbers: + + +E_FILE_DEVICE the device does not exist + +E_FILE_NOTREADY the device does not contain a medium + +E_FILE_DIR the directory does not exist + +E_FILE_NXIST the file does not exist + +E_FILE_LOCKED a process has name open + +E_FILE_ACCESS name is a read-only file + +E_FILE_PROTECT the medium is write protected or is read-only (eg a ROM SSD) + + +The following example copies the date of fred.doc to fred.txt. + + +P_INFO info; + + +p_finfo("fred.doc", &info) ; +p_fdate("fred.txt",info.modst) ; + + +Binary file access + + +To open a file to be manipulated as a flat binary file, you call p_open with the 3rd parameter mode or'ed +with P_FSTREAM. For example: + + +p_open (&fcb, "fred.dat",P_FSTREAM|P_FSHARE) opens a file for reading only. +p_open (&fcb, "fred.dat",P_FSTREAM|P_FUPDATE |P_FREPLACE|P_FRANDOM) creates a writable binary file. +The mode flags (eg P_FREPLACE) are described under p_open, below. + + +There is no practical limit to the number of channels that may be opened in the system or by a particular +process. + + +Once you have opened a binary file channel, the possible I/O operations are: + + +p_read to read from the file channel +p_ioc (P_FREAD) +p_ioa(P_FREAD) + + +p_write to write to the file channel +p_ioc (P_FWRITE) +p_ioa (P_FWRITE) + + +p_close to close the file channel + +p_seek to set and sense the channel file position + +p_iow (P_FSETEOF) to set the logical end of file + +p_iow (P_FFLUSH) to flush the file buffers + +p_iow (P_FCANCEL) to cancel all pending asynchronous requests (not actively supported) + + +Bytes can be read or written to the file in any length up to a maximum of P_rMaxss12ZE bytes per read or +write. + + +Shared access + + +Any number of processes can open the same file for reading only (but only if all the readers specify +P_FSHARE when they open the file). However, the file server does not allow multiple processes to open a +channel to the same file for writing. + + +Once a file has been opened for reading, it may not be opened again for writing (but it may be opened +again for reading). Once a file has been opened for writing, it may not be opened again for reading or for +writing. + + +11-24 + + +11 FILES + + +If you have an multi-process application design which needs to update shared data, consider one of the +following: + + +e put the shared data in a named segment (see the chapter Memory Allocation) + + +e access the shared file data via a server process (see the chapter Processes and Inter-Process +Messaging) + + +Example of binary file access + + +The following example, which compares the contents of two files, uses many of the functions described in +this chapter. + + +#include +typedef struct + + +INT ret; + +VOID *chan; + +LONG len; + +TEXT name [P_FNAMESIZE]; +UBYTE buf [P_FBLKSIZE]; +} FILE_DATA; + + +LOCAL_D FILE_DATA f1={0,NULL}; +LOCAL_D FILE_DATA f£2={0,NULL}; + + +LOCAL_C VOID CleanUp(TEXT *msg, FILE_DATA *pf) + + +{ +TEXT bb[E_MAX_ERROR_TEXT_SIZE]; + + +p_close(pf->chan) ; +pf->chan=NULL; +if (pf->ret<0) +{ +p_errs (&bb[0],pf->ret); +p_printf("Failed to %s %s (%s)",msg, &pf->name[0],&bb[0]); +pf->ret=0; +} +} + + +LOCAL_C VOID Exit (TEXT *msg) + +{ + +if (fl.ret>=0 && f£2.ret>=0) +p_printf (msg); + +CleanUp (msg, &f1); + +CleanUp (msg, &f£2); + +p_leave (0); + +} + + +LOCAL_C VOID OpenFile(FILE_DATA *pf, TEXT *name, TEXT *related) + + +{ +LONG pos; + + +if (pf->ret=p_fparse (name, related, &pf->name[0],NULL) ) +Exit ("parse"); + +if (pf->ret=p_open (&pf->chan, &pf->name [0], P_FSTREAM|P_FSHARE|P_FRANDOM) ) +Exit ("open") ; + +pf->len=0L; p_seek (pf->chan, P_FEND, &pf->len) ; + +pos=0L; p_seek (pf-—>chan, P_FABS, &pos) ; + +} + + +LOCAL_C VOID ReadFile(FILE_DATA *pf) +{ +pf->ret=p_read(pf->chan, &pf->buf[0],sizeof (pf->buf) ); +if (pf->ret!=E_FILE_EOF && pf->ret<0) +Exit ("read"); + + +11-25 + + +PLIB REFERENCE + + +LOCAL_C VOID CDECL CompareFiles (TEXT *filel, TEXT *file2) +{ +OpenFile(&f1,filel,NULL) ; +OpenFile(&f2,file2,&f1.name[0]); +p_printf ("Compare %s (%1d)",&f1.name[0],f1.1len); +p_printf(" with %s (%ld)",&f2.name[0],f£2.len); +if (fl.len!=f2.1len) +Exit ("Files are of different length"); +FOREVER +{ +ReadFile(&f1); +ReadFile(&f2) ; +if (fl.ret==E_FILE_EOF && f2.ret==E_FILE_EOF) +{ +fl.ret=f2.ret=0; +Exit ("Files are identical"); +} +if (p_bcmp(&f1l.buf[0],fl.ret,&f2.buf[0],f£2.ret) ) +Exit ("Files are different"); + + +} + + +GLDEF_C INT main(VOID) +{ +TEXT *p; +TEXT bb[P_FNAMESIZE]; + + +while (p_getl("Enter ? ",&bb[0],P_FNAMESIZE) ) +{ +p=p_skipch(&bb[0]); +if (*p) +*p++=0; +p_enter((VOID *)CompareFiles, &bb[0],p_skipwh (p)); +} +return (0); + + +} + + +The program solicits two file names to compare (where the second name is parsed with the first name as a +related name in CompareFiles) and reports whether they are the same or different. As well as illustrating +binary file access, the example gives a realistic illustration of the use of p_enter and p_leave. Note also +that the function cleanup takes advantage of the fact that p_close (NULL) is harmless. + + +p_open(P_FSTREAM) Open a binary file +INT p_open(VOID **ppfcb, TEXT *name, UINT mode); + + +Open a channel to the file specified by the zero terminated file specification name and, if successful, return +zero and write the channel to *ppfcb (ppfcb is not written to if the open fails). To open a file to be +manipulated as a flat binary file, mode should be or'ed with P_FsTREAM. + + +The file specification name is parsed with a nutt related file name (see p_fparse). If this fails, the open +fails and returns the return value from p_fparse. + + +The mode in which the file is opened is selected by oring in one (and only one) of the following bit fields +into mode: + + +P_FOPEN Open an existing file. If the file does not exist, the error E_LFILE_NXIST is +returned. This option would normally only be used to open a file for read +access. + +P_FCREATE Create a file which must not already exist. If the file does exist, the error + + +E_FILE_EXIST is returned. To enable write access to the file you must specify +P_FUPDATE (described below). + + +P_FREPLACE If the file exists, open it and truncate it to zero length. If the file does not exist, +then create a file. To enable write access to the file you must specify P_FUPDATE +(described below). + +P_FAPPEND This is the same as for P_FOPEN except that the initial current position is set to + + +the end of file such that the next write will append to the file. It is not necessary +to specify P_FRaNnpDom (described below) but to enable write access to the file you +must specify P_FUPDATE (described below). + + +11-26 + + +11 FILES + + +P_FUNIQUE Create a unique file using the passed path as the related path name in which to +create the file. The unique file name is written back to name (there should be +room for p_FNAMESIzE bytes). It is not necessary to specify p_FUPDATE +(described below). + + +The access which is subsequently permitted is formed by oring together a combination of the following +flags in mode: + + +P_FUPDATE specifies that write access as well as read access is required for the file. If an +attempt is made to write to a file when this flag has not been set, the error +E_FILE_RDONLY is returned. + + +P_FRANDOM specifies that random access (as opposed to sequential access) is required for +the file. If a call is made to p_seek with a file that has not been opened with +this option, the error E_FILE_INv is returned. You should not specify +P_FRANDoM unless you do intend to use p_seek because the file system may be +able to optimise the device access if it knows that only sequential access is +required. + + +P_FSHARE specifies that this open should not block the file from being opened again for +read access. If this flag is not set, a subsequent request to open a file (by the +same or another process) will fail with z_FILE_LOCKED. + + +Note that shared write access is not supported and p_rsHare can not be combined with p_ruppaTE. + + +Returns zero if successful or a negative error number if it fails. As well as the p_fparse error numbers +which may be returned if name fails to parse, p_open (P_FSTREAM) can return the following negative error +numbers: + + +E_GEN_NOMEMORY failed to allocate memory for the control block + +E_GEN_ARG mode contains an illegal combination of flags + +E_FILE_DEVICE the device does not exist + +E_FILE_NOTREADY the device does not contain a medium + +E_FILE_EXIST attempt to create a file which already exists + +E_FILE_NXIST attempt to open a file which does not exist + +E_FILE_ACCESS access to the file in the requested mode is not available + +E_FILE_DIRFULL there is no more room in the root directory + +E_FILE_PROTECT attempted to create/replace when the medium is write protected or is read-only +(eg a ROM SSD) + +E_FILE_FULL there is no room on the device to create/replace this file + +E_FILE_LOCKED the file is already open (possibly by another process) + +E_FILE_DEVICE the device in name does not exist + +E_FILE_DIR the directory in name does not exist + +p_close Close a binary file channel + + +INT p_close(VOID *pfcb) ; +Close the binary file channel pfcb and return zero if successful. If pcb is NULL, just return zero. + + +Although p_close can return an error, it will always succeed in closing the channel (and pfcb should not +be used subsequently). + + +If the file system buffers written data, the close operation may need to perform one or more write +operations on closing. Even if written data is not buffered, if data has been written to the file, the close +will update the modification date on the file. Because of this, p_close can return the some of the errors +numbers which can be returned from p_write and p_fdate. However, the failure to flush the data or to +write the new date will not cause the close operation to be aborted although the failure will be reported by +an error return. + + +11-27 + + +PLIB REFERENCE + + +Carefully written applications avoid this problem by using p_iow(P_FFLUSH) to flush the data and to apply +the date (and taking appropriate action if this fails) before closing the channel without risk of failure. + + +The toc: : file system on SIBO machines does not buffer written data. When EPOC is running on a PC, +the Loc:: file system is built over the MSDOS filing system which does buffer written data. + + +p_read Read from a binary file channel +INT p_read(VOID *pfcb, VOID *buf, UINT len); + + +Reads 1en bytes or the number of bytes remaining before the end of file, whichever is smaller, from the +current position of binary file channel pfcb and writes the data to buf. The current position is incremented +by the number of bytes read. + + +If the current position is already at the end of file, zero bytes are read and the negative error number +E_FILE_EOF is returned. + + +The parameter len must not be greater than p_rmaxss1zE (16K bytes). + + +The most efficient way of processing files is to read in multiples of P_rFBLKs1zE (512) while ensuring that +the file position remains on P_FBLKS1zE boundaries. + + +The function returns the number of bytes written to buf if successful or one of the following negative +error numbers: + + +E_FILE_EOF end of file encountered + + +E_FILE_ABORT the SSD containing the file is or was previously not present and the channel is +now in the abort state + + +E_FILE_READ failed to read from the file (eg because of a CRC failure on a floppy disk) + + +p_write Write to a binary file channel +INT p_write(VOID *pfcb, VOID *buf, UINT len); + + +Write len bytes from buf to file channel pfcb at the current file position. The current position is +incremented by the number of bytes written. + + +The parameter len must not be greater than p_rMaxss1zE (16K bytes). + + +The most efficient way of processing files is to write in multiples of P_FBLKs1z=z (512) while ensuring that +the file position remains on P_FBLKS1ZE boundaries. + + +When writing to Flash SSDs, you can physically overwrite a single byte (where len is one) provided that +the new byte can be written by just clearing bits in the old byte. In general, overwriting data on a Flash +SSD-based file will consume space and reduce the remaining capacity of the SSD. + + +The function returns zero if successful or one of the following negative error numbers: + + +E_FILE_FULL not enough room on the device for the data + +E_FILE_RDONLY the file channel was opened without the Pp_rupDaTE access bit set + +E_FILE_ABORT the SSD containing the file is or was previously not present and the channel is +now in the abort state + +E_FILE_WRITE failed to write to the file (eg because of a CRC failure on a floppy disk) + +E_GEN_BATFLASH failed to write to the file because the batteries are too low to write to a Flash +SSD + + +11-28 + + +11 FILES + + +p_seek (or f_seek) Position a binary file channel + + +INT p_seek (VOID *pfcb, INT sense, LONG *ppos) ; +INT f_seek(VOID *pfcb, INT sense, LONG *pos); + + +Set the current file position of file channel pfcb to a new file position which depends on sense and +*ppos, where sense is one Of: + + +P_FABS to set the current file position to *ppos + +P_FEND to set the current file position to *ppos relative to the current end-of-file +position + +P_FCUR to set the current file position to *ppos relative to the current file position + + +If successful, the new file position (which may be the same as the old) is written to *ppos and p_seek +returns zero. Otherwise, it returns one of the following negative error numbers: + + +E_FILE_INV the channel was not opened with p_rranpom + + +E_FILE_ABORT the SSD containing the file is or was previously not present and the channel is +now in the abort state + + +If the channel was opened with p_rsTREAM_TEXT on a remote file system, the full p_rszEx functionality +may not be supported. When this is the case, p_seek fails with r_F1LE_1nv. However, the following is +always supported on Pp_rSTREAM_TEXxT channels: + + +¢ using p_rass to set the current position to zero + + +¢ using p_FEND with a zero relative position to set the current position to the end of the file +(although with p_rsTREAM_TExT you should not use the value which is written to *ppos) + + +If calling p_seek results in an absolute file position which is negative then the file is positioned at the +beginning of the file. If the absolute file position is greater than the end of file then the new position is set +to the end of file. See p_iow(P_FSETEOF) for setting a new end of file. + + +The function £_seek is identical to p_seek except that, if there is an error, it calls p_leave (err) rather +than return the negative error number err. + + +For example, if the current file position is 0x2000 then +LONG pos; + + +pos=256L; +p_seek (pfcb, P_FCUR, &pos) ; + + +sets the current position to 0x2100 and + + +pos=-256L; +p_seek (pfcb, P_FCUR, &pos) ; + + +sets the current position to 0x1f£00 and + + +pos=0L; +p_seek (pfcb, P_FCUR, &pos) ; + + +does not change the current position but could be used to sense the current position (pos contains 0x2000 +after p_seek has returned). If the current end of file is 0x4000 then + + +pos=0L; +p_seek (pfcb, P_FEND, &pos) ; + + +sets the current position to the end of the file and senses the length of the file (pos contains 0x4000 after +p_seek has returned). To set the current position to the beginning of the file, use: + + +pos=0L; +p_seek (pfcb, P_FABS, &pos) ; + + +11-29 + + +PLIB REFERENCE + + +p_iow(P_FFLUSH) Flush internal file buffers + + +INT p_iow(VOID *pfcb, P_FFLUSH) ; +Flush all buffered written data to binary file channel pfcb and write the file's modification date. +Returns zero if successful (the negative error number returns are as for p_write). + + +The amount of information which is flushed depends on the file system and on the medium in the drive. +The RAM and Flash SSD PDDs do not buffer any file data (in this case, calling p_iow(P_FFLUSH) just +writes the file date). On Flash SSDs the last record written is held open until the file is closed or a write +occurs to another file on the same SSD (see the section Flash SSDs at the beginning of this chapter). +When EPOC is running on a PC, written file data is buffered to improve performance. Calling +p_iow(P_FFLUSH) will ensure that any buffered data is written to the file but repeated flushing is likely to +degrade performance. + + +Although harmless, there is absolutely no benefit in calling p_iow(P_FFrLusH) on file channels which were +opened without the p_ruppateE flag. + + +p_iow(P_FSETEOF) Set end of file + + +INT p_iow(VOID *pfcb, P_FSETEOF, ULONG *peof); + + +Set the logical end of file on channel pfcb to position *peof and return zero if successful (the negative +error number returns are as for p_write). The file channel must have been opened with p_FuPDATE. + + +If *peof is greater than the current end of file, the file size is extended to *peof. On block-structured +devices (ie excluding Flash SSDs), this is equivalent to appending indeterminate data to the end of the file +to pre-allocate storage. (It is not useful to extend a file on a Flash SSD.) The current position is not +affected when the file is extended with p_iow(P_FSETEOF). + + +If *peof is less than the current end of file, the file is truncated to *peof (the current position is also +reduced if necessary to the new end of file). + + +p_iow(P_FCANCEL) Cancel an asynchronous file channel request +INT p_iow(VOID *pfcb, P_FCANCEL) ; +Cancel all asynchronous I/O requests on channel pfcb and return zero. + + +The operation is harmless if no request is pending. In fact, for reasons which were described at the +beginning of this chapter (under the heading Asynchronous file operations), a call to p_iow (P_FCANCEL) +has no effect even when a request is pending. + + +However, if you are performing asynchronous file access (which is not at all common) you may (for the +sake of consistency and provided the status word is currently E_LFILE_PENDING) Use p_iow(P_FCANCEL) - +normally followed by a call to p_waitstat - to effect cancellation as you would do for any other +asynchronous request. It is always possible that a future implementation of the file server may process +P_FCANCEL operations. + + +At the time of writing, a preferable alternative is to simulate a cancel service, as illustrated in the earlier +example, under the heading Asynchronous file operations. + + +Stream text file access + + +Different file systems vary in their support of a text file type and (if such support is provided) implement +text files in different ways. + + +Some systems (for example, DEC's VMS operating system which runs on a Vax) support text file types +that are not implemented as crLF terminated records. Other systems (such as MSDOS, UNIX and the +EPOC toc: : file system on a SIBO machine or a PC) do not support a text file type, and on such systems +the following convention predominates: + + +e text records are terminated by a cRLF sequence - a carriage return (code 13) followed by a line +feed (code 10) + + +e a file may optionally be terminated by a sus character (code 26) + + +The terminating sus is not necessary on systems that store a logical file length and it is falling out of use. + + +11-30 + + +11 FILES + + +Applications running under EPOC that read or write text files can choose either to process the records in a +text file themselves, or to take advantage of the system's text file handling. The system support for text +files, using p_open (P_FTEXT) , is described in the next section of this chapter. + + +Applications that do their own text file processing, for performance purposes or otherwise, should use +p_open (P_FSTREAM_TEXT) in preference to p_open (P_FSTREAM) . + + +Using p_FsTREAM_TEXT when opening such a text file on the rem: : file system declares the intention that +the file is to be considered as a text file. It causes the remote file server to present the data from the file +as if it were implemented with criF terminated records. In more detail, this presentation layer does the +following: + + +when reading the text record content on the remote system is converted to that content +followed by a cRLF + + +when writing the data is parsed for crLF record terminators and converted into text records +on the remote system (the parser will also recognise cr, LF Or LFCR as a record +terminator) + + +Although in many cases (and certainly when opening a local file) opening with p_rsTREAM_TEXT has an +identical effect to opening with p_rsTReaw, there is no guarantee that the effect will be the same on a +remote file. There is no penalty to using p_rsTREAM_TExT - only a potential gain when accessing a remote +file. + + +The upshot of all this is... + + +All this sounds very complicated (and it is - especially for the implementor of the remote file server) but +you should trust the system and just remember this: + + +To open a text file to be manipulated as a flat binary file, you should call p_open with + +mode or'ed with p_rsTREAM_TEXT and not p_FSTREAM. +With the exception of p_open, all functions are exactly as for flat binary files, described in the previous +section. + + +p_open(P_FSTREAM_TEXT) Open a stream text file + + +INT p_open(VOID **ppfcb, TEXT *name, UINT mode); + + +Open a channel to the file specified by the zero terminated file specification name and, if successful, return +zero and write the channel to *ppfcb (ppfcb is not written to if the open fails). + + +To open a stream text file (a text file to be manipulated as a flat binary file) mode should be or'ed with +P_FSTREAM_TEXT. + + +For all other details, see the description p_open (P_FSTREAM) in the previous section. + + +Text file access + + +To open a file to be manipulated as a record oriented text file, you call p_open with the 3rd parameter +mode or'ed with p_rtext. For example: + + +p_open (&fcb, "fred. lis",P_FTEXT|P_FSHARE) opens a text file for reading only. +p_open (&fcb, "fred. lis", P_FTEXT|P_FUPDATE|P_FREPLACE) creates a text file which may be written to. +Once you have opened a text file channel, the possible I/O operations are: + + +p_read to read the next text record from the file channel +p_ioc (P_FREAD) +p_ioa(P_FREAD) + + +p_write to append a text record to the file channel +p_ioc (P_FWRITE) +p_ioa (P_FWRITE) + + +p_close to close the text file channel + + +11-31 + + +PLIB REFERENCE + + +p_seek to set and sense the channel file position + +p_iow (P_FSETEOF) to set the logical end of file + +p_iow (P_FFLUSH) to flush the file buffers + +p_iow (P_FCANCEL) to cancel all pending asynchronous requests (not actively supported) + + +The text file handling is not part of the file server but is implemented as a layer of code over the +P_FSTREAM_TEXT binary file access. The text file handling code runs in the caller's context ("on the client +side") in the same way as regular function calls. This layer of code is inserted between the application and +the file server by the F1L: device driver p_open code when it sees the P_FTEXT bit set in the mode +parameter. The data is, however, buffered in this layer, so flushing is necessary to ensure that any buffered +data is written to the file. + + +Implementing the code as a layer over P_FSTREAM_TEXT binary file access makes it independent of the file +system node which is providing the services. + + +What text file handling does +The text file handling assumes that text files obey the following conventions: + + +e text records are terminated by a cRLF sequence - a carriage return (code 13) followed by a line +feed (code 10) + + +e a file may optionally be terminated by a sus character (code 26) + + +The text file handling also assumes that the record content (excluding the record termination) does not +exceed a length of P_rmMaxRs1zE (256) bytes. A text record may not contain cr, LF or suB characters, but +there is no other restriction on the contents. + + +When reading a file, the text file handling parses a stream of bytes for cRLF record terminators such that +the application gets the data a record at a time (excluding the terminator). The parser will also recognise +CR, LF, LFCR or a SUB as a record terminator. If it sees a sus (either as a record terminator or immediately +after a CRLF, CR, LF Of LFCR record terminator), it will behave as if the end of file had been reached. + + +When writing to a file, the text file handling simply adds the record terminator (which is always CRLF) to +the end of the record data. A terminating svuB is not written. + + +For enthusiasts ... +This is for interest only and may certainly be skipped. + + +In case you were wondering what the Txt: device is, text file handling is implemented as an I/O device +driver (txT:) which layers over the FIL: P_FSTREAM_TEXT mode binary file access (which was described +in the previous section). The Fru: device redirects the p_open to TxT: when P_FTEXT is set in mode. This +means that the following calls to p_open: + + +p_open(&fcb, "fred.dat", P_FTEXT|P_FUPDATE|P_FREPLACE) ; +p_open (&fcb, "FIL: fred.dat", P_FTEXT|P_FUPDATE|P_FREPLACE) ; +p_open (&fcb, "TXT: fred.dat", P_FUPDATE |P_FREPLACE) ; + + +are all equivalent. (The above examples are provided to help de-mystify the I/O system and the FIL: +device and it would be obscure to use TxT: without good cause.) + + +p_open(P_FTEXT) Open a text file +INT p_open(VOID **ppfcb, TEXT *name, UINT mode); +Open a file to be manipulated as a record oriented text file where mode should be or'ed with P_FTExT. + + +Except for the use of P_FTEXT in place of P_FSTREAM or P_FSTREAM_TEXT, the parameters and returns are as +for opening a binary file, described in the previous section. + + +p_close Close a text file channel +INT p_close(VOID *pfcb); +Close the text file channel pfcb and return zero if successful. + + +Since text written to the file is buffered in the device driver, p_close may give rise to an E_FILE_WRITE +error. It is therefore advisable to call p_iow(pP_FFLusH) before calling p_close. Otherwise, the behaviour +and returns are as for closing a binary file, described in the previous section. + + +11-32 + + +11 FILES + + +p_read Read from a text file channel + + +INT p_read(VOID *pfcb, VOID *buf, UINT len); + + +Read the contents of the current record (ie excluding any record terminators) from text file channel pfcb, +writing up to 1en bytes to buf and, if successful, return the length of the record read (which is also the +number of bytes written to buf). The channel is positioned to the next record. + + +If 1en is less than the length of the current record, the first 1en bytes from the record are read and p_read +returns the negative E_FILE_RECoRD. The channel is still positioned to the next record. + + +Note that p_read returns zero if it encounters a record of zero length. + + +After the last record is read, the channel is positioned to the end of the file. When the channel is +positioned at the end of the file, p_ read returns the negative =_F1ILE_koF (nothing is written to buf). + + +Other negative error returns are: + + +E_FILE_ABORT the SSD containing the file is or was previously not present and the channel is +now in the abort state + +E_FILE_READ failed to read from the file (eg because of a CRC failure on a floppy disk) + +Example + + +LOCAL_D VOID *fcb=NULL; + + +LOCAL_C INT CDECL SearchFile(TEXT *file, TEXT *pattern) +{ +INT ret; +TEXT line [P_FMAXRSIZE+2]; + + +if (ret=p_open(&fcb, file, P_FTEXT) ) +panic("Failed to open file",ret); +while ((ret=p_read(fcb, &line[0],P_FMAXRSIZE) ) >=0) +{ +line [ret]=0; +if (ret && p_smatchi(é&line[0],pattern) ) +p_printf(&line[0]); +} +p_close(fcb); +if (ret!=E_FILE_EOF) +panic("Failed to read file",ret); +return (0); + + +} + + +p_write Write to a text file channel + + +INT p_write(VOID *pfcb, VOID *buf, UINT len); + + +Write a record of length 1en bytes (where 1en is zero to p_FMAxRS1ZE inclusive) from buf to the text file +channel pfcb. Returns zero if successful or one of the following negative error numbers: + + +E_FILE_FULL not enough room on the medium for the data + +E_FILE_RECORD the record size exceeds P_FMAXRSIZE + +E_FILE_RDONLY the file channel is opened without p_ruppatE being set in mode + +E_FILE_ABORT the SSD containing the file is or was previously not present and the channel is +now in the abort state + +E_FILE_WRITE failed to write to the file (eg because of a CRC failure on a floppy disk) + + +Records are always written to the end of file. + + +The data between buf and buf+1en should not include any record delimiters. + + +11-33 + + +PLIB REFERENCE + + +p_seek (or f_seek) Position a text file channel + + +INT p_seek (VOID *pfcb, INT sense, LONG *ppos) ; +INT f_seek(VOID *pfcb, INT sense, LONG *pos); + + +Set the current record position of text file channel pfcb to a position which depends on sense and *ppos, +where sense is one Of: + + +P_FREWIND to position to the first record (the value of ppos is ignored) +P_FRSENSE to get the position of the last record read or written +P_FRSET to set the record position which was previously got with a call to + + +p_seek (P_FRSENSE) +Returns zero if successful or the negative E_FILE_1nv if the file was not opened with P_FRANDoM. + + +Some remote file systems may not be capable of supporting p_seek (P_FRSET) and p_seek (P_FRSENSE) +and in this case p_seek will return E_FILE_INV. + + +The function f_seek is identical to p_seek except that, if there is an error, it calls p_leave (err) rather +than return the negative error number err. + + +It is important to note that this function sets the current record position for read operations only. Records +are always written at the end of file. + + +Example + + +while ((len=p_read(fcb, &buf[0],P_FMAXRSIZE) )>0) +{ +buf [len]=0; +if (buf[0]==':') +{ +p_seek (fcb, P_FRSENSE, &pos) ; +StoreLabel (&buf[1],pos); +} + + +p_iow(P_FFLUSH) Flush internal file buffers + + +INT p_iow(VOID *pfcb, P_FFLUSH) ; +Flush all buffered written data to text file channel pfcb and write the file's modification date. + + +The behaviour and returns are as for flushing a binary file, described in the previous section. Unlike the +binary file, however, data is buffered for all file systems and media. + + +p_iow(P_FSETEOF) Set end of text file + + +INT p_iow(VOID *pfcb, P_FSETEOF, ULONG *peof); +Set the logical end of file on channel pfcb to position *peof. + + +Behaviour and returns are as for flushing a binary file, described in the previous section. + + +p_iow(P_FCANCEL) Cancel an asynchronous file channel request +INT p_iow(VOID *pfcb, P_FCANCEL) ; +Cancel all asynchronous I/O requests on channel pfcb and return zero. + + +The behaviour and return values are as for cancelling a binary file request, described in the previous +section. + + +At the time of writing, a preferable alternative is to simulate a cancel service, as illustrated in the earlier +example, under the heading Asynchronous file operations. + + +11-34 + + +CHAPTER 12 + + +PROCESSES AND INTER-PROCESS MESSAGING + + +Processes + + +A process is a running program. It is normally created by loading an image file (also called an executable) +using p_execc. After loading the program, the process creator normally calls p_presume to start the +process running. + + +EPOC is a single-user multi-tasking operating system that rapidly switches contexts between a number of +independent processes - creating, at times, the illusion of multiple processes running in parallel. + + +The maximum number of processes that may exist is E_MAX_PROCESSES (24). + + +At any particular time, one process is actually running. On a reschedule, EPOC runs the process with the +highest priority that is ready to run. If there is only one ready process at the highest priority it will +continue to run indefinitely (and any lower priority ready processes will wait indefinitely). + + +Preemptive multi-tasking means that the running process may be replaced at any time - it does not have to +make a system call to yield the processor. A process which becomes ready will immediately run if it has +the highest priority. + + +If there is more than one ready process with the highest priority then each process is made current for a +fixed time period (4 system ticks) after which the operating system makes the next process of that priority +current in what is called a "round robin" fashion. On a SIBO machine, the system "ticks" 32 times a +second. + + +Because EPOC is a single-user system, the current process is comparatively rarely switched out by the +system tick. It is more likely to stop running because an event occurred that made a higher priority process +become ready or because the current process voluntarily gave up its ready status to wait for an event to +occur. + + +In EPOC, a process consists of at least the following: +e aprocess control block (described below) + + +e adata segment, containing the processor stack, static variables and the heap (as described in the +Memory Allocation chapter) + + +¢ aprimary code segment (which is shared if there are one or more other processes of the same +program) + + +e an I/O semaphore (as described in the chapter Asynchronous Requests and Semaphores) + + +On SIBO machines, a process that tries to write to a memory segment other than its own data segment +(except via functions that explicitly allow such activity) is panicked with panic number 60. + + +A code segment may exist in ROM or it may be loaded into a RAM memory segment from an executable. + + +A process may acquire other resources during its lifetime - for example, I/O channels or additional code +segments. The system automatically releases owned resources such as memory segments, I/O channels +and semaphores when it terminates. Server processes are also designed to clean up client resources when a +client process terminates. + + +12-1 + + +PLIB REFERENCE + + +System processes + + +When the operating system initialises itself, it creates a number of system processes some of which are +essential to the operation of EPOC. + + +After a system reset on a typical machine running EPOC, the system processes (by process name) are: + + +SYSSNULL.$01 the zero priority null process runs when no other process is ready to run and +switches the machine off (to reduce power consumption) after a period of +inactivity + +SYSSMANG.$02 the supervisor has a higher priority than any other process and performs many + + +critical system functions including memory segment moving and resource +clean-up when a process terminates + + +SYSSFSRV.$03 the file server (described in the Files chapter) has the second highest priority +and performs all file related operations, including loading an image to create a +process + +SYSSWSRV.$04 the window server (described in the Window Server manual) provides shared + + +access to the screen, keyboard and, if present, the digitiser (or mouse on a PC) + + +SYSS$SHLL.$05 the shell process provides a user interface that allows other processes to be +started (on a custom system it might provide a "turnkey" environment) + + +The extension of the process name gives the process number (assigned by the operating system). The +structure of process names is described later in this chapter. + + +The functions (described in this chapter) which change the process name, change the process priority and +suspend a process will fail when applied to syssnuLL, sySSMANG and SYSSFSRV. + + +On systems with a digitiser (or mouse), the window server creates a subsidiary process, sharing its data +segment, to draw the mouse icon. In EPOC, a subsidiary process that shares the data segment of its owner +is called a task and the window server task has a name such as sys$wsRV.@05. + + +The notifier service p_notify (described in the chapter Error Handling) may be provided by the window +server itself or it may be provided by a client of the window server. If a separate notifier exists, it has a +process name such as SYS$NTIFY.$07. + + +Process ID and process control block +Each process is identified by its process ID - a positive 16-bit number containing two bit fields: + + +e = The least significant 12 bits is the offset of the process control block in the operating system data +segment (also called the process slot). + + +e The most significant 4 bits contains a value in the range 0-7 (note that a valid process ID is +positive). This value is incremented modulo 8 each time a process slot is used so that a process +ID may be rejected after a process has terminated. + + +The function p_getpid returns the process ID of the caller. + + +If a system function is passed a process ID that is zero or negative, or in which the least significant 12 bits +is outside the range of the process table, the caller is panicked with panic number 7 (invalid process ID). + + +12-2 + + +12 PROCESSES AND INTER-PROCESS MESSAGING + + +The structure of the process control block is defined by the &_proc struct, defined in epoc.h as: + + +typedef struct e_proc + + +{ + + +struct e_proc *next; + + +struct e_proc *prev; +WORD queKey; +WORD queData; +deltaType; +addressTrap; + + +UBYT +UBYT +UBYT +UBYT +UBYT +UBYT +UBYT +UBYT +UBYT +UBYT +UWOR +UBYT +UBYT +UWOR +UBYT +UWORD + + +E +E +E +E +E +E +E +E +E +E +D +E +E +D +E + + +status; +sstatus; +priority; + + +priorityH; + + +ramOrRom; +isTask; + + +name [E_MAX_NAME+1]; + + +active; + + +semaphore; + + +*semHead; + + +*memBasePtr; + + +memGrowBy; +*mCtrlPtr; + + +minHeap; + + +HANDLE fServer; +HANDLE dataSeg; +HANDLE codeSeg; + + +UBYTE +UBYTE +UBYTE +UBYTE +UWORD +UWORD +UWORD + + +*saveSP; +*saveBP; +notify; +sndSem; +magic; +checkSum; + + +terminate; +} E_PROC;. + + +A copy of a process control block may be obtained by calling p_getosd (where zE_p1pMaskx is used to +mask out the address portion from the process ID) as follows: + + +E_PROC pcb; + + +p_getosd(&pcb, (VOID *) (pid&E_PIDMASK), sizeof (pcb) ); + + +Many of the fields of z_pRoc are described in the course of this chapter. The remaining fields are reserved +for system use. As an aside, and for the reader's interest, some miscellaneous fields (which would not +otherwise be described) are described below. It must be emphasised that none of these fields should be +modified directly by any application code. + + +sstatus + + +ramOrRom + + +isTask + + +active + + +semaphore + + +memBasePtr + + +memGrowBy + + +mCtrlPtr + + +TRUE if the process is waiting to be suspended (for example, if suspended while +on the time delta queue - on leaving the queue it will be suspended rather than +entering the ready queue) + + +TRUE if the process code segment is in RAM, ratss if the code segment is in +ROM + + +TRUE if the process is a task (a subsidiary process that shares the data segment +of its creator) + + +TRUE if the running of this process will stop the machine from switching off - as +set by p_marka and p_unmarka + + +the handle of the process I/O semaphore + + +the address of the start of the heap (4 bytes before that obtained from +p_allspace) + + +the heap granularity in paragraphs as set by p_hgran + + +contains the address of the message control block as set up by p_minit or zero +if p_minit has not been called + + +12-3 + + +PLIB REFERENCE + + +minHeap the minimum heap size in paragraphs + + +fServer the client ID as given by the file server or zero if the process has not connected +to the file server + + +dataSeg the handle of the process data segment + + +codeSeg the handle of the process code segment if the code is in RAM or the paragraph +address of the code segment if the code is in ROM + + +notify the notifier state as set by p_sentnotify (and sensed by p_getnotify) + + +sndSem TRUE if the process is waiting on the sound semaphore, to indicate the need to +call p_signal on termination of the process + + +magic the top 4 bits of the process ID, used to reject a process ID of a process that no +longer exists - even when another process has been created and re-uses the +same process slot + + +terminate contains the termination message type as set by p_onterminate or zero if +p_onterminate has not been called + + +Process states + + +Each process is in one of the following states (as stored in pcb. status): + + +E_PROC_CURRENT the process that is currently running (at any time, one process is in this state) +E_PROC_READY the process is waiting for a chance to run +E_PROC_SEMAPHORE the process is waiting on a semaphore, most likely its I/O semaphore +pcb. semaphore (described in the chapter Asynchronous Requests and +Semaphores) +E_PROC_DELTA the process is waiting in the timer delta queue (described in the chapter Time, + + +Timers and Dates) +E_PROC_SUSPENDED the process exists but will not run until it is resumed by calling p_presume + + +Process queues + + +Processes that are in the READY, SEMAPHORE Or DELTA State are in a doubly-linked queue (using pcb. next +and pcb. prev - see queues in the chapter Characters, Strings, Buffers and Queues). + + +The READY queue is ordered by the process priority as stored in pcb. priority. + + +Each semaphore heads a SEMAPHORE queue. This queue may be empty, or may contain one or more +processes in a first-in, first-out order. + + +The DELTA queue is a special kind of doubly-linked queue (called a delta queue, as described in +Characters, Strings, Buffers and Queues). It stores the time interval in system ticks between timer entries. + + +These queues are described in more detail in the chapter Asynchronous Requests and Semaphores. + + +Process priorities + + +When there is more than one process that is ready to run, the operating system runs the process with the +highest priority (an unsigned byte value in the range 1 to 255). Lower priority processes are blocked +indefinitely. + + +If there is more than one ready process with the same highest priority, they take it in turns to run every +four system ticks. + + +Applications should set their priority in the range E_MIN_PRIORITY (64) to E_MAX_PRIORITY (192) +inclusive (the operating system reserves the values outside this range). + + +The initial process priority is normally taken from a value stored in the program file or image (and is +generated by the tool used to build the image) but it may subsequently be changed using p_setpri +(p_getpri returns the priority of a process). + + +12-4 + + +12 PROCESSES AND INTER-PROCESS MESSAGING + + +Interactive application processes that are clients of the window server are normally created at the priority +E_PRIORITY_FORE (128) and subsequently leave it to the window server to change their priority depending +on whether the process is receiving user input or not. See the Window Server manual. + + +The supervisor runs at priority 248 and the file server at priority 240. A hardware interrupt runs at the +same priority as the process it interrupts. Critical sections of interrupt code are protected by switching off +pre-emption. + + +Preemptive scheduling + + +It is possible for a process to run for as long as it wants to and, in practice, this often happens. In this +case, the current process eventually gives up its cuRRENT state by changing its state to: + + +SEMAPHORE by calling p_iowait to wait on the I/O semaphore (or p_wait to wait on any +semaphore) + +DELTA by calling p_sleep, p_sleept OF p_sleepa + +SUSPENDED by calling p_psuspend on its own process ID + + +However, many events can cause a reschedule in which the current process is preempted by a higher +priority process without completing its course. Such events include: + + +e the fourth consecutive system tick +e asemaphore being signalled (eg as a result of user input) which releases a higher priority process +e the expiry of a higher priority process in the timer DELTA queue + +The current process may, by its own action, cause itself to be preempted by: + + +e signalling the I/O semaphore of a higher priority process (by calling p_iosignalbypia or, for +example, by sending it an inter-process message) + + +e calling p_presume to release a higher priority process from the susPENDED state (especially after +loading a process from an image) + + +e raising the priority of a another process by calling p_setpri +e lowering its own priority by calling p_setpri + +Process names + +A process name takes the following form: + + + +where the component contains between one and eight characters and the component +consists of a period, a s and a two digit number of the form 01, 02, 03 .... This number gives the index +(starting from 1) of the process slot. + + +If the process is a task (a subsidiary process that shares the same data segment), the s is replaced by a e@ +where, except for the @, the process name is otherwise the same as the creator of the task. + + +The maximum length of a process name is =_max_Name (12), excluding the zero terminator (buffers +normally allow &_mMax_NamE+2 bytes to include the zero terminator and to keep following variables on an +even address). + + +When a process is created by loading an image using p_execc, the process is created with a taken +from the file name of the image. For example, if a program called Loc: :\B:\UTILS\SoRT. IMG is loaded +twice the process names might be: + + +SORT .$07 +SORT.$11 + + +The component of a process name guarantees that the process name is unique. Note that the process +data segments are given the same names (see the chapter Memory Allocation) but that these segment +names are held independently of the process name. + + +To convert a process name into a process ID, you use p_pidfind. Since a program cannot anticipate the + component, p_pidfind allows wild card characters in a match string. For example, to get the +process ID of a database server process that was loaded from db$serv.img, you would use +p_pidfind("DBSSERV.*"). + + +When there is the prospect of more than one process of the same (because a program was loaded +more than once), p_pfind may be used to get the process IDs of all instances. + + +12-5 + + +PLIB REFERENCE + + +In the following example, the general purpose function ProcsOfThisProg returns the number of processes +having the same process name (excluding the extension) as this process (that is, it returns the number of +processes of the calling program). + + +GLDEF_C INT ProcsOfThisProg (VOID) +{ +TEXT *pp; +HANDLE h; +INT count; +TEXT mm[E_MAX_NAME+2]; +TEXT bb[E_MAX_NAME+2]; + + +p_pname (p_getpid(), &mm[0] +pp=(&mm[p_slocr(&mm[0],'.' +*pptt='"*'; *pp=0; + +for (h=0,count=0; (h=p_pfind(h, &mm[0], &bb[0]))>=0; count++) ; +return (count) ; + + +} + + +)+1)); + + +The function gets the name of this process using p_pname and p_getpid and builds a match string in mm[] +by replacing the extension with the '*' wildcard. It then uses this match string to count the number of +matching processes. + + +This function could be used to stop more than one process of a program (especially a server) from being +executed where, for example, if ProcsoOfThisProg returns more than one, the server program could panic. + + +Reserved statics (magic statics) + + +The reserved statics (otherwise known as magic statics) are variables with fixed, known, addresses, +existing in the process data space between addresses 0x00 and 0x40. They are 'magic' in the sense that +they are accessible from all parts of the process code, even from dynamic library code (which does not +have any data space and therefore may not, normally, access statics). + + +Some of these variables are used by the operating system as part of the process context. Others are used by +system code such as the window server, and the graphics user interface libraries. Such usage differs from +machine to machine in the EPOC range; you will find a description of any such usage in the +Programming Guide for the appropriate machine or in user interface library documentation. + + +The remaining reserved statics are freely available for use by the process code. A common use is to +provide access from dynamic library code to application-specific data, without the need for it to be passed +in function parameters. + + +0x00 DatWordDead The word at this address contains the value 0xDEapD. This value must not +be changed by application code. Many operating system calls check for +this value and will panic the process with panic reason code PanicDead0 +if it has changed. A change in this value is symptomatic of a common +software bug; the unintentional use of a NULL pointer. + + +0x02 DatHandNext The data at these two addresses are used as pointers to a queue of wait +0x04 DatHandPrev handler function descriptors. This data should not be modified by +application code. + + +0x06 DatCountrySeg This holds the segment handle of the data segment containing the country +and language specific fold tables for the process. This data should not be +modified by application code. + + +0x08 DatClassHandle In applications which use any of the object oriented programming calls + +0x0a DatClassPtr (this includes use of Hwif programs) these locations hold data required by +the operating system to work out how to send a message to an object's +superclass. It is recommended that application code does not modify the +contents of these locations. + + +0x0c DatEClassHandle In applications which use any of the object oriented programming calls + +0x0e DatEClassPtr (this includes use of Hwif) these locations hold data required by the +operating system to work out how to perform a p_exactsend. It is +recommended that application code does not modify the contents of these +locations. + + +12-6 + + +0x10 + + +0x12 + + +0x14 + + +0x16 +0x18 + + +Oxla + + +Oxlc + + +Oxle + + +0x20 + + +0x21 + + +Ox22 + + +0x24 + + +0x26 + + +0x28 +Ox2a +Ox2c +Ox2e +0x30 +0x32 +0x34 + + +DatEnterFramePtr + + +wClientData + + +wserv_channel + + +DatOsFramePtr + + +DatATFlag + + +DatHeapLocked + + +DatProcessNamePtr + + +DatCommandPtr + + +DatTest + + +DatApp1 +DatApp2 +DatApp3 +DatApp4 +DatApp5 +DatApp6 +DatApp7 + + +12 PROCESSES AND INTER-PROCESS MESSAGING + + +The enter and leave mechanism provided by the operating system uses +this address to store the pointer to the last enter frame generated on the +stack. When a leave occurs this pointer is used to unwind the stack and +restore the register set. This location should not be modified by +application code. + + +In applications that use system user interface libraries this location is +assumed to hold the object handle of an instance of the 'wserv' object. The +application is responsible for ensuring that this location is set up +correctly, normally by calling system code on application start-up. + + +In applications that use the application manager object (all object oriented +programs and Hwif programs) this location is assumed to hold the object +handle of an instance of the application manager object. The application +is responsible for ensuring that this location is set up correctly, normally +by calling system code on application start-up. + + +These locations are used by the window server process to store +information about your application. If you use any graphics functions you +should not modify the contents of these locations. + + +This location is used by the OPL language translator. If your application +does not use OPL then this location is free for use by application code. + + +This location is used by the OPL language runtime code. This location +should not be modified by application code. + + +This location contains a pointer to the last member of a linked list of +operating system calling frames. Following this linked list will show +which functions called which operating system services. This location +should not be modified by application code. + + +This byte location contains the current address trap status for the process. +Certain operating system calls cause address trapping to be turned on or +off and the operating system sets or clears this flag to record the current +address trap hardware status. Just setting the flag to zero will not disable +address trapping. This location should not be modified by application +code. + + +This byte location contains the current state of the heap locked flag. +While the heap is being modified (for example, being resized, due to a +memory allocation request) the heap is locked. This prevents the +operating system from compressing the segment while the data structures +used by the operating system to run the heap are in an inconsistent state. +This location should not be modified by application code. + + +System user interface library code assumes that this location contains +either NULL or a pointer to a zero terminated string that the application +wishes to be displayed as its name. Otherwise it is free for use by +application code. + + +This location contains a pointer, set up by the operating system. It points +to an alloc cell that contains the full path name, as a zero terminated +string, of the .img or .app file from which the process was loaded. +Immediately following the zero terminator, the alloc cell contains leading +byte counted initial command line data. + + +Psion's test system library code assumes that this location contains the +object handle of the test code. Otherwise it is free for use by application +code. + + +These locations are free for application code to use. + + +One exception is DatApp7, which is used within the ISAM library. Code +that accesses the ISAM library, either directly or indirectly, may not use +DatApp7, but otherwise it is free for use. + + +12-7 + + +PLIB REFERENCE + + +0x36 DatDialogPtr System user interface library code may assume that this location contains +a pointer to the current dialog structure. Otherwise it is free for use by +application code. + + +0x38 DatGate System user interface library code may assume that this location contains +an object handle. Otherwise it is free for use by application code. + + +0x3a DatLocked System user interface library code may assume that this location contains +a flag indicating whether the application is capable of receiving +termination or switch files messages. Otherwise it is free for use by +application code. + + +0x3c DatStatusNamePtr System user interface library code may assume that this location contains +a pointer to a zero terminated string that will appear in a status window. +Otherwise it is free for use by application code. + + +0x3e DatUsedPathNamePtr | System user interface library code may assume that this location contains +a pointer to a fully parsed file name. Otherwise it is free for use by +application code. + + +Shared code segments + + +When a second or subsequent process of the same program is loaded, the existing code segment (which +has segment name .$sc) is shared and not loaded from the image file (however, the initialized +static data values are still loaded into the created process data segment). + + +The system checks that the contents of the existing code segment matches the code in the image file by +comparing pcb. checkSum with the checksum stored in the image header (the checksum in the image +header is also used to check the integrity of the code when it is loaded). If the checksums do not match, +the load fails. It follows that you cannot run different programs of the same name (or different versions of +the same program) at the same time. + + +Image files + + +An image file is a form of executable (program) file that is run by calling p_execc. It normally has a . mc +file name extension. Application files (with a .ApP extension) are a particular type of image file. + + +An image file is created by applying the emake.exe tool to a DOS executable. This is normally done +automatically as part of the build process that generates an EPOC application program (for an example of +the use of emake.exe, see \ts\sys\tsprj.txt). + + +The creation process adds an ImgHeader struct (defined in epoc.h) to the front of the file and may +optionally concatenate a number of other files into the image file. + + +The ImgHeader struct is effectively defined as: + + +#define SignatureSize 16 +#define MaxAddFiles 4 + + +typedef struct +{ +UINT offset; +UINT length; +} ADDFILE; + + +typedef struct +{ + + +Gq +1 tO +K + + +HZQZGZZZZ2ZRZ ZZ ZZae + + +TE Signature [SignatureSize]; +[ ImageVersion; + +[ HeaderSizeBytes; + +[ CodeParas; + +[ InitialIP; + +[ StackParas; + +[ DataParas; + +[ HeapParas; + +[ InitializedData; + +[ CodeCheckSum; + +[ DataCheckSum; + +[ CodeVersion; + +r Priority; + +ILE Add[MaxAddFiles]; +DylCount; + +NG DylTableOffset; + +[ Spare; + +mgHeader;. + + +iw) + + +Jy + + +E + + +i i RB mm i 1 a en et + + +12-8 + + +12 PROCESSES AND INTER-PROCESS MESSAGING + + +The meanings of the elements of this struct are as follows: + + +Signature + + +ImageVersion + + +HeaderSizeBytes + + +CodeParas + + +InitialIP + + +StackParas + + +DataParas + + +HeapParas + + +InitializedData + + +CodeCheckSum + + +DataCheckSum + + +CodeVersion + + +Priority + + +Add + + +Dy1lCount + + +DylTableOffset + + +Spare + + +contains the string "ImageFileType**". + + +the version number of the software tools used to create the image file. At the +time of writing the version is 2.00F (0x200£) + + +the offset of the start of the executable code within the image file + + +the required size, in (16 byte) paragraphs, of the memory to be reserved for the +code segment + + +the initial instruction pointer offset in the executable code - determined by the +linker, (and normally 0) + + +the size, in (16 byte) paragraphs of the stack - determined by which PLIB C +startup module is linked into the program (see the discussion of startup +modules in the Introduction chapter) + + +the total size, in (16 byte) paragraphs, of the declared static data (including the +initialised data - see below) + + +the required size, in (16 byte) paragraphs, of the initial - and minimum - alloc +heap, user definable via a parameter to emake.exe (see below) + + +the size, in bytes, of the initialised static data +internally generated and verified checksum on the code +internally generated and verified checksum on the data + + +the version number of the executable code, user definable via a parameter to +emake.exe (see Dbf£Version in the chapter Database Files for the form of a +version number) + + +the start-up priority of the process that will be created from this image file, user +definable via a parameter to emake.exe (default value is 0x80) + + +an array of four ADDFILE structs, describing up to four additional files +included within the image file (common included files, in .APP files, are an +icon graphic and a resource file) + + +the number of object dynamic libraries (DYLs) concatenated into the image +file. See also the Object Oriented Programming chapter of this manual. + + +the offset within the file of the start of an array of pyLENTRy structs (defined in +epoc.h) with pyicount entries, giving the names and file offsets of the included +DYLs + + +reserved + + +The contents of this header may be displayed by applying the edump.exe tool to an image file. + + +For efficiency, the value of Heapparas should be adjusted to be equal to, or slightly larger than, the heap +space used by the running process immediately after it has started. Setting a smaller value means that the +heap will have to be grown one or more times during the initialisation of the process. Growing the heap +may involve moving large amounts of in-memory data and may, therefore, significantly increase the +process start-up time (see also The heap allocator in the chapter Memory Allocation). + + +12-9 + + +PLIB REFERENCE + + +IO Ka ns Tn st +Process termination + + +The subject of process termination (with associated functions) is described in detail in the chapter Error +Handling. The functions described include those that terminate a process: + + +p_pterminate or to terminate another process (typically in response to a user request) +p_pkill +p_ppanic to panic another process (normally following unreasonable behaviour from the + + +process being terminated) +and those functions that request notification of the termination of other processes: +p_logona to be signalled when the specified process terminates + + +p_logon to receive an inter-process message when the specified process terminates +(convenient for server processes to keep track of their clients) + + +p_watchall to receive an inter-process message when any process terminates (only one +process can call p_watchal1 - normally the Shell to monitor the termination of +all processes) + + +When a process terminates, pcb. status in the process control block (which normally holds the process +state) is set to E_LPROC_FREE to mark it as available for use by a new process. When a newly created process +re-uses the slot, pcb.magic is incremented modulo 8, as described above. + + +SS a ae a a re eT) +Creating a process + + +p_execc Load an image +HANDLE p_execc(TEXT *pName, VOID *pCommand, INT length); + + +Create a suspended process from the image file described by the zero terminated file specification pNname +and, if successful, return the positive process ID of the created process. + + +The created process is suspended so that the creator can perform any initialisation (eg to set the process +priority) before allowing the process to run by calling p_presume. If the created process has a higher +priority than the creator, the call to p_presume may not return for some time. + + +The file specification pName is parsed with a related name of ". mc". + + +The function allocates a command cell from the heap of the created process. This cell is loaded with the +following sequence: + + +¢ acopy of the zero terminated full file specification resulting from the parse of pName +e a byte containing length +e acopy of the length bytes from pcommand + + +where length must be between zero and E_MAX_COMMAND_BUFFER (127) inclusive. If pcommand is NULL, +length is taken to be zero, whatever is passed. + + +The address of this command cell is written to the reserved static Dat CommandPtr in the created process +data segment. This variable is accessed from C by declaring: + + +GLREF_D UBYTE *DatCommandPtr; + + +Note that there is no restriction on the data in pcommang; it may include binary data structures as well as +text. For example, it is often useful to pass the process ID of the caller in the command line. + + +The name of the created process is taken from the file name component (excluding any extension) of +pName. If a process, loaded from pName, already exists (as determined by a name and checksum match), the +created process shares the loaded code segment. In this case, the code is not reloaded from pName +(however, the initialized static data values are still loaded into the created process data segment). + + +12-10 + + +12 PROCESSES AND INTER-PROCESS MESSAGING + + +The function returns a positive process ID if successful or a negative error number if it failed. As well as + + +the p_fparse error numbers that may be returned if the parse of pName fails, p_execc can return the +following error numbers: + + +E_GEN_NOMEMORY insufficient free system memory + +E_FILE_DEVICE the device in pName does not exist + +E_FILE_NOTREADY the device in pName does not contain a medium + +E_FILE_DIR the directory in pName does not exist + +E_FILE_NXIST the file in pName does not exist + +E_FILE_EXIST a process of a different program (ie with a different checksum) with the same + + +name already exists + + +E_GEN_IMAGE the file is not a valid image or if the image is corrupt + +E_GEN_NOPROC there are no more free process slots (the maximum process limit has been +reached) + +E_GEN_ARG the total size of the data, stack and heap exceeds oxrrero bytes or length + + +exceeds E_MAX_COMMAND_BUFFER + + +The loading of an image is performed by the file server (see the Files chapter) and the caller must + + +have connected to the file server before calling p_execc (otherwise the caller is panicked with panic + + +number 41). The standard PLIB library connects to the file server before calling main. + + +Example + + +#include + + +LOCAL_C VOID Exec(TEXT *name, TEXT *cmd, INT len) +{ +INT ret; +TEXT bb[E_MAX_ERROR_TEXT_SIZE]; + + +ret=p_execc (name, cmd, len); +if (ret<0) +{ +p_errs (&bb[0],ret); +p_printf ("Failed to start %s (%s)",name, &bb[0]); +} +else +{ +p_printf("Process ID is %x",ret); +p_presume (ret) ; +} +} + + +GLDEF_C INT main(VOID) +{ +TEXT *pl,*p2; +TEXT bb[64]; + + +while (p_getl("Enter ? ", &bb[0],64)) +{ +pl=p_skipwh (&bb[0]); + + +if (!*pl) + +continue; +p2=p_skipch (pl); +if (*p2) + + +{ +*p2tt+="\0'; +p2=p_skipwh (p2) ; +} +Exec (pl,p2,p_slen(p2) +1); +} +return (0); + + +} + + +12-11 + + +PLIB REFERENCE + + +The program solicits a line of input and parses out the name of the image to run and a text string to pass +to the created process (which is passed with the zero terminator). If this program is used to run +dummy.img in the default path (which happens to be Loc: :D: \) by entering: + + +dummy fred +and the code for dummy.img is: + + +#include +GLREF_D UBYTE *DatCommandPtr; + + +LOCAL_C VOID PrintCommandPtr (VOID) + + +{ +UBYTE *p, *pe; +UINT lcell; + + +if (!DatCommandPtr) +p_panic (0); + +lcell=p_alen(DatCommandPtr) ; + +p_print ("sd [",lcell); + +for (p=DatCommandPtr, pe=p+lcell;p", *p) ; + +p_printf£("]"); + +} + + +GLDEF_C INT main(VOID) +{ + + +PrintCommandPtr(); +p_getch(); +return (0); + + +} +then dummy.img prints: + + +24 [LOC::D:\DUMMY.IMG<00><05>fred<00>] + + +p_execcasync Load an image asynchronously + + +INT p_execcasync(TEXT *pName, VOID *pCommand, INT length, WORD *pStatus, HANDLE *pPid)j; + + +This is the asynchronous version of p_execc, which may return before the operation is complete. See the +chapter Asynchronous Requests and Semaphores for an explanation of asynchronous requests. + + +See p_execc above for the meaning of the parameters pName, pCommand and length, the behaviour of the +operation and its possible error returns. + + +The function p_execcasync returns zero if the asynchronous request was successful or a negative error +number if the operation failed to start (eg E_FILE_NAME if pName failed to parse). + + +When the load completes, the completion status is written to *pStatus and the process I/O semaphore is +signalled. If the load completes successfully, *pstatus contains zero and *pPid contains the process ID of +the created process (this corresponds to the value returned by p_execc). If the load completes +unsuccessfully, *pstatus contains a negative error number (eg E_GEN_NOMEMORY). + + +If pName refers to a file on the Loc: : file system, the load will actually have completed by the time +p_execcasync has returned because the file server runs at a higher priority than any of its clients. +However, if the image is on a REm: : file system where the connection is via an RS232 cable, +p_execcasync will return well before the load is complete. + + +p_pcreate Create a process + + +HANDLE p_pcreate(E_CPB *pBlock) ; + + +Create a process from the information in the E_cpB struct pointed to by pBlock and, if successful, return +the positive process ID of the created process. + + +This is the primitive process creation service that does not involve the file server. In the vast majority of +cases, it is more convenient to use p_execc, which will eventually call this service. + + +12-12 + + +12 PROCESSES AND INTER-PROCESS MESSAGING + + +The &_pcs struct is defined in epoc.h as: + + +typedef struct +{ + +UWOR: +UWOR: + + +D codeParagraphs; +D +UWORD stackParagraphs; +D +D + + +initiallp; + + +UWOR +UWORD heapParagraphs; +UBYTE *commandLine; +UWORD checkSum; + +UWORD minHeap; + +UBYTE priority; + +UBYTE ramOrRom; + +UBYTE name [E_MAX_NAME]; +} E_CPB;. + + +dataParagraphs; + + +The function creates a process of initial priority pBlock->priority where the process name is taken from +the zero terminated (up to 8 characters) in pBlock->name. + + +If pBlock->ramOrRom is TRUE and a process of the same name already exists, its checksum is compared +with pBlock->checkSum and, if they match, the existing code segment is shared (in which case +pBlock->codeParagraphs is ignored). + + +If pBlock->ramOrRom IS TRUE and a process of the same name does not already exist, p_pcreate creates a +code segment of length pBlock->codeParagraphs paragraphs (and pBlock->checkSum is stored as the +code segment checksum). In this case, the caller must deposit the code into the created code segment +before resuming the process. + + +If pBlock->ramOrRom IS FALSE, pBlock->codeParagraphs is taken to be the paragraph address of the code +segment in the ROM. + + +When the process is resumed, the initial instruction pointer is set to pBlock->initiallIp. + + +A data segment is created, of sufficient size to include the stack (of length pplock->stackParagraphs) a +static data space (of length pplock->dataParagraphs) and a heap (of length pplock->heapParagraphs). +The total size of the data, stack and heap must not exceed oxrre paragraphs. The +pBlock->dataParagraphs area in the data segment is zero filled. The minimum heap size subsequently +allowed for the created process is pBlock->minHeap paragraphs. + + +If pBlock->commandLine 1S not nuuL it should point to a zero terminated string, immediately followed by a +leading byte count buffer where the leading byte is less than or equal to E_Max_COMMAND_BUFFER (as +described in p_execc, above). The whole pBlock->commandLine data structure is copied into a heap cell +that is allocated in the created process. + + +The function returns a positive process ID if successful or on of the following negative error numbers: +E_GEN_NOMEMORY insufficient free system memory + + +E_FILE_EXIST a process of a different program (ie with a different checksum) with the same +name already exists + + +E_GEN_NOPROC there are no more free process slots (the maximum process limit has been +reached) +E_GEN_ARG the total size of the data, stack and heap exceeds oxrreo bytes or the leading + + +byte count length in the pBlock->commandLine data structure exceeds +E_MAX_COMMAND_BUFFER + + +E_FILE_NAME pBlock->name is invalid + + +12-13 + + +PLIB REFERENCE + + +Operations on the current process + + +See the chapter Error Handling for the functions (p_exit and p_panic) that terminate the current process. + + +p_getpid Get this process ID +HANDLE p_getpid(VOID) ; +Return the process ID of the caller. +For example: +TEXT ProcessName [E_MAX_NAME+2]; +p_pname (p_getpid(), &ProcessName[0]); + + +writes the name of this process as a zero terminated string to ProcessName. + + +p_unmarka Mark this process as non-active +VOID p_unmarka (VOID) ; + + +Mark the calling process as non-active such that the running of the process will not keep the machine +switched on. + + +The zero priority null process switches the machine off (to reduce power consumption) after a period of +inactivity. A context switch to a process marked as non-active does not count as activity. + + +When a process is created it is initially marked as active. + + +General purpose server processes should mark themselves as non-active since not to do so would disable +their clients from effectively calling p_unmarka. For example, if the file server was marked as active, a file +request by a non-active client would cause the file server to run and reset the inactivity timer. As it is, the +file server is marked as non-active and it is left to the clients of the file server to reset the inactivity timer +or otherwise. + + +Applications that respond to a continuously restarted short interval relative timer (as in, for example, a +clock program) should also call p_unmarka. Otherwise, the machine would never switch off while the +program is running. + + +Interactive programs that do call p_unmarka do not need to take any measure to reset the inactivity timer +when responding to user input (a key press or the use of a pointing device if there is one) since the system +(by one means or another) guarantees to reset the inactivity timer on user input. To reset the inactivity +timer in response to an event other than user input, call p_tickle, described next. + + +Note that a compute-bound process (such as a game program that is computing its best next move) will +not allow the machine to switch off, simply because the null process never gets an opportunity to run. +Such a process should assume responsibility for allowing the machine to switch off by calling p_allowoff +from time to time. + + +p_tickle Register activity +VOID p_tickle (VOID) ; +Reset the auto-switch-off inactivity timer. + + +It is used by a process that is marked as inactive, but wishes to stop the system switching off. An example +would be to keep the machine going if serial data is received. + + +You don't need to call p_tickle in response to user input since the system automatically registers activity +in this case. + + +12-14 + + +12 PROCESSES AND INTER-PROCESS MESSAGING + + +p_marka Mark this process as active + + +VOID p_marka (VOID) ; + + +Mark the calling process as active such that the running of the process will stop the machine from +switching off. + + +The zero priority null process switches the machine off (to reduce power consumption) after a period of +inactivity. A context switch to a process marked as active resets the inactivity timer. + + +When a process is created it is initially marked as active and p_marka does not need to be called unless +p_unmarka has previously been called. + + +—EeEEeE—E—————— ey +Operations on any process + + +See the chapter Error Handling for functions (p_pterminate, p_pkill and p_ppanic) that terminate a +process. + + +p_getpri Get a process priority +INT p_getpri(HANDLE pid); + + +Return the positive priority of process pia, or the negative k_FILE_Nxtst if the process does not exist. + + +p_setpri Set a process priority +INT p_setpri(HANDLE pid, INT nPriority); + + +Set the priority of process pid to nPriority (between E_MIN_PRIORITy and E_MAX_PRIORITY inclusive) +and return zero if successful or one of the following negative error numbers: + + +E_GEN_RANGE nPriority 1s outside the range E_MIN_PRIORITY tO E_MAX_PRIORITY + +E_FILE_NXIST process pid does not exist + +E_GEN_FAIL attempted to change the priority of the null process, the supervisor, or the file +server + + +Calling p_setpri causes a reschedule. + + +p_presume Resume a process +INT p_presume (HANDLE pid); + +Resume process pia and return zero if successful or one of the following negative error numbers: +E_GEN_ARG pid 1s not suspended + +E_FILE_NXIST process pid does not exist + +If process pid has a higher priority than the caller, the call to p_presume may not return for some time. + + +If you actually want to wait for the resumed process to terminate before continuing, you can use +p_logona (described in the chapter Error Handling) as follows: + + +p_logona (pid, &stat) ; + + +p_presume (pid) ; +p_waitstat (&stat) ; + + +12-15 + + +PLIB REFERENCE + + +p_psuspend Suspend a process +INT p_psuspend (HANDLE pid); + +Suspend process pid and return zero if successful or one of the following negative error numbers: +E_FILE_NXIST process pid does not exist + +E_GEN_FAIL attempted to suspend the null process, the supervisor, or the file server + + +A process that is in the READY queue or is currently running (ie the calling process) is suspended +immediately. A process that is waiting on the SEMAPHORE queue or the DELTA queue is marked (in +pcb. sstatus) as requiring suspension and is subsequently placed in the susPENDED state when it would +otherwise have been transferred to the READY queue (unless the process is resumed before this happens). + + +p_pname Get a process name by ID +INT p_pname (HANDLE pid, TEXT *pName) ; + + +Write the name of process pid as a zero terminated string to pName (which should be big enough to receive +E_MAX_NAME+2 bytes) and return zero if successful or E_FILE_Nx1sT if the process does not exist. + + +The process name written to pName includes the process slot extension as in, for example, syS$NULL.$01. + + +p_prename Rename a process +INT p_prename (HANDLE pid, TEXT *pNewName) ; +Rename process pid to the zero terminated pNewName and return zero if successful. + + +The process name pNewName should not include a process slot extension (this is supplied by the system) +and should be between | and 8 characters long. No check is made that the new name is unique, but an +invalid name will return the error E_FILE_NamE. The possible error returns are: + + +E_GEN_ARG process pid is not suspended +E_FILE_NXIST process pid does not exist +E_FILE_NAME the new name is invalid + + +p_pidfind Get a process ID by name +HANDLE p_pidfind(TEXT *pName) ; + + +Return the positive process ID of the first process having a name matching the zero terminated pName +(which may contain wild card characters) or return E_FILE_Nxt1sT if there is no matching process. + + +For example, to find the process ID of a process created by loading db$serv.img, use: + + +pid=p_pidfind("DBSSERV.*") ; + + +p_pfind Find all processes +HANDLE p_pfind(HANDLE pid, TEXT *pMatch, TEXT *pName) ; + + +Called repeatedly to find all the processes that match the wild card string pointed to by pMatch, writing +the process name as a zero terminated string into pName (which should be big enough to receive +E_MAX_NAME+2 bytes). The first call should pass a zero pid. + + +Returns the positive process ID of the process found (which is also passed to the next find) or the negative +E_FILE_NXIST if no more matching processes can be found. + + +The wild card string pMatch should remain the same between successive calls. + + +No memory is used by this service and it can be abandoned at any time without taking any further action. + + +12-16 + + +12 PROCESSES AND INTER-PROCESS MESSAGING + + +For example, to print the names of all processes: + + +GLDEF_C INT main (VOID) +{ +HANDLE h; +TEXT b[E_MAX_NAME+2]; +for (h=0; (h=p_pfind(h,"*",&b[0]))>=0;p_printf(&b[0])); +p_getch(); + + +return (0); + + +} + + +p_getowner Determine the owner of a process +HANDLE p_getowner (HANDLE pid); +This function is only available in EPOC version 2.17 or later. + + +Returns the process ID of the process which last resumed process pia, that is, the last process to call +p_presume (pid). This process is defined to be the owner of process pid. + + +This mechanism will fail in the case where the process being resumed has not attempted to run between a +call to p_psuspend and a subsequent call to p_presume. This is because a process is only truly suspended +at the time that it first attempts to run following a call to p_psuspend. + + +Note that there is no guarantee that the process whose ID is returned by p_getowner still exists. + + +Accessing a process data segment + + +The functions p_pcpyfr, p_piscpyfr and p_pcpyto copy data between a (normally different) process data +segment and the caller's data segment (cf p_sgcopyfr and p_sgcopyto which copy data between any +segment and the caller's data segment). + + +p_pcpyfr Copy data from a process + + +INT p_pcpyfr(HANDLE pid, VOID *pSource, VOID *pTarget, UINT nBytes); + + +Copy nBytes bytes at offset psource from the data segment of process pid to address ptarget (in the +current process) and return zero if successful. + + +If psourcet+nBytes exceeds the size of the processes data segment, the data up to the end of the segment is +copied and zero is returned. + + +The system ensures that the copy is not interrupted by another process. + + +The function returns &_GEN_arc if the process pid does not exist. + + +p_piscpyfr Indirected string copy from a process +INT p_piscpyfr(HANDLE pid, VOID *pSourceAddr, VOID *pTarget, UINT nBytes); +This function is only available in EPOC version 2.14 or later. + + +Read the pointer at offset psourceAddr in the data segment of process pid. Then copy the zero terminated +string indicated by this pointer to address ptarget (in the current process) and return zero if successful. + + +wie + + +If the pointer is nuuu, a null string (""") is copied to ptarget. + + +If the string is longer than nBytes, only nBytes of data (plus a terminating zero) are copied and zero is +returned. + + +If the implied length of the source string extends beyond the end of the processes data segment, the data +up to the end of the segment (plus a terminating zero) is copied and zero is returned. + + +The system ensures that the copy is not interrupted by another process. + + +The function returns z_cEn_arc if the process pid does not exist. + + +12-17 + + +PLIB REFERENCE + + +For example: + + +GLREF_D TEXT *DatProcessNamePtr; + + +LOCAL_C INT GetCalcName (VOID) + + +{ +HANDLE h; +TEXT buf [0x40]; + + +h=p_pidfind("calc.*"); +if (h<0) +return (h); +p_piscpyfr(h, &DatProcessNamePtr, &buf[0],0x40); +return (0); + + +} + + +fetches the process name of the calculator. + + +p_pcpyto Copy data to a process + + +INT p_pcpyto(HANDLE pid, VOID *pTarget, VOID *pSource, UINT nBytes); + + +Copy nBytes bytes from pSource in the current process data segment to pTarget in the data segment of +process pid and return zero if successful. + + +The system ensures that the copy is not interrupted by another process. +Address trapping is automatically switched off for the duration of the copy. + + +Returns the negative E_GEN_arc if the process does not exist or if pTarget+nBytes exceeds the size of the +target process data segment (in which case the data is not copied). + + +5 ——————_________________s_;;; +Inter-process messaging + + +Inter-process messaging in EPOC is designed for the efficient implementation of client-server +relationships where a particular server may have multiple clients. + + +A server process is a commonly provided to share a resource amongst multiple client processes. The +EPOC operating system starts up with three multi-client servers: + + +e the supervisor, which performs critical system functions and provides shared access to memory +via the memory segment allocator + + +e the file server, which provides shared access to file storage devices + + +e the window server, which provides shared access to the screen, keyboard and, if present, a +pointing device + + +A server may also be a client of another server. For example, the window server is a client of the file +server (since, for example, it loads bitmap files) and all processes are implicitly clients of the supervisor. + + +In order that the relative priorities of client processes have their intended effect, a multi-client server +process should run at a higher priority than any of its clients. A client's priority is effectively lowered to +that of the server while waiting for completion of a service provided by a low priority server. + + +Message slots +A process that wishes to receive messages must first call p_minit to initialise the message system. + + +Calling p_minit (nMess, 1Mess) allocates nMess message slots (from the heap) where each message slot +contains an E_MESSAGE struct header followed by a buffer of length 1Mess. The E_MESsAGE struct is +defined in epoc.h as: + + +typedef struct message +{ +struct message *next; +UBYTE *status; +UINT type; +HANDLE pid; +} E_MESSAGE;. + + +12-18 + + +12 PROCESSES AND INTER-PROCESS MESSAGING + + +The structure of the 1mess bytes of data following the z_messacz header is defined by the receiver of the +message and is normally limited to a few words. For example, the file server and the supervisor both use +an iMess of 8. Note that the sender has no control over the length of the message sent (a later version of a +server could increase the message length to provide additional services while maintaining upward +compatibility). + + +When the sender calls p_msend (or a variant) the arriving message is copied into a previously free message +slot, which is also placed in the receiver's message queue. + + +From this time the message slot is allocated, in the sense that it cannot be overwritten by another +incoming message. It contains the message type (as specified by the sender) in type and the process ID of +the sender in pia, followed by 1mess bytes of data from the sender. (The fields next and status in the +E_MESSAGE header are used internally by the message system.) + + +The message slot is removed from the queue when the receiver calls, for example, p_mreceivew (which +returns the address of the message slot). The content remains safe from being overwritten until the +receiver calls p_mfree to indicate that it has completed processing the message. Calling p_mfree returns +the message slot to its free state, available to receive another incoming message. + + +What the server does + + +A server is always a passive process that waits for messages to arrive from a client process. It is not +expected that a server will ever initiate a transaction by sending a message to a client. + + +As described earlier, the server first calls p_minit to initialise the message system. The server then waits +for a message to arrive by calling p_mreceivew (an asynchronous version, p_mreceive, also exists). When +the message arrives, the function returns the address of the message slot. + + +The server always removes messages from the front of the queue. Arriving messages are normally inserted +at the end of the queue but if the client's priority is 0x80 or more, the arriving message is inserted at the +front, overtaking any existing messages, regardless of their sender's priority. + + +When it is necessary to send more than the amount of information allowed for by the (typically short) +message length, the message contains the data by reference (ie by address and length). The server then +uses p_pcpyfr to copy the data from the client's data segment. + + +The message may also contain the address or addresses of buffers to receive data from the server when the +service has been completed. Here, the server uses p_pcpyto to copy the data to the client's data segment. + + +When the message has been processed, the server frees the message slot using p_mfree. If the message +was sent in such a way that the sender is expecting an acknowledgment of some kind (ie the message was +sent using p_msendreceivew Of p_msendreceivea rather than p_msena), the call to p_mfree also writes +back a completion status value and signals the sender's I/O semaphore. + + +Servers request to be informed of the termination of a client by calling p_logon (pid, nType) to receive a +message of type nType when client pid terminates. Process termination and p_logon are described in the +chapter Error Handling. + + +What the client does + + +The client process requests a service of the server by sending it typed fixed length messages (where the +message length is determined by the server) using: + + +p_msend to send the message "blind", returning when the message has been deposited +(but not necessarily processed) + + +p_msendreceivew to send the message and wait for the server to reply by calling p_mfree + + +p_msendreceivea to send the message, returning when the message has been deposited (as for +p_msenda) having set up an asynchronous request for a reply + + +If the server does not have any empty message slots, the message sending function waits on a mutual +exclusion semaphore until a message slot becomes free. It can therefore be blocked indefinitely, even if +using the asynchronous p_msendreceivea. Multi-client servers avoid this prospect by allocating a slot for +each potential client (by allocating say E_max_PROCESSES minus the number of known processes). + + +12-19 + + +PLIB REFERENCE + + +The only preparation required by the client is to obtain the process ID of the server. Examples of ways in +which this is done are: + + +the client gets the ID via the process name using p_pidfind (this is normally what is done for +multi-client servers) + + +the client knows the ID because it created the server using p_execc + + +the server created the client and passed its process ID as a command parameter to p_execc (as in +the above example) + + +For multi-client servers, the client typically sends an opening message to connect to the server. + + +An example of a server + + +typedef struct + + +{ + +E_MESSAGE mess; +TEXT *bofs; +UWORD len; + +} MESS; + + +LOCAL_C VOID RunServer (VOID) + + +{ +MESS *pmsg; +TEXT buf[256]; + + +FOREVER +{ +p_mreceivew(&pmsg) ; +if (pmsg->mess.type) + +{ + +p_mfree(pmsg, 0); + +break; + +} +p_pcpyfr(pmsg->mess.pid, pmsg->bofs, &buf[0],pmsg—>len) ; +p_printf("%*s",pmsg-—>len, &buf[0]); +p_mfree(pmsg, 0); + +} +} + + +LOCAL_C VOID Exec(TEXT *name) + + +{ +HANDLE pid; +TEXT bb[E_MAX _ERROR_TEXT_SIZE]; + + +pid=p_getpid(); +pid=p_execc (name, (UBYTE *) &pid, sizeof (pid) ); +if (pid<0) +{ +p_errs (&bb[0],pid); +p_printf ("Failed to start %s (%s)",name, &bb[0]); +} +else +{ +p_printf("Process ID is %xd",pid); +p_logon (pid, TRUE) ; +p_presume (pid) ; +RunServer (); +} +} + + +GLDEF_C INT main(VOID) + + +12-20 + + +{ +TEXT bb[P_FNAMESIZE]; + + +p_minit (1, sizeof (MESS) -sizeof (E_MESSAGE) ) ; + +while (p_getl("Enter ? ", &bb[0],P_FNAMESIZE) ) +Exec (p_skipwh(&bb[0])); + +return (0); + + +} + + +12 PROCESSES AND INTER-PROCESS MESSAGING + + +In the above example, main solicits a file specification of an image to run. This image is then (in Exec) +loaded using p_execc (passing the created process the process ID of its creator) and then resumed using +p_presume. + + +While the image is running, the program acts as a server to it where messages of type FALSE are taken to +contain a buffer by reference. The data from this buffer is copied from the process using p_pcpyfr and +printed using p_printé. + + +Before resuming the process in Exec, the server logs on to the process by calling p_1ogon. When the +process terminates, the server receives a type TRUE message. This causes the program to return from +RunServer and solicit another image file specification. + + +Corresponding client code example + + +The following example shows how to write that part of the client side code that corresponds to the above +example of server code. + + +GLREF_D UBYTE *DatCommandPtr; + + +LOCAL_D HANDLE pid=0; +LOCAL_D TEXT bb[256]; + + +GLDEF_C VOID printf(TEXT *pfmt,...) +{ + + +struct +{ +TEXT *pbuf; +UINT len; +} msg; + + +msg.len=p_atob(msg.pbuf=&bb[0],pfmt, &pfmt+1); +if (!pid) +pid=* (HANDLE *) (DatCommandPtr+p_slen(DatCommandPtr) +2) ; +p_msendreceivew (pid, FALSE, &msg) ; +} + + +The printf function behaves in the same way as p_printf except that the printing is performed by the +creator of the process in its console window. Note that the call to p_msendreceivew does not return until +the server calls p_mfree. + + +This example does not show the sending of the message with a type TRUE on termination of the client +process. + + +Asynchronous messaging + + +The server-client example described above uses synchronous messaging in both the server and the client. +While this may be sufficient in simple cases, there are situations where such an implementation will prove +inadequate. + + +A client that sends messages synchronously is effectively suspended from the moment it calls +p_msendreceivew until the server completes processing the message and calls p_mfree. If completion is +dependent on an external event, such as the expiry of a timer or the arrival of serial data, the client may be +suspended indefinitely. This will, in general, be unacceptable behaviour (particularly if the client must +remain responsive to other events, such as user input) and in such a case the client should use +asynchronous messaging. + + +A server does not, in general, have a user interface. If its only task is to receive and process messages from +its clients, then synchronous server code may be perfectly acceptable. As in the example server code given +earlier, the server is effectively suspended until a message is received and returns to the suspended state as +soon as it has finished processing the message. If the server also has to respond to other events, such as +the expiry of a timer, then the receipt of messages must be handled asynchronously. + + +Suppose a client needs to use asynchronous messaging because completion of the processing of the +message may be delayed indefinitely by an external event. This implies that the server itself must respond +to at least two events (the receipt of a message and the external event) and so must also handle events +asynchronously. + + +12-21 + + +PLIB REFERENCE + + +The sequence of events that occur during messaging between asynchronous client and server is as follows: +e the server makes a call to p_minit + + +e the server then calls p_mreceive, passing the address of its messaging status word, and later +makes a call to p_iowait (usually in its main event-handling loop) + + +e the client calls p_msendreceiva, passing the address of a status word, and later calls p_iowait +(usually in its main event-handling loop) + + +e the server is signalled that a message has been received, by noting that its messaging status word +is no longer E_FILE_PENDING on areturn from p_iowait, and commences processing the message + + +¢ on completion of the processing the server calls p_mfree which notifies the client of the +completion + + +e the client is signalled that processing is complete, by noting that the relevant status word is no +longer E_FILE_PENDING on areturn from p_iowait + + +If the processing of the message itself involves an asynchronous request, the server may process any +number of synchronous messages from any of its clients (including the one sending the asynchronous +message) while the request is pending. It is therefore quite possible for a synchronous message to complete +before an earlier asynchronous message from the same client. + + +On the assumption that clients may send messages asynchronously because they do not want to wait, the +server will generally need more than one message slot to avoid the client having to wait for a message slot +to become free. How many slots to provide depends on many factors, such as: + + +e the maximum expected number of clients + +e the maximum number of outstanding messages allowed per client (rarely more than two) + +e whether it is acceptable for any client ever to be suspended while waiting for a free slot +Message processing order + + +A message sent by a client to a server is placed in a message queue, normally at the end of the queue. The +server receives a message by removing the one at the front of the queue (into one of its message slots). +Thus, in normal circumstances, messages are processed in the order in which they are sent. As mentioned +in the previous section, it is possible for synchronous messages to 'overtake' asynchronous messages from +the same client. + + +The window server has a requirement, particularly in an overlapping window environment, to give +priority to messages from the foreground task. For example, when an area of the screen covering all or +part of a number of task windows needs redrawing (after, say, the disappearance of a dialog) the +foreground task should be redrawn first. The following scheme has been adopted to satisfy the window +server's requirement without causing an unacceptable performance penalty. + + +In all cases, messages from a client process with a priority of 0x80 or above (the foreground task normally +has a priority of 0x80, which is higher than the priority of background tasks) are placed at the front of the +queue. They therefore overtake all other messages in the queue (including any earlier messages from the +same client) irrespective of the priorities of their sending processes. + + +This has the added advantage of reducing the risk that switching to the shell task (which always runs at a +priority higher than the foreground task) can be blocked by a 'rogue' task. + + +There is, however, one problem, which can be illustrated as follows. Suppose a client with a priority of +0x80 sends an asynchronous message to a server. This message is inserted at the front of the queue. Before +the server removes any messages from the queue, the same client sends a cancel message, to cancel its +previous request. This second message is again inserted at the front of the queue, overtaking the message +it is supposed to be cancelling. + + +For this situation to arise, all the following conditions must be satisfied: +e the client must have a priority of 0x80 or above +e the client must use asynchronous messaging +e the client must be sensitive to the order in which the server processes its messages + + +e the server must not have removed the first message from the queue by the time the second +message is queued + + +12-22 + + +12 PROCESSES AND INTER-PROCESS MESSAGING + + +The last of these conditions is rarely satisfied, since a server normally runs at a higher priority than its +clients. As soon as the server is signalled that a message has been queued the server pre-emptively +suspends the client. In most cases the client will not resume until the server has completed processing the +message and is waiting for another message. It is rare that a server has more than one message in the +message queue. + + +The main exception is when the processing of the message requires the server to call (directly or +indirectly) p_iowait, for example, to perform file I/O. + + +In such a case you should consider whether the client really needs to use asynchronous messaging. +Alternatively you can set the client's priority to be less than oxso. In this case the mechanism by which the +window server adjusts the priority of background and foreground tasks should be disabled (see the +description of wconnect in the Window Server manual). + + +Pa a a Ng eee +Server functions + + +All the server functions except p_minit call p_panic if messages have not been initialised and p_minit +itself calls p_panic if it is called a second time. + + +p_minit Initialise for message reception + + +INT p_minit (INT nMess, INT 1Mess) ; + + +Initialise a queue of nMess message reception slots of length 1Mess and return zero if successful or one of +the following negative error numbers: + + +E_GEN_NOMEMORY there is insufficient free memory to allocate the message queue + + +E_GEN_NOSEM there are no more free semaphores (p_minit creates a mutual exclusion +semaphore, initialised with nmess) + + +The message length imess excludes the &_messacg structure that is at the front of all messages. The +message queue is allocated as a single cell from the heap. Since this cell remains allocated for the lifetime +of the process, programs calling this service should do so early in their initialisation (before any cell has +been freed) to avoid heap fragmentation. All message slots are of the same size and the total size of the +message queue is nMess* (1Mess+sizeof (E_MESSAGE) ) bytes. + + +To avoid senders being blocked by message sending (quite different from waiting for a reply that can be +handled asynchronously), multi-client servers should allocate a message slot for each potential client. The +constant &_MAX_PROCESSES contains the total number of processes that can be supported by the system. In +practice this can be reduced by at least four, for the null process, supervisor, file server and window +server. + + +Only the least significant byte of nmess is significant, limiting the number of message slots to 255. + + +Calls p_panic if p_minit has already been called or if the least significant byte of nmess is zero. + + +p_mreceivew Wait for message reception + + +VOID p_mreceivew(VOID *pMess) ; + + +Return when a message has been received, where the address of the message slot containing the message +is written to *pMess. + + +The data in the message slot is protected from being overwritten by the receipt of another message until +the message slot is freed from the queue using p_mfree. + + +Calls p_panic if messages have not been initialised or if an asynchronous message receive request is +pending. + + +Example + + +typedef struct +{ +E_MESSAGE mess; +TEXT *bofs; +UWORD len; +} MESS; + + +MESS *pmsg; + + +p_mreceivew (&pmsg) ; + + +12-23 + + +PLIB REFERENCE + + +p_mreceive Asynchronous message reception + + +VOID p_mreceive (WORD *pStatus, VOID *pMess) ; + + +Make an asynchronous request to receive a message and return immediately without waiting for a message +to be received. + + +While the request is pending (and the message queue is empty), *pStatus contains E_FILE_PENDING. + + +When a message is received (or if there is already a received message in the queue) *pStatus is set to +zero, the address of the message slot containing the message is written to *pMess and the process I/O +semaphore is signalled. + + +The data in the message slot is protected from being overwritten by the receipt of another message until +the message slot is freed from the queue using p_mfree. + + +Calls p_panic if messages have not been initialised or if an asynchronous message receive request is +already pending. + + +Example + + +typedef struct +{ +E_MESSAGE mess; +TEXT *bofs; +UWORD len; +} MESS; + + +MESS *pmsg; +WORD status; + + +p_mreceive (&status, &pmsg) ; + + +p_mcancel Cancel a message receive request + + +VOID p_mcancel (VOID) ; + + +Cancel any pending asynchronous request to receive a message (which was previously requested using the +p_mreceive service). + + +It is not considered an error to call this service if no request is pending (since the request may complete at +any time). If the cancel is processed before a message is received, the associated status word *pStatus is +set to E_LFILE_CANCEL. + + +Note that this service does not cancel a pending p_msendreceivea (which is a client function). A server +may support a cancel service but this is invoked, like any other service, by sending the server a message. + + +p_mfree Free a message + + +VOID p_mfree(VOID *pMess, INT nReply); + + +.Free the message slot with address pMess (as returned from p_mreceivew or p_mreceive) and, if the +message was sent using p_msendreceivew Of p_msendreceivea, complete the request by signalling the +sending client's I/O semaphore and copying nRep1y to the client's status word (which is returned by +p_msendreceivew). A negative value of nReply normally indicates an error. + + +If the message was sent with p_msend, the message slot is just freed and nRep1ly is ignored. +The server should not read the contents of pMess after calling p_mfree. + + +If messages are not freed from the message queue then in due course sending processes will be blocked +waiting on the message queue mutual exclusion semaphore. + + +12-24 + + +12 PROCESSES AND INTER-PROCESS MESSAGING + + +Se ooo | Ht“fo#ooavouwHurNvwaavaH07U7TT84A«I0 °I™ 7v“T“>Yn=Nazsw—" +Client functions + + +p_msend Send a message + + +INT p_msend(HANDLE pid, UINT mType, VOID *pMessage) ; + + +Send message pMessage Of type mType to process pid and return zero when the message has been +deposited or the negative E_GEN_RECEIVER if pid does not exist or if process pid has not called p_minit. + + +The message is deposited into a free message slot in the server where the member type in the E_MESSAGE +header is set to mtype and the message body is copied from pMessage (where the length of the message +was specified by the server as a parameter to p_minit). + + +If pia does not have a free message slot, p_msend waits (on a mutual exclusion semaphore) until it does. + + +This function is only really suitable for sending messages where the whole information fits in the +message. That is, the data at pMessage should not contain the address of further data to be copied (using +p_pcpyfr) because there is no way of knowing when the server will copy the data so that pMessage may be +re-used. Where the message does reference further data, p_msendreceivew Of p_msendreceivea should be +used. + + +A client should certainly use p_msendreceivew Of p_msendreceivea if the service is to return information +(eg success or failure). + + +p_msendreceivew Send a message and wait for a reply + + +INT p_msendreceivew(HANDLE pid, UINT mType, VOID *pMessage) ; + + +Send message pMessage Of type mType to process pid and wait for the server to reply (which it does by +calling p_mfree (pid, nReply) ) and return the reply nreply. + + +Return immediately with the negative &_GEN_RECEIVER if pid does not exist or if process pia has not +called p_minit. + + +The message is deposited into a free message slot in the server where the member type in the E_MESSAGE +header is set to mtype and the message body is copied from pMessage (where the length of the message +was specified by the server as a parameter to p_minit). + + +If pia does not have a free message slot, p_msendreceivew waits (on a mutual exclusion semaphore) until +it does. + + +p_msendreceivea Asynchronous send message and get reply + + +INT p_msendreceivea (HANDLE pid, UINT mType, VOID *pMessage, WORD *pStatus) ; + + +Send message pMessage of type mType to process pia and asynchronously request a reply from the server. +Return zero if the message was successfully sent or the negative E_GEN_RECEIVER if pid does not exist or if +process pid has not called p_minit. + + +When the server completes the request and calls p_mfree (pid, nReply), *pStatus 1S Set to nReply and the +client's process I/O semaphore is signalled. While the reply is pending, *pstatus contains +E_FILE_PENDING. + + +The message is deposited into a free message slot in the server where the member type in the E_MESSAGE +header is set to mtype and the message body is copied from pMessage (where the length of the message +was specified by the server as a parameter to p_minit). + + +If pia does not have a free message slot, p_msendreceivea Waits (on a mutual exclusion semaphore) until +it does. + + +12-25 + + +CHAPTER 13 + + +GENERAL SYSTEM SERVICES + + +System information + + +p_version Get the operating system version +UINT p_version(VOID) ; +Return the operating system version number. +The returned version number should be interpreted as a 4-digit hexadecimal number of the form: +X.YYZ + + +where x is the major release number, yy is the minor release number and z is normally the hexadecimal +digit F (internal releases use a and B to designate alpha and beta releases, respectively). + + +For example, a return of 0x123F is interpreted as 1.23F. + + +p_romversion Get the ROM version +UINT p_romversion (VOID) ; +Return the ROM version number. + + +The ROM contains the operating system and other system components such as, for example, the window +server. The tool used to build the ROM requires a version number to be specified and this is the version +number that is retrieved by this function. + + +See p_version above for the interpretation of the version number. + + +p_getres Get the cause of the last system shut-down +INT p_getres (VOID); +Return a number indicating the cause of the last system shut-down, as follows: + + +E_IS_A_COLD_START The system started up for the first time (or after a period during which all +power had been removed, including the Lithium back-up). + + +E_IS_A_POWERFAIL_START The hardware forced a shut-down because the voltage got too low. This +should not happen because the system software gets a non-maskable +interrupt if the voltage drops below a certain threshold (but not low +enough for the hardware to force a shut-down) and this interrupt code +automatically switches the hardware off. However, if the clean-up takes +too long because of a poorly designed device driver, the hardware will +force the machine off before the interrupt completes - in which case +p_getres returns E_IS_A_POWERFAIL_START. The environment variables +and the contents of m: are preserved. + + +PLIB REFERENCE + + +E_IS_A_RESET_START The machine has been reset by pressing the recessed reset button. The +environment variables and the contents of m: will have been preserved (a +soft reset). + + +If the Esc key is held down while pressing the reset button, this causes a +hard reset. In this case both the environment variables and the contents of +m: will have been cleared. + + +Note that this value will not occur on a Workabout, since this machine +does not have a reset button. + + +E_IS_A_KERNEL_FAULT The system was reset because a serious fault occurred while executing in +the operating system kernel. This could result from: (1) a bug in the +operating system or a system process; (2) a program bug that managed to +overcome the operating system's defences or (3) a hardware problem such +as a RAM fault. The environment variables and the contents of mM: will be +preserved (unless the system detects a memory corruption). + + +On the Workabout, this value is also returned if the system is reset by +pressing Psion-Ctrl-Del. This is the equivalent of a soft reset on other +machine types and preserves both the environment variables and the +contents of M:. + + +E_IS_A_NEW_OS_START The system was reset after programming a new operating system into the +Flash ROM (normally after running the repro program). The +environment variables and the contents of m: have been cleared. + + +On the Workabout, this value is also returned if the system is reset by + +pressing Shift-Psion-Ctrl-Del. This is the equivalent of a hard reset on +other machine types and clears both the environment variables and the +contents of M:. + + +p_getosd Get operating system data +VOID p_getosd(VOID *pTarget, VOID *pSource, UINT length); +Copy length bytes from offset psource in the operating system data space to pTarget. + + +Operating system handles (such as memory segment handles and semaphore handles) are actually +addresses in the operating system data space of the appropriate control entry. + + +If you AND a process ID with E_PIDMASK you get the address in operating system space of the +corresponding process control entry - as described in the chapter Processes and Inter-Process Messaging. + + +p_getpsu Get power supply type +INT p_getpsu (VOID); + + +-Return one of the following values, defined in epoc.h, to indicate the power supply type on a SIBO +machine: + + +E_PSU_OLD +E_PSU_MAXIM +E_PSU_S3 +E_PSU_S3_A9 + + +Apart from this service EPOC hides the differences between the various power supplies. + + +Machines in the MC GI range of SIBO computers, for example, may use either the E_Psu_oLD or the +E_PSU_MAXIM power supply variants, each of which requires a slightly different variant of the EPOC +operating system. The REPRO program that blows a new operating system into the Flash ROM of the MC +GI range uses this service to blow the appropriate variant of EPOC. + + +13-2 + + +13 GENERAL SYSTEM SERVICES + + +Language and country + + +SIBO machines are produced in a number of language variants, differing in the following respects: +e the language code + + +e the language of the text used by the ROM-based software (for example, the error messages +returned by p_errs and the month names returned by p_nmmon) + + +e character type and conversion tables as described in the chapter Characters, Strings, Buffers and +Queues + + +e = the keyboard layout +e = the default country and country-dependent data + + +A particular language variant will always have a different language code and text but may not differ in all +the above. + + +The system was designed to be produced in a variety of languages and, as far as the system services are +concerned, all the above variations are encapsulated in a single configuration file in the ROM called +ROM: :SYS$CTRY.CFO. Depending on the machine, there may be further files (for example, "resource +files") containing language-dependent data for higher level system components. + + +Unlike the language-dependent data, the country-dependent data may be altered from the language- +dependent defaults. + + +p_getlanguage Get the language code +INT p_getlanguage (VOID) ; +-Return the language code from the ROM configuration file. + + +The language code can be used by applications that contain the text for more than one language to +determine which language to present. The language codes, defined in p_config.h, are as follows: + + +English +French +German +Spanish +Italian +Swedish +Danish +Norwegian + + +OMANI HDOBWNHE +hobo’ to bt tb obo tot + + +Finnish +USA +Swiss french +Swiss German +Portuguese +Turkish +Icelandic +Russian +Hungarian +Dutch +Belgian Flemish +Australian +New Zealand +Austrian + + +NNN N +WNHrRFROWOOAANAT AO PWN EF OO + + +Belgian french + + +p_gettext Get operating system text +INT p_gettext (INT n, TEXT *pBuffer); +Get the nth string from the ROM configuration file and write it to pBuffer. + + +Returns zero if successful or the negative z_cEN_arc if n 1s outside the range of the text strings in the +configuration file. + + +PLIB REFERENCE + + +This function is called by specific text retrieval functions such as p_errs and p_nmmon. + + +Applications only need to use p_gettext when retrieving text associated with a higher level of system +software (in which case the documentation of the higher level software will list appropriate values of n). + + +p_getctd Get country-dependent data +VOID p_getctd(E_CONFIG *pcfg); +Write a copy of the system E_conFiIc struct to pcfg where the E_conFIc struct is defined in p_config.h as: + + +typedef struct +{ + + +UWORD countryCode; + +WORD gmtOffset; + +UBYTE dateType; + +UBYTE timeType; + +UBYTE currencySymbolPosition; +UBYTE currencySpaceRequired; +UBYTE currencyDecimalPlaces; +UBYTE currencyNegativelInBrackets; +UBYTE currencyTriadsAllowed; +UBYTE thousandsSeparator; +UBYTE decimalSeparator; +UBYTE dateSeparator; + +UBYTE timeSeparator; + +UBYTE currencySymbol [9]; +UBYTE startOfWeek; + +UBYTE summerTime; + +UBYTE clockType; + +UBYTE dayAbbreviation; + +UBYTE monthAbbreviation; +UBYTE workDays; + +UBYTE units; + +UBYTE spare[9]; + + +} E_CONFIG; . + + +The count ryCode specifies a country by its international dialling code, and units is O for imperial units or +1 for metric units + + +See the description of p_getctd in the chapter Time, Timers and Dates for a description of the time- +related fields: gmtOffset, dateType, timeType, dateSeparator, timeSeparator, startOfWeek, +summerTime, clockType, dayAbbreviation, monthAbbreviation and workDays + + +See the description of p_getctd in the chapter Floating Point for a description of the fields that are +related to the display of floating point numbers and currency: currencySymbol, currencySymbolPosition, +currencySpaceRequired, currencyDecimalPlaces, currencyNegativelInBrackets, +currencyTriadsAllowed, thousandsSeparator and decimalSeparator. + + +p_setctd Set country-dependent data +VOID p_setctd(E_CONFIG *pcfg) ; +Sets the country-dependent data from the E_conrté structure pointed to by pcfg. +When changing a particular field or fields you would normally: +@ use p_getctd to get a copy of the E_conrie struct +e modify the field or fields, as required + + +@ use p_setctd to write back the modified E_conFIe struct + + +13-4 + + +13 GENERAL SYSTEM SERVICES + + +Switching on and off + + +By default, the auto-switch-off period is set to 300 seconds. The auto-switch-off period may be sensed and +set by calling p_getauto and p_setauto respectively. Auto-switch-off when a mains adaptor is connected +may be disabled by calling p_setautomains, and the corresponding state sensed by p_getautomains. + + +The zero priority null process automatically switches the machine off to reduce power consumption after +the system has been inactive for the auto-switch-off period. In situations where the null process does not +get an opportunity to run, a process can assume responsibility for allowing the machine to switch off by + +calling p_allowoff. + + +Some processes are marked as not being significant when it comes to determining what constitutes +activity. For example, a continuously running clock program should not stop the system from +automatically switching off in the absence of any significant activity. See p_unmarka and p_marka in the +chapter Processes and Inter-Process Messaging for additional details on how to avoid keeping the +machine switched on by continuously running applications. + + +p_off Switch off + + +VOID p_off(UINT uTime) ; + + +Switch off the machine indefinitely or for any time up to approximately 4.5 hours and return when the +machine switches on. + + +If uTime is oxf££f the machine switches off indefinitely and will stay off until an outstanding absolute +timer expires or the user switches on the machine. Equivalent to the machine automatically switching off +or being switched off by the user. + + +If uTime is greater than 8, the machine switches off for up to uTime 1/4ths of a second (although it will +still switch on if an outstanding absolute timer expires or the user switches on the machine). (If uTime is +less than or equal to 8, calling p_ofr has no effect.) + + +On the IBM PC version of EPOC, calling p_or¢ has no effect. + + +p_getauto Get the auto-switch-off period +INT p_getauto(VOID); +Return the current auto-switch-off period in seconds. + + +If the auto-switch-off period is oxf££4, the system does not automatically switch off. + + +p_setauto Set the auto-switch-off period +VOID p_setauto(INT n); + +Set the auto-switch-off period to n seconds. + +Passing an n of -1 (oxf££4£) stops the system from automatically switching off. + + +Calling p_setauto with n less than 15 is equivalent to calling p_setauto(15). + + +p_getautomains Get switch-off state when mains is present +INT p_getautomains (VOID) ; +This function is only available in EPOC version 3.18 or later. + + +Return true if auto-switch-off is disabled when mains is present, otherwise return FALSE. + + +PLIB REFERENCE + + +p_setautomains Disable/enable switch-off if mains is present +VOID p_setautomains (INT flag) + +This function is only available in EPOC version 3.18 or later. + +Disable or enable auto-switch-off if mains is present. + + +If flag is TRUE, auto-switch-off is disabled while mains is present and if flag is FALSE, auto-switch-off is +enabled. + + +Even if enabled, the machine will not switch off when mains is absent if switch-off has been stopped by +use of p_setauto. + + +p_allowoff Allow auto switch off +VOID p_allowoff (VOID) ; +Allow the machine to switch off if the auto-switch-off period has expired. + + +A compute-bound process which has marked itself as non-active (by calling p_unmarka) does not allow the +machine to switch off since the null process will never get an opportunity to run. Such a process should +call p_allowoff from time to time. There is no particular advantage in calling p_allowoff more +frequently than at intervals of 15 seconds - the shortest auto-switch-off period. + + +On the IBM PC version of EPOC, calling p_allowoff has no effect. + + +p_setonevent Enable/disable the ON key event +VOID p_setonevent (INT state) + +This function is only available in EPOC version 2.28 or later. + +Enables or disables the event that is sent to the window server when the ON key is pressed. + + +If state is FALSE, the event is disabled, any other value enables the event. + + +Pe i a __________________________iy +Power supply + + +This section describes functions to: + + +e determine the presence or absence of the main battery, the Lithium backup battery or the mains +adaptor (p_supplyinfo) + + +e get the voltage level of the main battery (or mains adaptor, if present) and the Lithium backup +battery (p_supply) + + +e determine whether the mains adaptor is connected (p_supp1ly) + + +e get the nominal maximum voltages of the main battery and the Lithium backup battery +(p_wsupply) + + +e¢ get the recommended low voltage warning levels for the main battery and the Lithium backup +battery (p_wsupply) + + +e get the time and date of insertion of the main battery, and information about main battery usage +(p_supplyinfo) + + +e sense and set the main battery type (p_getbat and p_setbat respectively) + + +The main battery type is only significant on machines that can take more than one battery type (such as +the MC GI range) and affects the voltages returned by p_wsupply. + + +13-6 + + +13 GENERAL SYSTEM SERVICES + + +The main battery types are as follows: + + +E_BATTERY_UNKNOWN the battery type is initially set to this value when EPOC starts up (equivalent in +its effect to E_BATTERY_ALKALINE) + + +E_BATTERY_ALKALINE the battery is an Alkaline + + +E_BATTERY_NICAD_600 __ the battery is a 600 mA hour NiCd rechargeable + + +E_BATTERY_NICAD_1000 _ the battery is a 1000 mA hour NiCd rechargeable + + +If the hardware is unable to identify automatically the battery type, it is the responsibility of the user to set +the battery type to match that actually fitted. The r_BaTTERY_UNKNowN value is intended to trigger the +system into prompting the user to identify the battery type. + + +p_supply Get power supply status +VOID p_supply(E_SUPPLY *pValue) ; +Write the status of the various supplies to the z_supp.y struct at pvalue where E_supp.y is defined as: + + +typedef struct +{ +UWORD mainBatteryReading; +UWORD lithiumBatteryReading; +WORD mainsPresent; +} E_SUPPLY;. + + +where: + + +mainBatteryReading is the main battery voltage in millivolts (or the mains adaptor voltage if the +mains adaptor is present) + + +lithiumBatteryReading _ is the Lithium backup battery voltage in millivolts + + +mainsPresent is negative if the mains adaptor status cannot be determined (because the SSD +pack doors are open); zero if the mains adaptor is not present; one if the mains +adaptor is present + + +p_supplyinfo Get additional power supply data +VOID p_supplyinfo(E_SUPPLY_INFO *pValue) ; + +This function is only available in EPOC version 3.18 or later. + +Write information concerning the various power supplies to the E_suPPLY_INFo Struct at pvalue. + +The &_suppLy_1nFo is defined in epoc.h as: + + +typedef struct + +{ + +UBYTE mainBatteryLevel; +UBYTE mainBatteryStatus; +UBYTE backupBatteryLevel; +UBYTE dcLevel; + +UWORD warningFlags; +ULONG insertionDate; +ULONG ticksInUseBattery; +ULONG ticksInUseDc; +ULONG maTicks; + +} E_SUPPLY_INFO;. + + +13-7 + + +PLIB REFERENCE + + +where: + + +mainBatteryLevel + + +mainBatteryStatus + + +backupBatteryLevel + + +dcLevel + + +warningFlags + + +insertionDate + + +ticksInUseBattery + + +ticksInUseDc + + +maTicks + + +is the present status of the main battery. It describes the voltage level as being in +one of four discrete states: + + +a) E_MBAT_GOOD +battery voltage is good + + +b) E_MBAT_LOW +battery voltage is low + + +C) E_MBAT_VERY_LOW +battery voltage is very low + + +d) E_MBAT_ZERO +there is no battery present! + + +No precise figures for the actual voltage levels corresponding to these states are +given. + +is the same as mainBatteryLevel described above except that it records the +lowest level that the battery has reached. It is reset when the main batteries are +removed from their housing. + + +is TRUE if the Lithium backup battery is present and ratse if the backup battery +level is low or the battery is not present + + +is TRUE if the mains adaptor is present and powered up +is a set of flags which can be one of: + + +a) E_SUPPLY_SYSTEM_TIME_CHANGED + +this flag only has meaning when the battery insertion date changes. If set, it +means that the system time has changed; if not set, it means that the main battery +has been changed. + + +b) E_SUPPLY_SOUND_WARNING + +this flag is set if the battery power level is too low to operate sound. Its setting +implies that the user has been warned at least once before of the failure of an +attempt to generate sound. + + +C) E_SUPPLY_FLASH_WARNING + +this flag is set if the battery power level is too low to operate a flash SSD. Its +setting implies that the user has been warned at least once before of the failure of +an attempt to write to flash. + + +These warning flags are intended to be used only for supplying information to a +user. The last two, in particular, do not necessarily imply that an attempt to +generate sound or to write to flash will definitely fail. Even if either or both of +these warning flags are set, the attempt may succeed - for example, either because +the battery voltage has recovered since an earlier failure, or because the machine +is now connected to mains power. An application is not expected to test either of +these flags before attempting the corresponding operation - failures should simply +be handled by standard error-recovery techniques. + + +is the system time when the present main battery was inserted + + +is the total length of time in 'ticks' (1/32 second) for which the machine has been +switched on and powered by the main battery. Any period during this time when +the machine has been powered by the mains adaptor is excluded from the total. + + +is the length of time in 'ticks' (1/32 second) for which the machine has been +switched on and powered using the mains adaptor. + + +is the cumulative current delivered by the present main battery; it is a product of +current x time and is measured in units of milliamps x 'ticks' where a 'tick' is 1/32 +second + + +On machines that use the ASIC1 chip (that is, the Series 3 classic and HC) this information is not +available, even if the machines contain version 3.18 or later of EPOC. In such a case, p_supplyinfo +writes zero values to all members of the E_SUPPLY_INFOo struct. + + +13-8 + + +13 GENERAL SYSTEM SERVICES + + +p_wsupply Get battery warning and maximum levels + + +VOID p_wsupply (E_SUPPLY_WARNINGS *pValue) ; + + +Write the recommended low voltage warning level and the nominal maximum voltage of the main battery +and the Lithium backup battery to pvalue. + + +The &_SUPPLY_WARNINGS Struct is defined as: + + +typedef struct +{ +UWORD mainBatteryWarning; +UWORD lithiumBatteryWarning; +UWORD mainBatteryMax; +UWORD lithiumBatteryMax; +} E_SUPPLY_WARNINGS; . + + +where: + +mainBatteryWarning is the recommended voltage at which to warn the user of a low main battery + +lithiumBatteryWarning is the recommended voltage at which to warn the user of a low Lithium +backup battery + +mainBatteryMax is the nominal maximum voltage of the main battery + +lithiumBatteryMax is the nominal maximum voltage of the Lithium backup battery + + +All voltages are provided in millivolts. + + +If the host machine can take more than one battery type, the voltages will depend on the battery type set +with p_setbat. + + +p_getbat Get the battery type + + +INT p_getbat (VOID); +Return the current battery type. +The battery types of the form =_BATTERY_xxx are described at the beginning of this section. + + +On machines whose hardware does not support detection of the battery type, a call to this function should +be preceded by a call to p_setbat. + + +p_setbat Set the battery type + + +INT p_setbat (INT nType); + + +Set the battery type to nType and return zero if successful or E_GEN_nsup if battery type nType is not +supported by the hardware. + + +The battery types of the form &_BATTERY_xxx are described at the beginning of this section. + + +This function has no practical effect on machines, such as the Workabout, whose hardware supports the +detection of the battery type. + + +Keyboard + + +p_getscancodes Get the state of all keys +INT p_getscancodes (UWORD *pScan) ; + +This function is only available in EPOC version 3.18 or later. + +Write the current state of all the keys on the keyboard to the array of ten words pointed to by pscan. + + +Each key corresponds to a bit in the word array. In the case of the Series 3a, the lowest eleven bits in each +of the first eight words are used. All other machines in the SIBO range use the lowest eight bits in all ten +words. If a key is depressed the corresponding bit will be set, otherwise it is clear. + + +13-9 + + +PLIB REFERENCE + + +The mapping between keys and bits in the array varies from machine to machine. In all cases, however, if +no key is depressed all ten words in the array will contain zero. The following example, to detect if any +key is pressed, is suitable for use on all SIBO machines: + + +GLDEF_C IsKeyDown (VOID) +{ +UWORD *p; +UWORD scans[10]; + + +p=&scans [0]; +p_getscancodes (p) ; +for (;p<=&scans[9];p++) +{ +if (*p) +return (TRUE) ; +} +return (FALSE) ; +} + + +The mapping between keys and the bits within the array for the Series 3a keyboard is given in the +description of the EPOC HwGetScancodes service, in the Hardware Management chapter of the EPOC +O/S System Services manual. + + +Display +p_geticd Get the system display type + + +INT p_getlcd(VOID); +-Return the (positive) system display type, where the display types are defined in epoc.h. +The function returns -1 if the host is a PC that has an unknown display type. + + +On a SIBO machine the display type is a good way of +identifying the model. The appropriate constants are defined in epoc.h. Examples are: + + +E_LCD_640_400 a 640x400 pixel display as on the MC 400 +E_LCD_640_200_SMALL a 640x200 pixel display as on the MC 200 +E_LCD_160_80 a 160x80 pixel display as on the HC +E_LCD_240_80 a 240x80 pixel display as on the Series 3 +E_LCD_480_160 a 480x160 pixel display as on the Series 3a +E_LCD_240_100 a 240x100 pixel display as on the Workabout + + +On a PC, the display types are: + + +E_PC_HERC Hercules graphics adaptor + +E_PC_CGA CGA graphics adaptor + +E_PC_MDA MDA display adaptor +E_PC_EGA_MONO EGA monochrome graphics adaptor +E_PC_EGA_COLOUR EGA colour graphics adaptor +E_PC_VGA_MONO VGA monochrome graphics adaptor +E_PC_VGA_COLOUR VGA colour graphics adaptor + + +If p_get1cd returns -1 (which can only happen on a PC), and you choose not to fail, it is recommended +that you proceed as if it had returned E_Pc_vGA_mMoNno. + + +p_Icdcontrastdelta Change the LCD contrast + + +VOID p_lcdcontrastdelta(INT nDelta); + + +Step the LCD contrast up or down depending on whether nbde1ta is positive or negative respectively (the +magnitude of nDelta is ignored. + + +The LCD contrast is changed through a sequence of values in a circular fashion. That is, stepping the +LCD contrast up when it is already at its maximum value sets it to its minimum value and vice versa. + + +The sequence of values that may be set varies from model to model. On a particular model, the values can +be ascertained by using p_get1cdcont rast, described below. + + +13-10 + + +13 GENERAL SYSTEM SERVICES + + +p_geticdcontrast Get the current LCD contrast + + +INT p_getlcdcontrast (VOID) + + +Return the current LCD contrast setting. + + +p_backlight Switch the backlight on or off +INT p_backlight (INT mode) ; + + +Switch the backlight on or off, depending on mode as follows: + + +E_BACKLIGHT_OFF switch the backlight off (if it is not already off) + +E_BACKLIGHT_ON switch the backlight on (if it is not already on) and reset the auto-switch-off +timer + +E_BACKLIGHT_TOGGLE switch the backlight on and reset the auto-switch-off timer if it is currently off +or switch the backlight off if it is currently on + +E_BACKLIGHT_QUERY does nothing and is used just to get the current backlight on/off state + + +For EPOC version 3.57 and above, provided a backlight is fitted, the function returns the on/off state +(&_BACKLIGHT_ON if on, E_BACKLIGHT_oFF if off) as it was as the function was entered. If no backlight is +fitted, the function returns E_GEN_NSUP. + + +For earlier versions of EPOC, the return value is unreliable. + + +p_setbacklight Set the backlight control value +VOID p_setbacklight (UINT flag) ; +Enable or disable the backlight key and set the backlight auto-switch-off interval in ticks. + + +If the most significant bit of f1ag is set (as given by the bit mask &_BACKLIGHT_DISABLE), the operating +system will not respond to the backlight key. (However, this does not stop the backlight from being +switched by a program calling p_backlight.) + + +The lower 15 bits of £1ag specifies the backlight auto-switch-off interval in ticks (1/32ths of a second). If +this value is zero, the backlight is not automatically switched off by a backlight timer and it will remain +on until the machine switches off. + + +For example: +p_setbacklight (96); + +sets the backlight auto-switch-off interval to 3 seconds and: +p_setbacklight (E_BACKLIGHT_DISABLE | (32*5)); + + +sets the backlight auto-switch-off interval to 5 seconds and disables the backlight key. + + +p_getbacklight Get the backlight enablement +UINT p_getbacklight (VOID) ; + + +Return the backlight control value as set by p_setbacklight, described above. + + +13-11 + + +PLIB REFERENCE + + +Sound + + +Most SIBO machines contain a piezo-electric buzzer in addition to a loudspeaker. + + +This section describes how to use the piezo to make a sound, and how to manipulate the set of flags used +to control the sound produced by the system. + + +The piezo uses very little power and is an easy way of generating sound, although it is fairly quiet. +Consider using the snp: device driver, which drives the loudspeaker, if greater sound complexity or a +louder sound is required. The snp: device driver is described in the I/O Devices Reference manual. + + +The bit masks for the flags controlling sound output are: + + +E_SOUND_KEYBOARD keyboard clicks are silenced if clear + +E_SOUND_BUZZER the piezo sound system is silenced (except for keyclicks) if clear +E_SOUND_DEVICE the snp: device driver is silenced if clear + +E_SOUND_LOUD the piezo will sound louder if set + +E_SOUND_DISABLE all sound in the system is silenced if set + +p_sound Make a sound with the piezo + + +VOID p_sound(UINT nDuration, UINT nPitch); + + +Make a sound through the piezo for nDuration system ticks and at pitch nPitch (where the pitch has +frequency 512/nPitch KHz). + + +Shared access to this piezo service is controlled by first waiting on a mutual exclusion semaphore that has +been pre-counted with 1 (mutual exclusion semaphores are described in the chapter Asynchronous +Requests and Semaphores). The effect of the mutual exclusion semaphore, assuming the piezo is not +already in use, is that the first call to p_souna will complete immediately but subsequent calls will wait +until the current operation completes. The result is that there could be an indefinite wait before the sound +is made. + + +If nDuration is passed as a negative value the call will always complete immediately, but will fail to make +a sound if the piezo is currently in use. + + +For example: +p_sound (5,320); + +makes a short beep, suitable for accompanying an error notification. The call: +p_sound (-5, 320); + + +will make the same sound, provided the piezo is not in use. + + +p_getsnd Get the sound flags +INT p_getsnd(VOID); +Return the current setting of the sound flags. + + +The flags are described at the beginning of this section. + + +p_setsnd Set the sound flags +VOID p_setsnd(INT nFlag); +Set the sound flags to nFlag. + + +The flags are described at the beginning of this section. + + +13-12 + + +13 GENERAL SYSTEM SERVICES + + +Sound on the Series 3a + + +The Series 3a machine does not contain a piezo-electric buzzer, so all sounds are made via the +loudspeaker. The Series 3a operating system does, however, contain a buzzer emulator (using the snp: +device driver) that supports the sound services described in the previous section. + + +This does, of course, mean that the p_sound service uses more power than in the case of machines that +contain a piezo-electric buzzer. Since all sounds are produced via the snp: device driver, sounds that, in +other machines, use the buzzer (keyclicks, for example) are disabled while the Series 3a is playing a +sound, such as an alarm. + + +Sound files +Series 3a sound files are files that contain a 32-byte header and a byte stream of A-Law encoded digital +sound. Such files normally have a .wve extension. + + +During recording 13-bit (a sign bit plus 12 magnitude bits) sound samples is converted to an 8-bit data +stream at 8000 bytes per second by CODEC hardware, using A-Law encoding. During playback the byte +stream is sampled at 8000 bytes per second and decoded to 13-bit sound by the CODEC. + + +In C, the file header is represented by the following struct (defined in epoc.h): + + +#define SignatureSize 16 +#define ALawSignature "ALawSoundFile**" + + +typedef struct +{ +TEXT Signature[SignatureSize]; +UWORD Version; +ULONG Samples; +UWORD SilenceInTicks; +UWORD Repeats; +UWORD Spare[3]; +} SndFile;. + + +This header is written and read by the Series 3a sound services described below. The meanings of the +items in the sndFile struct are: + + +Signature the 16-byte (including the zero terminator) string "ALawSoundFile**". + + +Version the Series 3a sound file version number as a 4-digit hexadecimal number of the +form xvyz, where x is the major release number, yy is the minor release number +and z is normally the hexadecimal digit r. See, for example, the description of + + +p_version. + + +Samples the number of bytes following the header. This must always be size of file less +the 32 bytes for the header. Dividing this by 8000 gives the duration of the +sound in seconds. + + +SilenceInTicks the number of system ticks of silence appended to each repeat on playback (in +practice, you get at least 2 ticks between repeats). + +Repeats the number of times to repeat the sound on playback (0 and | are the same). + +Spare reserved for future use. + + +A system tick is a 1/32th of a second, equivalent to 250 samples. + + +The program wav2wve.exe, supplied with the SDK (it is installed to the \sibosdk\sys directory) converts +.wav sound files to the .wve format. + + +The A-Law encoding scheme + + +The encoding scheme compresses signed, 12-bit magnitude (13 bits in all) samples into an 8-bit +representation. + + +A-Law encoding uses a logarithmic compression to reduce the size of sound files whilst preserving the +overall sound quality. The use of a logarithmic scale ensures that the low amplitude signals (which +contain most of the information in speech signals) are stored and reproduced with a minimal loss of +fidelity. + + +The A-Law encoding and decoding schemes are illustrated in the following sections. + + +13-13 + + +PLIB REFERENCE + + +Encoding + + +If the input data is represented by a normal two's complement signed value, it must first be converted into +a 12-bit magnitude, plus a 13th sign bit. For example, a value of -1 (represented by the 16-bit two's +complement value of 0xff£££) must be converted to the 13-bit binary representation (1) 000000000001, +where brackets indicate the sign bit. + + +The following table represents the range of possible 13-bit inputs. In this table an x character indicates +either a one or a zero (a "don't care" state) and an s character represents the sign bit: + + +0 +0 +0 +0 +0 +0 +0 +a + + +VrFOCCCCCO +TMrFDdAO0OCO +Qa7MmrFDVDGACO + + +faeces! +eucaeeeas + + +HANNNNHDADADN +xx AaATWrO +xxx AAOTM mM +xx xXKM ATS +xxx MM AAA +xx xxM MK OO +xxx MMM MM + + +A-Law compression of the above 13-bit inputs leads to the following range of 8-bit output values: + + +PRRERPODOO +PROOFRFOO +FPOrFPOFOFRSO +TOC OCC OO +aaaaaaa a + + +Ss +Ss +Ss +Ss +Ss +Ss +Ss +Ss + + +oo ooo mw ow w +aaaqaaaqaaaa + + +The compressed data is computed according to the following rules: +e the most significant bit preserves the sign bit of the original data item + + +e the following three bits represent the magnitude of the original data item, by recording the +position of the most significant non-zero bit (but note that the smallest magnitude group is +treated exceptionally) + + +e the remaining four bits record the next four most significant bits of the original data (in all but +the first group, these are the four bits that follow the most significant non-zero bit) + + +The compressed data is then manipulated to invert bits 0, 2, 4 and 6. This manipulation brings the ratio of +ones to zeroes closer to 50:50 and thus improves analog transmission of the data. + + +Examples of A-Law encoded data are given in the following table, where brackets identify the sign bit. + + +signed input 13-bit data compressed data encoded output +-1 (1)000000000001 (1)0000000 (1)1010101 ++2 (0)000000000010 (0)0000001 (0)1010100 +-371 (1)000101110001 (1)1000111 (1)0010010 ++2074 (0)100000011010 (0)1110000 (0)0100101 + + +A-Law encoding can be performed most simply and rapidly by means of a look-up table. Note that a 2048- +element table is sufficient, since the least significant bit of the input data has no effect on the encoded +value. + + +13-14 + + +13 GENERAL SYSTEM SERVICES + + +Where speed is not of the essence, an algorithmic method may be used, such as that illustrated by the + + +following code: + + +#define MAGICXOR 0x2a +#define ONE 1 +#define BIT8 0x80 +#define MASK2 0x03 +#define MASK3 0x70 +#define MASK4 Ox0f +#define MASK8 Oxff + + +GLDEF_C INT Compress(INT x) +/* + + +Compress input 16-bit 2's complement integer +8-bit signed compressed number using A-law. + + +ee: +{ +INT p,S,y; + + +/* convert 2's complement to sign bit and magnitude */ +p=BIT8; /* p is the (inverted) + + +if (x&0x1000) +{ + + +X= -X; +X&=OxFFF; +p=0; + + +} + + +if (x& (MASK4<<8)) /* Find leading + + +{ +if (x& (MASK2<<10) ) +s=(x& (ONE<<11)) ? +else +s=(x& (ONE<<9)) ? 5 +} +else +{ +if (x& (MASK2<<6) ) +s=(x& (ONE<<7)) ? 3 +else +s=(x& (ONE<<5)) ? 1 +} +if (s==0) +y=x>>1; +else + + +y=((x>>s) &MASK4) | (s<<4); +return ((~((y|p) *MAGICXOR) ) &MASK8) ; + + +} + + +sign bit */ + + +(13-bit magnitude) to + + +using binary search */ + + +Note that the final bit manipulation is done by adding in the (inverted) sign bit, performing an exclusive +or with maGIcxor (0x2a - inverting bits 1, 3 and 5) and then complementing the result. This exactly +corresponds with the formal definition of A-Law compression and also has the effect of restoring the sign + + +bit. + + +It would be marginally more efficient to replace the definition of macicxor with: + + +#define ALTXOR 0xD5 + + +and replace the last line of the function with: + + +return (((y|p) “ALTXOR) &MASK8) ; + + +13-15 + + +PLIB REFERENCE + + +Decoding + + +Decoding an A-Law compressed data value broadly consists of reversing the process that is described in +the previous section. + + +The bit manipulation is first reversed, by re-inverting bits 0, 2, 4 and 6. This results in the range of +possible 8 bit values as follows + + +0 +0 +0 +0 +1 +1 +1 +1 + + +ANDNHNANHADNA +PROORROO +FPOrROGCrROrROA +oo ooo ow w® +[on ON ON OE ON OME OO} +qgqaaqaaqaaqaaa +aaaaaaaa + + +Decompressing these 8 bit inputs using A-Law decoding leads to the following 13 bit outputs: + + +FOOCOCOO +CrFODCCCACO +ToMrFWCAOA0CO +QavTMrFDCOCSO +aanowraaonao +rPaATWMrFrAO +OrFaATMrFO +cooraQaqnoga yw +oooraq ogo +ooooraaqa +coooorga +COCO COOFRF + + +Ss +Ss +Ss +Ss +Ss +Ss +Ss +Ss + + +The decompressed data is computed according to the following rules: +e the most significant bit preserves the sign bit of the compressed data item + + +e the following three bits of the compressed data are used to determine the position of the most +significant non-zero bit of the decompressed data (but note that the smallest magnitude group is +treated exceptionally) + + +e the remaining four bits of the compressed data are used as the next four most significant bits of +the decompressed data (in all but the first group, these are the four bits that follow the most +significant non-zero bit) + + +e the next most significant bit of the decompressed data is set to one and any remaining trailing +bits are set to zero. The resultant value is thus set to the mean of all the possible values which, on +compression, give the value that is being decoded + + +If the output data is required in 16-bit two's complement format, then the sign bit must be extracted from +the data and, if it is set, the decoded value should be negated. + + +Examples of decoding are given in the following table, where brackets identify the sign bit. + + +encoded data compressed data 13-bit data signed output +(1)1010101 (1)0000000 (1)000000000001 -1 + +(0)1010100 (0)0000001 (0)00000000001 1 +3 +(1)0010010 (1)1000111 (1)000101111000 -376 +(0)0100101 (0)1110000 (0)100001000000 +2112 + + +The starting values in this table are the results from the encoding examples given in the previous section. +Notice that compression followed by decompression loses some of the information, as is expected. + + +13-16 + + +13 GENERAL SYSTEM SERVICES + + +As for encoding, A-Law decoding can be performed by means of a look-up table. In this case, a 256- +element table is sufficient. It is, however, simple to perform the decoding algorithmically, as illustrated in +the following code: + + +#define XORMASK 0x55 +#define BIT8 0x80 +#define MASK3 0x70 +#define MASK4 Ox0f +#define MASK8 Oxff + + +GLDEF_C INT ALawDecode (INT x) +/* +Expand input 8-bit signed compressed number to 16-bit +2's complement integer (13-bit magnitude) using A-law. +Si), + +{ + +INT s,y; + + +x= (x*XORMASK) &MASK8; +S=(x&MASK3) >>4; + + +y=0; +if (s) +{ +y=0x10; +s-=1; +} +y=(( (y+ (x&MASK4) ) <<1) +1) < + + +as well as the header files for using CLIB and/or PLIB. + + +Connecting to the window server + + +To use the services of the window server, a process must first connect to it by calling wconnect (or a +function that calls wconnect such as wStartup). + + +Not all processes are clients of the window server but an application process that is presenting a user +interface is likely to be a client”. + + +How you connect to the window server depends on whether you are using the CLIB or the PLIB C +startup module and what machine you are running on. + + +Note that the default project files set up by the installation of the SDK use the CLIB startup module. +Using the CLIB startup module on the HC, S3, S3a or Workabout + + +The CLIB startup module automatically opens a channel to the console device con:. This channel is +used to implement the CLIB functions that access the screen display and the keyboard. For example, +such functions as printf, gets, cprintf and cgets. + + +On an HC and all Series 3 machines, the console device is implemented such that opening it connects +to the window server, making the process a client of the window server. When using the CLIB startup +module, you take advantage of this console connection - as described in this section. If you mistakenly +attempt to connect a second time by calling wconnect or wStartup in your program, the process will +be panicked with panic number 100. + + +When the CLIB startup module opens con:, it puts the channel in the static variable winHandle, +which may be referenced as: + + +GLREF_D VOID *winHandle; + + +As well as connecting to the window server, opening a channel to the console creates and initialises a +backed-up window (which does not have to be redrawn). + + +As described in the Console chapter of the I/O Devices Reference manual, you can obtain the ID of +the console window using the r_1Nq I/O function, as in the following program: + + +#include +#include +#include + + +2One exception to this rule is on the MC where an application uses the services of the console process +(with process name SYS$CONS) to access the screen and keyboard. In this case it is SYSSCONS that is the +client of the window server - not the application process. On the MC, an OPL program (which is really a +process of SYS$OPLR) uses SYS$CONS to draw to the screen. + + +1-8 + + +1 INTRODUCTION + + +GLDEF_C INT main(VOID) +{ +CONSOLE_INFO cinfo; +WS_EV event; + + +p_iow (winHandle, P_FINQ, écinfo) ; +gCreateGC0 (cinfo.window_handle) ; +gPrintText (10,20,"Hello world!",12); +do + +{ + +wGetEventWait (&event) ; + +} while (event.type!=WM_KEY) ; +return (0); + + +} + + +where cinfo.window_handle is the console window ID. After displaying the "Hello world!" message, +the program waits for a key press event and then exits. + + +In CLIB programs you can prevent the automatic opening of a console channel by defining the +function p_xwind in your code, as in the following example: + + +extern void *winHandle; + + +void p_xwind (void) +{ +winHandle=(void *)1; + + +} + + +int main (void) + + +{ + + +return (0); + + +} + + +You should ignore the warning, given during the linking of your program, that the symbol _p_xwind +is duplicated. + + +If you use this technique, your CLIB program should not, of course, make any reference to stdin, +stdout Or stderr, unless you have redirected them. Setting winHandle to | (an illegal value for a +handle) will guarantee that any such reference will fail with a panic. + + +Using the PLIB startup module on the HC, S3, S3a or Workabout + + +The PLIB startup model does not open a channel to the console and the simplest way to get going is +to use the wstartup function that: + + +¢ connects to the window server +e creates and initialises a backed-up window to cover the whole screen +¢ creates a permanent graphics context on that window + + +After calling wstartup, you are in position to draw to the graphics context - as in the following +example: + + +#include +#include + + +GLDEF_C INT main(VOID) +{ +WS_EV event; + + +wStartup(); +gPrintText (10,20,"Hello world!",12); +do + +{ + +wGetEventWait (&event) ; + +} while (event.type!=WM_KEY) ; +return (0); + + +} + + +1-9 + + +WINDOW SERVER REFERENCE + + +Using the CLIB startup module on the MC + + +On the MC, the console device is implemented quite differently from the HC. When the con: device +is opened on an MC, a console display process is created by loading the SYS$CONS.IMG executable +from the ROM. When the opener of the console device calls the channel's I/O functions, the console +sends inter-process messages to the console display process which then sends inter-process messages +to the window server. The console process keeps a character map of the console screen which it uses +to redraw its window as necessary. The console process also manages a title bar that allows the +window to be moved and/or resized and a menu bar that allows the program to be stopped. + + +Because the console device is implemented in this way, the console does not support the p_F1nq I/O +function as described above for using the CLIB startup module on the HC. Because it is the console +and not the application process that is the client of the windows server, you can't use the console's +window. There is nothing to stop you from connecting to the window server using wStartup or +wConnect but you will then be running an application with two independent window systems and two +clients. The console channel is still in winHandle so you can close the console and terminate the +display process but this is hardly satisfactory. + + +In conclusion, on the MC, you are better off embracing the EPOC system more completely and using +the PLIB startup module. Despite what is said elsewhere, you can use some CLIB functions with the +PLIB header - those that do not rely on any initialisation. You can, for example, use strcpy - but you +can't use any I/O function such as open, or a memory allocation function such as malloc. + + +Using the PLIB startup module on the MC + + +As on the HC, the simplest way to get going is to use the wStartup function. + + +The MC is available with both version 2 and 3.5 of the window server. Version 2 does not support +bitmap backed-up windows. Even with version 3.5 on the MC, backed-up windows are less attractive +on a large screen where the bitmaps consume large amounts of memory and the processing overhead +of maintaining the bitmap is likely to be more noticeable. + + +You can still call wstartup but, with version 2 of the window server, you get a window that is not +backed-up and you have to deal with redraw events, as in the following example: + + +#include +#include + + +GLREF_D UINT wMainWid; + + +GLDEF_C INT main(VOID) +{ +WS_EV event; + + +wStartup (); +do +{ +wGetEventWait (&event) ; +if (event .type==WM_REDRAW) +{ +wBeginRedrawWin (wMainWid) ; +gPrintText (10,20,"Hello world!",12); +wEndRedraw() ; +} +} while (event.type!=WM_KEY) ; +return (0); + + +} +The global variable wMainwid contains the ID of the window that is created by wstartup. + + +On the MC with its larger screen, wStartup is probably too simplistic (for example, it creates a +window the full size of the screen) and is best seen as a quick starting point for exploratory +programming. In due course, you should look to using wconnect to implement a startup that is +appropriate to your application. + + +1-10 + + +1 INTRODUCTION + + +Error handling + + +How errors are signalled + +Should an error (such as out of system memory) occur in one of the window server functions, the +window server will do one of the following: + +e call p_leave, passing it the (negative) error number + + +e return the error number + + +By default, the window server calls p_1eave. You can make it return the error number by calling +wDisableLeaves (TRUE). From version 3.5 onwards of the window server, you can also set the +W_CONNECT_DISABLE_LEAVES flag when calling wconnect. This is equivalent to calling +wDisableLeaves (TRUE) except that it also affects whether wconnect itself leaves or returns an error. + + +The enter and leave mechanism (which uses p_enter; and .p_leave) is commonly used to implement +structured error recovery. See the Error Handling chapter of the PLIB Reference manual. + + +With the enter and leave mechanism, a call to p_1eave should only occur within the protection of a +p_enter harness. If you don't use p_enter and you don't call woisableLeaves and p_leave is called, +the process will be panicked with panic number 47. + + +Errors in blind operations + + +In the interests of performance, many of the functions performed by the window server have a "blind" +interface in the sense that the client does not receive any acknowledgement that the operation has +been performed. + + +Blind operations may be stored in a client-side buffer to be processed in batches when some condition +causes the buffer to be flushed (as described later). The functions that perform blind operations don't +return anything and are declared as vorp. + + +Many of the blind operations can't reasonably fail - such as drawing a line by calling gprawLine. +However, some functions can fail. For example, increasing or even decreasing the size of a bitmap +backed-up window by calling wset window can fail to allocate the additional memory (which is +required transiently when decreasing the size of a backed-up window). + + +If an error occurs in a blind operation, the window server goes into a special state in which it discards +all further blind operations until a function that can fail is called (such as wcreateWindow). + + +When such a non-blind function is called, it immediately fails - either by calling p_ieave or by +returning an error number, as described above. + + +When a failure does occur while drawing, you often don't care exactly where it failed and you can +happily wait until a non-blind function is called (which might mean waiting until weetEventWait, +wGetEvent Of wGetEvent Special is next called). + + +However, if you need to establish that the processing has been successful thus far, you can call +wCheckPoint which flushes the buffer and signals any failure (by calling p_ieave or by returning an +error number). + + +Cleaning up after an error + + +When handling an error while using the window server (say in response to a p_leave), you can use +wCleanUp to clean up any dangling window server resources where wcleanUp: + + +e frees the temporary graphics context (if it exists) +e ends a redraw if one was in progress + + +If there is a current graphics context that is attached to a window, wcleanUp also invalidates that +window so that it is not left in a partly drawn state. + + +1-11 + + +WINDOW SERVER REFERENCE + + +Panic numbers + + +See the Error Handling chapter of the PLIB Reference manual for a discussion of panics and panic +numbers. + + +The window server panics a client that attempts an illegal operation, using the following panic +numbers: + + +font does not exist + +illegal window or bitmap ID + +illegal window ID + +null handle given to server + +illegal graphics context ID + +illegal GMODE value (V2 only) + +illegal TEXTMODE value (V2 only) + +illegal font ID (V2 only) + +wBeginRedraw called while already in a redraw + +mouse icon does not exist + +illegal bitmap ID + +window tree is already initialised + +wEndRedraw Called when there isn't a redraw to end + +attempted to change the background of a backed-up window +wInitialiseWindowTree called when the parent window is not initialised +illegal parameters passed to wsAlertW, wsAlertA or wsAlertUpdate +illegal length in gPeekBit (V2 only) + +illegal x+length value in gPeekBit (V2 only) + +illegal ypos in gPeekBit (V2 only) + +tried to connect a second time + +tried to access a permanent graphics context while a temporary graphics context exists +illegal opcode in message + +command buffer received by wserv is too long + +generally bad message received + +wFree was called with an ID that doesn't refer to a freeable object +illegal DYL ID + +out of range count sent to wSetWinBitmap + +a bitmap was freed while still in use by a wSetwinBitmap command +illegal window-bitmap ID + +bad data or version in connect message + +called wGetEvent while the previous call was still pending + +function not available + +illegal clock ID in wssetClock + +illegal sprite ID (V4 only) + +client already has a sprite (V4 only) + +corrupt control block (possibly not connected) + +function number out of range + + +Note that because of client-side buffering, there may be a gap between calling the offending function +and the call to p_panic. When tracking down the cause of a window server panic, you may need to +insert temporarily calls to wFlush or wCheckPoint to precipitate the panic. + + +Series 3 compatibility mode. + + +To enable existing applications that were designed to run on the S3, to run successfully on the S3a +and Workabout while keeping the same 'look' and 'feel', version 4 of the window server can run in +what is called compatibility mode for that application. This mode is set or cleared by use of the +wCompatibilityMode function. + + +As far as is practicable, the window server on the S3a attempts to emulate its behaviour on the S3. +For example, in compatibility mode, all drawing to the screen is done in double pixel mode to +overcome the fact that the S3a has a screen of 480 x 160 pixels compared to the S3 screen of 240 x 80 +pixels. + + +When running in compatibility mode on the $3a or Workabout, the version_id member of the +CONNECT_INFO sub-structure will have ws_vERston_4 set. This constitutes the only difference between +the $3, S3a and Workabout in compatibility mode. + + +1-12 + + +1 INTRODUCTION + + +The Workabout has two different types of compatibility mode. In the first type, a 240 x 80 S3 display +is centred on the screen, leaving an unused area above and below the display. In this type of +compatibility mode, the only difference between the S3 and the Workabout is the version_id +member of conNECT_INFo, aS described above. + + +In the second type of compatibility mode for the Workabout, the display covers the full 240 x 100 +Workabout screen and uses a restyled status window. This type is intended for use by only those +applications that can adjust the dimensions of their windows to match the available screen size. It is +recommended that this type of compatibility mode should be used only if a centred 240x80 display is +truly unacceptable. + + +References to compatibility mode will occur throughout this manual. + + +Clients and the window server + + +Client-side functions + + +In the interests of performance, not all the window server functions cause an inter-process message to +be sent. + + +For example, the function gtextwidth, which calculates the printed width of a text string, is +implemented entirely on the "client side" without requiring any context switch between client and +window server. + + +Client-side buffer and flushing + + +Also in the interests of performance, functions that perform "blind" operations that have no return +values (such as most drawing operations) are not sent directly to the window server but are queued in +a client-side buffer. + + +In most cases, the client-side buffer is flushed automatically, when: + +e the buffer is about to overflow + +e an operation that requires a return value is requested + +e an input event is requested by calling wcetEventWait, wGetEvent Of wGetEvent Special + + +Applications should not, however, make any assumptions as to whether a particular window server +function call will or will not cause the buffer to be flushed. + + +The client-side buffer can be flushed explicitly (for example, to animate an image) by calling wriush. +In practice, it is rarely necessary to use wFlush and, although otherwise harmless, using wrlush +unnecessarily will degrade performance. + + +As described earlier, you can also flush the client-side buffer by calling wcheckPoint. + + +The client-side buffer is allocated from the heap when wconnect is called and is approximately 300 +bytes long. The address of the data structure that contains the client-side buffer is held in the +reserved static variable wclientData which may be referenced from C by declaring: + + +GLREF_D VOID *wClientData; + + +Testing for a connection + + +If a process has connected to the window server, wclientData will contain a non-zero value. If a +process has not connected to the window server, it will contain zero. + + +1-13 + + +WINDOW SERVER REFERENCE + + +Foreground and background clients + + +Of all the clients of the window server one client is the foreground client and all the other clients are +background clients. + + +The foreground client is the client that receives keyboard input from the user. + + +Some special key presses (such as the TASK key as described below) are processed by the window +server. A client can capture specific key presses (in which case it is sent the key whether it is +foreground or not) by calling wcapturekey. + + +The foreground client has its windows in front of the windows of any background client. On small +screen versions of the window server, that is, on the HC, S3, S3a and Workabout, the windows of any +background clients are not visible at all. + + +Events + + +For each client, the window server keeps a queue of events that inform the client of user input and +other events. The different types of window server events include: + + +e key presses + +e foreground/background changes + +e redraw events (described later) + +e mouse events (if the machine has a pointing device) + + +Mouse and key events are time stamped with a 16-bit time in system ticks which may be used to +calculate the time between successive events that occur within a short time period (such as a double +click). + + +Redraw and mouse events are directed at a particular window by a window handle event parameter. +This handle is specified by the client when the window is created (and is commonly the address of a +client data structure that contains the window ID). + + +The client can read the next event by calling wcetEventwait, which only returns when there is an +event to deliver. If the client's event queue is empty, wGetEventwait will wait indefinitely for an event +to occur. + + +Applications that need to respond to events other than just window server events (for example, serial +input) would use either of the asynchronous functions wGetEvent or wGetEventSpecial which +request an event without waiting. Asynchronous requests are described in the chapter Asynchronous +Requests and Semaphores in the PLIB Reference manual. + + +Note that wGetEvent Special is only available in version 4 of the window server and is a +generalisation of wGetEvent in that it permits the caller to select which events are to be delivered. +Calling wGetEvent Special (WE_EVENT_NORM) 1s equivalent to calling wcetEvent. + + +Task switching; + + +The window server keeps all the clients in a front to back task order. Position zero in the task order is +the front position and is held by the foreground client. Position 1 is held by the frontmost background +task and so on. + + +When a program connects to the window server, it normally takes the foreground. (A program can +connect in background by setting a parameter to wconnect.) + + +On an S3, an S3a or an HC that is running version 3.5 of the window server, when a process +disconnects, the window server attempts to make the "owner" of the process foreground. Here, the +owner is the process which last resumed it (by calling p_resume). If the owner has terminated or is +not a client of the window server, the shell is made foreground. + + +A client may bring itself or any other client to foreground (or put itself or any other client to +background) by calling wclientPosition. + + +Unless an application has taken steps to disable task switching, the user may switch tasks using the +machine-dependent task-switching keys, as described next. + + +3On large screen versions of the window server when one or more clients have attached to a client, you +can have multiple foreground clients (in the sense that they all last received a foreground event) but only +one of them (the frontmost client) receives key events. + + +1-14 + + +1 INTRODUCTION + + +Task switching on the HC + + +On an HC with an alpha-numeric keyboard (as opposed to just numeric), the window server brings +the foremost background client (at client position 1) to the foreground when the TASK key +(SHIFT+LEFT ARROW) is pressed (the former foreground client is moved to the end of the task list). + + +On an HC, an application can disable task switching in one of two ways: +e locking itself into foreground by calling wsystemModal (0) + +e capturing the task key by calling wcapturekey + +Task switching on the Workabout + + +On a Workabout, the window server brings the foremost background client (at client position 1) to +the foreground when the TASK key (SHIFT+ESC) is pressed (the former foreground client is moved to +the end of the task list). + + +On a Workabout, an application can disable task switching in one of two ways: +e locking itself into foreground by calling wsystemModal (0) + +e capturing the task key by calling wcapturekey + +Task switching on the S3 and the S3a + + +Task switching is controlled by the 8 membrane keys (called application keys) above the main +keyboard. Actually, the window server handles 16 application keys where a second set of 8 keys are +accessed by pressing the CONTROL shift key. + + +These keys are handled co-operatively by the window server and the shell. (The shell has process +name sysssHu and is known by the user as the System task.) + + +When the system starts up, the shell calls wappKkeyHandler to declare itself as the handler of the +application keys. The shell maintains two data structures pointed to by the reserved statics patapp1 +and DatApp2 which control the assignment of the application keys to particular applications. + + +When the system starts up, each application key is assigned to an in-built application. Using the +shell's user interface, the application keys other than the 2 System application keys (14 in all) may be +reassigned. + + +The application keys are handled as follows: + + +¢ On both the S3 and the S3a, if an application key (SHIFTed or otherwise) of an application +different from that of the foreground is pressed, the window server makes the frontmost process +of that application foreground‘. If no process of that application exists, the application key +handler (that is, the shell) is made foreground and sent a wM_TAsK_KEy event. + + +¢ On the S3 only, if an application key of the same application as that of the foreground is pressed, +the window server sends the foreground task a wm_xey event with key code w_kEy_MopE. +(Applications normally cycle through their display modes in response to this event.) + + +¢ On the S3 only, if a SHIFTed application key of the same application as that of the foreground is +pressed, the window server brings the frontmost background client of that application to the +foreground (the former foreground client is moved to the end of the task list). + + +¢ On the S3a under version 4 of the window server, pressing an application key of the same +application as that of the foreground brings the frontmost background client of that application to +the foreground (the former foreground client is moved to the end of the task list). Pressing the +SHIFTed application key of the same application as that of the foreground does the reverse. +In response to the DIAMOND key being pressed, the window server sends the foreground task a +WM_KEY event with key code w_kzy_mopg. (Applications normally cycle through their display +modes in response to this event.) +Note, however, that a foreground application running on the S3a in S3 compatibility mode will +also receive this event when the DIAMOND key is pressed. + + +¢ On both the S3 and the S3a, if a PSION shifted application key is pressed, the window server +makes the application key handler foreground and sends it a wm_TasK_kEy event. + + +4The application is identified by its name. For an $3 or S3a application process, the window server reads +the associated application name from the reserved static patProcessNamePtr. + + +WINDOW SERVER REFERENCE + + +The shell responds to a WM_TASK_KEY event (which indicates which key was pressed in a parameter) by +positioning to the appropriate icon. + + +The SYSTEM application key is permanently assigned to the shell. + + +The CONTROL+SYSTEM application key is assigned to a notional RunImg application such that if this key is +pressed, the window server makes the shell foreground and sends it a ww_TASK_KEY event. The shell then +positions to the RuniImg icon (a bubble containing the word IMG). + + +The shell calls wset TaskKey to assign SHIFT+SYSTEM as a task key. The window server responds to a task +key by moving the foreground client to the end of the task list thus bringing the client previously at +position | to the foreground. + + +The shell also calls wset BackTaskKey to assign SHIFT+PSION+SYSTEM to the "back-task" key which brings +the task furthest from the front to the foreground. + + +On the S3 and the S3a, an application can disable task switching in one of two ways: +e locking itself into foreground by calling wsystemModal (0) + + +¢ capturing all the application keys key by making 8 calls to wcaptureKey (capturing all shift states +in each call) + + +Task switching on the MC + + +On the MC, the windows of a foreground or background client that has a lower task position will, if they +overlap, obscure (partially or wholly) the windows of background client with a higher task position. + + +The user can change the task ordering by: + + +e pressing the TASK to move the foreground client to the end of the task list thus bringing the client +previously at position | to the foreground + + +¢ pressing SHIFT+TASK to cycle through tasks in the reverse direction + + +¢ pressing CTRL+TASK and CTRL+SHIFT+TASK that cycle in either direction in such a way that +iconised tasks are skipped + + +e using the digitiser to click on a background task's window + + +On the MC, it is also possible to attach a client to another (by calling wattachToClient or +wAttachToForegroundClient) such that the attached client and the client it is attached to behave as one +task (with the attached client in front). + + +An application can disable task switching by locking itself into foreground by calling wsystemModal (0). + + +Iconised clients + + +On large screen version of the window server such as the MC, a client can mark itself as iconised by +calling wclientIconised. + + +A client that marks itself as iconised is excluded from a form of window server controlled task switching +in which only non-iconised tasks are brought into the foreground. On an MC, if the user holds down the +CONTROL key while pressing the TASK key, the window server selects only non-iconised tasks. + + +If an iconised client is brought to the foreground by a call to wclientPosition (normally by another +process), the window server sends that client a WA_DEICONISE event (which would normally prompt the +client to deiconise itself). + + +Note that it is the client's responsibility to make any changes to its appearance as a result of a change in its +iconised state. + + +Client priorities + + +The window server can be instructed (by a parameter to wconnect or bya call to wSetPriorityControl) to +adjust automatically the process priority of a client when it gains and loses the foreground such that the +foreground client runs at a higher priority than any background clients. + + +A higher priority foreground client that is performing a computationally intensive task (for example, a +spreadsheet program that is calculating) will totally and indefinitely block any lower priority background +clients that are ready to run. This can be undesirable - particularly on the MC where the windows +belonging to background clients may be visible. + + +1-16 + + +1 INTRODUCTION + + +To avoid robbing background tasks of all processing, computationally intensive processing should be +bracketed with calls to wstartCompute and wEndCompute. In between the calls to wstartCompute and +wEndCompute, the window server holds the client's priority at the background client level regardless of +whether it has the foreground or not. + + +On machines using the small screen versions of the window server, where the windows belonging to +background clients are never visible, the arguments for using wstart Compute and weEndCompute are less +compelling but there may be circumstances when their use is still appropriate. For example, if a user +switches from a task which is printing to continue a game of chess, should the foreground chess task halt +the background task from printing? + + +System-modal clients + + +There is sometimes a requirement to disable task switching by locking a so called system modal task in the +foreground. For example, to notify the user of a condition that must be acknowledged or rectified before +proceeding. + + +A client may declare itself system modal by a parameter to wconnect, or may subsequently change its +system modal state by calling wsystemModal Of wCancelSystemModal. + + +The window server limits task switching to only those processes that have a lower client position than the +frontmost system modal task (if there is one). + + +A client that is system modal would normally be in one of the following client positions: +e take the foreground in which case task switching is disabled + + +e be furthest in the background (that is, with the highest client position) in which case task +switching excludes the system modal task + + +On larger screen versions of the window server (such as on an MC or a PC) where windows belonging to +different clients are typically simultaneously visible on the screen, a system modal client would normally +takes steps to make its windows invisible unless it has the foreground (since clicking on them will not +bring them to foreground). + + +Client management + + +The window server is in a natural position to undertake most of the work necessary to manage clients, for +example: + + +e handling foreground/background task switching + +e automatically adjusting client process priorities + +e notifying the user of clients which terminate abnormally (on machines other than the MC) +¢ supporting the link paste mechanism on the S3, S3a and Workabout + + +However, there are a few functions to support a special client (typically the shell, sysssHu1) taking on +some client management. These functions are: + + +wGetProcessList Gets the process IDs of the clients of the window server, in front to back order. +wClientPosition Used to bring a client into the foreground. + +wSendCommand Used to transfer up to 127 bytes from one window server client to another. +wGet Command + +wAppKeyHandler Used by the shell on the S3 and S3a to handle membrane keys (application + + +keys) in partnership with the window server. + + +wSystem Modify the behaviour of the window server on a non-client-specific level. For +example, to determine whether the window server handles the p_notify +service. See also the section System start-up at the end of this chapter. + + +wSetTaskKey Sets the window server to respond to additional keys that cycle through the +wCancelTaskKey tasks in the two directions. Provided mainly for the $3 and S3a (which do not +wSetBackTaskKey have a system task key on the keyboard). + +wCancelBackTaskKey + + +1-17 + + +WINDOW SERVER REFERENCE + + +Windows + + +A window is a rectangle in screen coordinates that provides a coordinate system for clipped drawing. + + +Once a window has been created using wcreat eWindow, its initial position and size may be changed (using +wSetWindow). + + +Note that at the window server layer, a window is invisible unless it is drawn to. If a window has a +boundary (or any other features) it is because the owning client drew it. + + +Most drawing is done to a graphics context to which a window has been assigned. Off-screen bitmaps can +also be assigned to a graphics context. Both windows and bitmaps are sometimes called drawables. + + +Window trees +Windows are linked in a hierarchy or tree with the screen as the root window. + + +A window is created relative to its parent window and is called the child window of the parent window. A +child window may be a parent of further child windows and so on to any depth. + + +The position of a child window is held relative to its parent. If a parent window is moved, all descendant +windows move by the same amount. You can obtain the offset between any two windows (wherever they +are in the hierarchy) by calling winquireWindowOffset. + + +A child window +e is in front of the parent (and will obscure any drawing to the parent window) +e is clipped to the boundaries of its parent. + + +Note that a child window may be smaller or larger than its parent. A window is often tiled with multiple +child windows which are smaller than the parent and where parts of the parent window may or may not be +visible depending on whether there are any gaps between the boundaries of the child windows. A window +may have a single child window that is slightly smaller than its parent and where the parent provides a +frame around the child window - any drawing to the child window is clipped to the boundaries of the child +window and will not corrupt the frame. A window may have as its child a larger window that is providing +a clipped scrolling view of some information (such as a list) where the view is scrolled by simply moving +the child window in its parent's coordinates. + + +A window is said to be the descendant of a window if it is its child or its grandchild and so on. All +windows are descendants of the root window. Child windows of the root window are sometimes called +top-level windows. + + +Child windows of the same parent are called sibling windows. Sibling windows have a front to back order +which is apparent if they overlap. + + +Ownership of windows + + +Except for the root window, all windows are owned by a particular client. A client does not have access to +windows belonging to other clients and can only create child windows of the root window (that is, top- +level windows) or of its own windows. + + +On larger screen versions of the window server such as on an MC or a PC, windows belonging to different +clients may (and typically are) simultaneously visible on the screen. + + +On small screen versions of the window server, only the foreground client's windows are visible at any +time. + + +Background client drawing + + +Background clients can still draw to their windows whether they are visible or not and programs do not +normally take any special measures to avoid drawing while in background. In fact, applications are +typically oblivious of whether they are foreground or background - they just don't get delivered any key +presses while in background. + + +In practice, background clients rarely draw to their windows on a small screen version of the window +server because they have been robbed of keyboard input. Exceptions are a client that is switched to +background while it is still processing and a client that is driven by events other than just key presses - for +example a terminal emulation program or a clock program. + + +1-18 + + +1 INTRODUCTION + + +Background clients of a large screen version of the window server commonly draw to their windows while +in background for two reasons. First, to take on the appearance of a background client (otherwise, unless +its windows are partially obscured by an overlapping window, it is difficult to differentiate between +background and foreground tasks). Second, to redraw its windows after being exposed by changes (of +position, size, front to back ordering or visibility) to windows that previously obscured it. + + +Drawing region + + +When you draw to a window, the drawing is clipped to the visible part of the window - called the drawing +region. When the window is partially obscured by overlapping windows, the drawing region is not a +simple rectangle (it is actually represented by a variable-length array of rectangles). + + +For example, suppose an application is displaying a clock as part of its main display area. On the +completion of a timer informing the application to update the appearance of the clock, the application can +happily go through the motions of drawing the entirety of the clock, without worrying whether part of +that display is being obscured by an overlapping dialog box or pulled-down menu. The window server +ensures that only drawing to unobscured portions of the window is effective: + + +In the diagram, any drawing to the dotted region in the Clock window will fail to appear. + + +The window server will discard a drawing region (since it can be recalculated at any time) rather than +maintain it unless the window is being drawn to or is assigned to a permanent graphics context. + + +Backed-up windows + + +A window can be created in such a way that all drawing to it is duplicated to off-screen bitmaps. The +window server can then automatically redraw the window without bothering the client. Prior to version 4, +the window needs to be created with a w_win_BACK_BITMap background. In version 4 upwards of the +window server the window can be created with one or both w_wIn_BACK_ BITMAP and +W_WIN_BACK_GREY_BITMap backgrounds (see creating and initialising a window in the Windows chapter). + + +This makes life much easier for the programmer. (Otherwise, the programmer has to respond to redraw +events and has to adopt a more sophisticated programming style, as described below.) + + +Prior to version 4, when a backed-up window is created, a single backup bitmap is also created with an +appropriate size. This bitmap is initialised with zeros corresponding to a clear screen (white on an LCD). + + +In version 4 of the window server, when a backed-up window is created which is enabled for drawing both +black and grey, two backed-up bitmaps are created with an appropriate size, one for the 'normal' plane and +one for the grey plane (see the Graphics chapter for a fuller discussion of grey). + + +If the size of a backed-up window is subsequently increased, the backup bitmaps are also increased and the +additional area (to the right and below) is filled with zeros. + + +If a backed-up window is scrolled using wsScrollRect Of wScrollwin, the area that is scrolled in from +outside the window is filled with zeros. + + +The disadvantages of using bitmap backed-up windows are: +e it takes longer to draw the image in the first place (since all drawing is duplicated) +e additional storage is required to store the backup bitmap(s) + + +Although the original drawing is slower, the window server redraws a backed-up window with blinding +speed. + + +WINDOW SERVER REFERENCE + + +Keeping backed-up bitmaps for a screen-sized window incurs a storage cost which varies according to the +machine type: + + +e On the HC (160 by 80 pixels), a backed-up bitmap occupies a modest 1600 bytes. +e On the S3 (240 by 80 pixels), a backed-up bitmap occupies 2400 bytes. + + +e On the Workabout (240 by 100 pixels) using version 4 of the window server, a backed-up bitmap +requires 3000 bytes. However, if the window is enabled to use both black and grey, two backed- +up bitmaps are needed, thus doubling the space required to 6000 bytes. + + +e On the S3a (480 by 160 pixels) using version 4 of the window server, a backed-up bitmap +requires 9600 bytes. However, if the window is enabled to use both black and grey, two backed- +up bitmaps are needed, thus doubling the space required to 19200 bytes. + + +e On the MC400, a full screen (640 by 400 pixels) bitmap requires 32K bytes. + + +Slowing down screen drawing is clearly more of a problem on a larger screen and, in summary, using +backed-up windows on an HC or an S3 with their smaller screens (and smaller windows) makes more +sense than on an MC. Using backed-up windows on an S3a or Workabout enabled to draw both black and +grey is questionable. + + +Note, however, that the size of the screen does not limit the size of the window. In most practical +situations, the windows will be smaller on a smaller screen model, but it is sometimes useful to create +windows that are larger (and possibly much larger) than the screen. For example, when presenting a +scrolling view of a map that is much larger than the screen size. With such large windows it would not be +desirable to use a backed-up window. + + +No-redraw windows + + +As well as backed-up windows, the programmer in search of an easy life should also consider windows +created with the w_wIN_No_REDRAW bit set (as a parameter to wcreat eWindow). + + +For such windows, the window server does not invalidate the window or generate redraw events. What it +does do when the window is partly or wholly invalidated (that is, when the backup bitmaps would have +been used if they existed) depends on the background parameter to wcreat eWindow as follows: + + +W_WIN_BACK_CLR prior to version 4, clears the pixels in the window (this is the default). This is +useful, for example, when the window is tiled with child windows but does not +itself contain any images. + + +in version 4, clears the pixels in the normal (black) plane of the window. + + +W_WIN_BACK_GREY_CLR available in version 4 only, clears the pixels in the grey plane of the window. + + +W_WIN_BACK_SET prior to version 4, sets the pixels in the window. This may be used, for +example, to implement a black thick border to a child window that is slightly +smaller and inset from its parent. + + +in version 4, sets the pixels in the normal (black) plane of the window. + + +W_WIN_BACK_GREY_SET available in version 4 only, sets the pixels in the grey plane of the window. + + +prior to version 4, either w_wIN_BACK_CLR or W_WIN_BACK_SET may be used when a window is entirely +covered with its child windows. For example, when a larger child window provides, in conjunction with +its parent, a scrolling view over a larger image. + + +In version 4, in addition to using either w_WwIN_BACK_CLR or W_WIN_BACK_SET, one of the corresponding +grey plane attributes w_wIN_BACK_GREY_CLR or W_WIN_BACK_GREY_SET may also be used, if appropriate. + + +Note that you should not rely on the fact that a window is always totally obscured by another window +(such as a child window) to suppress redraw events since the window server can send unnecessary redraw +events when there is insufficient free system memory to maintain update regions. For guaranteed +suppression of redraw events you should specify the w_wIN_No_REDRAW bit to wcreateWindow - even when a +window is always totally obscured. + + +In version 4 of the window server, redrawing can also be suppressed on a per-plane basis by setting the +. .._NO_REDRAW modes. This method is much preferred. + + +The w_wIN_No_REDRAWw bit does not need to be set. + + +1-20 + + +1 INTRODUCTION + + +The ..._No_rEDRaw background flags can be used as follows: + + +W_WIN_BACK_CLR_NO_REDRAW suppresses re-drawing to the normal plane but the window server +clears the pixels. + + +W_WIN_BACK_SET_NO_REDRAW suppresses re-drawing to the normal plane but the window server +sets the pixels. + + +W_WIN_BACK_NONE_NO_REDRAW suppresses re-drawing to the normal plane; the window server does +nothing to the pixels in this plane - it neither sets nor clears them. + + +W_WIN_BACK_GREY_CLR_NO_REDRAW suppresses re-drawing to the grey plane but the window server +clears the pixels. + + +W_WIN_BACK_GREY_SET_NO_REDRAW suppresses re-drawing to the grey plane but the window server sets +the pixels. + + +W_WIN_BACK_GREY_NONE_NO_REDRAW suppresses re-drawing to the grey plane; the window server does +nothing to the pixels in this plane - it neither sets nor clears them. + + +Bitmap sequences + + +A window may be given an animated image by attaching a sequence of up to twelve bitmaps to the +window by calling wsetwinBitmap. The sequence is modified by calling wchangewinBitmap and freed by +calling wrree (destroying the window automatically frees the bitmap sequence). + + +Each entry in the sequence specifies +e asource bitmap +e the position of the bitmap in the window +e the transfer mode + + +e the time to wait (in tenths of a second) before copying the next bitmap in the sequence to the +window + + +You should be careful about defining too short an interval between bitmaps (especially in combination +with large bitmaps) as the computational effort to maintain the sequence may leave little processor +bandwidth for the application to run. Note that the window server runs at a higher priority than its clients. + + +If the sequence contains a single bitmap, the bitmap is not animated. + + +Whether animated or not, a rectangle on the window that is currently covered by a bitmap in the sequence +is automatically redrawn when that part of the window is invalidated. + + +Any number of bitmap sequences may be attached to a window. Where there is an overlap, bitmaps from +sequences attached after another sequence appear behind that sequence. + + +Bitmap sequences are not designed to be used with backed-up windows and are typically used to produce: + + +e a window with a changing background bitmap for other drawing (however, if there is only one +bitmap in the sequence, the background does not change) + + +e a window that is only drawn from the bitmaps in the one or more bitmap sequences and which, +like backed-up windows, does not have to be redrawn (and the window should be created with the +W_WIN_NO_REDRAW attribute). + + +Unless the window is created with the w_wIN_No_REDRAw attribute, the window server invalidates the target +rectangle in the window after it has copied a bitmap (it also invalidates any parts of the previous rectangle +that is not covered by the new bitmap). The resulting redraw event is intended to prompt the client to draw +on top of the bitmap. If you do not intend to draw on top of the bitmap, you should create the window with +the w_wIN_No_REDRAW attribute. + + +As well as the changes that occur as the bitmaps in the sequence are cycled through by the window server, +you can make all manner of changes to the bitmaps themselves - for example, switching bitmaps and +drawing to them. + + +5The limit derives from the requirement to fit the sequence in the client-side buffer. + + +1-21 + + +WINDOW SERVER REFERENCE + + +In version 4 of the window server, bitmap sequences are, by default, drawn to the normal (black) plane +only and the grey plane will display the appropriate grey background as specified in the call to +wCreateWindow. However, there is nothing to prevent the client from drawing to the grey plane as a result +of a redraw event. + + +A member of a bitmap sequence can be made to appear grey by setting ws_wIN_BITMaAP_GREy for that +member in the call to wSetWinBitmap in which case the normal plane will display the appropriate normal +background. + + +If bitmap sequences are required which make use of both black and grey, then sprites (discussed later) +may be used instead. + + +Using an attached bitmap to avoid redraws + + +If you set up a no-redraw window with an attached bitmap sequence consisting of a single bitmap that fills +the window, you can draw to the bitmap and have that bitmap copied to the window by calling +wiInvalidateWin to invalidate the window. For flicker-free operation the window background should be +set to W_WIN_BACK_NONE. + + +In some cases, this may be more efficient than using backed-up windows (where everything is drawn +twice). + + +In version 4 of the window server, as mentioned before, the bitmap can be made to appear grey by setting +WS_WIN_BITMAP_GREY in the call to wSetWinBitmap. + + +The following program uses the technique described above and works on all versions of the window +server. + + +#include +#include + + +#define NWS_HANDLE 0 +#define MAIN_WIN 1 + + +GLDEF_D WSERV_SPEC wspec; + +GLDEF_D UINT gcid; + +GLDEF_D UINT wid; + +GLDEF_D P_POINT winsize={160, 80}; +GLDEF_D WS_WIN_BITMAP bitseq; + + +GLDEF_C VOID CreateBitmap (VOID) +{ +G_GC gc; + + +bitseq.bitmap=gCreateBit (0, &winsize) ; +bitseq.pos.x=0; + +bitseq.pos.y=0; + +bitseq.rect.tl.x=0; +bitseq.rect.tl.y=0; +bitseq.rect.br=winsize; +bitseq.mode=G_TRMODE_REPL; +gc.style=G_STY_BOLD|G_STY_DOUBLE; +gcid=gCreateGC (bitseq. bitmap, G_GC_MASK_STYLE, &gc) ; +gClrRect (&bitseq.rect,G_TRMODE_CLR) ; +} + + +GLDEF_C VOID CreateWindow (VOID) + + +{ +W_WINDATA windata; + + +windata.flags=W_WIN_NO_REDRAW; +windata.extent.tl.x=0; +windata.extent.tl.y=0; +windata.extent.width=winsize.x; +windata.extent.height=winsize.y; +windata.background=W_WIN_BACK_NONE; + + +1-22 + + +1 INTRODUCTION + + +wid=wCreateWindow (0,W_WIN_NO_REDRAW + +| W_WIN_EXTENT + +| W_WIN_BACKGROUND, &windata, MAIN_WIN) ; +wSetWinBitmap (wid,1, &bitseq) ; +wiInitialiseWindowTree (wid) ; + + +} + + +GLDEF_C INT main(VOID) +{ +WS_EV event; +P_RECT box; +TEXT bb[32]; + + +wConnect (&wspec, NWS_HANDLE, W_CONNECT_PRIORITY) ; +CreateBitmap(); +CreateWindow(); +box=bitseq.rect; +p_insrec(&box,1,1); +gDrawBox (&box) ; +winvalidateWin (wid) ; +p_insrec(&box,1,1); +for (77) +{ +wGetEventWait (&event) ; +if (event .type==WM_KEY) +{ +p_atos(&bb[0],"Key code: %d",event.p.key.keycode) ; +gPrintBoxText (&box, 50,G_TEXT_ALIGN_CENTRE, 0, &bb[0],p_slen(&bb[0])); +winvalidateWin (wid) ; +if (event.p.key.keycode==W_KEY_RETURN) +break; + + +} +return (0); + + +} +Sprites + + +In version 4 of the window server a window may be given an animated image by attaching a sprite to the +window. + + +A sprite is created at a specified position within the window and the animation produced by creating a +sequence of up to 13 bitmap sets attached to the sprite by calling wcreatesSprite. The bitmap sets and the +position of the sprite in the window can be changed by calling wset sprite; the sprite itself can be freed by +calling wrree. + + +Each bitmap set specifies: + + +e up to three source bitmaps for the normal plane, i.e. one for each of the three possible transfer +modes (set, clear and invert) + + +e up to three source bitmaps for the grey plane, i.e. one for each of the three possible transfer +modes (set, clear and invert) + + +e the position of the bitmaps relative to the sprite +e the time to wait (in tenths of a second) before displaying the next bitmap set + + +Unlike the pre-version 4 animated sequences, a sprite is not displayed as part of the window background. +The window server takes care of saving and restoring the contents of the underlying display even if this +changes during the sprite's existence. This can give the impression that the animation ‘floats’ above the +underlying display. + + +When the sprite is created, setting the flag w_spRITE_CLIP_CHILDREN allows child windows of the window +to which the sprite is attached, to clip the sprite. If the flag is not set, the sprite can only be clipped by the +edges of the window to which it is attached or by other non-related windows. + + +If the sequence contains a single bitmap set, the resulting display is not animated. + + +Only one sprite may be created for each client of the window server. + + +1-23 + + +WINDOW SERVER REFERENCE + + +Redrawing + + +Windows that are not backed up by bitmaps or an attached bitmap or are not created as no-redraw +windows must be redrawn as well as drawn. + + +If you intend to avoid redraws by using only backed-up windows, no-redraw windows and windows that +are drawn from bitmap sequences, none of this section applies. + + +Redraw events + + +A window should be redrawn by a client when it receives a redraw event from the window server (after +calling wGetEventWait, wGetEvent Or wGetEventSpecial). + + +A redraw event indicates +e the window to be redrawn +e arectangle within the window that needs to be redrawn +The rectangle is often ignored (especially for simple windows) and the whole window is drawn instead. + + +The window server keeps an update region for each window to record that part of a window that is +invalid. When the update region is not empty and the event queue is otherwise empty, the window server +will complete a client's call to wcetEventWait, wGetEvent Or wGetEventSpecial with a redraw event. + + +Note that user input events and foreground/background change events are effectively delivered at a higher +priority than redraw events. This is sometimes desirable and sometimes not. + + +Note also that, unlike other events, the sending of a redraw event by itself does not clear or otherwise +reduce the update region (this is described below). The window server will continue to send redraw events +indefinitely® until the update region is reduced by the client validating a part or the whole of the region - +normally by the client calling wBeginRedraw (or a variant thereof), as described below. + + +Update region + + +The update region is similar to the drawing region in that it consists of a list of rectangles that are used to +clip graphics output. Whereas the drawing region is used for drawing, the update region is used for +redrawing. The update region is also used to generate redraw events as described above. + + +The drawing region describes that part of the window that is visible. The update region describes that part +of the window that is both visible and invalid. + + +The window server automatically adds to a window's update region when: +e the window is first created +e the window's size is increased + + +e a previously obscured part of the window is exposed by changes (of position, size, front to back +ordering or visibility) to a window that previously obscured it + + +e the contents of a window is scrolled using wscrollRect or wScrollWin + + +A backed-up window always has an empty update region because the window server copies the data from +the backup bitmap rather than add to the update region. + + +Invalidating rather than drawing + + +The client can itself add to the update region by invalidating a part of the window or all of the window by +calling wInvalidateRect or wInvalidateWin respectively. + + +It is often simpler for an application (at the expense of performance) to invalidate a part of a window or +the whole of the window rather than draw to it.’ Invalidating causes the window server subsequently to +send redraw events to the client. + + +6A client that just ignores redraw events will loop indefinitely and "hog" the processor. + + +7If a window is not visible or is substantially obscured, invalidating can actually be more efficient than +drawing. However, this occurs rarely in practice. + + +1-24 + + +1 INTRODUCTION + + +The update region of a window is automatically reduced by the window server as a window becomes +obscured by other windows. However, in practice, the update region is normally reduced (partially or +wholly) before the client draws or redraws to it. + + +Validating before drawing or redrawing + + +You always automatically validate before redrawing (by calling a variant of wBeginRedraw) and you would +normally also validate before drawing (by calling wvalidateWin Of wvalidateRect). + + +As well as reducing the update region, validating can also prepare the background, depending on the +value of the background window attribute, as follows: + + +W_WIN_BACK_CLR prior to version 4 of the window server, clear the pixels in the window (this is +the default) + + +in version 4, clear the pixels in the normal (black) plane (this is the default) +W_WIN_BACK_SET prior to version 4 of the window server, set the pixels in the window +in version 4, set the pixels in the normal (black) plane +W_WIN_BACK_NONE do nothing; in version 4, this is specific to the normal (black) plane +In version 4 of the window server the above attributes can be OR'd with one of the following: + + +W_WIN_BACK_GREY_CLR Clear the pixels in the grey plane + + +W_WIN_BACK_GREY_SET set the pixels in the grey plane + + +W_WIN_BACK_GREY_NONE do nothing; specific to the grey plane + + +The w_wIn_Back_cur background is the easiest to deal with and is often used - particularly for simple +windows or for windows with no grey. For flicker-free drawing or redrawing, use w_WIN_BACK_NONE (and +W_WIN_BACK_GREY_NONE if using grey) and then program such that every pixel is covered when the +drawing code executes (for example, using gPrintBoxText rather than gPrintText). + + +Drawing +You normally draw to a window when the data it is displaying has changed (say as a result of user input). + + +When drawing a particular rectangle of a (non-backed-up) window, a client should call wvalidateRect +before commencing the drawing. When drawing the whole window (which is more common), the client +first validates the whole window by calling wvalidateWin. + + +You must validate before drawing if you are relying on the w_wIN_BACK_CLR, W_WIN_BACK_SET, +W_WIN_BACK_GREY_CLR Of W_WIN_BACK_GREY_SET Window attribute to prepare the background. + + +If you are drawing to a window with a w_wIN_BACK_NONE Or W_WIN_BACK_GREY_NonE background, you need +not validate before drawing to the window. If you don't validate, you will not preempt any redraw event +when the same area happens to be invalid at the time and the same image may subsequently be redrawn +unnecessarily (although, frankly, this is unlikely to be noticed by any user). + + +When drawing to a window, a client may use a permanent or a temporary graphics context. (Note that all +graphics output is directed at a current graphics context.) + + +When using a temporary graphics context, the calls to graphics output functions would be enclosed by +calls to gcreateTempcc and gFreeTempcc. If there is no requirement to change the default initial values of +the graphics context, you would use gcreateTempcco in place of gcreateTempGc. + + +When using a permanent graphics context (which was previously created and assigned to the window by a +call to gcreateGc OF gCreateGco), you would typically use gset cc or gsetcco to make the appropriate +permanent graphics context current before drawing. + + +Redrawing + + +While drawing is clipped to the window's drawing region, redrawing is clipped to the window's update +region (for appearance and efficiency reasons). + + +The client informs the window server that it is redrawing rather than drawing by enclosing the graphics +output function calls between calls to weeginRedraw and wEndRedraw. As well as informing the window +server that the client is about to redraw rather than draw, the call to wBeginRedraw also validates that +rectangle of the window (specified as a parameter to wBeginRedraw). + + +As with drawing, a client that is redrawing to a window may use a permanent or a temporary graphics +context. + + +1-25 + + +WINDOW SERVER REFERENCE + + +There are no fewer than six variants of wBeginRedraw which vary according to whether a temporary +graphics context is created (and, if so, whether it is to be altered from its default settings) and whether a +part or the whole of the window is being redrawn. The full set is as follows: + + +wBeginRedraw to redraw a part of the window using an independently created temporary or +permanent graphics context + + +wBeginRedrawWin to redraw the whole of the window using an independently created temporary +or permanent graphics context + + +wBeginRedrawGC to redraw a part of the window using a temporary graphics context that is +created and initialised with specified values + + +wBeginRedrawGC0 to redraw a part of the window using a temporary graphics context that is +created with default initial values + + +wBeginRedrawWinGC to redraw the whole of the window using a temporary graphics context that is +created and initialised with specified values + + +wBeginRedrawWinGC0 to redraw the whole of the window using a temporary graphics context that is +created with default initial values + + +When a begin redraw function is used to simultaneously create a temporary graphics context, the call to +wEndRedraw automatically frees it. + + +Note that if you mistakenly enclose the graphics output function calls between calls to wBeginRedraw and +wEndRedraw when drawing (rather than redrawing in response to a redraw event), the drawing will +probably not appear since it will be clipped to the update region (which is most likely to be null). + + +Going deaf + + +A client that owns one or more windows with invalid areas and which is not requesting events from the +window server is said to have "gone deaf". + + +An application goes deaf because it is performing a task that takes an extended time to complete. +Examples of such extended tasks are: + + +e loading or saving a large file (or some other processing of a large file) + +e astalled write to the parallel port (say, because the printer is out of paper) +e computing PI to a thousand decimal places + +e a bug that has caused the process to "hang" in an indefinite loop + + +Applications that process redraw events have a responsibility to process them within a reasonable time. If +this is not done, the screen may contain images drawn by some other client (which is very confusing to the +user). + + +With a window server in a preemptive multi-tasking operating system, deaf clients need not block the user +from switching to another task (as happens in non-preemptive multi-tasked window environments such as +Microsoft Windows and others, where a deaf application typically leads to an unwelcome mouse icon such +as an hour glass, a watch or, arguably more positively, a bee). With the window server handling the task +switch key or keys, an aberrant application task that has hung does not require a system reset - the user +can task to a suitable system application and terminate the task. + + +To make it easier to diagnose when a client has gone deaf, the window server has mechanisms to detect +deaf clients. On the HC, $3, S3a and Workabout, task switching to a deaf client will cause the "hung up" +status window to be presented. On the MC, the invalid areas are eventually covered with a grey pattern. +From the user's point of view, exposing a deaf client is preferable to leaving the debris of some other +client's windows which may lead the user to blame the wrong application. + + +The window server does not detect a client which is reading redraw events but discarding them. + + +Applications can avoid going deaf within potentially blocking functions such as a write to a parallel port +by performing such operations asynchronously - as described in chapter Asynchronous Requests and +Semaphores in the PLIB Reference manual. The same chapter also describes how to use p_ioyield to poll +at intervals for the receipt of a redraw message (after using the asynchronous wGetEvent or + +wGetEvent Special) while performing an extended process. Rather than polling, it is worth considering +using p_execc to create a transient sub-process to perform an extended task and to use p_logona to be +signalled when the process completes (as described in the chapter Processes and Inter-Process Messaging +in the PLIB Reference manual). + + +1-26 + + +1 INTRODUCTION + + +Applications that are structured to present percentage done indicators or a cancel option (or preferably +both) while performing an extended task are well structured to handle redraws and can easily avoid going +deaf. In any case, applications that are deaf (and dumb) to the user for extended periods are generally not +welcomed by them. + + +Redraw priority + + +Although redraw events always have a lower priority than user input events and background/foreground +events, there is a two-level redraw priority that operates between windows. + + +By default, windows are created at the lower priority and certain windows may be selected to receive their +redraw events before the crowd by specifying the w_win_pRiortty bit to wcreateWindow OF wSetWindow. +This is very much fine tuning, though. + + +More about windows + + +Creating and initialising a window system + + +A window is created by calling wcreateWindow where you specify such things as the parent window, the +position and size of the window (in the parent's coordinate system), whether the window is backed-up by +bitmaps and so on. + + +When sibling windows are created, they are created in front of any existing siblings (this is only +significant when sibling windows overlap - they often don't). You can set and sense the front-to-back +position of a window in its sibling list using wwindowPosition and wGetWindowPosition respectively. + + +Each successful call to wcreateWindow returns a window ID. The ID is used subsequently to refer to that +window. + + +After a successful return from wcreateWindow, the window is just a dormant data structure in the window +server's data segment with no visibility on the screen. You can't draw to the window and you won't get any +redraw events (or any mouse events if there is a pointing device) until the window is initialised by calling + + +wInitialiseWindowTree. + + +As its name suggests, wInitialiseWindowTree initialises not just the window but all its descendants as +well. In practice, a tree of windows is often created as a logical whole and it is desirable to activate the +whole tree at once by calling wInitialiseWindowTree (passing it the window ID of the parent) after + +having successfully set the tree up from the parent window down by successive calls to wcreatewindow. + + +The above is not meant to suggest that all new window systems take the form of a single tree with a single +parent (although this is the more common case). It is quite possible for the window system to be created to +consist of a number of (say sibling) windows or window trees. In such a case, you would still create the +whole system with successive calls to wcreateWindow and then make multiple calls to +wInitialiseWindowTree to initialise the system. + + +Note that wcreateWindow can fail through lack of system memory but wInitialiseWindowTree cannot. +When creating a window system you must be careful to destroy any partially created system should a call +to wCreat eWindow fail. + + +Destroying a window system + + +Just as windows are created a tree at a time, windows are, in general, destroyed a tree at a time by calling + + +wCloseWindowTree. + + +A client that builds window systems would keep at least the window IDs of the windows in client-side data +structures. In the client's data space, the data structures that contain the window IDs are unlikely to be +related in the same tree structure as the windows are in the window server. Where this is the case, it may +not be convenient for the client to recover the window side relationships and destroy windows a tree at a +time (effectively bottom up) when destroying a window system. If a client uses its relationships (which are +probably tree-like but a different tree) to destroy a window system, some windows would be destroyed +more than once (because wcloseWindowTree has to destroy any descendants as well as the specified +window). + + +In recognition of this problem in destroying window systems, the window server does not consider it an +error if a window is destroyed more than once. + + +This does (quite reasonably) assume that windows systems are destroyed without any intervening window +creations. + + +1-27 + + +WINDOW SERVER REFERENCE + + +Event sources other than the window server + + +You need only read this section if you are implementing a program that responds to event sources other +than just the window server (and therefore the program is using one of the asynchronous functions +wGetEvent Of wGetEventSpecial rather than wGetEventWait). + + +This section assumes familiarity with asynchronous requests - as described in the chapter Asynchronous +Requests and Semaphores in the PLIB Reference manual. + + +When responding to window server events that are requested asynchronously using wGetEvent or +wGetEvent Special, you should completely process a window server event (after returning from p_iowait +and having established that wcetEvent or wGetEvent Special has completed) before calling either +wGetEvent Of wGetEvent Special again to request the next event. + + +Bearing in mind the multi-tasking nature of the system and the fact that the window server runs at a +higher priority than its clients, it is quite possible for the request made by a call to wGetEvent or +wGetEvent Special to complete while responding to an event from a source other than the window server +(for example, the expiry of a timer or the receipt of some data from the serial port). + + +In particular, if one or more windows are directly destroyed in response to a non-window server event +there is the possibility that the next window server event (a redraw event say) will relate to a window that +has already been destroyed. + + +To guard against this possibility, you should not destroy a window or a window system directly in +response to a non-window server event but use wcancelGetEvent to instruct the window server to send the +caller a WM_CANCELLED event and then respond to the wM_CANCELLED event as you would otherwise have +responded to the non-window server event. + + +After a call to wcancelGetEvent, the window server delivers the w4_cANCELLED event at the highest +priority - any other events waiting in the window server client event queue are overtaken. The only +window server event WM_CANCELLED can't overtake is one that has already been delivered. + + +Visibility of windows + +A window is invisible when: +e it has been created (using wcreateWindow) but not yet initialised (using wInitialiseWindowTree) +e it has been made invisible by a call to wMakeInvisible; + + +e the window was created with the w_wIN_FOREGROUND_ONLY attribute set and belongs to a client +that is currently a background client (this case only applies to large screen versions of the +window server) + + +Note that wInitialiseTree, wMakeInvisible and W_WIN_FOREGROUND_ONLY all propagate their effect to +descendant windows. + + +After being initialised, a window is marked as visible. Once a window tree has been made invisible using +wMakeInvisible, it may be made visible again by calling wMakeVisible. + + +A call to wMakeVisible or wInitialiseWindowTree does not necessarily make all descendants visible +since wMakeInvisible may have been applied to a descendant. + + +The window server treats windows that are invisible as follows: +e if the window is backed-up, any drawing to it is drawn only to the backup bitmap(s) +e invalidating a window using wInvalidateRect or wInvalidateWin has no effect + + +e¢ windows behave as if they do not exist with respect to mouse input (this only applies when there +is a pointing device) + + +Scrolling + + +The contents of a window may be scrolled by a horizontal or vertical direction or a combination of the two +using wScrollWin Of wScrollRect. + + +Both these functions are better understood in terms of rectangle copying rather than scrolling where: + + +wScrollRect copies a source rectangle in a window to a rectangle of the same size in the +same window but displaced. + + +wScrollWin works just like wScrol1Rect except that the source rectangle is defined by the +boundaries of the window offset, in the opposite direction, by the amount of the +scroll. This is what is normally used to scroll the contents of a window. + + +1-28 + + +1 INTRODUCTION + + +Both functions copy only those parts of the source rectangle that are both visible and valid. This means +that the copy excludes the following from the source rectangle: + + +e those parts that are in the update region +e those parts that are obscured or clipped by other windows +e those parts that are beyond the boundaries of the window + + +Although these parts are not copied, their existence causes the corresponding region of the target +rectangle to be invalidated. + + +If the window is a backed-up window, the copy is also applied to the backup bitmap(s). For a backed-up +window: + + +e the update region is always empty +e those parts that are obscured or clipped can be recovered from the backup bitmap(s) +e those parts that are beyond the boundaries of the window are cleared. + + +Since these functions access the same window server operations that are applied when a window is moved +using wSetWindow, the above comments about not copying invalid regions applies to window moving too. +If you wish to simultaneously move and change the appearance of a window you should use +wInvalidateWin to invalidate those parts that are to change before using wSetwindow to move the window. + + +Continuous scrolling + + +The function wScro11win Is often used to scroll the contents of a window in response to user input (such +as down arrow key presses, for example). Calling this function necessarily introduces an invalid area at +the upwind border (or borders) of the direction of scroll. + + +If the window is a backed-up window, these areas are automatically cleared by the window server by the +wScrollWin operation and would subsequently be drawn by the client as part of the scroll processing. + + +If the window is not backed-up by a bitmap, the window server invalidates those areas brought in from +outside the window and there is the temptation to leave it to the redraw event handling to draw these +areas. + + +However, this is not good practice because redraw events are delivered only when there is no user input +and in the quite typical case where the user holds down the key that is causing the scroll, the redraws are +not processed until the user releases the key. This means that the screen rapidly fills with a copy of the +image that was at the upwind border of the scroll and the window is only redrawn with something sensible +when the key is released. + + +When using non-backed-up windows you should program as for backed-up windows and calculate the +area that needs to be drawn after the scroll and then validate and draw it. + + +Text cursor + + +A client can nominate at most one window at a time to contain a text cursor (which is optionally flashing) +by calling wrextcursor. The text cursor can subsequently be moved from one window to another by +calling wrextCursor again. To remove the text cursor from the window that contains it, you call +wEraseTextCursor. + + +The cursor is specified as a rectangle which is, in principle, xored with whatever is underneath it. +Applications typically define a text cursor as a vertical line in between characters, a horizontal line +underneath characters or a block cursor that fits over characters. + + +In version 4 of the window server, the cursor can be made to appear grey on those machines that support +grey such as the S3a and Workabout. + + +The window server handles the flashing of the cursor and ensures that it does not interfere with any +drawing or redrawing in its vicinity. + + +On large screen versions of the window server where the windows of more than one client are on the +screen at a time, the window server automatically ensures that only the foreground text cursor is visible. + + +1-29 + + +WINDOW SERVER REFERENCE + + +Bitmaps +Drawing to the screen from a bitmap + + +A bitmap is a piece of off-screen memory that is organised in the same way as the screen bitmap. A +bitmap can rapidly be copied to a window for display using one of: + + +gCopyBit to copy a rectangle from a bitmap to a given position in the current graphics +context +gDrawBit to copy a rectangle from an open bitmap file to a given position in the current + + +graphics context. This is available in version 4 of the window server. + + +gFillPattern to fill a rectangle in the current graphics context with repeated copies of a +bitmap +wSetWinBitmap to copy bitmaps to a window at specified time intervals from a sequence of + + +bitmaps (as described earlier) +All the above functions can copy a bitmap in one of four transfer modes: +G_TRMODE_REPL where bits in the source pattern replace corresponding bits in the destination. + + +G_TRMODE_SET where Is in the source pattern set corresponding bits in the destination (Os in +the source do not change corresponding bits in the destination). This would +normally be used to copy a bitmap on to a previously cleared destination. + + +G_TRMODE_CLR where Is in the source pattern clear corresponding bits in the destination (Os in +the source pattern do not change corresponding bits in the destination). This +would normally be used to copy a bitmap on to a previously set bitmap. + + +G_TRMODE_INV where Is in the source pattern toggle corresponding bits in the destination (Os +in the source pattern do not change corresponding bits in the destination). This +is suitable for copying over an existing pattern and may be reversed by a second +identical application. + + +Creation and storage of bitmaps + + +A bitmap is created uninitialised by calling gcreateBit or (more likely) it is loaded from a file that +contains one or more bitmaps using gOpenBit or gGetBit. A bitmap is freed using wrree. + + +The function gSetOpenAddress may be used immediately before gopenBit or gGet Bit to load the bitmap +from anywhere within the file (typically used to load a bitmap which has been embedded into the program +file). + + +In version 4 of the window server, gInitBit is used to open a multiple bitmap file ready for calls to +gGetBit OF gDrawBit. + + +When a bitmap is successfully created, gcreateBit, gopenBit and gGetBit return a bitmap ID (which is +subsequently used to reference the bitmap). + + +The window server keeps a built-in ROM-based grey bitmap (with a chequerboard pattern). This may be +accessed with the bitmap ID ws_s1Tmap_crey. The bitmap has size WS_BITMAP_GREY_S1ZE_X by +WS_BITMAP_GREY_SIZE_Y. + + +Note that version 4 of the window server supports grey for those machines such as the Series 3a that can +display true grey. + + +When a bitmap is created, it may be stored in the window server's data space or in a named memory +segment (named memory segments are described in the Memory Allocation chapter of the PLIB Reference +manual). + + +The window server automatically places bitmaps that are larger than 2K in named memory segments. You +can request that a bitmap be stored in a named segment rather than the window server's data segment +(regardless of the size). + + +A bitmap that is in a named memory segment can be accessed directly by the client using p_sgcopyfr and +p_sgcopyto (described in the Memory Allocation chapter of the PLIB Reference manual) or otherwise. + + +1-30 + + +1 INTRODUCTION + + +Drawing to bitmaps + + +Like windows, bitmaps can be drawn to using any of the window server graphics output functions. + + +However, unlike windows there is no drawing region or update region (so there is no such thing as +validating before drawing). Drawing is clipped only to the limits of the bitmap. + + +Bitmaps that are loaded from a file are typically read-only (which also makes them shareable). If you are +going to draw to a loaded bitmap, you should specify the ws_B1T_wRITE attribute when you call either +gOpenBit OF gGetBit to load the bitmap. + + +Graphics output is directed at a current graphics context (which may be assigned to a window or a +bitmap). As with drawing to a window, a program may use a permanent or a temporary graphics context. + + +When using a temporary graphics context, the calls to graphics output functions would be enclosed by +calls to gcreateTempGc and gFreeTempcc. If there is no requirement to change the default initial values of +the graphics context, you would use gcreateTempcGco in place of gcreateTempGc. + + +When using a permanent graphics context (which was previously created and assigned to the bitmap by a +call to gcreateGc Or gCreateGco), you would typically use gset cc or gsetcco to make the appropriate +permanent graphics context current before drawing. + + +Bitmap files + + +Bitmap files (which normally have the file name extension .pic) may be created in one of the following +ways: + + +e by saving the contents of a bitmap, a screen or a backed-up window using gsSaveBit (which saves +the whole bitmap) or gsaveRect (which saves a rectangle of the bitmap). In version 4 of the +window server, if the screen or a backed up window uses grey, saving either of them will create a +double bitmap. + + +e by saving the contents of a bitmap, a screen or a backed-up window using gSavemultiBit (which +saves the whole bitmap) or gsaveMultiRect (which saves a rectangle of the bitmap). If the screen +or a backed up window uses grey, saving either of them will create a double bitmap. Available in +version 4 only. + + +e by converting a PCX file using the wspcx program (which runs on a PC). Many PC-based +graphics applications are able to produce PCX files. + + +e by saving the whole screen to a file by pressing SHIFT-CTRL-PSION-S. This is not possible on +machines without a CTRL key (such as the HC). + + +Using wspcx + + +The wspcx.exe program (which is placed in the \sibosdk\sys directory by the installation) may be used to +convert PCX files to window server bitmap files and vice versa and also to link a number of .pic files into +one .pic file. + + +Where the .pcx file contains more than two colours, the following 'rules' apply: +¢ white is converted to white +e black is converted to black +e all other colours are converted to grey + +On conversion: + + +e If a.pcx file is marked as being black and white only, then the .pic file will contain a single +bitmap. + + +e =Ifa.pcx file is marked as being in colour, then the .pic file will contain a double bitmap, where +the first bitmap represents the normal plane and the second represents the grey plane. + + +e If a.pcx file is marked as being in colour but only contains an image using the black and white +"colours", then the .pic file will still contain a double bitmap. + + +1-31 + + +WINDOW SERVER REFERENCE + + +To convert a .pcx file to a window server .pic bitmap file, use: +wspcx -p [-i] [-o] [-s] [-x] + + +where the -p indicates PCX to PIC conversion and is the name of file to be converted (which is +assumed to have a .pcx extension unless otherwise specified). The remaining optional parameters are: + + +-i Invert the bitmap while converting. + + +-o Specifies the output file name and directory (otherwise it is the same as the +input file name with a .pic extension). + + +-x Clip or expand the bitmap to the specified size (in pixels). If expanded, the +-y bitmap is padded out with blank space. +-s Suppresses output messages. + + +For example: + +wspcx -p -i sausage.pcx +produces the inverted sausage.pic. +To convert from a .pic file to a .pcx file, you use: +wspcx -w [-i] [-o] [-s] +To just invert the bits in a .pic file without any other conversion, you use: +wspcx -i [-o] [-s + + +To link a number of .pic files into one output .pic file, you use: + + +wspcx -l [-o] [-s + + +where is a text file (with extension .p/k) that lists the .pic files to be linked to produce a file with +the same name as the .p/k file but with the .pic extension. A C header file (with extension .ph) is also +generated that contains #defines for the index number and dimensions of each component bitmap. + + +Capturing the screen to a bitmap file + + +Pressing SHIFT-CTRL-PSION-S on an MC, S3, S3a or a Workabout saves the current screen to a file called +screen.pic in the current path of the window server. Any existing file of the same name is replaced. + + +In practice, the current path of the window server on a SIBO machine is always LOC::M:\ (it is defined +when the window server process is started - well before you have any chance of influencing it). + + +However, if an environment variable with the name $WS_SD exists, the window server uses its value to +open the file to be created. For example, running the following program: + + +#include + + +GLDEF_C INT main(VOID) +{ +p_setenv ("SWS_SD", "B:\\SCREEN.PIC"); +return (0); + + +} +subsequently causes the screen dump to be written to the root directory of the local B: drive. + + +If the save fails for any reason (such as disk full), the file is not produced and no notification of the failure +is given. + + +You can use this behaviour to disable the SHIFT-CTRL-PSION-S screen dump key by setting up $WS_SD to +contain an illegal file specification. For example, just inserting the following line of code: + + +p_setenv("SWS_SD",""); + + +disables the screen dump key. + + +1-32 + + +1 INTRODUCTION + + +Screen capture program for the HC + + +The following program illustrates how you can construct your own screen capture program on an HC, or +an $3. The program will work on an S3a or Workabout provided that the screen does not contain grey. To +capture grey, the program code needs to be changed in order to capture the grey plane as well as the +normal plane (see gPeekBit in the Graphics Output chapter and any reference manual on PCX file +formats). + + +The program has a "quick and dirty" user interface constructed from the simple console functions +p_printf, p_getch and p_get1 (described in the PLIB Reference manual). The first call to p_printf +automatically connects to the window server and must precede the call to wcapturekey. + + +To save a screen (by default to rem::screen.pic), you task to the application and press PSION+S. + + +/* +SCAPT.C - Capture the screen to a file +*/ + + +#include +#include + + +GLDEF_C VOID main (VOID) + + +INT ret; +TEXT name[64]; + + +p_scpy (éname[0],"rem::screen.pic") ; +p_printf("\£"); /* connect to window server */ +wCaptureKey (W_SPECIAL_KEY|'s',0,0); +for (77) +{ +p_printf("\fCapture file is\r\n%s", &name[0]); +p_printf("\nE to Exit\r\nN to set file Name\r\nPsiont+S to capture"); +switch (p_getch() ) +{ + + +case 'e';: + +case 'E';: +p_exit (0); + +case 'n': + +case 'N': +p_getl("Name:", &name[0], 64); +break; + + +case W_SPECIAL_KEY|'s': +ret=gSaveBit (&name[0],0); +if (ret) +p_notifyerr(ret,"Screen save failed",0,0,0); +break; + + +} +Capturing the screen directly to a PCX file + + +It isn't that difficult to generate a PCX file directly from the screen or any other bitmap. The module +pcxsave.c (supplied in \sdkdoc\demo) contains the code which supports the function pcxScreenSave that +saves the entire screen in PCX format of a given name. + + +The source of pcxsave.c is as follows: +7. * +Save the screen to PCX file + + +x7: + + +#include +#include + + +#define BUFLEN 256 + + +GLREF_D WSERV_SPEC *wserv_channel; + + +1-33 + + +WINDOW SERVER REFERENCE + + +LOCAL_D VOID *fcb; + +LOCAL_D UBYTE *pbuf; +LOCAL_D UBYTE *pobuf; +LOCAL_D UBYTE obuf [BUFLEN]; + + +LOCAL_C VOID FlushBuffer (VOID) + + +f_write(fcb, &0buf[0],pobuf-&o0buf[0]); +pobuf=ésobuf [0]; + + +LOCAL_C VOID putb(INT b) + + +*pobuf++=b; + +if (pobuf==&0buf [BUFLEN] ) +FlushBuffer (); + +} + + +LOCAL_C INT rev(INT dat) +{ + + +INT i; +INT rdat; +rdat=0; +for (i=0;i<8;i++) +rdat |=((dat>>i) &1)<<(7-i); + + +return (rdat*0Oxff); + + +} + + +LOCAL_C VOID WritePCXLine(UBYTE *buf,UINT len) +{ +UBYTE *p; +UINT end; +UINT count; +INT byte; + + +p=buf; +byte=*ptt; +count=1; +do + + +{ +end= (p==(&buf[0]+len)); +if (byte==*p && count<0x3f && !end) +{ +count++; +ptt; +} +else +{ +byte=rev (byte) ; +if (count>1 || (byte&0xC0)==0xC0) +putb (count+0xC0) ; +putb (byte); + + +byte=*ptt; +count=1; +} + +} while (!end); + + +1-34 + + +1 INTRODUCTION + + +LOCAL_C VOID WriteHeader (TEXT *name,UINT width,UINT height,UINT bytewid) +{ +struct +{ +UBYTE manuf; +UBYTE hard; +UBYTE encod; +UBYTE bitpx; +P_RECT rect; +WORD hres; +WORD vres; +UBYTE clrma[48]; +UBYTE vmode; +UBYTE nplanes; +WORD bplin; +UBYTE padding[60]; +} header; + + +f_open (&fcb, name, P_FREPLACE|P_FSTREAM|P_FUPDATE) ; +p_bfil(&header, sizeof (header) ,0); +header.manuf=10; + +header.hard=3; + +header.encod=TRUE; + +header. bitpx=1; +header.rect.br.x=width-1; +header.rect.br.y=height-1; + +header. hres=640; + +header.vres=480; + +header.nplanes=1; + +header .bplin=bytewid; +f_write(fcb, &header, sizeof (header) ) ; + + +} +#pragma save, ENTER_CALL + + +LOCAL_C INT WritePCXFile (TEXT *name) +{ +UINT len; +P_POINT size; +P_POINT line; + + +size=wserv_channel->conn.info.pixels; +len=((size.x+15)>>3) &~1; +WriteHeader (name, size.x,size.y,len); +pbuf=f_alloc(len) ; +line.x=0; +for (line.y=0;line.y +#include + + +GLREF_D TEXT *DatCommandPtr; +GLREF_C INT pcxScreenSave (TEXT *name) ; + + +LOCAL_D WSERV_SPEC wSpec; + + +GLDEF_C INT main(VOID) + + +INT ret; +TEXT *pc; +TEXT name [P_FNAMESIZE]; + + +pc=p_skipch (DatCommandPtr) +1; +if (*pc) +pc=p_skipwh (pct1); +ret=p_fparse (pc, "REM: :SCREEN.PCX", &name[0],NULL) ; +if (!ret) +{ +wConnect (&wSpec, 0,W_CONNECT_AT_BACK) ; +ret=pcxScreenSave (&name[0]); +p_sound(1,512); +} +return (ret); + + +} +To build scapt.img from scapt.pr, scapt.c and pcxsave.c, just enter: +TSC/M SCAPT + + +You might consider using Tscx rather than Tsc. See the Installation chapter of the General Programming +Manual for more information. + + +The program scapt.img is designed to be run on the target from MCLINK on the PC. In preparation, copy +scapt.img to the root directory of the default drive on the target (an S3 say). To capture the screen to say +fred.pcx in the current directory of your PC, start MCLINK and enter: + + +RUN SCAPT FRED + + +The target machine beeps faintly (from the call to p_souna) when the screen has been saved. If you omit +the FRED, you get screen.pcx (from the related file name in the call to p_fparse). + + +The physical structure of bitmap files and bitmaps + + +Bitmap files start with a PICc_HEAD struct, defined in wlib.h as: + + +typedef struct +{ +P_FSIG sig; +UWORD count; +WS_PIC_HEADER wspic; +) PIC_HEAD; + + +1-36 + + +1 INTRODUCTION + + +The first member of this struct is a p_rstc header: + + +typedef struct +{ +TEXT app_id[3]; /* application ID */ +UBYTE chk_sum; /* application ID checksum */ +UBYTE file_vn; /* file version number */ +UBYTE app_vn; /* application version number */ +} P_FSIG; + + +where the p_Fsic struct is defined in p_file.h. For a bitmap file, the appropriate values for the p_rsic +header are: + + +P_FSIG sig = {"PIC",'PY+'I'+'C';,0n30;, 0x30}; + + +The p_rstc header is followed by a worp count of the number of bitmaps in the file. This is then followed +by an array of that many ws_PICc_HEADER structs. A ws_PIC_HEADER Struct is defined in wiib.h as follows: + + +typedef struct +{ +UWORD checksum; +P_POINT size; +UWORD byte_size; +ULONG offset; +} WS_PIC_HEADER; + + +The members of ws_Ppic_HEADER are as follows: + + +checksum is calculated by applying the p_crc function (described in the PLIB Reference +manual) to the bitmap that is referenced by the ws_p1c_HEADER struct +(excluding all headers). + + +size the pixel dimensions of the bitmap (size.x by size.y) +byte_size the byte size of the bitmap. +offset the relative offset from the end of this header to the start of the bitmap. + + +The bitmap consists of size.y scan lines from top to bottom. Each scan line consists of an array of +((size.x+15)/16) words describing the pixels in the scan line from left to right. The leftmost pixel in a +scan line corresponds to the least significant bit of the first word. + + +A named memory segment which contains a bitmap (created, for example, using gopenBit OF gGetBit) +contains just the bitmap, without the ws_p1c_HEADER header. + + +One example of the use of the physical bitmap structures described above is to animate the screen from a +previously generated sequence of equally sized bitmaps from a bitmap file. After creating the bitmap +memory segment using gOpenBit, gCreateBit OF gGetBit, the steps in the animation sequence are: + + +e@ use p_read to read the bitmap from the file into a buffer +@ use p_sgcopyto to copy the data to the bitmap segment +@ use gCopyBit to draw the bitmap to the screen + + +Since the bitmaps are stored sequentially there is no need to position the file between each p_read - you +only have to position each time you return to the first bitmap in the sequence. + + +Embedded bitmap files + + +A bitmap file may be built into a program file by including its name in an add-file list. This process is +more fully described in the Building an Application chapter of the General Programming manual. + + +1-37 + + +WINDOW SERVER REFERENCE + + +Text fonts + + +A text font is a bitmap that contains up to 256 bit-images called character graphics. The character +graphics in the font are indexed by a character code in the range 0 to 255. + + +Fonts are primarily used to implement the SIBO character set in different typefaces and sizes. + + +A font may also be used to implement any collection of bit-images that have the same height (as an +alternative to using independent bitmaps). + + +A text font may not contain character graphics for the whole 256 code range and within the code range +supported there may also be "holes" for which there is no character graphic.® + + +Although all the character graphics in a font are of the same height, their widths may in general vary. +When all the characters with codes greater than 31 have the same width, the font is said to be monospaced +(otherwise it is said to be proportional). + + +The SIBO character set is compatible with the IBM code page 850 character set for character codes in the +range 32 to 255. In some proportional fonts, the code page 850 block graphics characters (for example, +the box drawing characters) are absent. The characters with codes less than 32 are not compatible with +any standard and vary from font to font. + + +Fast fonts +Fast fonts are stored in an expanded form that uses more memory but can be drawn faster. +All characters in a fast font must be less than or equal to 8 pixels wide. + + +The window server automatically recognises the difference between normal and fast fonts. Window +servers before version 3.5 do not recognise fast fonts and will refuse to load them. + + +ROM-based fonts + + +An application can access the ROM-based fonts by font IDs that are known at compile time. The ROM- +based font IDs start at ws_rFonT_BASE and you can use WS_FONT_BASE+1 etc for as many fonts as are built +into the ROM. + + +The default font of a newly created graphics context, sometimes called the system font, is in most cases +the first font in the ROM - with ID ws_FonT_BASE. + + +Whenever it is expecting a font ID, the window server converts the constant ws_FoNT_SYSTEM to the +system font (WS_FONT_SYSTEM is outside the range of possible font IDs). You can also obtain the system +font ID directly from the system_font member of the W_SERVER_INFo struct (as described under wconnect +in the next chapter). + + +On the HC and the S3, the system font is determined by the sws_sF environment variable which should +contain a worp binary value of 0 for ws_FonT_BASE and | for Wws_FONT_BASE+1 and so on. If you change the +value of sws_sFr, you must reset the machine by pressing the recessed reset button to effect the change. + + +In version 4 of the window server which runs on the S3a, the system fonts are determined by the sws_Fnts +environment variable. This contains a series of words each of which contains the fonts used by the +window server in various situations (listed in the changes section earlier). The full list is repeated below +and is given in the correct order. + + +e §=©System font + +e §=6Notifier/Alert font + +e Status Window font + +e Symbols font used for the status window diamond symbol +e Medium 2 digital clock font + +e Medium 2 date font + +e §©Notifier/alert button font + + +e Small status window clock font + + +8If a client passes a character code for which there is no graphic, the graphic with the highest code is +selected. + + +1-38 + + +1 INTRODUCTION + + +On the MC, the system font is determined in the same way except that two environment variables are used +- sws_sF2 and sws_sr4. If the screen has fewer than 300 lines (as on the MC200), sws_sr2 is used. +Otherwise (as on the MC400), sws_sr4 is used. + + +The following program illustrates how the environment variable may be changed. +#include + + +GLDEF_C INT main(VOID) +{ +WORD flags; + + +flags=1; /* choose WS_FONT_BASE+1 */ +return (p_setenviron("SWS_SF",6,&flags,2)); +} + + +Changing the system font may upset existing applications. + + +In version 4 of the window server used on the Series 3a, fonts can be collected into what are called ‘font +groups’. A more detailed discussion of this concept can be found in the description of gconfigureFonts in +the Graphics Output chapter of this manual. + + +Briefly, font groups are a collection of fonts with a single identity. Essentially, each font within the group +will have been specially designed with a style or a combination of styles in mind. Where a font group is to +be used to print text, the window server will select the best font from within this group according to +criteria based on the style or combination of styles selected (i.e. bold, italics etc). Having selected a font +from within the group, it may, if necessary, algorithmically apply further styles. + + +The font groupings for the Series 3a and Workabout machines are summarised in the header file fonts.h, +which also supplies a range of defined constants that can be used to identify the various ROM-based fonts. + + +HC fonts +On a standard HC, there are six ROM-based fonts: + + +WS_FONT_BASE - large proportional +(the system font). Also the system +font on the MC400. + + +Normal text (15) Bald text +Ttale text Mang text + + +ier Doble bl + + +ia a =] feo i +SS ee + + +fF) +0 +i +A + +| + +I +I + + +| a eee . S| + + +Fi +: +| +f +l +i +i +i +( +i + + +J +oS +fo +t f +a4 +C +| +td +5 ft +da +i i +ii +Hf +a +EE +( ¢ +i + + +aA aot oa eee eos es ee re +_ = oe a SES S| asa +— od + + +1-39 + + +WINDOW SERVER REFERENCE + + +<< +, «LCE Fox Po aot -Com Co + + +a ot, ct a ey a Ree ee i eee | = + + +1oDeset 4. = -on Coo +| | ee ee ee | a +olsen pn BO Eee. we LC ble et neem en toc] jalor we oe Se I --e + + +Be Ef aicahe sm ne npsicias [SIE Lees lame ems ge cect tenth + + +co) a pee eee OO oe EOC + + +ofc eet eee Qt CoS = eS + + +coCI + ee ee ee oe EO +tt ee pes Heo Os) ---s |] SCO Dek RBG Ngee) OC +on |e oa eee eo Dose ES oo cao Coa Ea Oe +Oo fed 0 I a a ee ey eo]D Do oo aM oe tH a +Cars Pes oS cee Dali sn LW mS WbeoCoeD al H LO +oom Oo oe meee ac] PO [OD oS Seco Coe am sor +Owl © Danese +o ee ea is od MO +tsi O eet OR Oem coe laws] [| oO et oe Oe moe I ane CO +wo EO at +a: woo tee bao] JO = Soe oo eee oC Fado + + +Mow eS aa ad ae ee +vie GS Tt + + +Goes) Cer oo oP ooo, or ss Le Le oT Oo er boo 00 2 oo oo La Le GN Oo ue so rh oo eT oo Le Le + + +paced + + +(the console font). Only used on the + + +HC. + + +Bold +Mono text + + +proportional. Also the system font +on the MC200. + + +monospaced. The monospaced font +on the MC. + + +Hormal text (8) Bold tex + + +Italic text Mono text + + +ca +_ TI += +— += += +a += +cs +-—i +cu += +ou +—_— +—o += +— +coc + + +Double herant Double bo] + + +- +% +wu ++ += +—_ += +o +~~. +—_— +fn} +—" ++ +* +a +_ +a += +— +J += + + ++ +m +a + ++4 += += += + += + ++ +te + +au + += + ++ + +Lome! + + +WS_FONT_BASE+2 - fast monos + + += +— +— +— +=! +— +—— +— +— +[ a | +—" +—— +Semene + +#include + + +LOCAL_D WSERV_SPEC wSpec; + + +GLDEF_C INT main(VOID) + + +INT NotifierPid; + + +if ((NotifierPid=p_pidfind("SYSSNTFY.*") )>0) +{ +wConnect (&wSpec, 0,W_CONNECT_AT_BACK) ; +wSystem (WSERV_FLAG_NO_NOTIFIER_REBOOT, WSERV_FLAG_NO_NOTIFIER_REBOOT) ; +p_pterminate (NotifierPid, 0); +wSystem (WSERV_FLAG_HOOK_NOTIFIER, WSERV_FLAG_HOOK_NOTIFIER) ; +} + + +return (0); + + +} +If syssntFy exists, the program connects to the window server and: +e stops the window server from re-booting the notifier +e kills the notifier process +¢ causes the window server to hook the notifier + + +On the HC, the font used by the notifier is determined by the Internal Font environment variable, sws_ir, +which should contain a worp binary value of 0 for ws_ront_Base, | for ws_FONT_BASE+1, and so on. + + +If you change the value of sws_1r, you must reset the machine by pressing the recessed reset button to +effect the change. The height of the font should not exceed 12 pixels. + + +The "factory" setting of sws_t1F is 4 (which selects the S3 font). + + +In version 4 of the window server, the fonts used by the notifier are determined by the sws_Fnts +environment variable. This contains a number of words containing the font ids used by the window server +as described at the beginning of this chapter. + + +In particular, the second word contains the ID of the notifier font while the seventh word contains the ID +of the notifier button font. + + +The $WS_FL environment variable on the HC + + +On an HC with version 3.5 of the window server, the initial value of the internal parameter that is set by +wSystem 1s loaded from the sws_ri environment variable when the window server starts. + + +After setting sws_r1 to the desired worp value, you must reset the HC by pressing the recessed reset button +to make the new value effective. + + +Recall that environment variables survive a soft reset but are cleared (and loaded from a ROM +initialisation file) on a hard reset (where the ON key is pressed at the same time as the reset button). + + +The wsystem flags parameter is made up by ORing a number of bit fields of the form wsERV_FLAG_xxx +where some of the values of xxx are!?: + + +NO_NOTIFIER_REBOOT If set, the window server does not boot or re-boot the notifier. +HOOK_NOTIFIER If set, the window server attempts to hook the notifier. +NO_PANIC_NOTIFY If clear and the window server has successfully hooked the notifier, the window + + +server notifies the user of a process that terminates abnormally with a panic or +with a negative reason number. This flag is ignored unless the window server +has hooked the notifier. You would set this flag to prevent the window server +from reporting abnormal terminations when HooK_NOTIFIER Is Set. + + +12See the description of wsystem for the full set and also for the application of these flags to the $3, the +S3a and the MC. + + +1-59 + + +WINDOW SERVER REFERENCE + + +LOW_BATTERY_WARNINGS _ If set, the window server notifies the user of a low lithium or main battery. Note +that the window server only checks for low battery when the machine is turned +on and that the window server is only informed of the machine being switched +on after p_setonevent (TRUE) has been called. The on-event state is FALSE after +any reset. + + +HUNG_UP If set, the window server presents a "hung up" status window if the foreground +task is not using backed-up windows and fails to respond to redraw events. + + +After a hard reset on an HC with version 3.5 of the window server, the $ws_FL environment variable does +not exist (which is equivalent to it being zero). + + +The following example program sets the $ws_FL environment variable: + + +#include +#include + + +GLDEF_C INT main(VOID) + + +WORD flags; + + +f lags=WSERV_FLAG_NO_NOTIFIER_REBOOT |WSERV_FLAG_HOOK_NOTIFIER +| WSERV, FLAG LOW_BATTERY. WARNINGS |WSERV_FLAG_HUNG_UP_SW; + +return (p_setenviron("SWS_FL",6,&flags,2))j; + +} + + +After running this program and resetting the HC, the window server will: +e provide the notifier service +e report low battery voltages +e present a hung-up status window if an application hangs + + +¢ report a process that terminates with a panic or with a negative reason number + + +S3a + + +In version 4, some HC features from the later releases of version 3.5 have been added to the S3a variant of +the window server. This includes: + + +e the use of the environment variable sws_rt for the initial value of the window server system flags +(as referenced by wsystem). + + +Replacing the shell on the HC + + +By default, the window server runs Rom: :SyS$SHLL.1Mc. This program provides a classical command- +driven user interface to perform such commands as copy and pir and to run programs (for example, LINK) +in response to the program's file name being entered. + + +When developing a turnkey system, it is advisable to run an alternate custom shell that provides a +restricted end-user environment. With version 3.5 of the window server, this is particularly +straightforward as the window server can be persuaded to take over many of the responsibilities - +particularly the link paste services - that previously had to be provided by the shell. You simply call your +main application sys$sHELL.1Mc and place it in the root directory of any drive. The window server will +run the shell on system start-up and it will also re-run the shell should it terminate. + + +Since any restarting EPOC system will pick up a sys$sHLL. mc (such as the debugger, for example), it is +a good idea not to call such a program sysssHuL but to rename it when you copy it to its intended working +destination. + + +To revert to the ROM shell when using an SSD-based syss$su11, first remove the SSD and then either +terminate the existing shell process or reset the machine. If you have placed a sys$sHLL. IMG in M:\, you +can revert to the ROM shell by hard resetting the machine (which clears the contents of m: \ and resets the +environment variables) or you can place an alternate syS$sHLL.1mc in an SSD drive (since the drives are +scanned in alphabetic order). + + +The following simple shell/application program terminates any sys$nTFy process and sets up the window +server to provide the notifier service and other services (as described above) and then presents a user +interface that reports on key presses. + + +1-60 + + +1 INTRODUCTION + + +/* +HCSHELL.C - Sample shell for the HC +*/- + + +#include +#include + + +GLREF_D UINT wMainGc; +GLREF_D WSERV_SPEC wSpec; + + +LOCAL_D INT FontHeight; +LOCAL_D INT FontAscent; + + +LOCAL_C VOID SetFontHeight (VOID) + + +{ +G_FONT_INFO info; + + +gFontInfo (WS_FONT_SYSTEM, 0, &info) ; +FontHeight=info.height; +FontAscent=info.ascent; + + +} + + +LOCAL_C VOID CDECL PrintLine(INT line, INT align, TEXT *fmt,...) +{ +INT len; +P_RECT box; +TEXT b[80]; + + +box.tl.x=4; + +box.br.x=wSpec.conn.info.pixels.x-4; +box.tl.y=FontHeight*linet+4; +box.br.y=box.tl.y+FontHeight; +len=p_atob(&b[0],fmt, &fmt+1); +gPrintBoxText (&box, FontAscent,align,0,&b[0],len); + + +LOCAL_C VOID HandleKeyPress (WMSG_KEY *pk) + + +PrintLine (2,G_TEXT_ALIGN_CENTRE, "code:%02x mod:%02x count:%02x", +pk->keycode, pk->modifiers,pk->count) ; + + +LOCAL_C VOID MainEventLoop (VOID) + + +WS_EV event; + + +SetFontHeight (); +gBorder (W_BORD_SHADOW. D|w BORD_SHADOW_ON) ; +PrintLine(0,G_TEXT_ALIGN_LEFT, "Free memory: %dKbytes",p_sgfree()>>6); +for; (F<) + +{ + +wGetEventWait (&event) ; + +if (event .type==WM_KEY) + +HandleKeyPress (&event.p.key) ; + + +} + + +GLDEF_C INT main(VOID) + + +{ +INT NotifierPid; + + +1-61 + + +WINDOW SERVER REFERENCE + + +p_setonevent (TRUE); /* required on the HC */ + +wStartup(); + +wSystem(WSERV_FLAG_NO_NOTIFIER_REBOOT, Oxfff); + +if ((NotifierPid=p_pidfind("SYSSNTFY.*") )>0) +p_pterminate (NotifierPid, 0); + + +wSystem(WSERV_FLAG_HOOK_NOTIFIER|WSERV FLAG_LOW_BATTERY. WARNINGS |WSERV_FLAG_HUNG_UP_SW + + +, + + +WSERV_FLAG_HOOK_NOTIFIER|WSERV. FLAG _LOW_BATTERY. WARNINGS |WSERV_FLAG_HUNG_UP_SW) ; +MainEventLoop() ; + + +return (0); + + +} + + +You may prefer to use the following shell (the source may be found in \sibosdk\demo\lkshell.c) when +using the remote debugger on the HC: + + +/* +LKSHELL.C - Just starts up the link +xy: + + +include +include + + +LOCAL_D WSERV_SPEC wSpec; +LOCAL_D UINT wMainGc; +LOCAL_D UINT wMainWid; +LOCAL_D INT FontHeight; +LOCAL_D INT FontAscent; + + +LOCAL_C VOID SetFontHeight (VOID) +{ +G_FONT_INFO info; + + +gFontInfo (WS_FONT_SYSTEM, 0, &info) ; +FontHeight=info.height; +FontAscent=info.ascent; + + +} + + +LOCAL_C VOID CDECL PrintLine(INT line, INT align, TEXT *fmt,...) +{ +INT len; +P_RECT box; +TEXT b[80]; + + +box.tl.x=4; + +box.br.x=wSpec.conn.info.pixels.x-4; +box.tl.y=FontHeight*linet+4; +box.br.y=box.tl.y+FontHeight; +len=p_atob(&b[0],fmt,&fmt+1); +gPrintBoxText (&box, FontAscent,align,0,&b[0],len); +} + + +LOCAL_C VOID MainEventLoop (VOID) +{ +WS_EV event; + + +SetFontHeight (); +for (3-7) +{ +wGetEventWait (&event) ; +if (event .type==WM_REDRAW) +{ +wValidateWin (wMainWid) ; +gBorder (W_BORD_SHADOW. D|w BORD_SHADOW_ON) ; +PrintLine(0,G_TEXT_ALIGN_LEFT, "Free memory: %dKbytes",p_sgfree()>>6); +} +else if (event.type==WM_KEY && event.p.key.keycode==W_KEY_RETURN) +wiInvalidateWin (wMainWid) ; + + +1-62 + + +1 INTRODUCTION + + +GLDEF_C VOID main(VOID) +{ +INT NotifierPid; +WORD stat; + + +p_setonevent (TRUE) ; +wConnect (&wSpec, 0,W_CONNECT_PRIORITY) ; +wSystem (WSERV_FLAG_NO_NOTIFIER_REBOOT, WSERV_FLAG_NO_NOTIFIER_REBOOT) ; +if ((NotifierPid=p_pidfind("SYSSNTFY.*") )>0) +{ +p_logona (NotifierPid, éstat) +p_pterminate (NotifierPid, 0) +p_waitstat (&stat); +} + + +’ +’ + + +wSystem(WSERV_FLAG_HOOK_NOTIFIER|WSERV FLAG_LOW_BATTERY. WARNINGS |WSERV_FLAG_HUNG_UP_SW + + +’ + + +WSERV_FLAG_HOOK_NOTIFIER|WSERV. FLAG _LOW_BATTERY. WARNINGS |WSERV_FLAG_HUNG_UP_SW) ; +if (p_pidfind("SYSSNCP.*") <0) +p_presume (p_execc ("ROM: : LINK", NULL, 0) ); +wMainWid=wCreateWindow(0,0,0,1); +wsCreateClock (wMainWid, WS_CLOCK_WITH DATE|WS CLOCK_WITH_SECONDS, 104, 66,0); +wiInitialiseWindowTree (wMainWid) ; +wMainGc=gCreateGCO (wMainWid) ; +MainEvent Loop () ; +} + + +To save memory, the program processes redraw messages rather than keep a backup bitmap. Pressing +ENTER causes the "Free Memory" figure to be re-evaluated. + + +There is further information on creating a replacement shell in the HC Programming Guide. + + +PC EPOC + + +On the PC version, the window server looks for the shell and notifier in the following directories: +e the current directory +e the directory that contains sysswsRv.IMG + + +e the ROM + + +1-63 + + +CHAPTER 2 + + +GENERAL WINDOW SERVER FUNCTIONS + + +The connection to the window server + + +Before you use any window server services you must connect to the window server. + + +How you connect to the window server depends on whether you are using the CLIB or the PLIB C startup +module and what machine you are running on. See the section Connecting to the window server in the +first chapter for a full discussion. + + +The CLIB C startup module opens the console device con: before calling main. On the HC, S3 and S3a, +the console device open function connects to the window server. If you try to connect a second time, your +program will be panicked with panic number 100. + + +Provided the C startup module has not already connected the process, you may call either wstartup or +wConnect to connect. The convenience function wStartup calls wconnect and then carries on to perform +additional setting up that will satisfy the requirements of many applications. For a more sophisticated use +of the window server, you would use wconnect directly. + + +wStartup Connect and initialise a window +VOID wStartup (VOID) ; +Perform the following actions: + +e Connect to the window server using wconnect. + +e Create a window to cover the whole screen and store its ID in wMainwid. + +e Initialise wMainwid so that it is visible. + +e Create a permanent graphics context on the window and store its ID in wMainGe. + + +On version 3 of the window server, the window is created with a backed-up bitmap (so that no redraws are +required). + + +The code for wstartup is effectively!: + + +#include +#include + + +#define NWS_HANDLE 0 +#define MAIN_WIN 1 + + +GLDEF_D WSERV_SPEC wSpec; +GLDEF_D UINT wMainGc; +GLDEF_D UINT wMainWid; + + +!The actual code in WLIB is written in 8086 assembler. + + +2-1 + + +WINDOW SERVER REFERENCE + + +GLDEF_C VOID wStartup (VOID) +{ +UINT field_set; +W_WINDATA windata; + + +wConnect (&wSpec, NWS_HANDLE, W_CONNECT_PRIORITY) ; +field_set=0; +if ((wSpec.conn.info.version_id&WS_VERSION_MASK) !=WS_VERSION_2) + +{ + +field_set=W_WIN_BACKGROUND; + +windata.background=W_WIN_BACK_BITMAP; + +} +wMainWid=wCreateWindow (0, field_set, &éwindata,MAIN_WIN) ; +wiInitialiseWindowTree (wMainWid) ; +wMainGc=gCreateGCO0 (wMainWid) ; + +} + + +The created graphics context is the current graphics context and, after calling wstartup, you are ina +position to draw to the window. If necessary, you can reference wSpec, wMainGe and wMainWid by +including the following declarations: + + +GLREF_D WSERV_SPEC wSpec; +GLREF_D UINT wMainGc; +GLREF_D UINT wMainWid; + + +The following example is suitable for an HC, an S3 or an S3a: + + +#include +#include + + +GLREF_D UINT wMainGc; +GLREF_D WSERV_SPEC wSpec; + + +GLDEF_C INT main(VOID) +{ +WS_EV event; +G_GC gc; +P_RECT box; +TEXT bb[32]; + + +wStartup(); +box.tl.x=box.tl.y=0; +box.br=wSpec.conn.info.pixels; +p_insrec (&box, 8,8); +gBorder (W_BORD_SHADOW. D|w BORD_SHADOW_ON) ; +gc.style=G_STY_BOLD|G_STY_DOUBLE; +gSetGC (wMainGc, G_GC_MASK_STYLE, &gc) ; +for (77) +{ +wGetEventWait (&event) ; +if (event .type==WM_KEY) +{ +p_atos(&bb[0],"Key code: %d",event.p.key.keycode) ; +gPrintBoxText (&box, box.br.y>>1,G_TEXT_ALIGN_CENTRE, 0, +&bb[0],p_slen(&bb[0])); + + +if (event.p.key.keycode==W_KEY_RETURN) +break; + + +} + + +return (0); + + +} + + +2-2 + + +2 GENERAL WINDOW SERVER FUNCTIONS + + +wConnect Connect to the window server +VOID wConnect (.i.WSERV_SPEC *pwserv_spec, VOID *pnws_handle, UINT flags); +Connect to the window server. + + +The parameter flags should contain a combination of the following bit masks: + + +W_CONNECT_AT_BACK Connect as a background application (the default is foreground). +W_CONNECT_USER_FLAG The value of this flag is returned by a wclientInfo call. +W_CONNECT_SYSTEM_MODAL Makes the client system modal. + +W_CONNECT_PRIORITY Enables the window server's process priority handling for the client. In + + +version 4 of the window server, process priority handling can be both +enabled and disabled by a suitable call to wsetPriorityControl. + + +W_CONNECT_DISABLE_LEAVES If set, the window server will return negative error numbers rather than call +p_leave. Equivalent to calling woisableLeaves (TRUE) except that it also +affects whether wconnect itself leaves or returns an error. + + +The parameter pnws_hand1le is a handle that the window server will use in events sent to the client that +are not directed at a window (for example, key events). + + +The parameter pwserv_spec is the address of a wszRV_spPEc struct that must be maintained for the +duration of the connection (it holds information used by WLIB functions). The wszrv_spec struct is +typically implemented as a static variable or as allocated memory. + + +The wserv_spPeEc struct is defined as: + + +typedef struct +{ +UWORD handle_check; /* used internally */ +CONNECT_INFO conn; +Fi /* used internally */ +} WSERV_SPEC; + + +typedef struct +{ +UWORD client_handle; /* used internally */ +W_SERVER_INFO info; +} CONNECT_INFO; + + +where wConnect writes information useful to the client in the connEcT_1NFo sub-struct conn (the only part +of wsERv_spxc that should be accessed by the client). + + +The w_SERVER_INFO Struct is defined as: + + +typedef struct +{ +P_POINT pixels; /* display size */ +UWORD width_1000_pixels_mm; /* width of 1000 pixels in mm */ +UWORD height_1000_pixels_mm; +UBYTE set_is_dark; /* TRUE if set pixels are dark */ +UBYTE version_id; /* machine type and window server version */ +UWORD system_font_handle /* ID of default font */ + +cece /* extra space for future expansion */ + +} W_SERVER_INFO; + + +where: + +pixels the size of the screen in pixels (pixels.x wide by pixels.y high). + +width_1000_pixels_mm the width and height (in millimetres) of 1000 screen pixels for applications + +height_1000_pixels_mm that wish to draw objects of a certain physical size or to correct for the pixel +aspect ratio. Note that, for the Series 3 (but not for other machines, +including the Series 3a) these two values are not reliable. + +set_is_dark TRUE if a set bit appears dark on the display (as on an LCD display) and + + +FALSE otherwise (as for a CRT display). An application can invert drawings +according to this flag so that they appear the same on both types of display. +(Not reliable on a PC version of the window server.) + + +WINDOW SERVER REFERENCE + + +version_id the machine type and window server version number. +version_id|WS_TYPE_MASK is one of WS_TYPE_MC, WS_TYPE_HC, WS_TYPE_S3, +WS_TYPE_S3A or WS_TYPE_S3c depending on whether the machine is an MC, +HC, S3, S3a or Workabout. The value of version_id|WS_VERSION_MASK is +WS_VERSION_2, WS_VERSION_3 Of WS_VERSION_4 depending on whether a +connection was made to version 2, version 3 or version 4 of the window +server. In this context, version 3.5 is grouped with version 3. + + +system_font_id the ID of the default font that you get when you create a graphics context. +(Alternatively, you can use WS_FONT_SYSTE™ to specify the system font.) + + +Note that any application running on the S3a in S3 compatibility mode will find that the version_id is set +to WS_TYPE_S3A|WS_VERSION_4. In a similar situation, an application running on the Workabout will have +version_id Set to WS_TYPE_S3C|WS_VERSION_4. Therefore, the window server is not providing a +completely identical interface to such applications. + + +Whether wconnect was called directly or indirectly, the address of the wsERV_sPEc variable which was +passed is recorded in the reserved static wserv_channel. This can be used in general purpose code to +obtain the above information. For example: + + +GLREF_D WSERV_SPEC *wserv_channel; +LOCAL_D P_POINT ScreenSize; + + +ScreenSize=wserv_channel->conn.info.pixels; + + +The following example program (which requires the PLIB C startup module) illustrates the use of +wConnect to connect to the window server. + + +#include +#include + + +#define WBORDER 8 + + +GLDEF_D WSERV_SPEC wspec; +GLDEF_D UINT wid; +GLDEF_D WMSG_KEY key; + + +GLDEF_C VOID CreateWindow (VOID) +{ +UINT border; +W_WINDATA windata; + + +windata.flags=W_WIN_NO_REDRAW; +windata.background=W_WIN_BACK_SET; + + +border=wCreat eWindow (0, W_WIN_NO_REDRAW|W_WIN_BACKGROUND, &windata, 2) ; +windata.extent.t1.x=WBORDER; + +windata.extent.t1.y=WBORDER; + +windata.extent .width=wspec.conn.info.pixels.x-(2*WBORDER) ; +windata.extent .height=wspec.conn.info.pixels.y-(2*WBORDER) ; +windata.background=W_WIN_BACK_NONE; + +wid=wCreat eWindow (border, W_WIN_EXTENT |W_WIN_BACKGROUND, &windata, 1) ; +wiInitialiseWindowTree (border) ; + + +} + + +GLDEF_C INT main(VOID) +{ +WS_EV event; +G_GC gc; +P_RECT box; +TEXT bb[32]; + + +wConnect (&wspec, 0,W_CONNECT_PRIORITY) ; +CreateWindow(); + +box.tl.x=box.tl.y=0; +box.br.x=wspec.conn.info.pixels.x-(2*WBORDER) +box.br.y=wspec.conn.info.pixels.y-(2*WBORDER) + + +’ +’ + + +2-4 + + +2 GENERAL WINDOW SERVER FUNCTIONS + + +for (77) + +{ + +wGetEventWait (&event) ; + +if (event .type==WM_REDRAW) +{ +gc.style=G_STY_BOLD|G_STY_DOUBLE; +wBeginRedrawWinGC (wid, G_GC_MASK_STYLE, &gc) ; +p_atos(&bb[0],"Key code: %d",key.keycode) ; + + +gPrintBoxText (&box, box.br.y>>1,G_TEXT_ALIGN_CENTRE, 0, &bb[0],p_slen(&bb[0])); + +wEndRedraw(); +} + +if (event .type==WM_KEY) +{ +key=event.p.key; +if (key. keycode==W_KEY_RETURN) + +break; + +wiInvalidateWin (wid) ; +} + +} + +return (0); + + +} + + +The function creat eWindow sets up a two-window parent-child system where the parent implements a +thick border and all drawing is done to the child window. The main function contains an event loop that +handles redraw events and key events to display the code of the last key pressed. Note the use of +wInvalidatewin to update the screen on receipt of a key event by forcing a redraw. + + +The true screen and pixel dimensions of the various LCD screens are as follows: + + +Machine Screen Pixel Pixel Screen Screen + +type (pixels) pitch (mm) size (mm) size (cm) size (in) +HC 160x80 0.34x0.43 0.31x0.40 5.44x3.44 2.14x1.35 +S3 240x80 0.385x0.43 0.355x0.40 9.24x3.44 3.64x1.35 +Workabout 240x100 0.26x0.30 0.23x0.27 6.24x3.00 2.45x1.18 +S3a 480x160 0.259x0.259 0.20x0.20 12.477x4.156 4.915x1.637 +MC200 640x200 0.33x0.33 0.30x0.30 21.12x6.60 8.31x2.60 +MC400 640x400 0.33x0.33 0.30x0.30 21.12x13.20 8.31x5.20 + + +In the above table, the horizontal measure is shown before the vertical measure. The pixel pitch measures +the horizontal and vertical distance between the same points on adjacent pixels. The difference between +the pixel size and the pixel pitch gives the gap between pixels. + + +wDisconnect Disconnect from the window server + + +VOID wDisconnect (VOID) ; + + +Disconnect from the window server and free resources within the client process and within the window +server. + + +A client is automatically disconnected if it terminates. + + +wFlush Flush buffered commands + + +VOID wFlush (VOID); + + +Flush any contents of the client-side buffer. This will ensure that the window server has received and +executed all previous functions. + + +Note that wr1lush does not report any errors that occur in the processing of the client-side buffer. The +function wcheckPoint (described below) flushes the buffer and reports errors. + + +The client-side buffer is automatically flushed when: +e the buffer is about to overflow + + +e the client calls a function that returns a value that requires the window server process to run (for +example wcreateWindow returns the ID of the window it creates). The functions grextwidth, +gTextCount, gFont Info and wCheckBitmapid do not flush the client-side buffer because they are +implemented by code that runs in the client's process. + + +e = the client calls weetEventWait, wGetEvent OF wGetEvent Special + + +Most applications don't need to call wriush and calling wriush unnecessarily will degrade performance. + + +2-5 + + +WINDOW SERVER REFERENCE + + +Programs that perform animation or that respond to an event source other than the window server (such +as a serial I/O device) may need to use wFlush. For example, the following code, intended to produce +some animation: + + +gClrRect (prect,G_TRMODE_INV); /* invert a rectangle */ +p_sleep(5L); /* pause for half a second */ +gClrRect (prect,G_TRMODE_INV); /* invert it back again */ + + +does not have the intended effect. The code should be as follows: + + +gClrRect (prect, G_TRMODE_INV) ; +wF lush () ; + +p_sleep(5L); + +gClrRect (prect, G_TRMODE_INV) ; + + +When debugging a program, it can be useful to insert calls to wFlush (which are removed subsequently) to +force the screen to be updated. + + +Series 3 compatibility modes + + +Both the Series 3a and the Workabout can be set to operate in Series 3 compatibility mode. The +motivation for this is to be able to emulate Series 3 graphics, so that unmodified Series 3 applications can +run on either machine. Naturally, grey is not available to any application running in Series 3 compatibility +mode. + + +On the Series 3a, the compatibility mode is implemented by allowing all Window Server graphics +commands to draw with double size pixels. Because the Series 3a's screen has 480 x 160 pixels, compared +to the Series 3's 240 x 80 pixels, doubling up the pixels on the Series 3a screen gives the 'look' and ‘feel’ of +the Series 3 screen for Series 3 applications running on the Series 3a. + + +On the Workabout, with its 240 x 100 screen, full Series 3 compatibility is implemented by restricting +drawing to a 240 x 80 region, centred on the screen, leaving ten rows of pixels unused at both the top and +bottom of the screen. + + +The Workabout has a second compatibility mode that, while not allowing the use of grey, allows an +application to draw to the full 240 x 100 extent of the screen. This mode can only be used with a Series 3 +application that is written in such a way that it can adjust the sizes of its windows according to the screen +dimensions of the machine on which it is running. It is recommended that this mode be used only if the +appearance of a Series 3 application running in full Series 3 compatibility mode on the Workabout is truly +unacceptable. + + +Drawing with double size pixels is a feature that is available in version 4 of the window server. As well as +being used for compatibility mode on the Series 3a, it can be set for individual windows; see the Windows +chapter for further information. + + +The following two functions relate to compatibility mode. + + +wCompatibilityMode Set or cancel compatibility mode +VOID wCompatibilityMode(UINT flags,.i.WSERV_SPEC *pwspec) ; +On the S3a and Workabout, full S3 compatibility mode is turned on by setting flags to W_CTBY_S3. + + +On the Workabout, the S3 compatibility mode that allows use of the full 240 x 100 extent of the screen is +turned on by setting flags to W_CTBY_S3_SCR. + + +On both machines, Series 3 compatibility is turned off by setting flags to zero. + + +The pwspec parameter must point to the same WSERV_SPEC structure that was passed to the wconnect +function (see earlier in this chapter). wcompat ibiltyMode modifies information such as the screen +dimensions, held in this structure. + + +2-6 + + +2 GENERAL WINDOW SERVER FUNCTIONS + + +winquireCompatibility Inquire state of compatibility flags +UINT wInquireCompatibility (VOID) ; + + +The function returns the current state of the compatibility flags of the calling client. The flags are the +same as set by the function wcompatibilityMode. + + +Error handling + + +wCleanUp Return to defined state +VOID wCleanUP (VOID) ; +Put the window server back into a defined state by: + +e freeing the temporary Graphics Context if it exists + +e ending the redraw if one was in progress + + +If there is a current graphics context that is attached to a window, wcleanup also invalidates that window - +so that it is not left in a partly drawn state. + + +The function wcleanup is typically called in response to a p_leave. + + +wCheckPoint Check for an error +INT wCheckPoint (VOID) ; +Flush the client-side buffer (as for wriush) and return zero if there was no error. + + +If there is an uncleared error or if an error occurred in the processing of the buffer, call p_leave (err) or +return err, depending on whether woisableLeaves has been called, where err is the negative error +number. + + +wDisableLeaves Disable/enable leaves + + +UINT wDisableLeaves(UINT flag); + + +If £1ag is TRUE, the window server functions will (for the calling client) return an error code rather than +call p_leave when they encounter an error. If f1ag 1s FALSE, enable p_leaves. + + +Returns the previous value of £1ag (not before version 3.5). +By default, the window server functions that can fail call p_1eave when an error occurs. + + +Not available in version 2 of the window server. + + +Priority changing + + +The window server will not change a client's process priority unless the client has priority control +enabled. + + +Priority control is enabled if the client sets the w_conNEcT_PRIorRITY flag when it connects to the window +server or, if running version 4 of the window server, the client calls wsetPriorityControl (TRUE). + + +Priorities are set as follows: +e when a client loses the foreground or calls wstartCompute, its priority is set to E_PRIORITY_BACK + + +e when a client gains the foreground and is not in compute mode, its priority is set to the higher +priority E_PRIORITY_FORE + + +A client with priority control enabled should not change its own priority. + + +2-7 + + +WINDOW SERVER REFERENCE + + +wSetPriorityControl Set process priority handling on or off +INT wSetPriorityControl(UINT state); + + +Introduced in version 4 of the window server, this function enables and disables process priority handling +for a client. Setting state to TRUE enables it, while setting state to FALSE disables it. + + +The function always returns 0. + + +wStartCompute Enter compute mode +VOID wStartCompute (VOID) ; + + +Mark the client as being in compute mode, setting the caller's process priority to E_PRIORITY_BACK +regardless of whether it has the foreground or not. + + +Should be called before performing a computationally intensive task. + + +Has no effect unless the client has priority control enabled. + + +wEndCompute Leave compute mode +VOID wEndCompute (VOID) ; + +The caller is marked as not being in compute mode. + +Its priority will be set to E_PRIORITY_FORE whenever it is foreground. + + +Has no effect unless the client has priority control enabled. + + +General client functions + + +wClientinfo Get information about a client + + +INT wClientInfo(UINT pid); +Return a word mask giving information about the window server client with process ID pia. + + +If pia is a client of the window server, the function returns a bit mask that contains the following bit +fields: + + +W_CONNECT_CONNECTED this is set +W_CONNECT_USER_FLAG if set, the W_CONNECT_USER_FLAG was specified at connect time +W_CONNECT_SYSTEM_MODAL if set, the W_coNNECT_SYSTEM_MopAL flag was specified at connect time or + + +the client is in a system modal state as a result of calling wSystemModal +W_CONNECT_PRIORITY if set, priority control is enabled. + + +If pid is not a client of the window server, the function calls p_leave (E_FILE_NXIST) or returns +E_FILE_NXxIST, depending on whether wDisableLeaves has been called. + + +On version 2 of the window server, the function returns zero if pid is not a client of the window server. + + +wClientPosition Position client in task order +VOID wClientPosition(UINT pos, UINT pid); + + +Position client pid to position pos in the task order, zero being at the front and any value greater than the +number of connected tasks being at the back. + + +The constant WS_LAST_CLIENT_POSITION is provided to position a client at the back. +Passing a pid of zero is equivalent to passing the pid of the caller. + + +On a large screen version of the window server such as the MC, if the client pia is marked as iconised and +it is positioned to the front by a call to wclientPosition, it will be sent a WM_DEICONISE event. + + +2 GENERAL WINDOW SERVER FUNCTIONS + + +wClientlconised Mark client as iconised +VOID wClientIconised(UINT state); +Mark the caller as iconised if state is TRUE, Otherwise mark it as deiconised. + + +This function only applies to large screen version of the window server such as the MC (and is not +available on hand-held machines such as the HC, $3, S3a and Workabout). + + +On an MC, if the user holds down the CONTROL key while pressing the TASK key, iconised task are +skipped and only non-iconised tasks are selected. + + +If a client is marked as iconised, the window server generates a wM_DEICONISE event to client pid if +wClientPosition (pid, 0) is called (normally by another client) to make client pia the foreground client. +The wM_DEICONISE event would normally prompt the client to deiconise itself. + + +On the MC, the window server recognises the shell (with process name sys$shll) and sends it a +WM_DEICONISE event when the PSION+TASK key is pressed while the shell is iconised. + + +wSystemModal Make client system modal +VOID wSystemModal (UINT pos); +Make the caller system modal and place it at position pos in the task list. + + +The window server limits task switching to only those processes that have a lower client position than the +frontmost system modal task. If there are no clients with a lower client position, the system modal task is +locked into the foreground. + + +When wSystemModal is used, pos is commonly zero - to lock the client to the foreground. +Not available in version 2 of the window server. + + +It is important to note that calling this function does not prevent a task from being made foreground. For +example, a user pressing ENTER on a task in the system screen will cause that task to be made foreground. + + +To handle an attempt to bring an application into foreground, it must test for a ww_FoREGROUND event. In +response to this event, the application can call wcLientPosition to return itself to background. + + +wCancelSystemModal Cancel system modal state +VOID wCancelSystemModal(UINT pos); +Cancel the caller's system modal state and place it at position pos in the task list. + + +Not available in version 2 of the window server. + + +wEnablePauseKey Enable pause key +VOID wEnablePauseKey (VOID) + +Allow the user to pause the calling client's graphics output when it has the foreground. + +Useful, for example, to stop information scrolling off the top of a display. + + +On the HC, the pause key is PSION+LEFT-ARROW and on the $3, S3a, Workabout and MC, it is CTRL+S. +The user resumes the client by pressing any key. The key press that resumes the client is not delivered to +the client. + + +The pause key may be disabled by calling woisablePauseKey. +The pause key is disabled by default, except in Console applications, where it is enabled by default. + + +When the user presses the pause key, the client will be stalled within a window server function and can +not therefore process any events that occur in the meantime. Applications that redraw their windows or +that respond to events other than the window server (such as the receipt of data from the serial port) +should not enable the pause key. + + +Not available in version 2 of the window server. + + +2-9 + + +WINDOW SERVER REFERENCE + + +wDisablePauseKey Disable pause key +VOID wDisablePauseKey (VOID) ; + +Disable pause key processing for the calling client. + +The pause key is enabled by calling wEnablePauseKey. + + +Not available in version 2 of the window server. + + +wGetProcessList Get client list +VOID wGetProcessList (UWORD *pbuf) ; + + +Write the process IDs of the clients of the window server as a zero terminated list in front to back order to +pbuf. + + +There should be at least ws_max_cLIENTS+1 words of memory at pbuf. + + +Not available in versions prior to version 3.5 of the window server. + + +Screen-based output + + +When using the window server, graphics output can be directed at: +e a graphics context (as described in the Graphics Output chapter) +e a particular window (as described in the Windows chapter) +e the screen as a whole (as described next) + + +On the HC, the font used for output that is not graphics context directed is determined by the sws_iF +("Internal Font") environment variable. + + +This should contain a worp binary value of 0 for ws_ronT_BasE and | for Wws_FoNT_BASE+1 and so on. If +you change the value of sws_1Fr, you must reset the machine by pressing the recessed reset button to effect +the change. + + +The "factory" setting of sws_1F is 4 (which selects the S3 font). + + +In version 4 of the window server, the environment variable $ws_FNTs is used to contain the indices of the +fonts to be used by the window server for notifies, clocks and so on. + + +In order, they are: +e System font +e §=6Notifier/Alert font +e Status Window font +e Symbols font used for the status window diamond symbol +e Medium 2 digital clock font +e Medium 2 date font +e §=Notifier/alert button font + + +e Small status window clock font + + +2-10 + + +2 GENERAL WINDOW SERVER FUNCTIONS + + +winfoMsgCorner Present an information message +INT wiInfoMsgCorner (TEXT *pmsg,UINT corner) ; +Displays the zero terminated string pmsg for 2 to 2.5 seconds or until cancelled. + + +The message is displayed in one of the four corners of the screen depending on corner, which should be +one of: + + +W_CORNER_TOP_LEFT to display pmsg in the top left corner +W_CORNER_TOP_RIGHT to display pmsg in the top right corner +W_CORNER_BOTTOM_LEFT to display pmsg in the bottom left corner +W_CORNER_BOTTOM_RIGHT to display pmsg in the bottom right corner + + +The length of pmsg (excluding its zero terminator) should be less than or equal to w_INFO_MSG_MAX_LEN +(64) bytes. A longer pmsg is truncated. + + +The message display is cancelled when: + + +e the calling client loses the foreground (the message is never displayed if the caller is a +background client) + + +e wiInfoMsgCorner OF wInfoMsg is called again +e the message is explicitly cancelled by calling winfomMsg (NULL) Of wInfoMsg("") + + +The function behaves as for wcheckPoint in that it flushes the client-side buffer and reports any uncleared +error - either by calling p_ieave or by returning the error number. + + +winfoMsg Present an information message + + +INT wiInfoMsg(TEXT *pmsg) ; + + +Displays the zero terminated string pmsg in the bottom right hand corner of the screen for 2 to 2.5 seconds +or until cancelled. + + +Behaves as for wInfoMsgCorner (&msg, W_CORNER_BOTTOM_RIGHT). + + +wSetBusyMsg Present a flashing busy message + + +INT wSetBusyMsg(TEXT *pmsg,UINT corner_delay) ; + + +Displays the zero terminated string pmsg as a flashing "busy" message in the specified corner of the +screen. + + +The message continues to display whenever the caller has the foreground. +The message is cancelled by calling wcancelBusyMsg, wSetBusyMsg (NULL) Of wSetBusyMsg(""). + + +The parameter corner_delay specifies both the corner of the screen in which the message will appear and +a delay to stop the message from appearing instantly. The delay is used to stop the message from +appearing at all when there is the possibility that the task can be completed in a short time. + + +The time delay should be ored in with the corner mask, which should be one of: + + +W_CORNER_TOP_LEFT to display pmsg in the top left corner +W_CORNER_TOP_RIGHT to display pmsg in the top right corner +W_CORNER_BOTTOM_LEFT to display pmsg in the bottom left corner +W_CORNER_BOTTOM_RIGHT to display pmsg in the bottom right corner + + +The delay is specified in half seconds. For example: +wSetBusyMsg ("Saving",W_CORNER_TOP_LEFT | 6); + + +will display the message in the top left corner after 3 seconds if it has not been cancelled before the time is +up. + + +The delay can range from 0 to 63 half seconds, inclusive. + + +2-11 + + +WINDOW SERVER REFERENCE + + +The length of pmsg (excluding its zero terminator) should be less than or equal to w_BUSY_MSG_MAX_LEN +(20) bytes. A longer pmsg is truncated. + + +The function behaves as for wcheckPoint in that it flushes the client-side buffer and reports any uncleared +error - either by calling p_leave or by returning the error number. + + +While the window server is loading a large bitmap or font (gopenBit or gOpenFont) or saving a large +bitmap (gSaveBit), it doesn't maintain the busy message. In these cases, the busy message will not flash +and it might not even appear. + + +wCancelBusyMsg Cancel a flashing busy message + + +INT wCancelBusyMsg (VOID) ; +Cancel a busy message. + + +Entirely equivalent to wSetBusyMsg (NULL). + + +Alerts + + +The functions that support alerts are available on S3, S3a and Workabout machines - and on HC +machines that are running version 3.5 or later of the window server. + + +Alerts present a p_notify-like display where the user is presented with a message and prompted to +respond by pressing a button. Unless you are already familiar with the notifier services, you may find it +useful to read the Notifier Services section of the Error Handling chapter in the PLIB Reference manual. + + +Alerts extend the specification of p_notify as follows: + + +e the maximum number of message lines is increased from 2 to 3. In version 4 of the window +server, the maximum number is increased to 4 (provided the screen is large enough to display +four lines of text in an alert) + + +e message lines may be centred or placed at a specified horizontal position + + +e rather than specify the address of a text string, it is possible to specify built in text strings by +number (the same text strings that are obtained using p_gettext) + + +e an asynchronous function is also provided so that the calling program can perform other tasks +while waiting for the user to respond + + +The alert functions are: + + +wsAlertW presents the user with a message and waits for a response. This function is +similar in effect to p_notify. + + +wsAlertA is the asynchronous form of wsAlertw. Using this, the program can perform +other tasks while waiting for the user to respond. There is no asynchronous +form of p_notify. + + +wsAlertUpdate is used to update a pending alert (which was launched using wsAlerta). +For example, the program: + + +#include +#include + + +LOCAL_D WSERV_SPEC wSpec; + + +GLDEF_C INT main(VOID) +{ +wConnect (&wSpec, 0,W_CONNECT_PRIORITY) ; +wsAlertW (WS_ALERT_CLIENT, "Hello World",NULL, NULL) ; +return (0); + + +} + + +2-12 + + +2 GENERAL WINDOW SERVER FUNCTIONS + + +when compiled and linked to produce a program with the name sample.img, presents the following +display on the HC. + + +Hello World + + +Continue +Esc + + +From top to bottom, the display consists of 3 parts: + + +Title Displays the program name. If the reserved static patstatusNamePtr contains +other than NULL, it is assumed to point to a zero terminated string which is +taken as the program name (of up to 8 characters in length and stopping when +a'.' is reached). If patstatusNamePtr iS NULL (which it will be if not explicitly +set), the process name is used. The process name is normally the name of the +executable and, for a single source file program, the name of the executable is +normally the name of the source file so you can deduce that the above example +had the file name sample.c. On the S3, the title area also contains the date and + + +time. +Message The message area contains up to 3 lines of text. +Buttons The button area contains one, two or three buttons. + + +On the S3a, running version 4 of the window server, the display is slightly different. Using the above +code results in the following: + + +Sample +Hello World + + +Continue + + +On the Workabout, the appearance is as follows: + + +Sample + + +Hello World + + +Continue + + +If there is a single button, it is activated by Esc. With two buttons, the left button is activated by Esc and +the right button is activated by ENTER. With three buttons, the buttons are activated by, from left to right, +ESC, SPACE and ENTER. + + +Version 3.5 of the window server added the ability to provide the notifier services (accessed via p_notify +and p_notifyerr). In EPOC terminology, the window server is said to "hook the notifier". + + +On the S3, S3a and Workabout, the window server always hooks the notifier. + + +WINDOW SERVER REFERENCE + + +On an HC, version 3.5 the window server does not by default hook the notifier (for backward compatibility +with version 3 of the window server). However, an HC may be configured such that the window server +does hook the notifier - as described in the section System start-up in the first chapter. + + +If you remove the first parameter from wsAlertw or the first two parameters from wsAlerta, the remaining +parameters correspond to the 5 parameters to p_notify. + + +If the window server has hooked the notifier, the program: + + +#include + + +GLDEF_C INT main(VOID) +{ +p_notify ("Hello World",NULL,NULL, NULL, NULL) ; +return (0); + + +} + + +produces the same result as the above example using wsAlertw - visually at least (and assuming that the +program is still called sample.img). + + +However, there are differences between wsAlertW and p_notify: + + +e = The alert presented by p_not ify is system modal - the user can't task away from it. In contrast, +wsAlertw is not system modal. For example, if a program reports a "No system memory" error +using wsAlertw, it can reasonably include a "Retry" option because it is possible to task to +another process and release memory (say by exiting a task) before returning to the alert and +selecting the Retry button. + + +e =6The caller of p_notify need not be a client of the window server. + + +e = When p_notify is called, the alert is presented regardless of whether the calling client is +foreground or not (although calling p_not ify does not displace the foreground client). If a +background client calls wsAlertw, the alert is not drawn until that task is made foreground. In +some circumstances, it may be desirable to call wclientPosition(0,0) and then wrlush to make +the caller foreground before calling wsAlertw. + + +e As well as having an extra leading parameter, wsAlertw has a stack-based calling convention +which is prototyped in such a way that unnecessary trailing NULLs may be omitted whereas +p_notify uses a register calling convention that requires all 5 parameters to be present. + + +The similarities between p_notify and wsAlertw are: + + +e In terms of setting up the display, all the features of wsAlertw are also available via p_notify +and vice versa. (Unfortunately, this means that the additional parameters associated with the +increased functionality have been squeezed into the existing p_notify compatible parameters in a +somewhat inelegant way.) + + +e =They are both designed not to fail when there is no free system memory. Both are ideal for +reliably reporting errors - including a "No System Memory" error. + + +The extra parameters are provided by passing data structures that are differentiated from a zero terminated +string by a leading zero. It follows that zero length strings should not be used as parameters to any of the +alert-based functions (they should be converted to NULLS). + + +Calling an alert-based function does not flush the client-side buffer. + + +On the HC, the font used to present alerts is determined by the sws_ir environment variable - as described +earlier. + + +wsAlertW Present and wait for an alert +INT wsAlertW(INT mode, TEXT *pT1, TEXT *pT2, TEXT *pOl, TEXT *p02, TEXT *p0O3); + + +Present a p_notify-like display where the user is presented with a message and prompted to respond by +pressing a button. As with p_notify, the function waits for the user to respond and returns the index (in +the range 0 to 2) of the button pressed. + + +When called from a regular application, the mode parameter should be ws_ALERT_CLIENT. Other values can +only be used by a special "alarm server" client. (The alarm server is a system component on the S3 and +S3a.) + + +Except for the additional mode parameter and except for the behavioural differences noted above, this +function provides the same services as p_notify - as described in the PLIB Reference manual. + + +2-14 + + +2 GENERAL WINDOW SERVER FUNCTIONS + + +The following describes only the extensions to the functionality normally provided by p_notify. +Note that wsAlertw is actually prototyped as: +INT CDECL wsAlertW(INT, TEXT *,TEXT *,TEXT *,...); + + +so that you can leave out trailing nuLLs when it is appropriate to do so. The compiler will complain if you +leave out trailing nuLLs in a call to p_notify (because p_notify uses a register calling convention which +does not permit a variable number of parameters). + + +Access to built in text + + +You can access operating system text (such as an error message) by passing a 3 byte array in place of a +text string to any of the 5 text parameters. The contents of the array should contain: + + +byte 0 zero +byte | Oxfe (0376 in octal) +byte 2 the signed index of the operating system text as passed to p_gettext. + + +For example, the following program, again compiled and linked as sample.img: + + +#include +#include + + +LOCAL_D WSERV_SPEC wSpec; + + +LOCAL_C VOID AlertErr(INT err,TEXT *msg) + + +TEXT bb[3]; +bb[0]=0; + +bb[1]=0xfe; +bb [2]=err; + + +wsAlertW(WS_ALERT_CLIENT,msg, &bb[0],NULL) ; +} + + +GLDEF_C INT main(VOID) +{ +wConnect (&wSpec, 0,W_CONNECT_PRIORITY) ; +AlertErr (E_GEN_NOMEMORY, "Failed to save"); +return (0); + + +} +when run on the HC, displays: + + +Failed to saye +Mo system memory + + +Continue +Esc + + +when run on the S3a under version 4 of the window server, displays: + + +Failed to save +No system memory + + +Continue + + +2-15 + + +WINDOW SERVER REFERENCE + + +and when run on the Workabout displays: + + +Sample + + +Failed to save +No system memory + + +Continue + + +LEsc_] + + +Formatted text with 3 message lines + + +If the first two bytes at pT1 are zero, pT2 is ignored and wsAlertw assumes that the two zero bytes are +immediately followed by: + + +e an array of three DEsc structs + + +¢ immediately followed by a character buffer of maximum length w_ALERT_TEXT_MAx_LEN (80) that +contains the text for the three lines + + +The struct Desc is defined in wlib.h as: + + +typedef struct +{ +UBYTE hposition; +UBYTE length; +UWORD offset; + + +} DESC; +where +hposition is either 0xff for centred text or any other value to specify the pixel position +from the left of the alert +length is the length of the text for the line, to be taken from the buffer +offset is the offset of the start of the text relative to pti + + +Such a data structure would normally be built up by a function as in, for example: + + +LOCAL_C VOID CDECL Alert3(TEXT *m1,TEXT *m2,TEXT *m3) +{ +TEXT *pt; +TEXT **pps; +DESC *pd, *pdend; + + +struct { +WORD zero; +DESC line[3]; +TEXT buf [W_ALERT_TEXT_MAX_LEN]; +} al; + + +al.zero=0; + +pt=éal.buf[0]; + +pps=é&ml1; + +for (pd=éal.line[0],pdend=pd+3; pdhposition=0xff; +pd->length=p_slen(*pps) ; +pd->offset=pt-— (TEXT *)&al; +pt=(TEXT *)p_bcpy (pt, *pps++,pd->length) ; +} + +wsAlertW(WS_ALERT_CLIENT, (TEXT *) &al,NULL, NULL) ; + + +} + + +2-16 + + +2 GENERAL WINDOW SERVER FUNCTIONS + + +where the following line: +Alert3("Line 1","Line 2","Line 3"); + + +when executed on an HC, displays: + + +Line 1 +Line 7? + + +Line 3 +Continue + + +Esc + + +when executed on the S3a under version 4 of the window server, displays: + + +Continue + + +and when executed on the Workabout, displays: + + +Sample + + +Line 1 +Line +Line 3 + + +Continue + + +LEsc_] + + +Text with 4 message lines + + +This is possible in version 4 of the window server and is achieved by oring the ws_ALERT_B attribute into +the mode parameter. The interpretation of the parameters pt1 and pt2 is changed. + + +The text referenced by the parameter pT1 is used as the title and is placed above the main box. This +contrasts with the normal practice of wsAlertw in using the program name as the title. + + +The text referenced by the parameter pr2 is a single string but can include up to three carriage return +characters (0x13 or '\r' in C programs). Each carriage return character causes the remaining text to be +wrapped to a new line and each line is centred within the main display box. + + +Note that this text need not contain carriage return characters. If the text is too long to fit onto one line, +carriage returns will be inserted at appropriate points. Whole words, however, will not be split. + + +2-17 + + +WINDOW SERVER REFERENCE + + +The sample code fragment below illustrates how this can be done. Note also the use of three buttons in +this example: + + +TEXT *ptxt,text[108]; + +ptxt = p_scpy(&text[0],"This is an example \r to demo"); +ptxt = p_scpy(ptxt,"nstrate the use \r"); + +ptxt = p_scpy(ptxt,"of four\r"); + + +ptxt = p_scpy(ptxt," message lines in the alert box"); + + +wsAlertW(WS_ALERT_CLIENT|WS_ALERT_B, "Title Line", &text[0],"A","B","C"); + + +This results in the following alert when run on a Series 3a machine under version 4 of the window server: + + +Tithe Line + + +This is an example +to demonstrate the use +of four +message lines in the alert box + + +Although the Workabout uses version 4, its screen is not large enough to display four lines of text in an +alert. If the above code is run on Workabout, the fourth line is not displayed and the appearance of the +alert is as follows: + + +Title line + + +This is an example +to demonstrate the use + + +of four + + +Note that the techniques used to access built in text and formatted text with three message lines as +described earlier, cannot be used with the attribute ws_ALERT_B set. + + +If any illegal parameters are passed, the function will raise a W_PANIC_ALERT panic. + + +wsAlertA Present an alert +VOID wsAlertA(INT mode,WORD *pstat,TEXT *pt1,TEXT *pt2,TEXT *pbl,...); + + +This function is not suitable for general use in applications. It is intended to be used only by the process +designated to be the alarm server; any application, however, may use wsAlertw. + + +Presents a p_notify-like display where the user is presented with a message and prompted to respond by +pressing a button. + + +Functionally identical to wsalertw except that it returns immediately without waiting for the user to +respond. It is the asynchronous form of wsAlertw. + + +Asynchronous requests are described in the chapter Asynchronous Requests and Semaphores in the PLIB +Reference manual. + + +When the user does respond, the calling process I/O semaphore is signalled and the index of the button +pressed (0, | or 2) is written to *pstat. + + +Once launched, there is no way of cancelling an asynchronous alert - it can only be completed by the user. + + +If any illegal parameters are passed, the function will raise a W_PANIC_ALERT panic. + + +2-18 + + +2 GENERAL WINDOW SERVER FUNCTIONS + + +wsAlertUpdate Update a pending alert +INT wsAlertUpdate (TEXT *pt1,TEXT *pt2,TEXT *pbl,...); + + +This function is not suitable for general use in applications. It is intended to be used only by the process +designated to be the alarm server; any application, however, may use wsAlertw. + + +Update an asynchronous alert where the parameters pt1, etc are as for wsAlerta. +Does nothing if the user has already responded to the alert. + + +If any illegal parameters are passed, the function will raise a w_pANIC_ALERT panic. + + +Pe ee En a ee +Status windows + + +Status windows are part of the $3, S3a and Workabout user interfaces. + + +In principle, status windows are also supported on an HC that is running version 3.5 of the window server. +However, their use requires the cooperation of a client which has declared itself as the application key +handler by calling wappKeyHandler (the application key handler is the shell on the $3, S3a and +Workabout). In practice, it would be difficult for an external developer to set up status windows on the +HC. + + +The window server supports two kinds of status window: + + +temporary If temporary status windows are enabled, the window server displays a pop-up +transient status window in front of the foreground client's existing windows +when PSION+MENU is pressed. The status window remains for 2 to 2.5 seconds. + + +permanent While enabled, the window server maintains a permanent status window to the +right of the screen and behind existing windows. If an application supports a +permanent status window, it is meant to "tile" its main top-level window with +the status window. On the S3 and S3a, higher level software toggles the +presentation of a permanent status window in response to a CTRL+MENU press. + + +The following shows the S3 World application's display with a temporary status window to the right of the +screen using a version prior to version 4 of the window server: + + +7 616 B44 + + +Wellinatoriy +Hew “ealand Dist! 11689 fi + + +There is no difference between the appearance of a permanent and a temporary status window. + + +The status window gives the user a view of (from top to bottom): + + +a program icon A client's icon is determined by a structure pointed to by the application key +handler. +a program name If the reserved static patStatusNamePtr contains other than NULL, it is assumed + + +to point to a zero terminated string that gives the program name (of up to 8 +characters, terminated by any'.'). If patstatusNamePtr is NULL, the process +name is used. + + +time and date The time and data is presented following the information in the £_conrte struct +as obtained by calling p_getctd. + + +2-19 + + +WINDOW SERVER REFERENCE + + +The following shows the S3a World application's display with a temporary status window to the right of +the screen using version 4 of the window server: + + +3 616 64 4 + + +gellington, +Dist: 11689 Miles United|_Thuz9 + + +|New Zealand + + +Note that the S3a has a larger and finer grained screen (480 x 160) pixels). + + +In version 4 of the window server, the status window has been modified. The program name and the +program icon have changed places and four new features can be displayed (although not all are shown in +the above example): + + +e Low battery indicator +e SSD pack indicators +e Remote link indicator +e Caps lock indicator + + +Each of these features can be disabled by setting the appropriate flags when configuring the window +server uSiNg wSystem. + + +The following illustration shows the S3a Database application display with a permanent status window to +the right of the screen. The application's main window has been neatly tiled with it: + + +First Name(s}: A.P. +Surname(s)-+ Another +Address: 123 Anyavenue +Anytown +Anycounty + + +Post Code: <1 0A +#2 Home: 071-123-4567 + + +Find: another + + +On the Workabout, an equivalent display of the Database application appears as shown below: + + +Name->A.P. Another +a Home: 071-123-4567 +Address: 123 Anyavenue +Anytown, Anycc + + +Find: another + + +Applications can have different 'modes' of operation, the precise definition being dependent on the +application. As well as using menu options and ‘hot' keys to switch between the different modes, an S3a +application can set the diamond key to cycle around some or all of them. + + +By using the wsSetList function, introduced in version 4, the program icon in the status window can be +replaced by a list of modes. In the S3a display shown above, all three modes of the Database application +are shown with the diamond symbol pointing to the current mode. + + +Note that the Workabout status window does not display either the application's icon or a list of modes. + + +2-20 + + +2 GENERAL WINDOW SERVER FUNCTIONS + + +Compatibility mode status window + + +In version 4, applications on the S3a and Workabout can run in $3 compatibility mode. This allows an +application to have the 'look' and 'feel' of the same application running on an S3. On the S3a, this is +achieved by doubling up the pixels. For example, a line which is 10 x 1 pixels on the S3 will be drawn 20 +x 2 pixels on the S3a and should 'look' the same. On the Workabout, applications running in compatibility +mode will normally exactly match the S3 appearance. + + +If an application is running in compatibility mode on the S3a or Workabout, then a call to wsEnable +creates a compatibility mode status window which looks and behaves like an S3 status window. + + +Alternatively, the version 4 function wst atusWindow can be used to create a compatibility status window. + + +wsEnable Enable the permanent status window + + +VOID wsEnable (VOID) ; + + +Create and maintain a permanent status window, behind existing windows. Does nothing if a permanent +status window already exists. + + +Before calling wsEnab1e, the calling application should resize its main window such that it is tiled with +the status window. + + +Under version 4, the required window extent should be determined by calling wInquirestatusWindow to +get the size of the status window and then performing a simple calculation. Under earlier versions of the +window server, uS€ wsScreenExt. + + +In version 4, if running in compatibility mode on the S3a or Workabout, the status window will have the +appearance of the S3 status window. + + +wStatusWindow Set the state of the status window + + +VOID wStatusWindow(INT state); + + +Available in version 4 only, this sets the permanent status window into one of a number of mutually +exclusive states by setting the parameter state to one of the following: + + +W_STATUS_WINDOW_OFF no status window is visible + +W_STATUS_WINDOW_SMALL display the small version of the status window +W_STATUS_WINDOW_BIG display the full size version of the status window +W_STATUS_WINDOW_CTBY display the S3 compatibility status window + +Calling this function with the parameter value w_sTATUS_WINDOW_oFF is equivalent to calling +wsDisable(); calling this function with the parameter value w_sTATUS_WINDOW_BIG (or +W_STATUS_WINDOw_cTBy if in S3 compatibility mode) is equivalent to calling wsEnable(). + + +See the description of wInquireStatusWindow (or, for versions of the window server earlier than version +4, wsScreenExt) for a means of determining the size and position of a status window. + + +wsScreenExt Get screen extent for tile with status window +VOID wsScreenExt (P_EXTENT *pext) ; + + +This function should only be used when running versions of the window server earlier than version 4. It is +available in version 4 for compatibility only. + + +It is strongly recommended that the function wInquireStatusWindow be used instead of wsScreenExt in +version 4 of the window server. + + +The function writes the extent of the screen remaining to the data structure pointed to by pext when there +is a permanent status window. + + +2The resize may fail with out of memory - so it is best to delay wsEnable until after the resize is +successful. + + +2-21 + + +WINDOW SERVER REFERENCE + + +The P_EXTENT struct is defined as: + + +typedef struct +{ +WORD x; +WORD y; +} P_POINT; + + +typedef struct +{ +P_POINT tl; +WORD width; +WORD height; +} P_EXTENT; + + +Series 3 applications that support permanent status windows running under older versions of the window +server (i.e. earlier than version 4) can use wsScreenExt to determine the extent of the window to use while +a permanent status window is enabled. + + +Recall that the size of the entire screen (used in the absence of a permanent status window) may be +obtained from the wsERv_sPEc struct filled in by wconnect. For example: + + +GLREF_D WSERV_SPEC *wserv_channel; +LOCAL_D P_POINT ScreenSize; + + +ScreenSize=wserv_channel->conn.info.pixels; + + +wsUpdate Update the permanent status window +VOID wsUpdate(INT flags); + +Update the displayed permanent status window. + +The parameter flags can be one of: + + +WS_UPDATE_NAME to change the displayed permanent status window name (for example, after +changing DatStatusNamePtr). + + +WS_UPDATE_CLOCK to update any displayed clocks (for example, after changing settings such as +12/24 hour, analog/digital, the time separator and so on). + + +wsDisable Disable the permanent status window +VOID wsDisable (VOID) ; +Destroy the permanent status window (if one exists). + + +Before calling wsDisab1le, the calling application should resize its main window to take up the whole +screen. As with wsEnable, the required window extent may be determined by calling +wiInquireStatusWindow and doing a simple calculation. + + +wsEnableTemp Enable temporary status windows +VOID wsEnableTemp (VOID) ; +Enable the window server's processing of PSION+MENU to present a temporary status window. + + +Unlike wsEnable, the effect of this call is system wide. On the S3 and S3a, wsEnableTemp is called by the +shell as part of its initialisation. + + +wsDisableTemp Disable temporary status windows + + +VOID wsDisableTemp (VOID) ; +Disable the processing of PSION+MENU to present a temporary status window. + + +The effect of this call is system wide. Calling wsDisableTemp on the $3 and S3a will disable temporary +status windows for all applications. + + +2-22 + + +2 GENERAL WINDOW SERVER FUNCTIONS + + +wsSetList Set list of modes to display in status window + + +INT wsSetList (UINT count, TEXT **plist,UINT pos); + + +Available in version 4 only, this function sets up the text for the list of modes to be displayed in the status +window. + + +The count parameter is the number of text items in the list; the plist parameter is a pointer to an array of +string pointers (one string per mode) and pos is the position within the list where the diamond symbol is +to be placed. The first position is given a value of 0. + + +If the diamond symbol is not to be shown, pos should be set to w_STATUS_WIN_NO_DIAMOND. + + +To replace the list of modes with the application icon, count should be set to w_sTATUS_WINDOW_ICON. +With count set to this value, the other two parameters are ignored. Typically, a call would look like this: + + +wsSetList (W_STATUS_WINDOW_ICON, NULL, 0) ; + + +The function returns 0 if successful or =_GEN_Nomemory if it fails to allocate space for the new list. + + +Note that calling wssetList on the Workabout has no visible effect, since its status window does not +display a list of modes. + + +wsSelectList Set select position in status window mode list + + +VOID wsSelectList (INT pos); + + +Available in version 4 only, this function allows the diamond symbol in the list of modes in the status +window to be (re-)positioned. + + +The position is specified by giving a value to the parameter pos. The first position is given a value of 0. If +the diamond symbol is not currently shown, setting a position will cause it to reappear. Giving pos a value +of w_STATUS_WIN_NO_DIAMoND causes the diamond symbol to be removed from the status window. + + +Note that calling wsselectList on the Workabout has no visible effect, since its status window does not +display a list of modes. + + +winquireStatusWindow Inquire state and extent of status window +INT wiInquireStatusWindow(INT state,P_EXTENT *pextent) ; +Available in version 4 only, this function does two things: + + +e it returns the current state of the status window as set by wstatusWindow. It returns one of the +values w_STATUS_WINDOW_OFF, W_STATUS_WINDOW_SMALL, W_STATUS_WINDOW_BIG and +W_STATUS_WINDOW_CTBY. + + +e it fills in the pextent of the status window corresponding to state. In other words, by setting +state to one of the values w_sTATUS_WINDOW_OFF, W_STATUS_WINDOW_SMALL, +W_STATUS_WINDOW_BIG Of W_STATUS_WINDOW_CTBY, it supplies the position, width and height of a +status window of that type. + +Further, if state is given a value of -1, the extent of the current status window is supplied. + + +It is interesting to note that if the status window is off, the extent information describes a status window +located at the right hand edge of the screen with zero width and full height. + + +For a description of the p_ExTENT structure, see wsScreenExt. + + +2-23 + + +WINDOW SERVER REFERENCE + + +Configuring the window server + + +The functions which have a system wide effect on the window server (as opposed to just affecting the +calling client) are: + + +wSystem which is described next +wsEnableTemp to enable/disable permanent status windows (as described above) +wsDisableTemp + + +These functions should only be used when an application takes over the whole machine. This is more +likely on an HC than say an S3, S$3a or Workabout. + + +wSystem Configure the window server +INT wSystem(UINT new_flags,UINT flag_mask) ; + + +Set an internal set of flags to modify the system-wide behaviour of the window server where: + + +new_flags is a bit mask containing the values of the bit flags to be modified +flag_mask is a bit mask indicating (by those bits that are set) the bit flags that are to be +modified + + +The function returns the old value of the flags. +The flags are of the form ws—ERV_FLAG_xxx where xxx is one of: + + +Stops the window server from restarting the shell (that is, sys$shll.img) +NO_SHELL_REBOOT whenever it terminates. Clearing this flag when there is no shell running causes +the window server to restart the shell. Available on all machines. + + +NO_NOTIFIER_REBOOT The same as above except it applies to the notifier process (sys$ntfy.img). +Available on the HC and MC. + + +Prior to version 4, the window server on the S3 always provides the notifier +itself and never starts a sys$ntfy.img. + + +Under version 4, this flag can be set for the S3a and Workabout because the +possibility of building a separate notifier process exists. + + +HOOK_NOTIFIER If set, the window server attempts to hook the notifier, as explained in the +earlier Alerts section of this chapter. All MC versions are unable to hook the +notifier. + + +Prior to version 4, this flag applies to the HC only; the S3 effectively assumes +that it is permanently set. + + +Under version 4, this flag can be set for the S3a and Workabout. + + +NO_PANIC_NOTIFY Disables the window server from reporting processes which terminate with a +panic or a negative reason code. Available on the HC, $3, S3a and Workabout +but not the MC. This flag is ignored unless the window server has hooked the +notifier. On machines other than the MC, you would set this flag to prevent the +window server from reporting abnormal terminations when HOOK_NOTIFIER is +set. + + +UPDATE_MSGS Enables the window server to send wM_TASK_UPDATE events to the shell to +inform it of the termination of any process (not just clients of the window +server). The MC version does not support WM_TASK_UPDATE events. + + +Prior to version 4, this flag applies to the HC only; the S3 effectively assumes +that it is permanently set. + + +Under version 4, this flag can be set for the S3a and Workabout. + + +2-24 + + +2 GENERAL WINDOW SERVER FUNCTIONS + + +LOW_BATTERY_WARNINGS _ If set, the window server notifies the user of a low lithium or main battery. Note +that the window server only checks for low battery when the machine is turned +on. On the HC, the window server is only informed of the machine being +switched on after p_setonevent (TRUE) has been called. The MC version of the +window server does not support low battery warnings. + + +Prior to version 4, this flag only applies to the HC; on the S3, the window +server always reports low battery warnings. + + +Under version 4, this flag can be set for the S3a and Workabout. + + +HUNG_UP_SW If set, the window server presents a "hung up" status window if the foreground +task is not using backed-up windows and fails to respond to redraw events. The +MC version of the window server does not support status windows. + + +Prior to version 4, this flag only applies to the HC; the S3 effectively assumes +that it is permanently set. + + +Under version 4, this flag can be set for the S3a and Workabout. + + +The following flags are introduced in version 4 and apply only to S3a and Workabout machines. + + +SW_NO_LOW_BATTERY If set, it disables the low battery indicator in the status window. +SW_NO_PACKS If set, it disables the two pack indicators in the status window. +SW_NO_LINK If set, it disables the link indicator in the status window. +SW_NO_CAPS If set, it disables the caps lock indicator in the status window. + + +Prior to version 4, when the window server starts, the internal flags are all clear although, on the HC, this +can be altered by setting the sws_rn environment variable. + + +Under version 4 of the window server the internal flags on the S3a and Workabout can be altered, like on +the HC, by setting the sws_rL environment variable. + + +In practice, wsystem 1s more likely to be used on the HC rather than the S3, S3a, Workabout or MC. See +the section System start-up in the Introduction chapter for further discussion (including further details on +$wS_FL) and examples of the use of wsystem. + + +Attached Clients + + +This section only applies to large screen versions of the window server, such as the MC. + + +Clients can attach to and detach from each other by use of the wattachToClient, +wAttachToForegroundClient and wDetachClient Calls. + + +The client that calls the attach function is attached in front of the client it is attaching to. + + +When clients are attached they move round in the task order together - when one of the attached tasks +moves, it pulls the other task (or tasks) with it. When they become foreground, all attached tasks are sent a +WM_FOREGROUND event. + + +Two examples of the use of attached clients on the MC are: + + +e The system notifier sys$ntfy uses wAttachToForegroundClient to attach itself to the foreground client +to display its message. + + +e The voice server uses wAttachToClient to attach itself to its client (where both are clients of the +window server) to implement a dialog box as a separate process. + + +In both cases, the attaching client is behaving as if it were part of the client it is attached to. The notifier +could have been implemented using wclientPosition to make itself visible but the holder of the +foreground would then inappropriately go into background (and get a wM_BACKGROUND event). + + +When a client attaches to another, the window server sends a wM_ATTACHED event to the client being +attached to. When the attaching client detaches, it sends a wm_DETACHED event to the client being detached +from. + + +A detaching client is positioned to the back of all clients. + + +2-25 + + +WINDOW SERVER REFERENCE + + +wAttachToClient Attach to client + + +INT wAttachToClient (UINT pid); +Attach the caller to client pid. + + +If client pid does not exist, the function leaves or returns E_FILE_NXIST. + + +wAttachToForegroundClient Attach to foreground client + + +VOID wAttachToForegroundClient (VOID) ; +Attach the caller to the foreground client. + + +Does nothing if the caller has the foreground. + + +wDetachClient Detach from client + + +VOID wDetachClient (VOID) ; +Detach from a client and position to the back of all clients. + + +If the caller is no longer attached to another client (say because that client has terminated), the caller is +just positioned to the back. + + +PSO Oe a eae | +Miscellaneous + + +A number of general functions which do not fit under any of the previously discussed topics are described +here. Unless otherwise stated, they are all introduced in version 4 of the window server. + + +wSupportinfo Get information on supported features + + +VOID wsSupportInfo(.i.W_SUPPORT_INFO *pinfo); + + +The function fills the w_suppoRT_INFo type structure with information on the currently supported +features. The supplied parameter pinfo must point to a structure of type Ww_SUPPORT_INFO. + + +It can set the following values in the flags member: +W_SUPPORT_GREY if set, the window server supports the current scheme for drawing grey graphics + + +W_SUPPORT_CTBY_S3 if set, the window server supports a Series 3 compatibility mode (there is no +distinction between different Series 3 compatibility modes, such the two that +are available on the Workabout) + + +Currently, no other information is returned. The rest of the w_supPpoRT_INFo structure is set to zeros. The +function is well placed for expansion in future versions and releases of the window server. + + +The w_SUPPORT_INFO structure is defined as follows: + + +typedef struct +{ +UINT flags; +UINT fillers[15]; /* will be filled with 0's */ +} W_SUPPORT_INFO; + + +wDisableKeyClick Set or cancel key click disable state + + +VOID wDisableKeyClick(INT state); +If state is set to TRUE, the behaviour of the key click for an application is changed: + + +e = The key click is disabled while the application is in foreground. +e = The key click state is reset when the application goes to background. + + +Setting state to FALSE cancels this state for an application. + + +2-26 + + +CHAPTER 3 + + +WINDOWS + + +Creating and initialising a window + + +Window attributes + + +The functions: +wCreateWindow +wSetWindow + + +wiInquireWindow + + +to create a window and set its attributes +to set a window's attributes + + +to sense a window's attributes + + +take the address of a w_winpata struct as a parameter to hold the window attributes where the w_winpaTa +struct is defined as: + + +typedef struct + + +{ +WORD x; +WORD y; + + +} P_POINT; + + +ttypedef struct + + +{ +P_POINT + + +tale + + +WORD width; +WORD height; +} P_EXTENT; + + +ttypedef struct + + +{ + + +UWORD flags; +P_EXTENT extent; +WORD mouse_icon; +UBYTE background; +UBYTE filler; + +} W_WINDATA; + + +where: + + +flags + + +extent + + +mouse_icon + + +background + + +is a set of binary attributes, described below. In the root window, the flags field +is zero (so all the binary attributes are clear). + + +is the position and size of the window relative to its parent in pixel coordinates. +In the root window the extent coincides with the whole screen. + + +is the ID of the window mouse icon (only used when the machine has a +pointing device such as on the MC) + + +specifies whether the window is backed-up by a bitmap (or bitmaps) and, if not, +how the window should be prepared when it is validated + + +3-1 + + +WINDOW SERVER REFERENCE + + +background (up to version 3.5) + + +In versions of the window server up to and including 3.5 the background field of the w_winpata struct +should be one of: + + +W_W + + +W_W + + +W_W + + +W_W + + +IN_BACK_BITMAP all drawing to the window is duplicated to an off-screen bitmap. Redraws are +automatically done from this bitmap, so no ww_REDRAW events are ever +generated. When the background has this value, it may not be altered by calling +wSetWindow. Not available on version 2 of the window server. + +IN_BACK_CLR clear the pixels in the window on validation (the root window has this value). +This is the default value. + +IN_BACK_SET set the pixels in the window on validation. + +IN_BACK_NONE do nothing on validation (on the assumption that the drawing covers every + + +pixel). Best for flicker-free graphics. + + +background (version 4) + + +In version 4 of the window server, there are changes in meaning and values caused by the introduction of +grey. To control drawing to the normal (black) plane, one of the following must be set: + + +W_WIN_BACK_BITMAP all drawing to the normal (black) plane of the window is duplicated to an +off-screen bitmap. Redraws are automatically done from this bitmap, so no +WM_REDRAW events are ever generated. When the background has this value, +it may not be altered by calling wset window. + +W_WIN_BACK_CLR clear the pixels in the normal (black) plane of the window on validation (the +root window has this value). This is the default value. + +W_WIN_BACK_SET set the pixels in the normal (black) plane of the window on validation. + +W_WIN_BACK_NONE do nothing to the normal (black) plane of the window on validation (on the +assumption that the drawing covers every pixel). Best for flicker-free +graphics. + +W_WIN_BACK_CLR_NO_REDRAW to clear the pixels in the normal (black) plane of the window but prevent +any drawing or redrawing to this specific plane. + +W_WIN_BACK_SET_NO_REDRAW to Set the pixels in the normal (black) plane of the window but prevent any +drawing or redrawing to this specific plane. + +W_WIN_BACK_NONE do nothing to the normal (black) plane of the window on validation but also + +NO_REDRAW prevent any drawing or redrawing to this specific plane. + + +To control drawing to the grey plane, one of the following must be ored into the background field with + + +one of the above normal plane values: + +W_WIN_BACK_GREY_BITMAP all drawing to the grey plane of the window is duplicated to an off-screen +bitmap. Redraws are automatically done from this bitmap, so no ww_REDRAW +events are ever generated. When the background has this value, it may not +be altered by calling wset window. + +W_WIN_BACK_GREY_CLR clear the pixels in the grey plane of the window on validation (the root +window has this value). + +W_WIN_BACK_GREY_SET set the pixels in the grey plane of the window on validation. + +W_WIN_BACK_GREY_NONE do nothing to the grey plane on validation (on the assumption that the +drawing covers every pixel). Best for flicker-free graphics. + +W_WIN_BACK_GREY_CLR to clear the pixels in the grey plane of the window but prevent any drawing + +NO_REDRAW or redrawing to this specific plane. This is the default value. + +W_WIN_BACK_GREY_SET to set the pixels in the grey plane of the window but prevent any drawing or + +NO_REDRAW redrawing to this specific plane. + +W_WIN_BACK_GREY_NONE do nothing to the grey plane of the window on validation but also prevent + +NO_REDRAW any drawing or redrawing to this specific plane. + + +3 WINDOWS + + +If drawing is enabled to both the normal (black) and the grey planes, then both planes will be moved when +scrolling or moving a window. + + +If no drawing is intended for one of the planes in a window, then overheads can be cut by disabling the +unused plane. For example, if no drawing is to be done to the grey plane, disable this plane by NOT +setting any of w_WIN_BACK_GREY_CLR, W_WIN_BACK_GREY_SET, W_WIN_BACK_GREY_NONE OF +W_WIN_BACK_GREY_BITMAP. + + +Note that if both w_wmn_BAcK_BITMAP and w_WIN_BACK_GREY_BITMapP are set, then the window will be +backed up to two bitmaps, one for the normal plane and one for the grey plane. + + +Also note that setting one of: + + +W_WIN_BACK_CLR_NO_REDRAW + + +W_WIN_BACK_SET_NO_REDRAW + + +W_WIN_BACK_NONE_NO_REDRAW + + +and setting one of: + + +W_WIN_BACK_GREY_CLR_NO_REDRAW + + +W_WIN_BACK_GREY_SET_NO_REDRAW + + +W_WIN_BACK_GREY_NONE_NO_REDRAW + + +is equivalent to setting the w_wIN_No_REDRaw bit (as a parameter to wcreat eWindow). +flags (all versions) +The following bits of f1ags apply to all versions of the window server on all machines: + + +W_WIN_NO_REDRAW windows with this flag set never receive redraw events. This flag may not be +altered by a wSetwindow command. + + +W_WIN_PRIORITY redraw events for windows with this flag set have priority over redraw events +for windows with this flag clear. + + +flags (version 4) + +The following bit of f1ags applies to version 4 of the window server: + +W_WIN_DOUBLE_PIXEL when set, causes all graphics in this window to work in double pixel mode. +Large screen flags + +The following bit of f1ags applies only to large screen versions of the window server such as the MC: + + +W_WIN_FOREGROUND_ONLY if set, the window is only visible while the client is foreground. Note that a +descendant window of a roREGROUND_ONLY window is necessarily also +FOREGROUND_ONLY regardless of the value of this flag. This flag may not be +altered by a wSetwindow command. + + +Mouse-related flags + + +The following bit of f1ags apply only when the machine has a pointing device, such as on the MC: + + +W_WIN_NO_MOUSE a window with this flag set will not receive any mouse events (however, +the mouse cursor is still displayed). All other mouse-related flags have no +affect when this flag is set. + + +W_WIN_INACTIVE if a mouse click occurs anywhere in a window with this flag set or in any +of its descendants, a wM_AcTIVE event is sent to the window. + + +W_WIN_INPUT_ONLY if set, the window is input-only. Input-only windows are invisible and exist +solely for the purpose of detecting mouse events. This flag may not be +altered by a wSetwindow command. + + +W_WIN_MOUSE_MOVE if set, mouse movement events are generated when the mouse button is up. +W_WIN_MOUSE_DRAG if set, mouse movement events are generated when the mouse button is +down. + + +3-3 + + +WINDOW SERVER REFERENCE + + +W_WIN_MOUSE_GRAB if set, the mouse is automatically grabbed when the mouse button is +pressed. The grab is automatically released when the mouse button is +released and a wM_MOUSE event of type WM_MOUSE_RELEASE is sent to the +grabbing window, even if the release occurs outside the window. If +W_WIN_MOUSE_DRAG is also set, any intermediate wM_MouSE_MOVE events are +also delivered to the grabbing window. + + +W_WIN_RUBBER_BAND If a mouse down event occurs in a window with this bit set, it and + +CAPTURE subsequent mouse and keyboard events are captured to the window server's +rubber band processing until the rubber band mode is terminated. This first +mouse click generates a WW_RUBBER_BAND_INIT event to which the client +must respond with a call to wRubberBand. This flag may not be altered by a +wSetWindow command. + + +W_WIN_RUBBER_BAND If when calling wRubberBand in response to a WM_RUBBER_BAND_INIT event + +COMPLETE_ON_RELEASE you specify that the rubber band should be completed on a mouse up event, +you should also set this bit. This flag may not be altered by a wSet Window +command. + +wCreateWindow Create a window + + +INT wCreateWindow(UINT parent_id, UINT field_set, .i.W_WINDATA *pwindata, UWORD handle); +Create a window and, if successful, return the positive ID of the window where: + + +parent_id is the window ID of the parent window. To create a top-level window, where +the parent is the root window (ie the whole screen), pass parent_id as zero. + + +handle is the client's own identifier for the window (which must be non-zero) to be +embedded in events which are directed at the window (for example, redraw and +mouse events). In medium to large applications, handle is commonly the +address of a control block which contains the window ID. + + +field_set is a set of bit flags which specify (by being set) which fields in the pwindata +struct are to be used to set the window attributes. In most cases, an attribute +which is not set from pwindata is inherited from parent_id (as detailed +below). If field_set is zero, pwindata 1s ignored. + + +pwindata is the address of a W_WINDATA struct as described above. If field_set is zero, +pwindata is ignored. + + +The bits in field_set are made up of the same bit masks as for pwindata->flags to indicate that the +corresponding bit in pwindata->flags should be used. And, in addition, field_set may contain: + + +W_WIN_EXTENT to uSe pwindata->extent +W_WIN_MOUSE_ICON to use pwindata->mouse_icon +W_WIN_BACKGROUND to uSe pwindata->background + + +If a field_set bit is clear, the corresponding attribute is inherited from the parent window parent_ida, +except for: + + +W_WIN_RUBBER_BAND_CAPTURE +W_WIN_INACTIVE +W_WIN_NO_REDRAW +W_WIN_PRIORITY +W_WIN_FOREGROUND_ONLY + + +These five attributes are never inherited from any parent window. If they are not set explicitly, by setting +the appropriate bit in fielda_set and the corresponding data value in the w_winpata struct pointed to by +pwindata, they are set to zero. + + +If parent_id has one or more child windows, the new window is created in front of its siblings. + + +After a successful return from wcreat eWindow, the window is just a dormant data structure in the window +server's data segment with no visibility on the screen. You can't draw to the window and you won't get any +redraw events (or any mouse events if there is a pointing device) until the window is initialised by calling +wInitialiseWindowTree, described below. + + +3-4 + + +3 WINDOWS + + +If the function fails because there is insufficient memory, it calls p_leave (E_GEN_NOMEMORY) or returns +E_GEN_NOMEMoRY, depending on whether wDisableLeaves has been called. + + +See the description of wconnect for an example. + + +wSetWindow Set window attributes + + +VOID wSetWindow(UINT wid, UINT field_set, .i.W_WINDATA *pwindata) ; + + +Set one or more window attributes of the window with ID wia where field_set and pwindata are as for +wCreateWindow, described above. + + +The function wSetwindow ignores the following bits in field_set which correspond to window attributes +which are not modifiable: + + +W_WIN_NO_REDRAW + +W_WIN_INPUT_ONLY +W_WIN_FOREGROUND_ONLY +W_WIN_RUBBER_BAND_COMPLETE_ON_RELEASE + + +You cannot modify any of the attributes of the root window. +In practice, wSetWindow 1s commonly use to move and/or resize a window. + + +If the size of a backed-up window is increased, the backup bitmap(s) will also be increased and the +additional area (to the right and below) is filled with zeros. + + +In this situation, the call can fail with an out-of-memory condition; it should be noted that such a failure +might not be reported immediately because of the buffering of window server requests (see the Clients and +the window server section in the Introduction chapter). + + +Any areas of the window that are exposed as a result of making the call to wset window (because the effect +has been to expand or move the window) are invalidated. Areas that are covered, moved offscreen, or lost +because the window has become smaller are marked as valid, thus preventing any redraws that might have +been pending for these areas. The validity of any other areas is not affected by the call. + + +winquireWindow Get window attributes + + +INT wiInquireWindow(UINT wid, .i.W_WINDATA *pwindata) ; + + +Write a copy of window wia's extent and flags to *pwindata (pwindata->mouse_icon and +pwindata->background are left undefined). + + +wlnitialiseWindowTree Initialise window tree + + +VOID winitialiseWindowTree(UINT wid); + +Initialise window wid and all its descendants. + +None of these windows may be initialised again. + +Provided that the window is not made invisible between creation and initialisation, the following occurs: + + +backed-up window! The backup bitmap (which is initialised with zeros when the window is created) +is copied to any visible parts of the window, clearing it. In version 4 of the +window server there may be two backup bitmaps which are copied to the visible +parts of the window's normal and grey plane respectively. + + +no-redraw window2 Any visible pixels are cleared if the background attribute is w_wIN_BACK_CLR or +set if the background attribute is w_win_Back_seEt. In version 4 of the window +server, these attributes clear or set the visible pixels in the window's normal +plane while w_wIN_BACK_GREY_CLR and W_WIN_BACK_GREY_SET Clear or set the +visible pixels in the window's grey plane. + + +non-backed-up redraw _— Any visible parts are added to the update region (which will subsequently cause +window redraw events to be generated). + + +!Where the window attribute background is W_WIN_BACK_BITMaP (and/or w_WIN_BACK_GREY_BITMAP in +version 4 of the window server). + + +2Where the w_wIn_No_REDRAw window attribute is set. + + +3-5 + + +WINDOW SERVER REFERENCE + + +wCloseWindowTree Destroy a window and its descendants + + +VOID wCloseWindowTree(UINT wid); + + +Destroy window wid and all its descendants, freeing any associated window server resources (such as an +attached graphics context). + + +When destroying a window system, it is sometimes difficult to destroy windows bottom-up with respect to +the window parentage tree. To make life easier, the window server allows windows to be destroyed more +than once as long as other window server objects, such as graphics contexts, bitmaps, fonts, icons or +windows are not created in the mean time. + + +If you are using wGetEvent or wGetEvent Special rather than wGetEventWait, you should be very careful +about destroying windows while a request made by calling wcetEvent or wGetEvent Special is pending. +Bearing in mind the multi-tasking nature of the system and the fact that the window server runs at a +higher priority than its clients, it is quite possible for an event to be delivered before the window is +destroyed in which case there is the possibility that the next event will relate to a window which has +already been destroyed (a redraw event, say). + + +The solution to this problem normally involves calling wcancelGetEvent, as described in the first chapter. + + +winquireWindowOffset Get window to window offset + + +INT wiInquireWindowOffset (UINT from_wid, UINT to_wid, .i.P_POINT *poffset); +Write the offset of to_wid relative to from_wid tO poffset and return zero. +The P_POINT struct is: + + +typedef struct +{ +WORD x; +WORD y; +} P_POINT; + + +Useful when positioning windows relative to each other. To find the absolute position of a window on the +screen set from_wid to zero (the root window ID). + + +If the window server has a pending error with error number err, the function calls p_leave (err) or +returns err, depending on whether wDisableLeaves has been called. + + +wReassignRootWindow Reassign the root window + + +VOID wReassignRootWindow(UINT wid); + + +Reassign the window ID of zero to mean the window wid rather than the root window which covers the +whole screen. + + +The assignation applies only to the calling client. +Passing a wid of zero resets the window ID of zero to mean the whole screen. + + +Used for creating development environments on a large screen version of the window server which +simulate a small screen environment. + + +Not available in version 2 of the window server. + + +Visible and invisible windows + + +wMakelnvisible Make window invisible +VOID wMakeInvisible(UINT wid); +Mark window wid as invisible. +When a window is marked as invisible it and all its descendants are made invisible. +The window server treats windows which are invisible as follows: +e if the window is backed-up, any drawing to it is drawn only to the backup bitmap(s) +e invalidating a window using wInvalidateRect or wInvalidateWin has no effect + + +e¢ windows behave as if they do not exist with respect to mouse input (this only applies when there +is a pointing device) + + +3-6 + + +3 WINDOWS + + +wMakeVisible Make window visible +VOID wMakeVisible(UINT wid); +Mark window wid as visible. + + +Unless wMakeInvisible has been applied to a descendant, calling wMakevisible makes all descendants +visible. + + +Sibling positions + + +wWindowPosition Change position in sibling list +VOID wWindowPosition(UINT wid, UINT pos); +Move window wid to the position pos in its sibling list. + + +If pos is greater than the number of siblings then window wia will go to the back of the sibling list, if pos +is zero then it will go to the front of the sibling list. + + +wGetWindowPosition Get position in sibling list +INT wGetWindowPosition(UINT wid); +Return the position of window wid in its sibling list. + + +The function behaves as for wcheckPoint in that it flushes the client-side buffer and reports any uncleared +error - either by calling p_ieave or by returning the error number. + + +Not available in version 2 of the window server. + + +Scrolling + + +wScrollRect Copy a rectangle +VOID wScrollRect (UINT wid, .i.P_RECT *prect, P_POINT *poffset); + +Copy the pixels in rectangle prect in window wid to the same sized rectangle, displaced by poffset. + +The structs p_pornt and p_rRect are defined as: + + +typedef struct +{ +WORD x; +WORD y; +} P_POINT; + + +typedef struct +{ +P_POINT tl; /* top left pixel (internal) */ +P_POINT br; /* bottom right pixel (external) */ +} P_RECT; +The copy excludes the following from prect: +e those parts which are in the update region (that is, those parts which are invalid) +e those parts which are obscured or clipped by other windows + + +e those parts which are beyond the boundaries of the window + + +Although these parts are not copied, their existence causes the corresponding region of the displaced +rectangle to be invalidated. + + +3-7 + + +WINDOW SERVER REFERENCE + + +In version 4 of the window server, if drawing is enabled to both the normal and the grey planes, then the +copying activity described above is done to both planes. + + +If the window is a backed-up window, the copy is also applied to the backup bitmap(s). For a backed-up +window: the update region is always null; those parts which are obscured or clipped can be recovered from +the backup bitmap(s); those parts which are beyond the boundaries of the window are cleared. + + +Note that wScrol1Rect may also be applied to a bitmap where wid is a bitmap ID (but not in version 2 of +the window server). + + +wsScrollWin Scroll a window +VOID wScrollWin(UINT wid, .i.P_POINT *poffset) ; + +Scroll the whole of window wid by displacement poffset. + +Entirely equivalent to wScrollRect with prect set to a rectangle covering the whole window. + + +Note that wScrollwin may also be used to scroll a whole bitmap where wid is a bitmap ID (but not in +version 2 of the window server). + + +Redrawing + + +There are six variants of wBeginRedraw which vary according to whether a temporary graphics context is +created (and, if so, whether it is to be altered from its default settings) and whether a part or the whole of +the window is being redrawn, as follows: + + +wBeginRedraw to redraw a part of the window using an independently created temporary or +permanent graphics context + + +wBeginRedrawWin to redraw the whole of the window using an independently created temporary +or permanent graphics context + + +wBeginRedrawGC to redraw a part of the window using a temporary graphics context which is +created and initialised with specified values + + +wBeginRedrawGC0 to redraw a part of the window using a temporary graphics context which is +created with default initial values + + +wBeginRedrawWinGC to redraw the whole of the window using a temporary graphics context which is +created and initialised with specified values + + +wBeginRedrawWinGC0 to redraw the whole of the window using a temporary graphics context which is +created with default initial values + + +Note that the last character in both wBeginRedrawGco and wBeginRedrawwWincco is the digit zero (and not +the letter 'o'). + + +When a begin redraw function is used to simultaneously create a temporary graphics context, the +corresponding call to wEndRedraw automatically frees it. + + +All variants validate at least a part of a window and cause subsequent drawing to use the update region +rather than the normal drawing region. If the background attribute of the window is w_wIN_BACK_CLR, +validated pixels in the update region are cleared and if the background attribute is w_wIn_BACK_SET, the +same pixels are set. + + +In version 4 of the window server, the above two background attributes apply to validated pixels in the +normal (black) plane in the update region. In addition, if the background attribute of the window is +W_WIN_BACK_GREY_CLR Or W_WIN_BACK_GREY_SET, validated pixels in the grey plane in the update region +are cleared or set respectively. + + +A way of ensuring flicker-free redrawing, is to set the background attribute to w_wIN_BACK_NONE and cover +every pixel in the redraw. + + +In version 4 of the window server, W_WIN_BACK_NONE applies only to the normal (black) plane. To achieve +the same effect when drawing to the grey plane, the corresponding attribute w_wIN_BACK_GREY_NONE +should also be set. + + +3-8 + + +3 WINDOWS + + +wBeginRedraw Start a partial redraw + + +VOID wBeginRedraw(UINT wid, .i.P_RECT *prect); + + +Validate the rectangle prect in window wia and clip subsequent drawing to the intersection of prect and +the window's update region (as it was before the validate). The normal drawing region is restored when +wEndRedraw is called. + + +The struct p_rect is defined as: + + +typedef struct +{ +WORD x; +WORD y; +} P_POINT; + + +typedef struct +{ +P_POINT tl; /* top left pixel (internal) */ +P_POINT br; /* bottom right pixel (external) */ +} P_RECT; + + +wBeginRedrawWin Start a full redraw + + +VOID wBeginRedrawWin(UINT wid); + + +Validate the whole of window wia and clip subsequent drawing to the window's update region (as it was +before the validate). The normal drawing region is restored when wEndRedraw is called. + + +Equivalent to calling wBeginRedraw with a rectangle covering all of window wia. + + +wBeginRedrawGC Start a partial redraw (GC) + + +VOID wBeginRedrawGC (UINT wid, .i.P_RECT *prect, UINT field_set, G_GC *pgc); + + +Validate the rectangle prect in window wia and clip subsequent drawing to the window's update region +(as it was before the validate). + + +In addition, create a temporary graphics context which is initialised with those fields from pgc which have +their corresponding bit fields set in field_set. + + +The c_cc struct is defined in wlib.h as: + + +typedef struct +{ + + +UBYTE gmode; /* G_TRMODE_SET, CLR, INV (line) */ + +UBYTE textmode; /* G_TRMODE_SET, CLR, INV, REPL (text) */ + +UBYTE style; /* G_STY_NORMAL, _BOLD, _UNDERLINE, _INVERSE, _DOUBLE, _MONO, +_ITALIC */ + +UBYTE flags; /* controls use of grey & double pixel mode */ + +WORD font; /* ID of font to use */ + +} G_GC; + + +where the bit fields for field_set are: + + +G_GC_MASK_GMODE corresponding to the gmode member +G_GC_MASK_TEXTMODE corresponding to the textmode member +G_GC_MASK_STYLE corresponding to the style member +G_GC_MASK_FONT corresponding to the font member + +G_GC_MASK_GREY corresponding to the flags member (version 4 only) +G_GC_MASK_DOUBLE corresponding to the £1ags member (version 4 only) + + +The flags member is introduced in version 4 of the window server. Prior to version 4, the space occupied +by this member was unused. + + +See the Graphics Output chapter for a complete description of the fields in a c_cc struct. + + +The graphics context is freed (and the normal drawing region is restored) when wendRedraw is called. + + +3-9 + + +WINDOW SERVER REFERENCE + + +wBeginRedrawGCOo Start a partial redraw (GCO) + + +VOID wBeginRedrawGCO (UINT wid, .i.P_RECT *prect); + + +Validate the rectangle prect in window wid and clip subsequent drawing to the window's update region +(as it was before the validate). + + +In addition, create a temporary graphics context with default initial values. + + +The graphics context is freed (and the normal drawing region is restored) when wEndRedraw is called. + + +wBeginRedrawWinGC Start a full redraw (GC) + + +VOID wBeginRedrawWinGC(UINT wid, UINT field_set, .i.G_GC *pgc); + + +Validate the whole window wid and clip subsequent drawing to the window's update region (as it was +before the validate). + + +In addition, create a temporary graphics context which is initialised with those fields from pge which have +their corresponding bit fields set in field_set. + + +The graphics context is freed (and the normal drawing region is restored) when wEndRedraw is called. +The c_cc struct is defined in wlib.h as: + + +typedef struct +{ + + +UBYTE gmode; /* G_TRMODE_SET, CLR, INV (line) */ + +UBYTE textmode; /* G_TRMODE_SET, CLR, INV, REPL (text) */ + +UBYTE style; /* G_STY_NORMAL, _BOLD, _UNDERLINE, _INVERSE, _DOUBLE, _MONO, +_ITALIC */ + +UBYTE flags; /* controls use of grey & double pixel mode */ + +WORD font; /* ID of font to use */ + +} G_GC; + + +where the bit fields for field_set are: + + +G_GC_MASK_GMODE corresponding to the gmode member +G_GC_MASK_TEXTMODE corresponding to the textmode member +G_GC_MASK_STYLE corresponding to the style member +G_GC_MASK_FONT corresponding to the font member + +G_GC_MASK_GREY corresponding to the flags member (version 4 only) +G_GC_MASK_DOUBLE corresponding to the flags member (version 4 only) + + +The flags member is introduced in version 4 of the window server. Prior to version 4, the space occupied +by this member was unused. + + +See the Graphics Output chapter for a complete description of the fields in a c_cc struct. +Example + + +LOCAL_C VOID BeginRedraw(INT wid, INT fid, INT style) +{ +G_GC gc; + + +gc.font=fid; +gc.style=style; + + +wBeginRedrawWinGC (wid, G_GC_MASK FONT |G GC_MASK_STYLE, &gc) ; +} + + +wBeginRedrawWinGCo Start a full redraw (GCO) + + +VOID wBeginRedrawWinGCO(UINT wid); + + +Validate the whole of window wid and clip subsequent drawing to the window's update region (as it was +before the validate). + + +In addition, create a temporary graphics context with default initial values. + + +The graphics context is freed (and the normal drawing region is restored) when wEndRedraw is called. + + +3-10 + + +3 WINDOWS + + +wEndRedraw End a redraw +VOID wEndRedraw (VOID) ; + +End a redraw. + +Drawing is set back to use the normal drawing region (which clips to the visible region of a window). + + +If a temporary graphics context was created by calling wBeginRedrawGC, wBeginRedrawWinGC, +wBeginRedrawGCO OF wBeginRedrawwineco, the temporary graphics context is freed. + + +Validating + + +Validating a rectangle in a window removes that rectangle from the window's update region (if the +window has an update region). Validating the whole window deletes the window's update region. + + +When responding to the receipt of a wm_REDRAw event (see the Events chapter) it is essential to perform a +validation: until a window's update region has been entirely validated, wm_rEDRaw events will continue to +be received. + + +The normal response to a wM_REDRAW event is to perform a validation and to draw all or part of the window +(drawing will be clipped to the intersection with the window's update region). The rectangle that is +validated should correspond exactly to the rectangle that is drawn, rather than to the rectangle specified by +the wM_REDRAW event. + + +Depending on the window's background attribute, validation may also set, clear or leave unchanged all the +pixels in the rectangle. You should set the background attribute to select the action that is most +appropriate for the particular situation. + + +If the background attribute of the window is w_wIN_BAck_cLR, validated pixels in the drawing region are +cleared and if the background attribute is w_wIN_BACK_sET, the same pixels are set. + + +In version 4 of the window server, these attributes refer to validated pixels in the normal (black) plane of +the update region. In addition, if the background attribute w_wIN_BACK_GREY_CLR is set, validated pixels in +the grey plane of the drawing region are cleared and if the background attribute w_wIN_BACK_GREY_SET 1S +set, the same pixels are set. + + +A way of ensuring flicker-free redrawing of a window is to set the background attribute to +W_WIN_BACK_NONE and cover every pixel in the draw. + + +In version 4 of the window server, the w_wIN_BACK_NONE attribute refers to the normal (black) plane. If you +are also drawing to the grey plane, then the same result can be achieved in this plane by setting the +W_WIN_BACK_GREY_NONE attribute. + + +wValidateRect Validate a rectangle of a window +VOID wValidateRect (UINT wid, .i.P_RECT *prect); + +Validate the rectangle prect in window wid. + +The struct p_rect is defined as: + + +typedef struct +{ +WORD x; +WORD y; +} P_POINT; + + +typedef struct +{ +P_POINT tl; /* top left pixel (internal) */ +P_POINT br; /* bottom right pixel (external) */ +} P_RECT; + + +wValidateWin Validate a whole window + + +VOID wValidateWin(UINT wid); +Validate the whole of window wid. + + +Equivalent to calling wvalidateRect with a rectangle covering window wid. + + +3-11 + + +WINDOW SERVER REFERENCE + + +a +Invalidating + + +Invalidating a rectangle in a window adds that rectangle to the window's update region. Invalidating the +whole window sets the window's update region to cover the whole window. + + +When a client wishes to draw an area in one of its windows, there are two approaches: +e to draw directly to the area (normally after calling wvalidateRect or wValidateWin) + + +e to invalidate a rectangle and make use of the code which redraws its window in response to a +WM_REDRAW event + + +The advantages of invalidating are: +e It makes use of the code which must in any case be provided to redraw the window. + + +e An application can effectively use the window server's update region to accumulate disjoint +invalid areas without having to worry about whether those areas overlap (since overlapping areas +will generate a single redraw). + + +e Because the areas invalidated are clipped to the visible areas of the window, responding to the +WM_REDRAW events can require less work than drawing the whole window (since the whole +window may be partially or totally obscured or it may be invisible). + + +The main disadvantage of invalidating is the loss of performance resulting from the extra context +switching from the client to the window server to process the invalidate command and then back to the +client to process the redraw. + + +winvalidateRect Invalidate a rectangle +VOID wiInvalidateRect (UINT wid, .i.P_RECT *prect) ; + +Invalidate the rectangle prect in window wid. + +The struct p_RecT is defined as: + + +typedef struct +{ +WORD x; +WORD y; +} P_POINT; + + +typedef struct +{ +P_POINT tl; /* top left pixel (internal) */ +P_POINT br; /* bottom right pixel (external) */ +} P_RECT; + + +winvalidateWin Invalidate a window +VOID wiInvalidateWin(UINT wid); +Invalidate the whole of window wid. + + +Equivalent to calling wInvalidateRect with a rectangle covering the whole of window wid. + + +————e—————————— EE eT) +Text cursor + + +wTextCursor Draw a text cursor + + +VOID wTextCursor(UINT wid, .i.W_CURSOR *pcursor) ; +Present a text cursor (which is optionally flashing) in window wid. + + +There is only one text cursor per client. If a text cursor already exists, it is removed before the new cursor +is positioned (you do not have to call wzEraseTextCursor if you are moving the cursor to another position +in the same or a different window). + + +Version 4 of the window server allows the text cursor to appear grey. This is achieved by setting +W_CURSOR_GREY in the flags member of the w_cursor structure. + + +3-12 + + +3 WINDOWS + + +The w_cursor struct is defined in wlib.h as: + + +typedef struct +{ +WORD x; +WORD y; +} P_POINT; + + +typedef struct +{ +P_POINT pos; /* text cursor position */ +UBYTE height; /* text cursor height */ +BYTE ascent; /* text cursor ascent */ +UBYTE width; /* text cursor width */ +UBYTE flags; /* for obloid cursor and to disable flashing */ +} W_CURSOR; + + +The height, ascent and width members specify the height, ascent and width of the text cursor. The flags +member may be zero or it may contain any combination of the following bit flags: + + +W_CURSOR_OBLOID to round off the corners of the cursor +W_CURSOR_NO_FLASH to disable the flashing of the cursor +W_CURSOR_GREY to make the text cursor appear grey + + +The position of the cursor is consistent with positioning conventions for text where the top left of the +cursor is ascent above the position passed to wrextCursor. In fact, the x, y position for wrextcursor +should be the same as for drawing a text string. See the description of gPrintText in the Graphics Output +chapter. + + +Applications which use a vertical line cursor to indicate a position between two characters should (by +convention) place the cursor in the leftmost position of the character cell which is to the right of the +cursor. In this case, width is set to 1 (or 2), and ascent and height are set according to the font currently +in use. + + +A block or underline cursor is sometimes appropriate when using a monospaced font where width should +be set to the width of a characters in the font. + + +For an underline cursor, height should be set to 1. To draw the underline along the baseline of the font, +ascent Should be set to zero. To draw it along the bottom line of the characters, ascent should be set to +(font.ascent—font.height+1). + + +The window server controls the flashing of the cursor and makes sure that it does not interfere with any +drawing. + + +On large screen versions of the window server such as the MC, the window server automatically ensures +that only the foreground text cursor is visible. + + +wDrawTextCursor Draw a text cursor + + +VOID wDrawTextCursor(UINT wid, .i.W_CURSOR *pcursor) ; + + +A now defunct function to support older applications which leave pcursor->flags undefined (before +version 3.5 of the window server, pcursor->flags was a filler for word alignment). + + +This function is the same as wrextCursor except that it ignores pcursor->flags and consequently does +not support w_CURSOR_OBLOID, W_CURSOR_NO_FLASH OF W_CURSOR_GREY. + + +New applications should use wrextcursor. + + +wEraseTextCursor Erase a text cursor +VOID wEraseTextCursor (VOID); +Remove the caller's text cursor. + + +In programming terms, calling this function when there is no cursor is harmless. However, be aware that +careless use of this function can cause problems. + + +3-13 + + +WINDOW SERVER REFERENCE + + +Only one cursor is ever visible on the screen at any one time and wEraseTextCursor erases the text cursor +regardless of the window in which it appears. An application, therefore, must ensure that a text cursor is +erased at the appropriate time. + + +An inappropriately timed call to weraseText Cursor can "steal" the cursor from the currently emphasised +window. + + +EEE +Bitmap sequences + + +The window server has the ability to attach an animated sequence of bitmaps to a window. This sequence +specifies the bitmap, position, bitmap source rectangle, blit mode and time to wait before advancing the +sequence. The sequence is set up by the wSetWinBitmap call, modified by the wchangewWinBitmap call and +freed with wrree. + + +A bitmap is displayed as part of the window background, and a client can draw on top of the bitmap. +Because of this the client will normally be sent a wM_REDRAW event telling it to redraw the window +containing the bitmap every time the sequence advances. If you do not require to draw on top of the +bitmap you should set the w_wIn_No_REDRaw flag for the window so that your application is not slowed +down by unnecessary WM_REDRAW events. + + +wSetWinBitmap Attach bitmap sequence to window +INT wSetWinBitmap(UINT wid, UINT count, .i.WS_WIN_BITMAP *pdata) ; + + +Attach a sequence of one to twelve bitmaps to window wid where pdata is the address of an array of count +bitmap sequence records. + + +The structure of a bitmap sequence record is described by the ws_wIn_BiTmap struct which is defined as: + + +typedef struct +{ +WORD x; +WORD y; +} P_POINT; + + +typedef struct +{ +P_POINT tl; /* top left pixel (internal) */ +P_POINT br; /* bottom right pixel (external) */ +} P_RECT; + + +typedef struct +{ +WORD bitmap; /* Bitmap ID */ +P_POINT pos; /* position of bitmap */ +P_RECT rect; /* Source rectangle in bitmap */ +UWORD mode; /* Blit mode */ +ULONG time; /* Time till next bitmap in sequence */ +} WS_WIN_BITMAP; + + +where: + +bitmap is the bitmap ID. If any of the bitmaps in the sequence is freed before the +bitmap sequence is freed, the window server will panic the calling client when +it tries to display the freed bitmap. + +pos is the target position in the window wid of the top left of the bitmap + +rect is the rectangle within the bitmap to copy from + +mode is the graphics mode to use when copying the bitmap (one of G_TRMODE_REPL, +G_TRMODE_SET Of G_TRMODE_CLR Or G_TRMODE_INV). In version 4 of the window +server, a member of a bitmap sequence can be made to appear grey. This is +achieved by OR'ing the flag ws_wIN_BITMAP_GREY into this member. + +time is the interval in tenths of a second after which the window server advances to + + +the next bitmap (in a circular fashion). If this time is too short, the window +server will hog the processor animating the bitmaps and the performance of the +rest of the machine will be degraded. + + +Returns the ID of the bitmap sequence. + + +3-14 + + +3 WINDOWS + + +wChangeWinBitmap Change a bitmap +VOID wChangeWinBitmap(UINT bsid, UINT index, .i.WS_WIN_BITMAP *pdata) ; +Replace bitmap sequence record index in the bitmap sequence with ID bsia with the contents of pdata. + + +The whole of pdata must be set up even if only one of the elements of the structure is being changed. + + +wFree Free a bitmap sequence +VOID wFree(UINT bsid); +Free bitmap sequence bsid. + + +A bitmap sequence is automatically freed if the window it is attached to is destroyed. + + +Sprites +In version 4 of the window server, an animated sequence of bitmaps known as a 'sprite' can be created. + + +While a sprite is 'connected' to a particular window, it differs from an animated bitmap sequence in that it +is not displayed as part of the window background. The window server takes care of saving and restoring +the contents of the underlying window display. This can give the impression of the sprite 'floating' above +the underlying display. + + +Each application (or client, in general) can have only one sprite at a time and each sprite consists of a +sequence of up to thirteen bitmap sets. Each bitmap set consists of up to six bitmaps, three for the normal +plane and three for the grey plane. + + +wCreateSprite Create a sprite + + +INT wCreateSprite (INT wid,P_POINT *pos,INT flags,INT count,.i.W_SPRITE *psprite); + + +Available in version 4 of the window server, this function creates a sprite connected to the window with +ID wia based at the position specified by the p_pornt struct pointed to by pos. + + +The value of f1ags controls clipping of the sprite. If it contains the flag w_spRITE_CLIP_CHILDREN, the +sprite will be clipped by any child windows of the window to which the sprite is connected. If this flag is +not set, the sprite can only be clipped by other windows or by the limits of its own window. + + +The use of the w_spRITE_CLIP_CHILDREN flag needs some care. If this flag is set, the sprite should not be +connected to the root window. The application's top level window is always a child window of the root +which would clip or overlay a sprite. + + +Menus and dialog boxes are not child windows of any of the application's windows; therefore a sprite will +always be clipped by menus and dialog boxes regardless of the setting of w_sPpRITE_CLIP_CHILDREN. + + +The count parameter specifies how many bitmap sets the sprite has. + + +The psprite parameter points to an array of w_spRITE structures, one for each bitmap set. Note, therefore, +that there are count elements in the array. + + +The structure of w_spRrteE is defined as follows: + + +typedef struct +{ + + +WORD bit_set; /* (normal plane) bitmap for pixels to be set 1 A +WORD bit_clr; /* (normal plane) bitmap for pixels to be cleared */ +WORD bit_inv; /* (normal plane) bitmap for pixels to be inverted*/ +WORD bit_gr_set; /*(grey plane) bitmap for pixels to be set ay: +WORD bit_gr_clr; /* (grey plane) bitmap for pixels to be set */ +WORD bit_gr_inv; /* (grey plane) bitmap for pixels to be set */ + + +P_POINT offset; +UWORD time; +} W_SPRITE; + + +3-15 + + +WINDOW SERVER REFERENCE + + +The time parameter indicates the length of time in units of 1/10th of a second that the bitmap set is to be +displayed. However, this field is ignored if the sprite consists of only one bitmap set (i.e. count is set to +one). + + +The members bit_set, bit_clr, and bit_inv contain the bitmap ids to be displayed in the normal plane +using the modes G_TRMODE_SET, G_TRMODE_CLR and G_TRMODE_INV respectively (see the section on +Graphics contexts in the chapter Graphics Output). + + +Similarly, bit_gr_set, bit_gr_clr and bit_gr_inv contain the bitmap ids to be displayed in the grey +plane. + + +Note that setting a bitmap field to zero means that no bitmap will be used for the relevant plane and mode. + + +The bitmap fields can be set in any combination as appropriate. Setting all of them to zero results in the +sprite being left blank for the specified time. + + +The offset parameter indicates the (x,y) offset of the top left-hand position of the bitmaps relative to the +specified sprite position. + + +All bitmaps within a bitmap set must be the same size or else E_GEN_aRG will be returned. +If successful, the function returns the sprite id. + + +If the application (or client, in general) already has a sprite, the function panics with panic +W_PANIC_SPRITE_EXISTS. + + +wSetSprite Change a sprite's bitmaps and position + + +INT wSetSprite(INT id,P_POINT *pos, INT index,.i.W_SPRITE *psprite) ; + + +Available in version 4 of the window server, this function allows the position and individual bitmap sets +of an existing sprite to be changed. + + +The parameter id must be a valid sprite handle as returned from a call to wcreateSprite, otherwise the +function panics with a W_PANIC_SPRITE. + + +If the parameter pos is not NULL, it is assumed to point to a P_POINT structure specifying the new position +for the sprite. If the parameter is NULL, it is ignored and the sprite's position will be left unchanged. + + +If the parameter psprite is not NULL, it is assumed to point to a W_SPRITE type structure specifying a new +bitmap set. The index parameter indicates which of the original bitmap sets is to be replaced; a zero value +refers to the first. If the psprite parameter is NULL, then both it and the index parameters are ignored and +the sequence of the bitmap sets will be left unchanged. + + +If the sprite is being enlarged, then this call can fail with an E_GEN_MEMory. Changing the position of the +sprite cannot fail. + + +wFree Free a sprite +VOID wFree(UINT id); + + +This function frees the sprite identified by the parameter ia. + + +Clocks + + +On the Series 3, the Series 3a and an HC that is running version 3.5 and upwards of the window server, +the window server can maintain a date and time clock in a window. + + +The various clock displays are influenced by the date and time related members of the E_conrie struct +(see the description of p_getctd in the Time, Timers and Dates chapter of the PLIB Reference manual). +On the S3 and S3a, the E_conFic struct is used to store system-wide user preferences. + + +On the S3, the textual components of the clock displays use the $3 system font. + + +On the HC, the font used for clock displays is determined by the sws_ir ("Internal Font") environment +variable (as with all output that is not directed at a graphics context). The "factory" setting of this +environment variable selects the same font as is used on the S3. + + +3-16 + + +3 WINDOWS + + +On the S3a, the clock displays depend on the function used to draw the clock. The description and +discussion of the function wscreateClock (see below) applies equally to the S3 and the S3a. However, +wsCreateClock was designed for the S3 with its 240 x 80 pixel screen. On the S3a with its 480 x 160 +pixel screen, a clock drawn using wsCreateClock will 'work' but will appear clumsy and ungainly. + + +The enhanced version 4 function wscreateClock2 1s to be preferred for applications running on the S3a. + + +wsCreateClock Create a clock + + +INT wsCreateClock(UINT wid, UINT flags, INT xpos, INT ypos, INT offset); + + +In version 4 of the window server, this function is superseded by wscreateClock2 which includes ALL of +its functionality. wscreateClock should only be used if running earlier versions of the window server. + + +Create and maintain a clock at pixel position (xpos,ypos) in window wid. The clock displays the system +time offset by offset minutes. + + +In all cases, (xpos,ypos) specifies the internal position of the top left corner of a rectangle containing the +time display. + + +The appearance of the clock is controlled by the f1ags parameter which should be one of: + + +WS_CLOCK_SMALL_DIGITAL To present a small digital clock. Displayed in the system font on the S3. +Displayed in the S3 system font on the S3a (in native and compatibility +mode). Displayed in the ‘internal’ font on the HC (as used by wInfomsg and +wSetBusyMsg). The coordinates (xpos,ypos) specify the top left corner of +the rectangle containing the first character of the time display. + + +WS_CLOCK_MEDIUM To display a medium sized clock in either digital (using double height +characters) or analogue (using a 36x32 bitmap) form. Unless overridden by +the flags described below, the selection between analogue and digital is +controlled by the clockType member of the z_conFie struct (which should +contain either E_ANALOGUE_CLOCK Of E_DIGITAL_CLOCK). Whether digital or +analogue, the coordinates (xpos,ypos) specify the top left corner of a 36 +pixel wide by 32 pixel high rectangle containing the time display. + + +WS_CLOCK_LARGE_ANALOG To display a large analogue clock using a 66x60 bitmap. The coordinates +(xpos,ypos) specify the top left corner of the 66 pixel wide by 60 pixel high +clock bitmap. + + +The above values may be qualified by oring in combinations of the following flags: + + +WS_CLOCK_WITH_DATE To also display the date. With ws_cLocK_SMALL_DIGITAL, the date is +displayed to the left of the time. With ws_cLock_mEep1um, the date is +displayed under the time. Not available with ws_cLocK_LARGE_ANALOG. + + +WS_CLOCK_WITH_SECONDS To also display seconds. With ws_cLock_sMALL_DIGITAL, the seconds field +is added to the end of the display. With ws_cLock_LARGE_ANALOG, a second +hand is added. Not available with ws_cLock_mMEDIUM. + + +WS_CLOCK_FORCE_ANALOG Valid only with ws_cLock_mep1vm to display an analogue clock regardless +of the value of the clockType member of the z_conrie struct. + + +WS_CLOCK_FORCE_DIGITAL Valid only with ws_cLock_mep1vm to display a digital clock regardless of +the value of the clockType member of the =_conrFie struct. + + +WS_CLOCK_AM_PM To also display an am/pm indicator when the timeType member of the +E_CONFIG Struct is E_TIMEz_12 (although the relative positions may still be +altered when timeType iS E_TIME_24). With ws_cLOCK_SMALL_DIGITAL, the +am/pm indicator is displayed at the end of the time string. With a +WS_CLOCK_MEDIuM analogue clock, the am/pm indicator is displayed to the +right of the base of the clock face. With a ws_cLock_mep1Ivm digital clock, +the time digits are moved up and the am/pm indicator is displayed between +the time digits and the position of the date. Ignored if +WS_CLOCK_LARGE_ANALOG is set. + + +WS_CLOCK_CENTERED Only applies to ws_cLocK_SMALL_DIGITAL with ws_cLOcK_AM_pPM set. +Causes the time string to be centred in the wider space that allows for the +am/pm indicator when the timeType member of the E_conr1e struct is +E_TIME_24. + + +3-17 + + +WINDOW SERVER REFERENCE + + +If successful, the function returns the ID to use when calling wsSetClock and wrree. Otherwise, the +function can leave or return &_GEN_NOMEMORY. + + +The following sample program: + + +#include +#include + + +LOCAL_D WSERV_SPEC wSpec; +LOCAL_D UINT wid; + + +LOCAL_C VOID MainEventLoop (VOID) + + +WS_EV event; + + +for (77) + +{ + +wGetEventWait (&event) ; + +if (event .type==WM_REDRAW) +{ +wBeginRedrawWinGCO (wid) ; +gBorder (W_BORD_SHADOW. D|w BORD_SHADOW_ON) ; +wEndRedraw (); +} + + +} + + +GLDEF_C VOID main(VOID) +{ +wConnect (&wSpec, 0,W_CONNECT_PRIORITY) ; +wid=wCreateWindow(0,0,0,1); +wsCreateClock (wid, WS_CLOCK_LARGE_ANALOG|WS_CLOCK_WITH_SECONDS, 4, 4,0); + + +wsCreateClock (wid, WS_CLOCK_MEDIUM|WS_CLOCK_FORCE_DIGITAL|WS_CLOCK_WITH_DATE, 4+66+6, 4,0 +i + + +wsCreateClock (wid, WS_CLOCK_MEDIUM|WS_CLOCK_FORCE_ANALOG | WS_CLOCK_WITH_DATE, 4+66+6+36+6 +14,0); + + +wsCreateClock (wid, WS_CLOCK_SMALL_DIGITAL|Wws CLOCK_WITH DATE |WS CLOCK_WITH_SECONDS, 104, +66,0); + +wiInitialiseWindowTree (wid) ; + +MainEvent Loop () ; + + +} + + +when run on an HC, produces: + + +1438 L-: + + +fon 24 Mon 28 + + +Morn 28 Jan 14835812 + + +Note that the seconds field of the small digital clock is badly drawn because it changed from 11 to 12 +while the screen was being captured. + + +The screen was in fact captured using the scapt program described in the Bitmaps section of the first +chapter. It is left as an exercise for the reader to convert pcxsave.c (which is used by scapt) to take true +snapshots of a changing screen?. + + +3One strategy is to save the screen as a bitmap to a temporary local file using gsaveBit and then to +convert the file. + + +3-18 + + +3 WINDOWS + + +wsCreateClock2 Create a clock - Enhanced version + + +INT wsCreateClock2(.i.WS_CREATE_CLOCK *pclock,TEXT *pfmt) ; + + +This function is introduced in version 4 of the window server and is an enhanced version of the +wsCreateClock function. It is much preferred and should be used for applications designed to run on the +Series 3a. + + +Note that this function includes the functionality of wscreateClock. + + +The clock it creates is based on the values in the ws_cREATE_CLOcK structure pointed to by the parameter +pclock and the value in the second parameter pfmt. + + +The structure ws_CREATE_cLocK can be found in wilib.h but is defined as follows: + + +typedef struct +{ +UINT id; /* window ID */ +UINT type; /* clock type */ +P_POINT pos; /* position ey: +INT offset; /*time offset */ +INT flags; /*clock flags */ +INT font; +INT style; +} WS_CREATE_CLOCK; + + +The function creates a clock in window id at position pos of the specified type. The clock displays the +system time offset by the number of minutes specified in the of fset member. + + +The possible values for type and flags include those values which can be specified in the flags +parameter in the old wscreateClock function. However, in wsCreateClock2, some values apply to type +while the others apply to flags. + + +The second parameter pfmt and the ws_cREATE_CLOCK members font and style are only relevant when +the type of clock being created is ws_cLocK_FORMATTED. For all other types of clock pfmt must be set to +NULL. + + +To summarise, type should be one of the following: + + +WS_CLOCK_SMALL_DIGITAL To present a small digital clock. This clock has the appearance as described +in wsCreateClock and is designed for the Series 3 screen. On the Series 3a +in non-compatibility mode it will appear small and is not recommended. + + +WS_CLOCK_MEDIUM To present a medium sized clock. This clock has the appearance as +described in wsCreateClock and is designed for the Series 3 screen. On the +Series 3a in non-compatibility mode it will appear small and is not +recommended. + + +WS_CLOCK_MEDIUM2 To display a medium sized clock that is larger than the old medium sized +clock. It behaves in a similar way to the old medium clock in that, unless +overridden by the flags described below, the selection between analogue and +digital is controlled by the clockType member of the E_conFIe struct. + + +This clock is drawn using black/white and grey. The analog clock uses a +58x51 bitmap. + + +WS_CLOCK_LARGE_ANALOG To display a large analog clock. This clock has the appearance as described +in wsCreateClock and is designed for the Series 3 screen. On the Series 3a +in non-compatibility mode it will appear small and is not recommended. + + +WS_CLOCK_XL_ANALOG To display an extra-large analog clock as used in alerts. +This clock is drawn using black/white and grey. It uses a 99x99 bitmap. + + +WS_CLOCK_FORMATTED To display a formatted digital clock/date. The display is controlled by the +format string whose address is passed in the second parameter pfmt. The +meaning of the format string is the same as for the PLIB function p_dt2str. +See the PLIB manual for more detail on the syntax and meaning of this +string. The font and style are specified by the font and style parameters in +the ws_CREATE_CLOCK Structure. + + +The clock types described above can be modified by setting combinations of the following flags in the +flags member of the ws_cREATE_CLOcK Structure: + + +3-19 + + +WINDOW SERVER REFERENCE + + +WS_CLOCK_WITH_DATE + + +WS_CLOCK_WITH_SECONDS + + +WS_CLOCK_FORCE_ANALOG + + +WS_CLOCK_FORCE_DIGITAL + + +WS_CLOCK_AM_PM + + +WS_CLOCK_CENTERED + + +WS_CLOCK_BOX + + +WS_CLOCK_GREY + + +To also display the date. With ws_cLockK_SMALL_DIGITAL, the date is +displayed to the left of the time. With ws_cLock_mMED1um and +WS_CLOCK_MEDIUM2, the date is displayed under the time. Not available with +WS_CLOCK_LARGE_ANALOG Or WS_CLOCK_XL_ANALOG. Not applicable to +WS_CLOCK_FORMATTED. + + +To also display seconds. With ws_cLocK_SMALL_DIGITAL, the seconds field +is added to the end of the display. With ws_cLockK_LARGE_ANALOG, +WS_CLOCK_XL_ANALOG and the analog version of WS_CLOCK_MEDIUM2, a +second hand is added. Not available with ws_cLocK_Mep1Iv™ or the digital +version of WS_CLOCK_MEDIuM2. Not applicable to ws_cLOcK_FORMATTED. + + +Valid only with ws_cLock_MEDIUM and WS_CLOCK_MEDIUM2 to display an +analogue clock regardless of the value of the clockType member of the +E_CONFIG struct. Not applicable to ws_cLOCK_FORMATTED. + + +Valid only with ws_cLock_MEDIUM and WS_CLOCK_MEDIUMz2 to display a +digital clock regardless of the value of the clockType member of the +E_CONFIG struct. Not applicable to ws_cLOCK_FORMATTED. + + +Valid as for wsCreateClock. In addition, this is not available for +WS_CLOCK_MEDIUM2 and is not applicable to ws_cLOCK_FORMATTED. + + +Only applies to ws_cLOCK_SMALL_DIGITAL with ws_CLOCK_aAM_PM set. Causes +the time string to be centred in the wider space that allows for the am/pm +indicator when the timeType member of the E_CONFIG struct is E_TIME_24. +Not applicable to ws_cLOCK_FORMATTED. + + +Only applies to ws_cLocK_FORMATTED. Causes graphics to be drawn +enclosing the formatted clock as shown in one of the examples. + + +If set, it causes those clocks which are normally drawn in black & white +only, to be drawn in grey. + + +It has no effect on those clocks which are drawn in both black/white and +grey. + + +If successful, the function returns the ID to use when calling other 'clock' functions such as wsSet Clock + + +and wFree. + + +For example, when run on the S3a, the code: + + +#include +#include + + +GLREF_D WSERV_SPEC wSpec; +GLREF_D UINT wMainWid; + + +LOCAL_C VOID MainEventLoop (VOID) + + +{ +WS_EVENT event; + + +for (77) + + +{ + + +wGetEventWait (&event) ; +if (event .type==WM_KEY) + + +{ + + +if (event.p.key.keycode==W_KEY_RETURN) + + +break; + + +3-20 + + +3 WINDOWS + + +GLDEF_C INT main (void) +{ +WS_CREATE_CLOCK clock; + + +wConnect (&wSpec, 0,W_CONNECT_PRIORITY) ; +wCompatibilityMode (0, &wSpec) ; +wMainWid = wCreateWindow(0,0,0,1); + + +winitialiseWindowTree (wMainWid) ; +clock.id = wMainWid; + +clock.type = WS_CLOCK_XL_ANALOG; +clock.pos.x = 200; + +clock.pos.y = 40; + +clock.offset = 0; + +clock.flags = WS_CLOCK_WITH_SECONDS; + + +wsCreateClock2 (&clock, NULL) ; +MainEventLoop() ; +return (0); + + +} + + +displays the extra large analog clock with +a seconds hand as shown opposite. + + +An example of a formatted clock is given next. The digital clock/date is displayed in bold, with double +height and surrounded by a neat box. The code used to display the clock is as follows: + + +#include +#include +#include + + +GLREF_D WSERV_SPEC wSpec; +GLREF_D UINT wMainWid; + + +LOCAL_C VOID MainEventLoop (VOID) +{ +WS_EVENT event; + + +for (77) +{ +wGetEventWait (&event) ; +if (event .type==WM_KEY) +{ +if (event.p.key.keycode==W_KEY_RETURN) +break; + + +GLDEF_C INT main (void) +{ +WS_CREATE_CLOCK clock; + + +wConnect (&wSpec, 0,W_CONNECT_PRIORITY) ; +wCompatibilityMode (0, &wSpec) ; + +wMainWid = wCreateWindow(0,0,0,1); +wiInitialiseWindowTree (wMainWid) ; + + +3-21 + + +WINDOW SERVER REFERENCE + + +clock.id = wMainWid; + +clock.type = WS_CLOCK_FORMATTED; + +clock.pos.x = 150; + +clock.pos.y = 70; + +clock.offset = 0; + +clock.flags = WS_CLOCK_BOX; + +clock.font = FONT_ID_SWISS_8; + +clock.style = G_STY_DOUBLE|G_STY_BOLD; +wsCreateClock2 (&éclock, "Sh%:%m%:%s Se %da%/Sm%s/Sy") ; + + +MainEvent Loop (); +return(0); + + +} + + +Take particular note of the text string +forming the second parameter to 1 — +wsCreateClock2. The format and structure | 17a Wednesday 18/88/1993 +of this text string governs the display of +this clock. + + +wsSetClock Set the clock offset + + +VOID wsSetClock (INT clock_id, INT offset); + + +Change the time offset (in minutes from the system time) of clock clock_id (where clock_id was +returned from a call to wscreateClock). + + +wFree Free a clock +VOID wFree(INT clock_id); +Free the clock clock_id (where clock_id was returned from a call to wscreateClock). + + +A clock is automatically freed if the window it contains is closed as a result of a call to +wCloseWindowTree. If a clock is freed by wcloseWindowTree, it must not be freed a second time by a call +to wFree. + + +Mouse icons + + +On the large screen version of the window server (such as that on the MC), each window has an +associated mouse icon - as specified by the mouse icon ID in the mouse_icon window attribute. The +mouse_icon window attribute is set when you create the window by calling wcreateWindow and it may +subsequently be changed by calling wset Window + + +Mouse icons can be selected from one of three categories: + + +e The two built-in icons, the default icon w_WwIN_MI_STANDARD and the invisible mouse icon +W_WIN_MI_NULL. + + +¢ ROM-based icons which are automatically loaded by the window server when it boots up. + + +e External mouse icons which are loaded from a file by calling gopenMouseIcon (which returns the +mouse icon ID). + + +On MC machines, the following mouse icons are built into the ROM: +W_WIN_MI_STANDARD standard mouse icon. + +W_WIN_MI_NULL invisible mouse icon. + +W_WIN_MI_PUSHER hollow standard mouse icon. +W_WIN_MI_TEXT text window mouse icon. + +W_WIN_MI_CROSS cross. + + +3-22 + + +W_WIN_MI_MARGIN text window margin icon. +W_WIN_MI_PG_DOWN page down scroll bar icon. +W_WIN_MI_PG_UP page up scroll bar icon. +W_WIN_MI_VSLIDE scroll bar vertical slider icon. +W_WIN_MI_HSLIDE scroll bar horizontal slider icon. +W_WIN_MI_TO_BIG resize gadget expand window icon. +W_WIN_MI_TO_SMALL resize gadget shrink window icon. +W_WIN_MI_RESIZE resize gadget move-resize icon. +W_WIN_MI_MOVE move window icon. + +W_WIN_MI_LEFT horizontal scroll bar move left icon. +W_WIN_MI_RIGHT horizontal scroll bar move right icon. +gOpenMouselcon + + +INT gOpenMouselIcon(TEXT *filename, UINT index) ; + + +Load mouse icon index from file filename. + + +3 WINDOWS + + +Load a mouse icon + + +Returns the positive ID of the mouse icon to use in the w_winpata structure when calling wsetwindow or + + +wCreateWindow. + + +If an error with error number err occurs while loading the mouse icon, the function calls p_leave (err) or + + +returns err, depending on whether wDisableLeaves has been called. + + +If filename is not a full file specification, the unspecified components are taken from the window server's + + +default path which, in practice, is always the internal drive M:\. + + +See also gSetOpenAddress in the next chapter for loading a mouse icon file which is embedded in another + + +file. + + +wFree + + +VOID wFree(UINT mouse_icon_id) ; + + +Free a mouse icon. + + +Any windows using the freed icon revert to using the default icon. + + +Free a mouse icon + + +3-23 + + +CHAPTER 4 + + +GRAPHICS OUTPUT + + +Graphics contexts + + +You must create a graphics context before performing any graphics output (apart from the screen and +window directed graphics described in the previous two chapters). + + +The use of a graphics context reduces the number of parameters required when calling graphics functions. +A graphics context contains the following: +e the ID of a drawable (a window or a bitmap) that is the ultimate recipient of the graphics output + + +e whether to set, clear or invert pixels when drawing lines using gDrawLine, gDrawPolyLine, +gDrawBox, gBorderRect, gBorder, gBorder2Rect Of gBorder2 + + +e the font, style and transfer mode to use when drawing text using gPrintText, gPrintClipText, +gXPrintText, gPrintBoxText OF gShadowText. + + +The drawable is set once and for all when the graphics context is created (using gcreateGc or a variant +thereof). The rest of the content can be set up when the graphics context is created and it can also be +altered subsequently (using gSetcc). + + +A graphics context is set with the aid of a c_cc struct, which is defined in wlib.h as: + + +typedef struct +{ + + +UBYTE gmode; /* mode for line drawing */ + +UBYTE textmode; /* mode for writing text */ + +UBYTE style; /* style of text: bold, underline etc. */ +UBYTE flags; /* controls use of grey & double pixel mode */ +WORD font; /* ID of font to use */ + +} G_GC; + + +Note that the flags member is introduced in version 4 of the window server. Prior to version 4, the space +occupied by this member was unused. + + +Introduced in version 4, grey is available (in one shade only) on the S3a and Workabout. At a software +level this is implemented by introducing the concept of a plane. + + +There are two planes to which drawing can be directed. The normal plane can be thought of as being +associated with the drawing of black while the grey plane, as its name implies, is associated with the +display of grey. + + +Drawing is normally done to one or both planes. However, they are not entirely independent; for example, +to display grey, the normal plane should be clear and the grey plane set. If a pixel in the normal plane is +set, it is displayed black regardless of the grey plane setting. This is best thought of as the normal plane +‘overlaying’ the grey plane. + + +Also introduced in version 4, all graphic commands can be set to perform all drawing with double sized +pixels. This feature is motivated by the need to run Series 3 applications on the Series 3a; in other words, +to use the S3a in S3 compatibility mode. + + +4-1 + + +WINDOW SERVER REFERENCE + + +gmode + + +The gmode field is used by the line drawing functions gDrawLine, gDrawPolyLine, gDrawBox, +gBorderRect, gBorder2Rect, gBorder, gBorder2, wDOrawButton and wDrawButton2 and may be one of: + + +G_TRMODE_SET set pixels in the line. This is the default. +G_TRMODE_CLR clear pixels in the line. + +G_TRMODE_INV invert pixels in the line. + +textmode + + +The textmode field controls the method of writing text in gPrintText and gPrintClipText and may be +any of: + + +G_TRMODE_SET where Is in the font set bits in the destination and Os do not change bits in the +destination (used to print on to a previously cleared area). This is the default. + + +G_TRMODE_REPL where Is and Os in the font overwrite the destination (used to print over +unprepared areas). + + +G_TRMODE_CLR where Is in the font clear bits in the destination and Os do not change bits in +the destination (used to print on to a previously set area). + + +G_TRMODE_INV where Is in the font toggle corresponding bits in the destination and Os in the +source pattern do not change bits in the destination (used to print over an +existing image and may be reversed by a second application). + + +style + + +The style field controls the style of text in gPrintText, gPrintClipText, gXPrintText, gPrintBoxText, +gShadowText, wDrawButton and wDrawButton2. The precise mechanism of applying a style depends on +the version of the window server. Prior to version 4, styles may be any combination of: + + +G_STY_NORMAL text is drawn as it is in the font. This is the default. + + +G_STY_BOLD text is drawn bolded (generally bolded characters are one pixel wider than +normal characters). + + +G_STY_UNDERLINE text is drawn underlined where each character (including space) is drawn with +a horizontal line beneath its graphic. + + +G_STY_INVERSE text is drawn in inverse video (where the bits in the font are inverted before +drawing). +G_STY_DOUBLE text is drawn with double height characters where each row of pixels in the + + +character graphic is doubled up before drawing. + + +G_STY_MONO text is drawn with additional space around the characters of a proportional font +to turn it into a monospaced font. For this to be effective, the proportional font +should be designed with monospacing in mind (as is the built in font on the + + +Series 3). + +G_STY_ITALIC text is drawn italicised by shifting the top half of each character across by one +pixel. + +G_STY_SUPERSCRIPT indicates an intention to draw in superscript, not processed by the window +server. + +G_STY_SUBSCRIPT indicates an intention to draw in subscript, not processed by the window server. + + +Fast text printing of a fast font only works with normal style or with just c_sty_mono. The use of any other +style will cause text drawing to fall back to the slower algorithm. + + +In version 4 of the window server and upwards, the above styles still apply. However, in version 4, font +groups are available as discussed in the section on ROM-based fonts in the Introduction chapter of this +manual and in the description of gconfigureFonts later in this chapter. + + +If the font to which the above styles (except G_sTY_SUPERSCRIPT and G_STY_SUBSCRIPT) are applied is a +font group, then the window server will select the most appropriate font from within that group. + + +4-2 + + +4 GRAPHICS OUTPUT + + +Depending on how the font group is configured and the combination of styles to be applied, some further +algorithmic styling, as described above, may be necessary. + + +In version 4 of the window server and upwards, the following two styles are also available: + + +G_STY_SUPERSCRIPT2 text is drawn in superscript. This style only has meaning when used in +conjunction with a font group configured with a suitable superscript font. + + +If this style is used with a single font (ie not a font group), then the style is +ignored. + + +G_STY_SUBSCRIPT2 text is drawn in subscript. This style only has meaning when used in +conjunction with a font group configured with a suitable subscript font. + + +If this style is used with a single font (ie not a font group), then the style is +ignored. + + +Note that when configuring a font group to include fonts for the c_sty_suPERSCRIPT2 and +G_STY_SUBSCRIPT2 Styles, the AscentAdjust field in the c_ront_conrie data structure can be used to +adjust the font's ascent when printing (see the gconfigureFonts function later in this chapter). + + +The bits c_sty_SUPERSCRIPT and G_sTy_SUBSCRIPT are reserved for higher level software. For example: + + +LOCAL_C VOID DrawTextBox(INT fid, INT style,TEXT *str,P_RECT *prect,INT ascent) +{ +G_GC gc; + + +gc.font=fid; +gc.style=style; +gSetGC (0, G_GC_MASK. FONT |G GC_MASK_STYLE, &gc) ; +if (style&G_STY_SUPERSCRIPT) +ascent-—=1; +if (style&G_STY_SUBSCRIPT) +ascentt=1; +gPrintBoxText (prect, ascent, G_TEXT_ALIGN_LEFT,0,str,p_slen(str)); +} + + +flags + + +Introduced in version 4 of the window server, the flags member is used to indicate the plane to which +drawing is to be directed. It is also used to indicate whether drawing should be done in double or single +pixel mode. Possible values are: + + +G_GC_FLAG_GREY_PLANE graphics drawing is directed to the grey plane only +G_GC_FLAG_BOTH_PLANES — graphics drawing is directed to both the grey plane and the normal plane + + +G_GC_FLAG_DOUBLE if set, all drawing is done in double pixel mode. Unsetting this puts the GC +back into single pixel mode; this can be used to reverse a previous call to set +double pixel mode or in windows that are in this mode by default either +because the application is in compatibility mode or the window has the +W_WIN_DOUBLE_PIxEL flag set. + + +Note that this flag should not be set if drawing is done to a backed-up +window. If the window needs to be restored from the backup, then the +drawing will be displayed in single pixel mode. In this situation, it is best to +set the whole window into double pixel mode. + + +font + + +The font field contains the ID of the font to be used in gPrint Text, gPrintClipText, gXPrintText, +gPrintBoxText, gShadowText, wDrawButton and wDrawButton2. + + +The font ID may be that of a ROM-based font or an ID of a font that was loaded from a file by calling +gOpenFont. + + +The ROM-based font IDs start at ws_ronT_BaAsE and you can use wS_FONT_BASE+1 etc for as many fonts as +are built into the ROM. + + +By default, a graphics context is initialised with the ID of the system font (as described in the section Text +fonts in the first chapter). You can reset a graphics context back to the system font by specifying +WS_FONT_SYSTEM. + + +4-3 + + +WINDOW SERVER REFERENCE + + +a —Ss +Creating a permanent graphics context + + +gCreateGC Create a permanent GC +INT gCreateGC(UINT drawable_id, UINT field_set, G_GC *pgc); + + +Create a permanent graphics context that is assigned to the drawable drawable_id (the ID of a previously +created window or bitmap) and select the created graphics context as current. + + +The c_cc struct is defined as: + + +typedef struct +{ + + +UBYTE gmode; /* G_TRMODE_SET, _CLR, _INV (line) */ + +UBYTE textmode; /* G_TRMODE_SET, _CLR, _INV, _REPL (text) */ + +UBYTE style; /* G_STY_NORMAL, _BOLD, _UNDERLINE, _INVERSE, _DOUBLE, _MONO, +_ITALIC */ + +UBYTE flags; /* G_GC_FLAG_DOUBLE, _GREY_PLANE, _BOTH_PLANES */ + +WORD font; /* ID of font to use */ + +} G_GC; + + +Note that the flags member is introduced in version 4 of the window server. Prior to version 4, the space +occupied by this member was unused. + + +If field_set is Zero, pgc is ignored and the graphics context is created with default values (but, in this +case, you should use gcreateGCco). + + +If field_set is non-zero it should contain a bit mask to specify which fields in pgc are used to set the +graphics context, as follows: + + +G_GC_MASK_GMODE to use pgc->gmode + +G_GC_MASK_TEXTMODE to use pgc->textmode + +G_GC_MASK_STYLE to use pgc->style + +G_GC_MASK_FONT to use pgc->font + +G_GC_MASK_GREY to use pgc->flags (looks at G_GC_FLAG_GREY_PLANE and + + +G_GC_FLAG_BOTH_PLANES only) (version 4 only) +G_GC_MASK_DOUBLE to use pge->flags (looks at G_GC_FLAG_DOUBLE only) (version 4 only) +Returns the ID of the graphics context if successful. + + +If an error (with error number err) occurs, the function calls p_leave (err) or returns err, depending on +whether wDisableLeaves has been called. Possible values for err are: + + +E_GEN_NOMEMORY insufficient system memory +E_GEN_ARG an invalid gmode, textmode, style or font was specified +E_GEN_FAIL none of the grey background modes had been previously set for the window and + + +an attempt was made to set G_GC_FLAG_GREY_PLANE. This error can only be +returned in version 4 of the window server. + + +In version 2 of the window server, the function calls p_panic if an invalid gmode, textmode, style or font +is specified. + + +In version 4 of the window server, setting the c_cc_MasK_GcREyY bit in field_set causes the window server +to look at the two grey flags in the flags member; setting the G_cc_MASK_DOUBLE bit in field_set causes +the window server to look at the double pixel flag in the flags member. + + +Setting G_GC_FLAG_GREY_PLANE directs graphics to the grey plane only, while setting +G_GC_FLAG_BOTH_PLANES directs graphics to both the normal and the grey planes. + + +Setting G_GC_FLAG_DOUBLE causes all drawing to be done in double pixel mode. + + +4 GRAPHICS OUTPUT + + +gCreateGCO Create a permanent GC with default values +INT gCreateGCO(UINT drawable_id); +A code saving convenience routine, equivalent to: + + +gCreateGC (drawable_id,0,0); + + +wFree Free a permanent GC +VOID wFree(UINT gc_id); + +Free the permanent graphics context with ID gc_ia. + +To free a temporary graphics context, use gFreeTempGc not wrree (WS_TEMPORARY_GC) . + + +Because graphics contexts consume memory, they should be freed when they are no longer required. + + +Creating a temporary graphics context + + +gCreateTempGC Create a temporary GC + + +VOID gCreateTempGC (UINT drawable_id, UINT field_set, G_GC *pgc); + + +Create a temporary graphics context that is initialised with those fields from pgc which have their +corresponding bit fields set in field_set. + + +The c_cc struct is defined as: + + +typedef struct +{ + + +UBYTE gmode; /* G_TRMODE_SET, _CLR, _INV (line) */ + +UBYTE textmode; /* G_TRMODE_SET, _CLR, _INV, _REPL (text) */ + +UBYTE style; /* G_STY_NORMAL, _BOLD, _UNDERLINE, _INVERSE, _DOUBLE, _MONO, +_ITALIC */ + +UBYTE flags; /* G_GC_FLAG_DOUBLE, _GREY_PLANE, _BOTH_PLANES */ + +WORD font; /* ID of font to use */ + +} G_GC; + + +where the bit fields for field_set are: + + +G_GC_MASK_GMODE corresponding to gmode +G_GC_MASK_TEXTMODE corresponding to textmode +G_GC_MASK_STYLE corresponding to style +G_GC_MASK_GREY corresponding to flags (version 4 only) +G_GC_MASK_DOUBLE corresponding to flags (version 4 only) +G_GC_MASK_FONT corresponding to font + + +Note that the f1ags member is introduced in version 4 of the window server. Prior to version 4, the space +occupied by this member was unused. + + +The behaviour is as for gcreatecc, apart from the following: + + +@ gCreateTempcc does not return an ID. This improves efficiency, because the window server does +not have to reply to the gcreateTempGc. + + +@ gCreateTempcc remembers the currently selected permanent graphics context (if any), and +gFreeTempec reselects that same graphics context. + + +4-5 + + +WINDOW SERVER REFERENCE + + +While a temporary graphics context exists, you may not call: +e gCreateGC +e gCreateTempGC +e gSetGCo +@ gSetéc to set a graphics context other than ws_TEMPORARY_GC +e wrree (for any graphics context) + + +e wBeginRedrawGC, wBeginRedrawGC0, wBeginRedrawWinGC Or wBeginRedrawWinGCO + + +gCreateTempGCOo Create a temporary GC with default values +VOID gCreateTempGC0 (UINT drawable_id) ; +A code saving convenience routine, equivalent to: + + +gCreateTempGC (drawable_id,0,0); + + +gFreeTempGC Free a temporary GC +VOID gFreeTempGC (VOID) ; +Free the temporary graphics context created by gcreateTempGc or gCreateTempGCo. + + +If a permanent graphics context was current before the temporary graphics context was created, it is +reselected. + + +Setting a graphics context + + +gSetGC Set a graphics context + + +VOID gSetGC(UINT gc_id, UINT field_set, G_GC *pgc); + + +Select gc_id as the current graphics context and alter those fields from pge which have their +corresponding bit fields set in field_set. + + +The c_cc struct is defined as: + + +typedef struct +{ + + +UBYTE gmode; /* G_TRMODE_SET, _CLR, _INV (line) */ + +UBYTE textmode; /* G_TRMODE_SET, _CLR, _INV, _REPL (text) */ + +UBYTE style; /* G_STY_NORMAL, _BOLD, _UNDERLINE, _INVERSE, _DOUBLE, _MONO, +_ITALIC */ + +UBYTE flags; /* G_GC_FLAG_DOUBLE, _GREY_PLANE, _BOTH_PLANES */ + +WORD font; /* ID of font to use */ + +} G_GC; + + +where the bit fields for field_set are: + + +G_GC_MASK_GMODE corresponding to gmode +G_GC_MASK_TEXTMODE corresponding to textmode +G_GC_MASK_STYLE corresponding to style +G_GC_MASK_GREY corresponding to flags +G_GC_MASK_DOUBLE corresponding to flags +G_GC_MASK_FONT corresponding to font + + +Note that the flags member is introduced in version 4 of the window server. Prior to version 4, the space +occupied by this member was unused. + + +4-6 + + +4 GRAPHICS OUTPUT + + +To alter a temporary graphics context with gsetGc, pass gc_id aS WS_TEMPORARY_GC. + + +In version 3 and upwards of the window server, passing gc_ia as zero will modify the current graphics +context, be it temporary or permanent. In version 2, passing a gc_id of zero will panic the process with +panic number 85 (illegal graphics context ID). + + +gSetGCo Make a permanent GC current +VOID gSetGCO(UINT gc_id); + +Make the permanent graphics context with ID gc_ia current. + +Equivalent to: + + +gSetGC (gc_id,0,0); + + +———EE— EE —————————————— ESS — Sy +Line drawing + + +The functions in this section are all directed at the drawable associated with the current graphics context +and are subject to the gmode field of the current graphics context. + + +gDrawLine Draw a line +VOID gDrawLine(INT xl, INT yl, INT x2, INT y2); +Draw a line between pixel (x1,y1) and pixel (x2, y2). + + +When drawing a horizontal line with y1 equal to y2, the line includes the pixel with the lower x +coordinate and excludes the pixel with the higher x coordinate. + + +Similarly, when drawing a vertical line with x1 equal to x2 the line includes the pixel with the lower y +coordinate and excludes the pixel with the higher y coordinate. + + +When drawing a line in which both coordinates change, the window server turns the coordinates of the +end pixels into a rectangle with a top-left internal pixel and a bottom-right external pixel. The line +drawing algorithm then fills in those pixels that are intersected by a mathematical line between the +corners of the mathematical rectangle on the boundary of those pixels that are in the rectangle. + + +gDrawPolyLine Draw a sequence of lines +VOID gDrawPolyLine(INT x, INT y, WORD *plist); +Draw a sequence of lines as specified in the polyline piist, starting at the position (x,y). + + +A polyline is a sequence of line drawing and movement commands. The drawing is self-relative in that +each operation is relative to the end point of the last. + + +The polyline 1ist has the following structure: + + +UWORD n; /* number of word-pairs following */ +WORD xl, /* flag and x displacement */ +WORD yl; /* y displacement */ + + +/* +Bit Bo As S22 FAs OM 9 6B 6252-4 32-21 0 +$----------------------------- +--+ +| X-displacement | | Move/draw flag +$----------------------------- +--+ +| Y-displacement | +$------------------------------- + +af +WORD x2,y2; /* 2nd flag and x, y displacement */ +WORD xn,yn; /* nth flag and x, y displacement */ + + +WINDOW SERVER REFERENCE + + +Each element of the polyline list consists of an x,y displacement, and a bit flag that is set to move and +clear to draw. The move/draw flag is held in bit 0 of the x displacement word where bits 1..15 contain the +actual x displacement!. The y displacement is stored as normal. + + +In version 2 of the window server plist is limited to 61 move/draw operations. + + +For example, the following polyline draws a button consisting of two concentric squares of dimensions +50x50 and 30x30 as in the following diagram: + + +static WORD button[]= +{ + + +95, /* 9 operations follow */ +50*2, 0, /* draw right 50 */ +0*2, 50, /* draw down 50 */ +-50*2, 0, /* draw left 50 */ + + +0*2, -50, /* draw up 50 */ +(10*2) |1, 10, /* move right 10, down 10 */ + + +30*2, 0, /* draw right 30 */ +0*2, 30, /* draw down 30 */ +=30%*2; 0; /* draw left 30 */ + + +0*2, -30 /* draw up 30 */ +hi + + +gDrawPolyLine(0,0,&button[0]); + + +gDrawBox Draw a box +VOID gDrawBox(P_RECT *prect) ; + +Draw a box composed of the outermost pixels in the rectangular block of pixels specified by prect. + +The P_RECT struct is defined as: + + +typedef struct +{ +WORD x; +WORD y; +} P_POINT; + + +typedef struct +{ +P_POINT tl; /* top left pixel (internal) */ +P_POINT br; /* bottom right pixel (external) */ +} P_RECT; + + +gBorderRect Border a rectangle + + +VOID gBorderRect (P_RECT *prect, UINT flags); +This function is not available in version 2 of the window server. + + +Draw a border inside the rectangular block of pixels specified by prect, as controlled by flags where +flags should be one of: + + +Zero to use corner type 2 +W_BORD_CORNER_1 to use corner type | +W_BORD_CORNER_4 to use corner type 4 +W_BORD_OPEN a special case used for menus on the S3 and the S3a + + +'For example, you can get the x displacement into bits 1..15 by multiplying the required x displacement +by 2 (which also clears bit zero). If you want to move rather than draw, you must then set bit zero. + + +4-8 + + +4 GRAPHICS OUTPUT + + +One of the three corner types may be qualified by oring in a combination of the following bit fields: + + +W_BORD_CUSHION to leave a one pixel clear cushion all around + +W_BORD_SHADOW_S for a single shadow area (mutually exclusive with w_porD_SHADOW_D) +W_BORD_SHADOW_D for a double shadow area (mutually exclusive with w_porD_SHADOW_S) +W_BORD_SHADOW_ON the pixels in the shadow area are set - otherwise they are cleared (meaningless + + +unless either the w_BoRD_SHADOW_S OF W_BORD_SHADOW_D flag is set) + + +W_BORD_TOP_ON to draw an arrow in the top right corner +W_BORD_TOP_OFF to clear an arrow in the top right corner +W_BORD_BOT_ON to draw an arrow in the bottom right corner +W_BORD_BOT_OFF to clear an arrow in the bottom right corner + + +The meanings of the flags are illustrated by the following diagrams: + + +W_BORD_CUSHION |W_BORD_CORNER_1 + + +W_BORD_CUSHION |W_BORD_CORNER_4 W_BORD_CUSHION|W_BORD_SHADOW_S + + +W_BORD_CUSHION |W BORD_SHADOW s|w. BORD_SHADOW_ON + + +W_BORD_CUSHION |W BORD_CORNER 4|w BORD_SHADOW s|w. BORD_SHADOW_ON + + +W_BORD_CUSHION |W BORD_CORNER 4|w. BORD_SHADOW. D|w BORD_SHADOW_ON + + +W_BORD_CUSHION |W BORD_SHADOW. D|w BORD_SHADOW_ON W_BORD_OPEN + + +W_BORD_SHADOW. D|w BORD_SHADOW_ON + + +Although some of the effects may look gross on the above diagrams, bear in mind they will typically be +used on much larger windows. + + +Some of the flag combinations presuppose a minimum size of rectangle. + + +4-9 + + +WINDOW SERVER REFERENCE + + +The w_Borp_opEN flag is a special case that overrides all the others. The top two corners are drawn as for +W_BORD_CUSHION |W_BORD_SHADOW_S |W_BORD_SHADOW_ON, but the bottom two are laws unto themselves. +Note also the non-appearance of lines along the bottom. This is used for the header of a Series 3 or +Series 3a pull-down menu. + + +Except for those combinations designed to change shadows and arrows, the borders are designed to be +drawn over a clear background. For example, those pixels at the perimeter of the rectangle that are +obtained with w_BoRD_CUSHION are not explicitly cleared. + + +The above assumes that gmode in the graphics context is set to G_TRMODE_SET (its default value). + + +Drawing shadows + + +The first line of a shadow is inset by 2 pixels at the bottom left and at the top right, and a second line (for +double shadowing) is inset a further one pixel. + + +At the bottom right, the outside line matches the inside line, just being displaced either one or two pixels +diagonally downwards and outwards. + + +The pixels that are set for w_BORD_SHADOW_ON are explicitly cleared when this flag is absent, so that the +call + + +gBorderRect (prect, W_BORD_SHADOW_S) ; +can be used to de-emphasise a window formerly emphasised using + + +gBorderRect (prect, W_BORD_SHADOW s|w. BORD_SHADOW_ON) ; + + +Arrows + + +The following shows the use of W_BORD_BoOT_oN to draw an arrow in the bottom right corner on the S3 or +the S3a: + + +Process name Alloc bytes Alloc cells Let stack +Sy SEMANGEAS +SSE SRY EAS CFe 2356 +SyYSE/SRY64 1DFa 14C + + +STSPSHLLFHS = 1518 300) +TIME.$86 BF2 430 +DATAFer BE 463 + + +Remember, that when running version 4 of the window server on the Series 3a in Series 3 compatibility +mode, the image will be drawn in double pixel mode! + + +gBorder Border a drawable +VOID gBorder(UINT flags); +Equivalent to gBorderRect where the rectangle covers the entire drawable (bitmap or window). + + +Not available in version 2 of the window server. + + +gBorder2Rect Draw a 'shadowed' border +VOID gBorder2Rect (INT type, P_RECT *prect,INT flags); + + +Introduced in version 4 of the window server, this function is similar to gBorderRect but includes the +ability to draw a 3-dimensional style border. + + +This function can be regarded as a generalisation of gBorderRect as not only can it draw the 3D style +borders but includes the functionality of gBorderRect itself. + + +It draws a border inside the rectangular block of pixels specified by the parameter prect with a style +specified by the parameter type. The flags parameter 'fine-tunes' the border display. + + +The type can be one of: +¢ W_BORDER_TYPE_0 - to draw a border in the old style as done by gBorderRect + + +¢ W_BORDER_TYPE_1 - to draw a 3-dimensional grey and black border. + + +4-10 + + +4 GRAPHICS OUTPUT + + +Note that for w_BoRDER_TYPE_1 borders, the window must be enabled for drawing grey. + + +The flags parameter can be used to fine-tune the border display. They are, to all intents and purposes, the +same as those used in the function gBorderRect with some minor changes in meaning. + + +Flags should be one of: + + +W_BORD_CORNER_2 to draw a corner type 2, the same as that drawn by gBorderRect. This is the +default corner and need not be explicitly coded. This flag applies to both border +types. + +W_BORD_CORNER_1 to draw a corner type 1, the same as that drawn by gBorderrRect. This flag +applies to both border types. + +W_BORD_CORNER_4 to draw a corner type 4, the same as that drawn by gBorderRect. This flag +applies to both border types. + +W_BORD_OPEN to draw a special corner used for menus on the S3 and S3a and is the same as +that drawn by gBorderRect. This flag applies to w_BorRDER_TyPE_o borders +only. + +The corner types can be qualified by OR'ing a combination of the following bit fields: + +W_BORD_CUSHION to leave a | pixel clear cushion right around the border. This flag applies to +both border types + +W_BORD_SHADOW_S to draw a single shadow area. This flag applies to a w_BoRDER_TYPE_o border +only. + +W_BORD_SHADOW_D to draw a double shadow area for a w_BoRDER_TYPE_O border. + + +to set the thickness of the grey and black areas, which give the 3-D effect, to 4 +pixels (compared to a default value of 2 pixels) for a w_BoRDER_TYPE_1 border. + + +W_BORD_SHADOW_ON to set the pixels in the shadow area for a w_BoRDER_TYPE_0 border. One of +W_BORD_SHADOW_S OF W_BORD_SHADOW_D must also be set. If this flag is not set, +the pixels are cleared. + + +to draw a rectangle with the shadowed effect in grey and black as shown in the +diagrams below for a w_BoRDER_TYPE_1 border. In drawing, it draws only the +grey and black parts of the border. It leaves the white parts untouched because +it assumes a pre-cleared background. + + +If this flag is not set, it draws the outline of the border as shown and clears the +area between the two outlines. This allows the shadow effects to be turned off +by simply calling gBorder2Rect again. + + +The following diagrams show examples of the various 3-dimensional style borders introduced with this +function. All are of type w_BORDER_TYPE_1. The caption below each diagram shows the flag combinations +used to draw it. + + +LJ OC + + +W_BORD_CORNER_4 W_BORD_CORNER_4 | W_BORD_SHADOW_ON W_BORD_CORNER_4 | W_BORD. + + +SHADOW_ON | W_BORD_SHADOW_D + + +W_BORD_CORNER_1 | W_BORD_SHADOW_ON W_BORD_CORNER_2 | W_BORD_SHADOW_ON + + +4-11 + + +WINDOW SERVER REFERENCE + + +gBorder2 Draw a 'shadowed' border +VOID gBorder2 (INT type, INT flags); + + +Introduced in version 4 of the window server, this is equivalent to gBorder2Rect but the rectangle is set to +be the whole drawable, either the whole window or a bitmap. + + +gDrawObject Draw a graphics object +VOID gDrawObject (INT type,P_RECT *prect,INT flags) ; + + +Introduced in version 4 of the window server, this draws the scaleable graphics object specified by type. +The object is scaled to fit inside the rectangle specified by the parameter prect. + + +The type of objects currently available are: + + +G_DRAW_OBJECT_TYPE_0 a 3-dimensional box + + +The flags applicable to this type of object are as follows: + + +W_BORD_CORNER_2 to draw the box with a corner type 2, the same as that drawn by gBorder. This +is the default and need not be explicitly coded. + +W_BORD_CORNER_1 to draw the box with a corner type 1, the same as that drawn by gBorder. + +W_BORD_CORNER_4 to draw the box with a corner type 4, the same as that drawn by gBorder. + +W_BORD_SHADOW_D to draw the box with double the thickness of the dark and light edge effects. + + +Area filling + + +The functions in this section act upon the drawable associated with the current graphics context. + + +gCirRect Change a rectangle +VOID gClrRect (P_RECT *prect, UINT mode); + + +Change all pixels within the rectangular block specified by prect where the change depends on mode as +follows: + + +G_TRMODE_SET set the pixels +G_TRMODE_CLR clear the pixels +G_TRMODE_INV invert the pixels (this is reversible by another invert) + + +The P_RECT struct is defined as: + + +typedef struct +{ +WORD x; +WORD y; +} P_POINT; + + +typedef struct +{ +P_POINT tl; /* top left pixel (internal) */ +P_POINT br; /* bottom right pixel (external) */ +} P_RECT; + + +4-12 + + +4 GRAPHICS OUTPUT + + +gilnvObloid Invert an obloid + + +VOID gInvObloid(P_EXTENT *pext) ; +Invert all the pixels (except the four corner pixels) in the rectangular block specified by pext. +The p_extEnT struct is defined as: + + +typedef struct +{ +P_POINT tl; +WORD width; +WORD height; +} P_EXTENT; + + +Not available in version 2 of the window server. + + +gFillPattern Fill a rectangle with a bitmap + + +VOID gFillPattern(P_RECT *prect, UINT bitmap_id, UINT mode); + + +Repeatedly copy the bitmap with ID bitmap_ia over the rectangular block of pixels specified by prect as +many times as is necessary to fill the rectangle. + + +The parameter mode should be one of: +G_TRMODE_REPL where bits in the source pattern replace corresponding bits in the destination. + + +G_TRMODE_SET where Is in the source pattern set corresponding bits in the destination (Os in +the source do not change corresponding bits in the destination). + + +G_TRMODE_CLR where Is in the source pattern clear corresponding bits in the destination (Os in +the source pattern do not change corresponding bits in the destination). + + +G_TRMODE_INV where Is in the source pattern toggle corresponding bits in the destination (Os +in the source pattern do not change corresponding bits in the destination). + + +A larger bitmap will give improved performance. If the pattern is all ones or all zeros, gFillPattern is +equivalent to gclrRect, but less efficient. + + +There is a built in grey bitmap with the handle ws_prTmap_crey and size ws_BITMAP_GREY_STzE_x by +WS_BITMAP_GREY_SIzE_y. This is not true grey as found on the Series 3a but is a pseudo-grey, built up +from a pattern of alternate black and white pixels (ie pixels alternately set on and off in the normal plane). + + +The parameter bitmap_id can also be the ID of a backed-up window to refer to the backup bitmap (but not +in version 2). + + +For example to fill the current drawable with the grey cheque board pattern: + + +LOCAL_C VOID GreyWin (VOID) +{ +P_RECT rect; + + +rect.tl.x=0; + +rect.tl.y=0; + +rect.br.x=10000; + +rect.br.y=10000; +gFillPattern(&rect,WS_BITMAP_GREY,G_TRMODE_REPL) ; +} + + +In version 4 of the window server, when bitmap_id refers to a backed-up window, the function has a +special way of handling grey: + + +e In normal mode, the black plane only is copied from the source to the destination. + + +e In G_GC_FLAG_GREY_PLANE mode, the grey plane from the source is selected and copied to the +grey plane of the destination. If the source only has one plane, then that is used as the source. + + +e In G_GC_FLAG_BOTH_PLANES mode, and with a two plane source, both planes are copied to their +respective destination planes. If only one plane exists, then it will be copied to both planes of the +destination. + + +Note that this does not apply when copying from any other form of bitmap - in all other cases the black +and grey planes must be copied by two separate calls to gFillPattern. + + +4-13 + + +WINDOW SERVER REFERENCE + + +—EeE——E—E—————————————————————————— ee) +Text fonts + + +Fonts are generally described in terms of: +e ascent, descent, and vertical leading +e width and horizontal leading +e low character and high character (the range of ASCII values covered). + + +To clarify the meaning of some of these terms, refer to the following diagram: + + +The string 'Specify' has been printed at a point (x, y) which is indicated in the diagram by a pair of +partially drawn lines. The horizontal of the pair of lines is known as the baseline. + + +The descent of a character is the number of pixels that it extends below the baseline. Thus in the font +shown, 'S' has a zero descent whereas 'p' has a descent of 1. + + +The ascent of a character is the number of pixels that it extends above the baseline. In the font shown, 'S' +has an ascent of 7 whereas 'p' has an ascent of 5. The ascent quoted for a font is always the maximum +ascent of all the characters in the font, and likewise for the descent. The sum of the ascent and the descent +is the height of the font. + + +Vertical leading is the number of additional pixels that separate adjacent lines of text, over and above the +stated height of each line of text. This is usually at least one, to prevent the highest ascent of one line ever +joining up with the lowest descent of the line above. On occasion, however, such joining up may actually +be intended, for example to support box-drawing via the IBM graphics characters in the extended portion +of a font. In any case, it should be noted that, strictly speaking, vertical leading is not a characteristic of a +font as such; rather, it describes how a font is used on a particular occasion. To complicate matters, +different uses of a font will in fact often have different vertical leading. + + +Horizontal leading is the number of pixels that separate adjacent characters in a line of text. + + +The term width is, unfortunately, possessed of two subtly different meanings. The more useful of the two +meanings is that the width of some text is the number of pixels from the start of that text to where a piece +of text following on from the first one would start. This is the value returned by window server inquiry +functions such as gText Width. Thus the width of the character 'S' in the above font is the number of pixels +from the start of the 'S' to the start of the following character (‘p'), namely 6. With this meaning, all the +characters shown in the diagram have width 6, except for 'i' (4) and 'f' (5). + + +The second of the two meanings of width discounts the horizontal leading, so that, by this reckoning, the +width of 'S' is just 5 pixels. This latter meaning of width is sometimes referred to as basic width. + + +There is an important difference between horizontal and vertical leading: horizontal leading is always +supplied as part of the font; on the other hand the amount of vertical leading (if any) to be applied is up to +the user of the font. Stated otherwise, applications have no choice about horizontal leading, but do have +choice over vertical leading. For this reason, the simple term leading is commonly used to denote what is +here being called vertical leading (since horizontal leading is usually just taken for granted). + + +The width of the widest character in a font is called the maximum width, and the width of the numeric +character '0' is called the numeric width, or sometimes the column width. (In any well designed font, all +numeric characters will have the same width). + + +Occasionally, a font is described in terms of its body cell. The font depicted has a basic body cell of 5 by 8 +(which excludes both vertical and horizontal leading), and a corresponding expanded body cell of 6 by 9. + + +Not all the character codes within the range need have a representation within the font. When drawn, +these characters will be represented by the last character in the font. + + +4-14 + + +4 GRAPHICS OUTPUT + + +An application can switch between many different fonts of varying sizes. Each Graphics Context may +have a different font. The appearance of text can also be altered by various style options such as underline +or bold (these are independent of the font). + + +Fonts are generally proportional, ie the characters within the font can be of differing width. It is left to an +application to determine the width of text and make decisions about layout accordingly. + + +Information is provided to allow fonts of differing heights to be aligned vertically about a baseline. When +characters are drawn, the y-coordinate given corresponds to the baseline of the character. If a line of text +is drawn using characters from fonts of different height, this ensures that the text lines up vertically. + + +gOpenFont Open a font +INT gOpenFont (TEXT *filename) ; +Load the font from filename and return the font ID. + + +If an error (with error number err) occurs (for example, the file does not exist or if it is not a valid font +file), the function calls p_leave (err) or returns err, depending on the wDisableLeaves State. + + +To use the font for text drawing functions, the font ID must be assigned to a graphics context (using +gSetGC). + + +Note that the parameter filename is ultimately passed to p_open by the window server process - not the +client process. If fi 1ename is not a full file specification, the unspecified components are taken from the +window server's default path which, in practice, is always the internal drive M.\. This is unlikely to meet +the requirements of a finished product so filename should specify the drive and directory as well as the +file name. Typically, you might place a font file in the same location as the application file in which case +you would use something like: + + +GLREF_D TEXT *DatCommandPtr; + + +LOCAL_C INT OpenFont (TEXT *name) +{ +TEXT full [P_FNAMESIZE]; + + +f_fparse (name, DatCommandPtr, &full[0],NULL) ; +gOpenFont (&full[0]); +} + + +See also gSetOpenAddress for loading a font file which is embedded in another file. + + +gSetOpenAddress Set pos to open font/bitmap/mouse icon +VOID gSetOpenAddress (UINT mode, ULONG pos); + + +Set the file position for the next call to gopenFont, gOpenFont Index, gInitBit, gOpenBit or +gOpenMouselcon as a function of mode and pos. + + +The possible values of mode are defined by constants of the form c_opEN_MopE_xxx where xxx is one of: + + +OFFSET to indicate that pos is the file position of the data + +WORD_PTR_OFFSET to indicate that pos is the file position of a uworp containing the file position of +the data + +LONG_PTR_OFFSET to indicate that pos is the file position of a uLonc containing the file position of +the data + +NORMAL to cancel the effect of any previous unused call to gsetopenaddress (pos iS +ignored) + + +The effect of the call only lasts until the next call to gopenFont, gopenFontIndex, gInitBit, gOpenBit OF +gOpenMouseIcon So you wouldn't normally need c_opEN_MoODE_NoRMAL - especially as a call to +gSetOpenAddress would normally occur immediately before the gopenxxx call it is intended to effect. + + +The data at the effective file position should be the entire contents of the normal font, multiple font, +bitmap or mouse icon file - including all headers. + + +4-15 + + +WINDOW SERVER REFERENCE + + +wFree Free a font +VOID wFree(UINT font_id); + + +Free a previously loaded font. + + +gFontinfo Get font information + + +INT gFontInfo(UINT font_id, UINT style, G_FONT_INFO *pinfo); + + +Write information about the font with ID font_id as modified by the text style style to the G_FoNT_INFO +struct at pinfo where the G_FONT_INFO struct is defined in wlib.h as: + + +typedef struct +{ + + +UWORD low_ch; /* lowest character code in font */ + +UWORD high_ch; /* highest character code in font */ + +UWORD height; /* height of font */ + +UWORD descent; /* height of bottom part of a character */ + +UWORD ascent; /* height of top part of a character */ + +UWORD numeric_width; /* width of the '0' character */ + +UWORD max_width; /* width of widest character in the font */ + +UWORD flags; /* flags specifying information about the font */ +TEXT name[16]; /* Text name of the font */ + + +} G_FONT_INFO; + + +The field numeric_width is actually the width of the '0' (zero) character, however any well designed font +will have all its numeric characters the same width. If a font is monospaced, all characters are of width + + +max_width. + + +The field max_width is set by the font designer when the font is created. It is not necessarily the widest +character in the font, since the font designer will normally exclude any special characters that are rarely +used - max_width is normally the width of 'M' or 'W'. + + +The fields numeric_width, max_width, height, descent and ascent can be modified from their base +values by the style given. + + +The flags field consists of the following bit fields: + +G_FONT_FLAG_ASCII the font contains the standard ASCII character set +G_FONT_FLAG_CP850 the font contains the IBM code page 850 character set +G_FONT_FLAG_BOLD the font is designed to look bolded +G_FONT_FLAG_ITALIC the font is designed to look italic + +G_FONT_FLAG_SERIF the font character graphics have serifs + + +Returns zero if successful or, if font_id is invalid, it calls p_leave (E_GEN_NOFONT) or returns +E_GEN_NOFONT, depending on whether wDisableLeaves has been called. + + +To get information on the system font, font_id may be set to WS_FONT_SYSTEM. + + +On version 2 of the window server you should not call gFont Info with an invalid font_id (if you do, +gFont Info writes garbage to pinfo). + + +gTextWidth Get text width + + +INT gTextWidth(UINT font_id, UINT style, TEXT *pbuf, UINT len); +Return the width in pixels of the 1en characters at pbuf when drawn with font font_id and style style. + + +Any character code in pbuf that does not have a corresponding character graphic in the font is taken to +have the width of the last character in the font. + + +Note that the style can affect the width returned because bolding, italicising, mono-spacing etc widens +each character. + + +To get the text width when using the system font, font_id may be set to WS_FONT_SYSTEM. + + +If font_id is invalid, the function calls p_leave (E_GEN_NOFONT) or returns E_GEN_NOFONT, depending on +whether wDisableLeaves has been called. + + +4-16 + + +4 GRAPHICS OUTPUT + + +gTextCount Clip text to pixel width + + +INT gTextCount (UINT font_id, UINT style, TEXT *pbuf, UINT len,UINT *pwidth) ; + + +Return the number of characters from pbuf (up to 1en) that will fit in their entirety in *pwidth pixels +when drawn with font font_id and style style. Also overwrite *pwidth with the remaining width. + + +Any character code in pbuf that does not have a corresponding character graphic in the font is taken to +have the width of the last character in the font. + + +Note that the style can affect the width returned because bolding, italicising, mono-spacing etc widens +each character. + + +When using the system font, font_id may be set to wS_FONT_SYSTEM. + + +If font_ida 1s invalid, the function calls p_leave (E_GEN_NOFONT) or returns E_GEN_NOFoONT, depending on +whether wDisableLeaves has been called. + + +gGetWidthTable Get a font width table + + +INT gGetWidthTable(UINT font_id, UINT style, UBYTE *ptab); +Generate a usyTE array of character pixel widths in *ptab for font font_id and style style. + + +The first byte in *ptab is the width of the character with code 1ow_ch and the length of the array written is +high_ch-low_ch+1 (where low_ch and high_ch are from the font's c_rontT_inro struct). + + +The function is provided to speed optimise calculations based on character widths - such as those +performed by gTextwidth and gTextCount. + + +Any character code that does not have a corresponding character graphic in the font is taken to have the +width of the last character in the font. + + +Note that the style can affect the width returned because bolding, italicising, mono-spacing etc widens +each character. + + +When using the system font, font_id may be set to ws_FONT_SYSTEM. + + +Returns zero if successful or, if font_id is invalid, it calls p_leave (E_GEN_NOFONT) or returns +E_GEN_NOFONT, depending on whether wDisableLeaves has been called. + + +wSetSystemFont Set the system and internal fonts + + +INT wSetSystemFont (INT mode, INT handle, UINT style); + + +Available in version 4 of the window server, this function mat be used on the Series 3a and Workabout to +set up the system and internal fonts. + + +The mode parameter is used to indicate which font type is to be the target of the set up. This parameter can +take one of the following values: + + +W_SYSTEM_FONT_S3B sets up the native system font +W_SYSTEM_FONT_S3 sets up the Series 3 compatibility mode system font +W_SYSTEM_FONT_INTERNAL_S3B _ sets up the native internal font +W_SYSTEM_FONT_INTERNAL_S3 __ sets up the Series 3 compatibility mode internal font +The handle parameter references the font to be used as the source for the setup. This can be: +e the handle returned for a loaded font +e the handle of one of the built-in fonts +e the handle of a font group created by gconfigureFonts + + +The style parameter can be used to modify the style of text when setting up either of the two internal font +types. This parameter is ignored if setting up any of the other font types. The style parameter adopts the +same values as those applicable to the sty1e field in the graphics context. + + +4-17 + + +WINDOW SERVER REFERENCE + + +The function returns zero if successful, =_cEN_Noront if an invalid font handle is supplied or =_cEN_are if +an invalid mode is supplied. Alternatively, it calls p_leave if wDisableLeaves has been called. + + +Note that at the time of writing, there is no way of notifying applications that the system font has changed. + + +gOpenFontindex Open a font from a multiple font file + + +INT gOpenFontIndex(TEXT *fname,UINT index) + + +Available in version 4 of the window server, this function is similar to gopenFont except that it allows a +font to be loaded from a file containing more than one font. + + +The index parameter is used to indicate which font within the file is to be loaded. The first font in the file +corresponds to an index of zero, while the second font corresponds to an index value of one and so on. + + +Single-font files can be opened by setting index to zero. +Multiple-font files are invalid to older versions of the window server. +If index refers to a font file beyond the final one in the file, error E_FILE_EOoF is reported. + + +If an error (with error number err) occurs, the function calls p_leave (err) or returns err, depending on +whether wDisableLeaves has been called. + + +Multiple-font files can be created by versions 2.00 upwards of the font compiler WSFCOMP. + + +gConfigureFonts Configure a font group +INT gConfigureFonts (INT count,G_FONT_CONFIG *pfcfg[]) +Available in version 4, this function is used to create a font group and return its id. + + +A font group is a compromise solution to the problem of deciding whether to use the window server's +algorithmic method of obtaining a style (see style subsection of the Graphics context section) or to use a +font designed specifically for the purpose. This is even more important where the situation is ambiguous. +For example, given a bold font and an italicised font, if the application wishes to print in bold and italics, +does it choose to apply the bold style to the italicised font or apply the italic style to the bold font? + + +Designing a font for every combination of style is impractical while the result of applying the window +server's algorithmic method may not always give satisfactory results. + + +Essentially, a font group is a list of font id's and style combinations. + + +When an application wishes to print text, typically it will specify a (group) font ID and a combination of +styles to be applied. In response, the window server scans down each entry in the list searching for the best +match. It then uses the font in this entry for printing. + + +The font group is specified by the parameter pfcfg which points to an array of G_FONT_CONFIG structures. +The array has count elements. Each element in the array is, in effect, an entry in the list discussed above. +The G_FonT_conF1IG structure is defined as follows: + + +typedef struct +{ +UINT FontId; /*Replacement Font is +UINT RepStyles; /*Styles needing to be replaced*/ +UINT FontStyles; /*Styles used with this Font ay +UI +} + + +NT AscentAdjust; /*Adjustment to Font's ascent */ +G_FONT_CONFIG; + + +The order of the elements in the array is important because of the way the search algorithm works. This +proceeds as follows: + + +1. The window server initially chooses the base font as the 'best'. In other words, the first entry +in the array. + + +2. Initially, each entry in the array is scanned, starting with the first, until one is found where +the RepStyles field contains styles which are a subset of the styles to be printed. + + +4-18 + + +4 GRAPHICS OUTPUT + + +3. Subsequently, the scan continues, searching for entries whose RepStyles field contains +styles which are a subset of the styles to be printed and which also (as a minimum) contain +the styles of the current 'best' entry. Where such an entry is found, this becomes the 'best'. + + +4. The process, numbered 3 above, is repeated until the array is exhausted, The window server +uses the font corresponding to the Font1d of the ‘best’ entry in the array. + + +Having found a suitable font, the window server then applies those styles which the application wants +printed but which are not specified in the Repstyles field. For example, suppose the application wants +bold and italic printed. Suppose also that the 'best’ entry in the array specifies only the bold style in the +RepStyles field. The window server will use the Font 1d as the font to be used and will apply the italic +style to this font. + + +In addition, the rontstyles member of each entry in the array specifies styles which are also to be applied +to the chosen font when it is drawn. + + +The Ascentadjust field specifies an adjustment to be made (positive or negative) to the font's ascent when +printing. This is primarily of use for superscript and subscript fonts. See the c_sty_suBscRIPT2 and +G_STY_SUPERSCRIPT2 styles at the beginning of this chapter. + + +gReadFontHeader Read a font header from a file + + +INT gReadFontHeader (TEXT *fname, INT index,UBYTE *pbuffer) + + +Available in version 4 of the window server, this function reads up to a maximum of +FONT_MAX_HEADER_LEN bytes of font data from the font referenced by fname and index into the buffer +pointed to by pbuffer. + + +fname references the font file while the index parameter indicates the actual font within the file. For a +single font file, index must be set to 0; for a multiple font file, an index value of zero refers to the first +file, an index value of one refers to the second file and so on. + + +If the call is successful, the function returns the length of data actually read. + + +If an error (with error number err) occurs (for example, the file does not exist or it is not a valid font file), +the function calls p_leave (err) or returns err, depending on the wDisableLeaves State. + + +gReadFontGroupHeader Read a font group header from a file + + +INT gReadFontGroupHeader (TEXT *fname,UBYTE *pbuffer) + + +Available in version 4 of the window server, this function reads up toa maximum of +FONT_MAX_HEADER_LEN bytes of font header data from the font file referenced by fname into the buffer +pointed to by pbuffer. + + +In the first word of the buffer, the function places the number of fonts contained in the file. This word is +followed by the group header. This means that the actual maximum length of header data that can be +stored in the file is FONT_MAX_HEADER_LEN - 2 bytes. + + +If the call is successful, the function returns the length of data actually read. + + +If an error (with error number err) occurs (for example, the file does not exist or it is not a valid font file), +the function calls p_leave (err) or returns err, depending on the wDisableLeaves State. + + +See the description of wsfcomp for information on how to add header data. + + +Text output functions + + +The functions in this section are all directed at the drawable associated with the current graphics context +and are all subject to the style and font fields of the current graphics context. + + +The functions gPrintText and gPrintClipText are also subject to the textmode field. The functions +wDrawButton, and wDrawButton2 are also subject to the gmode field. + + +In version 4 of the window server, the plane to which drawing is directed in the current graphics context +will affect the 'colour' of the display. + + +4-19 + + +WINDOW SERVER REFERENCE + + +gPrintText Print text +VOID gPrintText (INT x, INT y, TEXT *pbuf, UINT len); + + +Print the len characters at pbuf horizontally from pixel position x, y where len must not be greater than +WS_MAX_PRINT_TEXT_LEN. + + +The first character graphic is positioned such that its leftmost pixel that is just above the baseline is over +pixel (x,y) of the drawable. (The baseline is the mathematical line between the upper ascent pixels and +the lower descent pixels that make up the height of the font.) + + +The text is printed relative to the baseline so that the characters in a line of text that contains different +fonts (with potentially different ascents and descents) line up correctly, as illustrated by the following +diagram: + + +Baseline + + +Descent + + +sil + + +X is the printing position. + + +The text is printed according to the textmode, style and font in the current graphics context. + + +Any character code in pbuf that does not have a corresponding character graphic in the font is printed as +the last character in the font. + + +Note that gPrintText performs no special processing on control characters (ie characters with a code that +is less than 32) and if they are not represented in the font then they will also be printed as the last +character in the font. + + +gPrintClipText Print clipped text +INT gPrintClipText (INT x, INT y, TEXT *pbuf, UINT len, UINT clip_width) ;;; +Similar to gprintText except that it only draws as many characters as will fit inside clip_width. + + +Returns the number of characters actually printed. + + +gPrintBoxText Print text in a box + + +VOID gPrintBoxText (P_RECT *prect, UINT ascent, UINT align, INT margin, TEXT *pbuf, UINT +len); + + +Print the len characters at pbuf with a fixed textmode of G_TRMODE_REPL within the rectangular block of +pixels specified by prect, clearing (or setting) those pixels that are not replaced by characters from the +font (1en must not be greater than ws_Max_PRINT_BOX_TEXT_LEN). + + +If necessary, the drawing is pixel-clipped to the rectangle defined by prect. +The P_REcT struct is defined as: + + +typedef struct +{ +WORD x; +WORD y; +} P_POINT; + + +typedef struct +{ +P_POINT tl; /* top left pixel (internal) */ +P_POINT br; /* bottom right pixel (external) */ +} P_RECT; + + +4-20 + + +4 GRAPHICS OUTPUT + + +The characters are positioned vertically such that there are ascent pixels between the top of the rectangle +and the base line of the characters (unless you intend to clip the top off the text, ascent should be greater +than or equal to the current font's ascent) as illustrated by the following diagram: + + +ascent ascent +of +font + + +baseline of font + + +The excess space around the text is cleared or set depending on the inverse bit in the style. + + +The text may be left or right aligned, or centred within prect depending on whether align is +G_TEXT_ALIGN_LEFT, G_TEXT_ALIGN_RIGHT Of G_TEXT_ALIGN_CENTRE. + + +The parameter margin is used to clear extra space to the left or right of the text where margin is +interpreted as follows: + + +align = G_TEXT_ALIGN_LEFT + + +left-aligned text + + +align = G_TEXT_ALIGN_RIGHT + + +right-aligned text + + +For centred text, the margin can be placed either to the right or to the left of the text according to the sign +of margin, as follows: + + +align = G_TEXT_ALIGN_CENTRE, margin>=0 + + +centred text + + +align = G_TEXT_ALIGN_CENTRE, margin<0O + + +centred text + + +The text is printed according to the style and font in the current graphics context (but not textmode). + + +Using gPrintBoxText avoids the flicker that is generated between a separate clear and print. + + +gXPrintText Print text with embellishment + + +VOID gXPrintText (INT x, INT y, TEXT *pbuf, UINT len, UINT flags); + + +Print the 1en characters at pbuf horizontally from pixel position x, y with highlighting in a style that +depends on the value of f1ags (1en must not be greater than ws_MAx_PRINT_TEXT_LEN). + + +4-21 + + +WINDOW SERVER REFERENCE + + +The text is printed according to the style and font in the current graphics context (but not textmode). + + +Equivalent to calling gPrintText with a fixed textmode of G_TRMODE_REPL followed by some +embellishment depending on the value of f1ags. Possible flag values are illustrated below for the string +‘Specify’, in each case printed with the same value of x and y. + + +Zero (no embellishment). | + + +rT TT : 8 +The partially drawn lines indicate H Sian: CMM. SUMMERS Ros CaGd Ce +the point to which the coordinates x l ial laa fe i +and y-apply; _ TTT "a1: iF sae _ + + +G_XP_INV_BLOCK + + +G_XP_INV_OBLOID + + +G_XP_INV. BLOCK |G XP_REDUCED + + +G_XP_INV_OBLOID|G_XP_REDUCED + + +G_XP_UND_BLOCK nnnn a Be +a nnnE ann EEE BB a ] | +ann 6G _ Ho no One 66 ] +| a HEREE 8 | f a | +et | a ] a nnnE +nnnE 6G EERE SEE Boe OU a + + +G_XP_UND BLOCK |G XP_REDUCED + + +All the reduced forms are intended for use on text strings with no characters having descenders, such as +numbers and upper case letters. + + +A zero flags is equivalent to gPrintText with a textmode of G_TRMODE_REPL and may be used to cancel an +embellishment set up previously. + + +Not available in version 2 of the window server. + + +In version 4 of the window server, by setting the graphics context to draw to the grey plane and making +sure that the window is enabled for drawing grey, all of the text and embellishments in the above +examples will be drawn in grey. + + +4-22 + + +4 GRAPHICS OUTPUT + + +gShadowText Print shadowed text + + +VOID gShadowText (INT posx,INT posy, G_SHADOW *pshadow, TEXT *ptxt,INT len); + + +Introduced in version 4 of the window server, this function prints the 1en characters at ptxt with a +shadowed effect from pixel position posx, posy where 1en must not be greater than +WS_MAX_PRINT_TEXT_LEN. + + +It uses the current font and style (ie the current graphics context) but ignores the current textmode. +The pshadow parameter must point to a structure of type c_sHaDow which is defined as follows: + + +typedef struct +{ +UBYTE BodyColour; +UBYTE ShadowColour; +UBYTE LightColour; +UBYTE filler; +UWORD Flags; +WORD ShadowSizexX; +WORD ShadowSizey; +WORD LightSizex; +WORD LightSizeyY; +WORD Spacing; +} G_SHADOW; + + +The shadow is always placed at the bottom right of the text while the lighting effect is always placed at the +top left of the text. + + +The size of the shadow effect is specified by snadowSizex and ShadowSizey. The size of the lighting effect +is specified by Lightsizex and LightSizey. + + +The 'colours' for the body, shadow and light can be one of black, grey, white or none by setting the +G_SHADOW Members BodyColour, ShadowColour and LightColour to one of G_COLOUR_BLACK, +G_COLOUR_GREY, G_COLOUR_WHITE Of G_COLOUR_NONE. + + +The display can consist of either a single copy of the text giving an impression of the text floating above +the shadow or a solid block linking the text to the background. By default, the floating style shadow is +used. The solid block effect is achieved by setting the riags member to G_SHADOW_SOLID. + + +The gap between characters can be set by giving the spacing member a suitable value. This is useful if a +character's shadow effects are not to overlap the following character. + + +The following picture shows four examples of the effect of using gshadowText: + + +t Ihe + + +In all examples, shadowSizex was Set to 6, ShadowSizey was Set to 6, LightSizex was set to 2 and +LightSizey was Set to 2. + + +Spacing was Set to 6 to allow sufficient space between the characters so that the shadow effects could be +seen. + + +4-23 + + +WINDOW SERVER REFERENCE + + +Looking at each example from left to right, the following values were used: + + +1. BodyColour set to G_COLOUR_BLACK +ShadowColour Set tO G_COLOUR_GREY +LightColour set to G_COLOUR_NONE + + +2. BodyColour set to G_COLOUR_BLACK +ShadowColour Set tO G_COLOUR_GREY +LightColour set to G_COLOUR_NONE +Flags set to G_LSHADOW_SOLID + + +3. BodyColour set to G_COLOUR_BLACK +ShadowColour Set tO G_COLOUR_GREY +LightColour set tO G_COLOUR_WHITE +Flags set to G_LSHADOW_SOLID + + +4. BodyColour set tO G_COLOUR_WHITE +ShadowColour Set tO G_COLOUR_BLACK +LightColour set to G_COLOUR_GREY +Flags set to G_LSHADOW_SOLID + + +wDrawButton Draw a text button +VOID wDrawButton(P_RECT *prect, TEXT *pstr, UINT depressed); + + +Draw a button within rectangle prect containing the zero terminated string pstr. If depressed 1s TRUE, +draw the button with the text and the box displaced to give a 3D illusion of a depressed button. + + +The length of pst r must not be greater than w_DRAW_BUTTON_MAX_LEN (240). + + +The text is printed according to the style and font in the current graphics context. Both the box lines and +the text string are drawn according to the gmode (the value of textmode is ignored). + + +The P_REcT struct is defined as: + + +typedef struct +{ +WORD x; +WORD y; +} P_POINT; + + +typedef struct +{ +P_POINT tl; /* top left pixel (internal) */ +P_POINT br; /* bottom right pixel (external) */ +} P_RECT + + +~ + + +The intended use of worawButton is illustrated by the following example: + + +include +include + + +LOCAL_D WSERV_SPEC wSpec; +LOCAL_D UINT wMainWid; +LOCAL_D UINT FontID; + +LOCAL_D UINT FontStyle; +LOCAL_D G_FONT_INFO FontInfo; + + +LOCAL_C VOID SetFont (INT fid, INT style) + + +gFont Info (Font ID=fid, FontStyle=style, &FontInfo) ; + + +LOCAL_C VOID SetGC (VOID) + + +G_GC gc; + + +gc.font=FontID; + +gc.style=FontStyle; + +gSetGC (0, G_GC_MASK FONT |G GC_MASK_STYLE, &gc) ; +} + + +4-24 + + +4 GRAPHICS OUTPUT + + +LOCAL_C VOID DrawButton(INT state) + + +{ +P_RECT rect; + + +rect.tl.x=20; + +rect.tl.y=(40-2) -FontInfo.height; +rect.br.x=140; +rect.br.y=(40+2)+FontInfo.height; +wDrawButton(&rect,"Press any key",state) ; + + +} + + +LOCAL_C VOID MainEventLoop (VOID) + + +{ +WS_EV event; + + +for (77) + +{ + +wGetEventWait (&event) ; + +if (event .type==WM_REDRAW) +{ +wBeginRedrawWinGCO (wMainWid) ; +gBorder (W_BORD_SHADOW. D|w BORD_SHADOW_ON) ; +SetGC(); +DrawButton (FALSE) ; +wEndRedraw (); +continue; +} + +if (event .type==WM_KEY) +{ +gCreateTempGCO0 (wMainWid) ; +SetGC (); +DrawButton (TRUE) ; +wF lush () ; +p_sleep(51); +DrawButton (FALSE) ; +gFreeTempGC () ; +} + + +} + + +GLDEF_C VOID main(VOID) + + +{ +wConnect (&wSpec, 0,W_CONNECT_PRIORITY) ; + + +wMainWid=wCreateWindow(0,0,0,1); +wiInitialiseWindowTree (wMainWid) ; +SetFont (WS_FONT_SYSTEM, G_STY_BOLD) ; +MainEvent Loop () ; + + +} + + +wDrawButton2 Draw a text button + + +VOID wDrawButton2 (INT type, P_RECT *prect, TEXT *ptext, UINT state); + + +Introduced in version 4 of the window server, this function not only draws the new style Series 3a buttons, +but also the old style Series 3 types. + + +The parameter prect points to a p_REcT structure that specifies a rectangle that fully encloses the button +in all of its states. + + +The ptext parameter specifies a zero terminated string to be drawn inside the button in the current font +and style. It is the responsibility of the caller to make sure that the text will fit inside the button; there is +no clipping of text. The maximum length of text is w_DRAW_BUTTON_MAX_TEXT. + + +The parameter type indicates which style of button is to be drawn. This can have the following values and +meanings: + + +W_BUTTON_TYPE_1 draws the Series 3 style buttons + + +W_BUTTON_TYPE_2 draws the Series 3a style buttons + + +4-25 + + +WINDOW SERVER REFERENCE + + +The state parameter has different meanings for the different types. +For w_BUTTON_TYPE_1 buttons, 0 draws a raised button while | draws a depressed(flat) button. + + +For w_BUTTON_TYPE_2 buttons, 0 draws a raised button, 1 draws a semi-depressed button while 2 draws a +fully depressed(sunken) button. + + +The following picture shows three examples of w_BUTTON_TYPE_2 buttons. From left to right, the +examples show: a state O button (raised), a state | button (semi-depressed) and a state 2 button (fully +depresses). + + +raised Sen] depressed fully depressed + + +For the purpose of comparison, the following picture shows examples of w_BUTTON_TYPE_1 buttons. From +left to right, the examples show: a state 0 button (raised) and a state | button (fully depressed). + + +raleed fully depressed + + +It is important to note that before calling worawButton2 to draw W_BUTTON_TYPE_2 buttons, the window +must be enabled for drawing grey. + + +Bitmaps + + +Although directed at the drawable associated with the current graphics context, the graphics output +functions in this section do not depend on any of the settable fields in the graphics context. + + +gCreateBit Create a bitmap +INT gCreateBit (UINT flags, W_OPEN_BIT_SEG *pbitseg) ; + + +Create an uninitialised bitmap where the size of the bitmap and its method of storage is controlled by +flags and the W_OPEN_BIT_SEG struct at pbitseg. + + +The W_OPEN_BIT_SEG Struct is defined as: + + +typedef struct +{ +P_POINT size; +TEXT seg_name[14]; +} W_OPEN_BIT_SEG + + +where pbitseg->size specifies the dimensions of the bitmap in pixels and pbitseg->seg_name is written +to by gcreateBit when requested by the bit in flags (as described next). + + +If f£1ags is zero, the bitmap may be stored in the window server's data space or in a named memory +segment depending on the size of the bitmap. If the bitmap requires less than 2.5K bytes, it is stored in +the window server's data space. + + +The storage of the bitmap is controlled by setting the following bits in flags: +WS_BIT_SEG to store the created bitmap in its own memory segment (regardless of its size) + + +WS_BIT_SEG_ACCESS to create the bitmap in its own memory segment and to write the name of the +segment as a zero terminated string to pbitseg->seg_name. The segment name +can be used to access the bitmap directly using p_sgcopyfr and p_sgcopyto +(described in the Memory Allocation chapter of the PLIB Reference manual) or +otherwise. + + +WS_BIT_SEG_ZERO_SIZE Used in conjunction with ws_BIT_SEG_ACcCcEss to create the bitmap's memory +segment with zero size. You must subsequently increase the size at a later date. +This is designed to be used in conjunction with graphics functions that are +added using wLoadDYL. + + +4-26 + + +4 GRAPHICS OUTPUT + + +If flags is either zero or WS_BIT_SEG, pbitseg—>seg_name is not written to and, in this case, pbitseg may +just be the address of a p_pornt struct. The prototype for gcreateBit actually declares pbitseg asa +voIp * so that you can pass either a wS_BIT_SEG * Of a P_POINT *. + + +You may use all the window server graphics functions to draw to a bitmap unless the +WS_BIT_SEG_ZERO_S1ZE flag is set, in which case the graphics functions will have no effect. + + +Returns the positive ID of the bitmap if successful. + + +If the function fails because there is insufficient memory, it calls p_leave (E_GEN_NOMEMORY) or returns +E_GEN_NOMEMoRY, depending on whether wDisableLeaves has been called. + + +gOpenBit Load a bitmap +INT gOpenBit (TEXT *filename, UINT index, UINT flags, W_OPEN_BIT_SEG *pbitseg) ; + + +Load bitmap index from file filename where index is used to select a bitmap from a file that contains +multiple bitmaps (a zero index selects the first bitmap). To load from a file containing a single bitmap, +pass the index as zero. + + +The function writes to the w_oPEN_BIT_sSEG Struct at pbitseg where w_opEN_BIT_SEG is defined as: + + +typedef struct +{ +P_POINT size; +TEXT seg_name[14]; +} W_OPEN_BIT_SEG + + +If the bitmap is successfully loaded, the dimensions of the bitmap in pixels is written to pbitseg->size +and the ID of the bitmap is returned. + + +If £1ags is zero, the bitmap may be stored in the window server's data space or in a named memory +segment depending on the size of the bitmap. If the bitmap requires less than 2.5K bytes, it is stored in +the window server's data space. + + +The storage of the bitmap is controlled by setting the following bits in fags: +WS_BIT_SEG to store the loaded bitmap in its own memory segment (regardless of its size) + + +WS_BIT_SEG_ACCESS to store the loaded bitmap in its own memory segment and to write the name of +the segment as a zero terminated string to pbitseg->seg_name. The segment +name can be used to access the bitmap directly using p_sgcopyfr and +p_sgcopyto (described in the Memory Allocation chapter of the PLIB +Reference manual) or otherwise. + + +WS_BIT_WRITE if set, you are given write access to the bitmap and a new bitmap is always +created. If the flag is not set, the bitmap will only be created once and if any +client calls gopenpit on the same bitmap, the loaded bitmap will be shared. + + +Provided that the ws_B1T_wr1TE flag is set, you may use all the window server graphics functions to draw +to a bitmap. If the ws_B1T_wr1te flag is not set, the graphics output functions will have no effect. + + +If ws_BIT_SEG_ACCESS iS not set in flags, pbitseg->seg_name is not written to and, in this case, pbitseg +may just be the address of a p_pornt struct. The prototype for gopenBit actually declares pbitseg as a +voIp * so that you can pass either a wS_BIT_SEG * Of a P_POINT *. + + +If an error (with error number err) occurs, the function calls p_leave (err) or returns err, depending on +whether wDisableLeaves has been called. + + +Note that the parameter filename is ultimately passed to p_open by the window server process - not the +client process. If filename is not a full file specification, the unspecified components are taken from the +window server's default path which, in practice, is always the internal drive M:\. This is unlikely to meet +the requirements of a finished product so filename should specify the drive and directory. + + +4-27 + + +WINDOW SERVER REFERENCE + + +Typically, the bitmap file might be built into the application to create a .app file as described in the +Building An Application chapter in the General Programming manual. In this situation you might have a +code fragment that looks like: + + +GLREF_D TEXT *DatCommandPtr; + + +LOCAL_C INT OpenBit (TEXT *name) + + +{ +W_OPEN_BIT_SEG bseg; +TEXT full [P_FNAMESIZE]; + + +f_fparse (name, DatCommandPtr, &full[0],NULL); +gOpenBit (&full[0],0,0, &bseg) ; +} + + +See also gSetOpenAddress for loading a bitmap file which is embedded in another file. + + +wFree Free a bitmap + + +VOID wFree(UINT bitmap_id); +Free the bitmap with ID bitmap_ia. + + +Any Graphics Contexts drawing to bitmap_id is automatically freed. + + +gSaveBit Save a bitmap + + +INT gSaveBit (TEXT *filename, UINT bitmap_id) ; + + +Save the bitmap with ID bitmap_id to file filename or, if bitmap_id is zero, save the screen to file + + +filename. + + +The parameter bitmap_id can also be the ID of a backed-up window to refer to the backup bitmap (but not +in version 2). + + +Returns zero if successful. + + +If an error (with error number err) occurs, the function calls p_leave (err) or returns err, depending on +whether wDisableLeaves has been called. + + +If filename is not a full file specification, the unspecified components are taken from the window server's +default path which, in practice, is always the internal drive M:\. + + +In version 4 of the window server, the function will save a double bitmap when saving the screen or a +backed-up window with a grey plane. + + +gSaveRect Save part of a bitmap +INT gSaveRect (TEXT *filename, UINT bitmap_id, P_RECT *prect); + + +Save the rectangular block of pixels specified by prect from the bitmap with ID bitmap_id to file +filename or, if bitmap_id is zero, save the rectangular block of pixels specified by prect from the screen +to file filename. + + +The P_REcT struct is defined as: + + +typedef struct +{ +WORD x; +WORD y; +} P_POINT; + + +typedef struct +{ +P_POINT tl; /* top left pixel (internal) */ +P_POINT br; /* bottom right pixel (external) */ +} P_RECT; + + +4-28 + + +4 GRAPHICS OUTPUT + + +The parameter bitmap_id can also be the ID of a backed-up window to refer to the backup bitmap (but not +in version 2). + + +Returns zero if successful. + + +If an error (with error number err) occurs, the function calls p_leave (err) or returns err, depending on +whether wDisableLeaves has been called. + + +If filename is not a full file specification, the unspecified components are taken from the window server's +default path which, in practice, is always the internal drive M:\. + + +Not available in version 2 of the window server. + + +In version 4 of the window server, the function will save a double bitmap when saving the screen or a +backed-up window with a grey plane. + + +gCopyBit Copy a bitmap to a window +VOID gCopyBit (P_POINT *pos, UINT bitmap_id, P_RECT *prect, UINT mode); + + +Copy the rectangular block of pixels specified by prect in the bitmap with ID bitmap_ia to position pos +in the destination. + + +The parameter mode should be one of: +G_TRMODE_REPL where bits in the source pattern replace corresponding bits in the destination. + + +G_TRMODE_SET where Is in the source pattern set corresponding bits in the destination (Os in +the source do not change corresponding bits in the destination). + + +G_TRMODE_CLR where Is in the source pattern clear corresponding bits in the destination (Os in +the source pattern do not change corresponding bits in the destination). + + +G_TRMODE_INV where Is in the source pattern toggle corresponding bits in the destination (Os +in the source pattern do not change corresponding bits in the destination). + + +The p_point and p_rect structs are defined as: + + +typedef struct +{ +WORD x; +WORD y; +} P_POINT; + + +typedef struct +{ +P_POINT tl; /* top left pixel (internal) */ +P_POINT br; /* bottom right pixel (external) */ +} P_RECT; + + +This function should not be used to copy from a bitmap onto itself, since it does not handle overlapping +source and destination areas - gcopyRect should be used instead. + + +The parameter bitmap_id can also be the ID of a backed-up window to refer to the backup bitmap (but not +in version 2). + + +In version 4 of the window server, when bitmap_ia refers to a backed-up window, the function has a +special way of handling grey: + + +e In normal mode, the black plane only is copied from the source to the destination. + + +e In G_GC_FLAG_GREY_PLANE mode, the grey plane from the source is selected and copied to the +grey plane of the destination. If the source only has one plane, then that is used as the source. + + +e In G_GC_FLAG_BOTH_PLANES mode, and with a two plane source, both planes are copied to their +respective destination planes. If only one plane exists, then it will be copied to both planes of the +destination. + + +Note that this does not apply when copying from any other form of bitmap - in all other cases the black +and grey planes must be copied by two separate calls to gcopyBit. + + +4-29 + + +WINDOW SERVER REFERENCE + + +gCopyRect Copy a bitmap onto itself +VOID gCopyRect (P_RECT *prect, P_POINT *pos, UINT mode); + +Copy the rectangular block of pixels specified by prect to position pos. + +The parameter mode is as for gcopyBit, described above. + + +This function should only be used when the current graphics context is assigned to a bitmap. It should not +be used to copy parts of windows since it does not handle invalid areas or possible obscuring windows - +wScrollRect should be used instead. + + +gPeekBit Read a bitmap +INT gPeekBit (UINT bitmap_id, P_POINT *pstart, UINT len, UBYTE *presult) ; + + +Copy a horizontal slice of 1en bits starting at (pstart->x, pstart->y) from bitmap_id to presult +(which must be at least (((1en+15)/8) & (~1)) bytes long). + + +To copy from the screen, set bitmap_id to zero. +If the section specified by start and len extend outside the bitmap then gPeekBit will call p_panic. +The parameter bitmap_id can also be the ID of a backed-up window to refer to the backup bitmap. + + +On version 2 of the window server, 1en must be less than (8*MAX_WSERV_TO_CLIENT_BUFFER) bits long. + + +In version 4 of the window server, if the most significant bit of the bitmap_id is set, then the function will +‘peek' from the grey plane. For example, the following code fragment re-directs the function to ‘peek’ from +the grey plane: + + +bitmap_id |= 0x8000; + +gPeekBit (bitmap_id, ... ); +gCheckBitmapID Check if a bitmap is valid +INT gCheckBitmapID(UINT bitmap_id) ; +Check if a bitmap is valid. + + +Returns zero if it is valid. Otherwise the function calls p_leave(E_FILE_NxIST) or returns E_FILE_NXIST, +depending on whether woisableLeaves has been called. + + +Not available in version 2 of the window server. + + +Multiple bitmaps + + +In version 4 of the window server, a set of bitmap functions is available that allows a bitmap file to be +opened so that bitmaps within the file can be loaded or drawn direct from the file. + + +Loading multiple bitmaps from a file with this method is considerably quicker than repeated calls to +gOpenBit as the file does not have to be opened and closed for every bitmap loaded. + + +Drawing bitmaps direct from a file is advantageous when drawing part of a large bitmap; only the parts +actually drawn are loaded, saving on access time and storage. + + +When using this method to draw the whole bitmap, there is a trade-off between memory usage and the +time taken to perform the draw. While loading the bitmap "bit by bit" as it is drawn makes it slower than +loading the whole bitmap in one go and then drawing it, it needs less memory, as only that part of the +bitmap to be drawn needs to be in memory at any one time. + + +4-30 + + +4 GRAPHICS OUTPUT + + +glnitBit Open a bitmap file +INT gInitBit (TEXT *filename, INT *pcount) ; + + +Available in version 4 of the window server, this function opens the bitmap file £i1ename ready for calls +to gGet Bit OF gDrawBit. + + +If the open is successful, the function returns the handle of the open file and the number of bitmaps held +in the file is written to *pcount. + + +If filename is not a full file specification, the unspecified components are taken from the window server's +default path which, in practice, is always the internal drive M:\ + + +If an error (with error number err) occurs, the function calls p_leave (err) or returns the (negative) error +number, depending on whether woisableLeaves has been called. + + +See also gSetOpenAddress for opening a bitmap file which is embedded within another file. + + +gGetBit Load a bitmap from an open file + + +INT gGetBit (UINT handle, UINT index,UINT flags, W_OPEN_BIT_SEG *pbitseg) ; + + +Available in version 4 of the window server, this function loads a bitmap from the bitmap file referenced +by handle (as returned from a previous call to ginitBit). + + +index indicates the position of the bitmap within the file; zero indicates the first bitmap, one indicates the +second and so on. + + +The behaviour of the function and the meaning of the parameters flags and pbitseg are the same as for +gOpenBit. + + +Returns the ID of the bitmap if successful. + + +If an error (with error number err) occurs, the function calls p_leave (err) or returns the (negative) error +number, depending on whether woisableLeaves has been called. + + +gDrawBit Draw a bitmap from an open file +INT gDrawBit (P_POINT *pos, INT handle,P_RECT *prect, INT mode, INT index) ; + + +Available in version 4 of the window server, this effectively performs a gGetBit, gCopyBit and wrree. +The pos, prect and mode parameters are the same as for gcopyBit in that they specify what is drawn. The +handle and index parameters are the same as for gcetBit in that they reference the open bitmap file and +indicate the position of the source bitmap within the file (relative to zero). + + +Only the relevant scan lines for the parts to be drawn are loaded; these are loaded one at a time. This +means that no extra memory needs allocating. + + +Returns zero if successful. + + +If an error (with error number err) occurs, the function calls p_leave (err) or returns, depending on +whether woisableLeaves has been called. + + +gQueryBit Query the size of a bitmap + + +INT gQueryBit (INT handle, INT index, P_POINT *psize); + + +Available in version 4 of the window server, this function queries the size of a bitmap within a file opened +by gInitBit. The open file is referenced by handle while index indicates the position of the bitmap +within the file (relative to zero). The structure pointed to by psize is filled in with the size of the bitmap. + + +Returns zero if successful. + + +If an error (with error number err) occurs, the function calls p_leave (err) or returns, depending on +whether woisableLeaves has been called. + + +4-31 + + +WINDOW SERVER REFERENCE + + +wFree Close an open bitmap + + +VOID wFree(UINT handle) ; + + +In version 4 of the window server, if passed the handle referencing an opened bitmap file (as returned +from a call to ginitBit), the function closes the bitmap file but leaves loaded any bitmaps that came from +that file. + + +ginitMultiSave Initialise a multiple bitmap file +INT gInitMultiSave (TEXT *fname, INT count) ; + + +Available in version 4 of the window server, this function creates a file fname prepared to receive up to +count bitmaps. + + +The call returns a positive handle if the file was successfully opened and initialised. This handle should be +used in subsequent calls to gSaveMultiBit, gSaveMultiRect and gEndMultiSave. + + +Any errors generated by the filing system when creating the file will be returned (or leave called). In this +event, any file created will be deleted. + + +gSaveMultiBit Save a bitmap to a multi bitmap file +INT gSaveMultiBit (INT handle, INT bitmap) ; + + +Available in version 4 of the window server, this function attempts to save the bitmap with ID bitmap to +the initialised multiple bitmap file referenced by hand1e. If bitmap is zero, the screen is saved to the file. + + +The call returns zero if successful. + + +Any error generated by the filing system when writing to the file will be returned (or leave called) in the +same way as for gSaveBit. If an attempt is made to save more than the maximum permitted number of +bitmaps (set by the parameter count in the call to ginitMultiSave) the function will return +E_GEN_TOOMANY. + + +If the call fails (for whatever reason), the multiple bitmap file will be left in good condition and any +bitmaps already saved will still be accessible. However, any further attempts to save to the file will not be +allowed and it must be closed by a call to gzEnaMultiSave. + + +gSaveMultiRect Save part of bitmap to multi bitmap file +INT gSaveMultiRect (INT handle, INT bitmap, P_RECT *prect); + + +Available in version 4 of the window server, this function behaves in the same way as gSaveMultiBit. +However, only that part of the bitmap specified by the rectangle defined by prect is saved. + + +The call can fail for exactly the same reasons as gSaveMult iBit returning the same values. + + +gEndMultiSave End multiple bitmap save and close file +INT gEndMultiSave (INT handle) ; + + +Available in version 4 of the window server, this function ends the saving of bitmaps to a multiple bitmap +file referenced by handle and closes the file. + + +The call returns zero if successful. + + +Any error generated by the filing system when closing the file will be returned (or leave called). + + +ginquireChecksum Inquire screen or bitmap checksum +VOID gInquireChecksum(INT handle, UWORD *pchecksum) ; + + +Available in version 4 of the window server, this function calculates a checksum and places the value in a +UWORD pointed to by pchecksum. + + +handle references the object of the checksum operation and can be the ID of a bitmap or a backed-up +window. If handle is zero, the object of the checksum operation is the whole screen. + + +4-32 + + +4 GRAPHICS OUTPUT + + +Adding graphics output functions + + +The window server can be extended by building additional low-level graphics output services, that write +directly to the screen memory, into a dynamic link library (DYL). Such a DYL, when loaded using +wLoadDYL, effectively becomes part of the window server. + + +Note that the services described in this section are not suitable for loading and accessing any other type +of DYL. + + +Producing the window server extension DYL itself is an advanced topic and is not documented in this +Software Development Kit. At the time of writing, no such DYL exists. + + +A DYL that extends the window server must first be loaded by calling p_1oad1ib (described in the Object +Oriented Programming chapter in the PLIB Reference manual). It must then be loaded by the window +server using wLoadDYL. The services supplied by the DYL can then be accessed using wcalipyL and +wCallDYLReply. + + +wLoadDYL Load a DYL + + +INT wLoadDYL(TEXT *name) ; +Load the loaded window server extension DYL name into the window server. +The DYL should already have already been loaded into memory by a call to p_loadlib. + + +The parameter name is the DYL segment name (which is the same as the DYL file name, but does not +include the directory or the device). + + +Returns the ID of the DYL (to be used by wcalipyu and wcal1DyLReply). + + +Example + + +GLDEF_C UINT LoadWservDYL (VOID) +{ +f_leave(p_loadlib("C:\DYL\TEST.DYL", &test_dyl_handle, TRUE)); +return (wLoadDYL("TEST.DYL") ); +} + + +wCallIDYL Call a DYL function + + +VOID wCallDYL(UINT dyl_id, UINT class, UINT size_of_data, VOID *pdata); + + +Call a graphic function within the DYL ay1_id where class specifies which function within the DYL to +call (as specified by the builder of the DYL). + + +pdata points to the parameters to be passed to the DYL. + + +size_of_data 1s the number of bytes of data at paata. + + +wCallDYLReply Call a DYL enquiry function +INT wCallDYLReply(UINT dyl_id, UINT class, UINT size_of_data, VOID *pdata, VOID *presult) ; +Call an enquiry function within the DYL where the function called should not do any graphics output. +pdata points to the parameters to be passed to the DYL. + +size_of_data is the number of bytes of data at paata. + + +Returns the value returned by the DYL function (negative return values cause p_leave to be called, +positive values are returned normally). + + +The DYL function may also return a buffer of data, if it does presult should point to a buffer large +enough to hold the returned data. + + +4-33 + + +CHAPTER 5 + + +EVENTS + + +DS ew En a FS EF +Getting the next event + + +wGetEventWait Wait for an event + + +VOID wGetEventWait (WS_EV *event) ; + + +Wait for a window server event and return with the event type and parameters written to the ws_zv struct +at address event where ws_Ev is defined as: + + +typedef struct +{ +WORD type; +UWORD handle; +UWORD time; +WS_EVENT_UNION p; + + +} WS_EV; + +where: + +type is the positive event type of the form wu_xxxx + +handle For events that are directed at a window (eg wM_REDRAW, WM_MOUSBE), this is the +handle that was specified to wcreateWindow. For events that are not directed at +a window (eg WM_KEY, WM_FOREGROUND), it is set to the value specified to +wConnect. + +time is set by key and mouse events. It gives the low order word of the system tick +count (a tick is 1/32 of a second) when the event occurred. It may be used, for +example, to detect double clicks. + +Pp is a union of event type-dependent parameters + + +The ws_EVENT_UNION union is defined as: + + +typedef union +{ +UWORD uword; +UBYTE *dpoint; +P_RECT rect; +WMSG_KEY key; +WMSG_MOUSE mouse; +WMSG_RUBBER rubber; +WMSG_CAPS caps; +} WS_EVENT_UNION; + + +These event-specific parts are described under the description of the associated event type, in the course of +this chapter. + + +5-1 + + +WINDOW SERVER REFERENCE + + +wGetEvent Asynchronously request an event +VOID wGetEvent (WS_EV *event) ; + + +Request an event from the window server and return without waiting for the request to complete. This is +the asynchronous version of wGetEventWait. For more information on asynchronous events, see the +chapter Asynchronous Requests and Semaphores in the PLIB Reference manual. + + +Calling wGetEvent initially sets event->type to E_FILE_PENDING to indicate that no event has yet arrived. +When there is an event to deliver, the window server sets event->type to the event type and also sets the +rest of event as appropriate for event->type. It then signals the caller's I/O semaphore. + + +Only one wGetEvent may be outstanding at a time. The window server panics the process if a second +wGetEvent is called when one is already pending. + + +wGetEventSpecial Asynchronously request selected events +VOID wGetEventSpecial (WS_EV *event,UINT flags); + + +Introduced in version 4 of the window server, this is an enhanced version of the function wGetEvent, +where the flags parameter is used to select which type of event(s) the window server is to deliver. + + +There can only be one call outstanding to either wGetEvent or wGetEvent Special at any one time. + + +To change the type of event(s) selected in an outstanding wGetEvent or wGetEvent Special, use the +function wGetEventUpdate. + + +The following flags can be used to select the corresponding events. They can be ored together: + + +WE_KEY Selects key and task key events + +WE_REDRAW Selects wM_REDRAW events + +WE_STATUS Selects the WM_FOREGOUND, WM_BACKGROUND and WM_oN events + +WE_MOUSE Selects mouse and rubber band events + +WE_OTHERS Selects all events other than those listed above. + +WE_NORMAL Selects all of the above events + +WE_ESC This is only relevant when wE_KEy is not set. If the ESC key is pressed, the +keyboard buffer is thrown away and a wM_EScaAPE event is delivered to the +application. + + +Note that calling weetEvent Special with the we_Normat flag set is equivalent to calling wGetEvent. + + +wGetEventUpdate Change event types selected +VOID wGetEventUpdate(UINT flags); + + +Introduced in version 4 of the window server, this function modifies the type of event(s) that the window +server is to deliver where there is an outstanding wGetEvent or wGetEvent Special call. + + +The previously selected event type(s) are discarded and replaced with a new set as specified in the flags +parameter. The possible values for f1ags are the same as those described in wGetEvent Special. + + +Note that if there is no outstanding call to either wGetEvent or wGetEvent Special then calling +wGetEventUpdate will have no effect. + + +5-2 + + +5 EVENTS + + +Event types +This section describes event types that are common to more than one machine type. +The following descriptions assume that event is declared as: + + +WS_EV event; + + +WM_KEY Key press event + + +Sent when a key is pressed where the key press is described by the wasc_xey struct event.p.key where +wMsG_kEy is defined as: + + +typedef struct +{ + + +UWORD keycode; /* Code for the key pressed */ +UBYTE modifiers; /* State of mouse button, shift keys etc */ +UBYTE count; /* Used to accumulate auto-repeat counts */ + + +} WMSG_KEY; +Count +For single key presses, event .p.key.count is l. + + +If a key is held down, count will get to be greater than | when the client is unable to process keys at the +rate at which the system generates repeated keys. + + +As described in the Keyboard input section of the first chapter, application programmers are best advised +just to ignore the repeat count. + + +Modifiers + + +event .p.key.modifiers is a Set of bit flags: + + +W_SHIFT_MODIFIER SHIFT key down +(0x02) + +W_CTRL_MODIFIER CTRL key down +(0x04) + +W_PSION_MODIFIER PSION key down +(0x08) + +W_CAPS_MODIFIER caps lock on +(0x10) + + +W_NUM_LOCK_MODIFIER num lock on (MC only) +(0x20) + + +Keycode + + +When a "standard" key that represents a character from the SIBO character set! is pressed, + +event .p.key.keycode contains the character code of the corresponding character in the range 0x20 to +(nominally) oxt£ but excluding ox7£. The actual upper limit on the code which can be directly produced +from the keyboard is less than oxfr and depends on what language (eg French, German) the keyboard is +produced for. + + +The SHIFT and CAPS LOCK keys modify the keycode following the normal conventions and as suggested by +the labelling of the key. + + +In most cases on the HC and MC and for those keys that are used as accelerators on the S3 and S3a, the +PSION shift key produces a keycode that is generated by adding 0x200 (w_spEcIAL_kEy) to the unshifted +keycode with caps lock off. For example, pressing PSION+A with or without CTRL and SHIFT and regardless +of the caps lock state produces a keycode of 0x261 (the code for lower case 'a' plus w_SPECIAL_KEY). + + +'Similar to IBM's code page 850 - see the section Text Fonts in the first chapter. + + +WINDOW SERVER REFERENCE + + +On machines which have a CTRL key (that is, excluding the HC), you can generate any keycode from 0x00 +to 0xff indirectly by holding down the CTRL key and typing the required code as a 3-digit decimal number +(using leading zeros as necessary). In this case, a single key event is generated after the third decimal +number is pressed. Also, following normal conventions, pressing CTRL-A to CTRL-Z produces a keycode + + +from 0x01 to Oxia. + + +Many of the keys do not represent printable characters from the SIBO character set (these keys are +sometimes called "special keys"). Such keys generate a keycode which is either less than 0x20, 0x7f or + + +greater than Oxff. + + +The following lists the key codes produced by the special keys: + + +W_KEY_TAB (0x9 or +"\t') + + +W_KEY_DELETE_LEFT +(0x08 or '\b') + + +W_KEY_DELETE_RIGHT +(Ox7£) + + +W_KEY_RETURN (0x0d + + +or ' Nx) + + +W_KEY_ESCAPE (0x1b) + + +W_KEY_UP (0x100) + + +W_KEY_DOWN (0x101) + + +W_KEY_RIGHT (0x102) + + +W_KEY_LEFT (0x103) + + +W_KEY_PAGE_UP + + +(0x104) + + +W_KEY_PAGE_DOWN + + +(0x105) + + +W_KEY_HOME (0x106) + + +W_KEY_END (0x107) + + +W_KEY_TASK (0x108) + + +W_KEY_VOICE (0x109) + + +5-4 + + +Produced by TAB, with or without SHIFT or CTRL. On the HC and MC only, the +PSION key adds w_sPECIAL_KEY. On the Workabout, the PSION key (but not +SHIFT+PSION) converts the keypress to W_KEY_TASK. + + +Produced by DEL on the HC, DELETE with or without CTRL or PSION on the S3 +and $3a, BACKSPACE with or without SHIFT or CTRL on the MC, and DEL +without SHIFT on the Workabout. On the HC and MC, the PSION key adds +W_SPECIAL_KEY. + + +Produced by SHIFT+DEL on the HC and Workabout, SHIFT+DELETE on the $3 +and S3a, DELETE with or without SHIFT or CTRL on the MC. On the MC only, +the PSION key adds w_sPECIAL_KEY. + + +Produced by ENTER, with or without SHIFT or CTRL. On the HC and MC only, +the PSION key adds w_sPECIAL_KEY. + + +Produced by ESC, without SHIFT or CTRL on the Workabout; with or without +SHIFT or CTRL on all other machines. On the HC and MC only, the PSION key +adds w_SPECIAL_KEY. + + +Produced by UP ARROW, with or without SHIFT or CTRL. On the HC and MC +only, the PSION key adds w_SPECIAL_KEY. + + +Produced by DOWN ARROW, with or without SHIFT or CTRL. On the HC and MC +only, the PSION key adds W_SPECIAL_KEY. + + +Produced by RIGHT ARROW on the HC, RIGHT ARROW with or without SHIFT or +CTRL on the $3, S3a, Workabout and MC. On the HC and MC only, the PSION +key adds w_sPECIAL_KEY. + + +Produced by LEFT ARROW on the HC, LEFT ARROW with or without SHIFT or +CTRL on the $3, S3a, Workabout and MC. On the HC and MC only, the PSION +key adds Ww_SPECIAL_KEY. + + +Produced by PSION+UP ARROW on the $3, S3a and Workabout, PAGE UP with or +without SHIFT or CTRL on the MC. On the MC only, the PSION key adds +W_SPECIAL_KEY. + + +Produced by PSION+DOWN ARROW on the $3, S3a and Workabout, PAGE DOWN +with or without SHIFT or CTRL on the MC. On the MC only, the PSION key adds +W_SPECIAL_KEY. + + +Produced by PSION+LEFT ARROW on the $3, S3a and Workabout, HOME with or +without SHIFT or CTRL on the MC. On the MC only, the PSION key adds +W_SPECIAL_KEY. + + +Produced by PSION+RIGHT ARROW on the $3, S3a and Workabout, END with or +without SHIFT or CTRL on the MC. On the MC only, the PSION key adds +W_SPECIAL_KEY. + + +Produced by SHIFT+LEFT ARROW (TASK) on the HC, TASK with or without SHIFT +or CTRL on the MC and PSION+TAB on the Workabout. On the MC only, the +PSION key adds W_SPECIAL_KEY. + + +Normally processed by the window server to switch the foreground task and not +passed to clients. However, you can use wCaptureKey to capture the W_KEY_TASK +key (as described under wcaptureKey). + + +Produced by RECORD with or without SHIFT or CTRL on the MC only. The PSION +key adds w_sPECIAL_KEY. + + +W_KEY_CAPS_LOCK +(0x10c) + + +W_KEY_BACKLIGHT +(0x120) + + +W_KEY_INFO (0x121) + + +W_KEY_MENU (0x122) + + +W_KEY_HELP (0x123) + + +W_KEY_DIAMOND +(0x124) + + +W_KEY_APP1 to + + +W_KEY_APP8 (0x131 to + + +0x138) + + +W_KEY_MODE (0x130) + + +W_KEY_LCD (0x2000) +W_KEY_LCD_MINUS +(0x2001) + + +W_KEY_ON (0x2002) + + +5 EVENTS + + +Produced by CAPS LOCK on the $3 and MC, by PSION+DIAMOND on the S3a and +by PSION+SPACE on the Workabout. + + +This key press is processed by the operating system to set the caps lock state +and passed to the window server on the $3, S3a and MC (but not on the HC). +On the MC, the window server generates a wM_KEYBOARD_STATE_CHANGE event +to the shell. The window server does not normally pass it on to the foreground +client. You can use wcaptureKey to capture the w_KEY_cAPs_LOocK key. + + +Produced by the BACKLIGHT key with or without SHIFT on the HC and the +Workabout. On the HC only, the PSION key adds w_spECIAL_KEY. + + +This key is normally processed by the operating system although you can +disable it by calling p_setbacklight as described in the General System +Services section of the PLIB Reference manual. The key is normally passed +through to the foreground client (unless captured by a client using +wCaptureKey). + + +Produced by SHIFT+RIGHT ARROW (INFO) on the HC only. + + +Produced by MENU with or without SHIFT on the HC and by MENU with or +without SHIFT, CTRL or PSION on the S3, S3a and Workabout. On the HC only, +the PSION key adds w_spEcIAL_KEY. + + +If wsEnableTemp has been called, the window server processes PSION+MENU to +present a temporary status window (in which case it does not pass the key press +on to the client). By convention on the S3 and S3a, CTRL+MENU is processed by +clients to present a permanent status window. + + +Produced by HELP with or without SHIFT, CTRL or PSION on the S3 and S3a, and +by ESC with either SHIFT or CTRL, but not PSION, on the Workabout. + + +As suggested by the S3/S3a key labels, PSION+HELP on these machines should +be interpreted as a DIAL key. + + +Produced by DIAMOND on the S3a only. Used by applications to switch from one +mode to another. + + +Produced by the 8 membrane keys on the S3 from left to right (also called +application keys). + + +These are normally handled by the window server in co-operation with the +system task. For more information, see the section on Clients and the Window +Server in the Introduction chapter of this manual. + + +Produced on the S3 only when the application key that is associated with the +foreground application is pressed. Applications normally cycle through their +display modes in response to this key event. + + +Produced by DIAMOND on the S3a when running in S3 compatibility mode. + + +Produced by the LCD BRIGHTER and LCD DIMMER keys on all machines except +the Workabout. On the Workabout the single LCD BRIGHTER key produces +W_KEY_Lcp only, and SHIFT+LCD BRIGHTER is used to dim the LCD. + + +These keys are processed by the operating system rather than the window server +so you can't use wCaptureKey to disable them. These keys are normally passed +through to the foreground client. + + +Produced on an HC with version 3.5 of the window server, and on the S3, S3a +and Workabout when the ON key is pressed. + + +Also, when the machine switches on for any reason (such as the expiry of an +absolute timer) the operating system manufactures an w_KEyY_on event to the +window server?. + + +2On the HC, the window server is only informed of the machine being switched on after +p_setonevent (TRUE) has been called. + + +5-5 + + +WINDOW SERVER REFERENCE + + +This event is normally processed by the window server to: + + +1. pass a WM_ON event to the foreground client (provided it has called +wiInformOn) or, in version 4 of the window server, pass a WM_ON event +to a client whether it is in foreground or background (provided it has +called wInformonAll (TRUE) ) + + +2. present an info message to inform the user of any low battery state? +3. to present the password alert if a password has been set. + + +When processed by the window server, the w_KEY_on event is not passed to the +foreground client. + + +You can use wCaptureKey to capture the w_KEy_oNn key. This will disable all +window server processing of this event. + + +W_KEY_OFF (0x2003) Produced by the OFF key on the HC, $3, S3a and Workabout only. + + +Normally processed by the window server to turn the machine off and not +passed to clients. However, you can use wCaptureKey to capture the OFF key (as +described under wcapturekey). The capturer can turn the machine off by +calling p_off - as described in the General System Services section of the PLIB +Reference manual. (The same section also describes p_setauto which can be +used to stop the machine from automatically switching off.) You don't get a +W_KEY_OFF event when the machine automatically switches off. + + +WM_REDRAW Redraw event (WM + + +Sent when the client's event queue is empty and one or more windows has an update region. + + +The parameter event .p.rect describes a rectangular block of pixels from the update region (and which +needs to be redrawn). + + +The only event type that has a lower priority than wM_REDRAW is WM_USER_MSG. + + +WM_BACKGROUND Background event + + +Sent to a foreground client when it goes background. +Only event.type is set. + + +On all machines except the MC, you generally do not need to do anything when you receive a +WM_BACKGROUND event. However, if you are doing anything that requires real-time input from the user (a +game, for example) or you are doing an animated display, you should suspend the operation until you +receive a WM_FOREGROUND event. + + +WM_FOREGROUND Foreground event + + +Sent to a background client when it becomes foreground. + + +Only event.type is set. + + +WM_CANCELLED Cancellation event + + +Sent in response to a call to wcancelGetEvent command - see the description of wcancelGetEvent in this +chapter. + + +Only event.type is set. + + +3See also the description of the wsERV_FLAG_LOW_BATTERY_WARNINGS flag in wsystem. + + +5-6 + + +5 EVENTS + + +WM_USER_MSG User message event + + +Sent in response to a call to wusermsg. This event has the lowest priority of all and can be used to indicate +that the window server has no more messages to send - see the description of wuserMsg in this chapter. + + +Only event .type is set. + + +WM_ON Machine switched on event + + +Available in version 3.5 of the window server; if the client has called wrnformon, it is sent this event when +the machine is switched on and it is in foreground. + + +The event is designed to prompt the foreground client to update its display. + + +On the HC, the window server is only informed of the machine being switched on after +p_setonevent (TRUE) has been called. + + +In version 4 of the window server, if the client has called winformonAll (TRUE), it is sent this event when +the machine is switched on, whether it is in foreground or background. + + +Only event .type is set. + + +WM_COMMAND Command received from another client + + +This is sent in response to a wSendCommana from another client to prompt the receiver of the event to call +wGetCommand to get the command data. It is only available in version 3.5 of the window server. + + +Only event .type is set. + + +WM_TASK_UPDATE Inform shell of process termination + + +Sent to the shell if it is foreground and any process terminates (not just clients of the window server). + + +Available only on the $3, $3a and Workabout, and on an HC running version 3.5 upwards of the window +server. Disabled by default on the HC - see the description of wsystem. + + +Only event .type is set. + + +WM_TASK_KEY Inform application key handler + + +Sent to the application key handler when: +e an application key is pressed and no process of that application exists +e a PSION shifted application key is pressed + +Applies only to the S3, S3a and Workabout. + + +The index of the application key in the range 0 to 15 is written to event.p.key. keycode. The window +server handles 16 application keys, where a second set of 8 keys are accessed by holding down the +CONTROL key. + + +WM_DATE_CHANGED Change of date event + + +Introduced in version 4 of the window server. Sent whenever the date changes, either because the date has +en reset or the clock has gone past midnight. + + +The message is sent to any Series 3a or Workabout application which is not in Series 3 compatibility +mode and is in foreground at the time of the event + + +Non compatibility mode applications which are in background will receive the message the next time they +come into foreground. + + +If the machine is off at the time of the event, the message is delivered when the machine is next turned on. + + +WINDOW SERVER REFERENCE + + +WM_ESCAPE Escape-key event + + +In version 4 of the window server, this message is delivered to an application when the ESC key is pressed +in the following circumstances: + + +e =The application must have asynchronously requested selected events by calling +wGetEventSpecial. + + +e Among the events selected for delivery, WZ_EVENT_ESC must be included but wE_EVENT_KEY must +be excluded. + + +In this situation, the content of the keyboard buffer is discarded. + + +Large screen events + + +The event types in this section are only generated on large screen versions of the window server, such as +on the MC200 and MC400 machines. + + +WM_DEICONISE Deiconisation event + + +Sent to a client to tell it to deiconise. The client will have previously declared itself iconised with a +wClientIconised call. + + +Only event .type Is set. +A client receives this message when another client calls wclientPosition to position it to the foreground. + + +It is also sent to the system application (sys$shll.img) when it is iconised and selected by the PSION-TASK +key press. + + +WM_ATTACHED Attachment event + + +Sent to a client to tell it another client has attached itself on top of it. The uword field of the +WS_EVENT_UNION structure is set to the process ID of attached client. After receiving this message the +client will not be able to receive wM_KEyY events until the attached client detaches, terminates or +disconnects from the window server. + + +Only event.type is set. + + +A client will receive a WM_ATTACHED event when the notifier process (sys$nt fy) attaches itself to the +foreground client when any process calls p_notify or p_notifyerr. + + +WM_DETACHED Detachment event + + +Sent to a client when a previously attached client detaches (either by a wDetachClient call, by terminating +or by disconnecting from the window server). + + +Only event .type is set. + + +WM_KEYBOARD_STATE_CHANGE Keyboard state change event + + +This event is only ever sent to the system application (sys$shll.img). It is sent when either the numlock or +capslock state changes. The new states of these can be read from event .p.caps.modifiers. + + +5 EVENTS + + +a EEEEEEEEEOEOEOEeEeEeEeEeseseseeess +Mouse events + + +The event types in this section are only generated on machines with a pointing device, such as on the +MC200 and MC400. + + +WM_MOUSE Mouse event + + +Sent when ever there is a change of state on the mouse (digitiser). +The wmsc_mouse structure is defined as: + + +typedef struct +{ +UBYTE event; /* type of mouse event */ +UBYTE state; /* state of mouse button, shift keys etc */ +P_POINT pos; /* mouse position (relative to window) */ +} WMSG_MOUSE; + + +event .p.mouse.event gives the type of the mouse event that occurred and is one of: + + +WM_MOUSE_MOVE mouse movement event (this is filtered out by default) +WM_MOUSE_PRESS mouse press event +WM_MOUSE_RELEASE mouse release event + + +Mouse movement events (wmM_MousE_move) are filtered out unless explicitly enabled, on a per-window +basis. See wcreateWindow and wSetWindow for details. + + +event .p.mouse.state gives the state of the mouse and the key modifiers when the event occurred, it may +be tested using the bit masks: + + +W_MOUSE_DOWN mouse button down + +W_MOUSE_OUTSIDE mouse event occurred outside window +W_SHIFT_MODIFIER SHIFT key down + +W_CTRL_MODIFIER CTRL key down + +W_PSION_MODIFIER PSION key down + +W_CAPS_MODIFIER Caps lock on + + +W_NUM_LOCK_MODIFIER Num lock on + + +The w_mMousE_ouUTSIDE bit is set when a mouse event occurs outside the visible portion of the given +window. This can happen when either: + + +a window has grabbed the mouse, by specifying the w_wIN_mMousE_GRAB bit, WM_MOUSE_RELEASE +events are sent to the same window that received the wm_MousE_PRESS event, even if the mouse +has subsequently moved outside the visible portion of the window. + + +or: +a window has captured the mouse by calling wcaptureMouse. + + +Testing the w_mousk_ouTSIDE bit is not equivalent to checking the mouse position against the extent of the +window, because a client can never know if part of the window has been obscured. + + +WM_RUBBER_BAND INIT Start rubber band + + +This is a special version of the wu_mousE message, it also uses the wmsc_mouseE Structure. It is sent instead +of a wM_MousE event when a mouse press occurs inside a window with the w_wIN_RUBBER_BAND_CAPTURE +flag set. + + +See the Rubber Band section for details. + + +WINDOW SERVER REFERENCE + + +WM_RUBBER Complete rubber band + + +Sent on completion of a rubber band. + + +See the Rubber Band section for details. + + +WM_ ACTIVE Activation event + + +Sent to a window that has previously set the w_wIN_INacTIVE bit (in a call to wcreat eWindow or +wSetWindow) whenever a WM_MOUSE event of type WM_MOUSE_PRESS is sent to the window or any of its +descendants. + + +Only event .type is set. + + +WM_ACTIVE notifies a parent that the mouse has clicked somewhere in its window tree. The wm_mousE event +is then sent straight to the window where the click occurred (unless that window has the w_wIN_No_MoUSE +bit set). + + +If a window and its descendant both have the w_w1n_1NacTIVE bit set, they both receive a WM_ACTIVE event +if there is a click in a descendant of the descendant window. + + +SSS SSS SS — SS ——————————e +Event functions + + +wCancelGetEvent Request a cancel event +VOID wCancelGetEvent (VOID) ; +Instruct the window server to send the caller a WM_CANCELLED event. + + +After a call to wcancelGetEvent, the window server delivers the w4_CANCELLED event at the highest +priority - any other events waiting in the window server client event queue are overtaken. + + +wUserMsg Request a user event +VOID wUserMsg (VOID) ; +Instruct the window server to send the client a w“_USER_MsG as soon as it has no other event to report. + + +A second call to this function before the first w1_usER_msc is delivered will have no effect. + + +wSendCommand Send a command to another client +INT wSendCommand(HANDLE pid, VOID *pbuf, UINT len); +Send the 1en bytes of data at pbuf to the window server client with process ID pia. + + +If the call is successful, the function returns zero and client pid will receive a wM_COMMAND event to which +it should respond by calling wGet command (as described below). + + +If no client with process ID pid exists, the function leaves or returns with the error number E_FILE_NXIST. + + +The function can be used to send up to 127 bytes. If 1en is | or 2, the function does not allocate any +memory. If 1en is greater than 2, the function could leave or return with the error number +E_GEN_NOMEMORY. + + +Only available in version 3.5 and upwards of the window server. + + +5-10 + + +5 EVENTS + + +wGetCommand Get a command from another client + + +INT wGetCommand (VOID *pbuf) ; + +Write to pbuf, the command data that was last sent to this process (with a call to wsendcommand). +This function should be called in response to the receipt of a wa_commanp event. + +There should be at least 127 bytes of memory at pbuf. + + +If another command is sent to the client before it has read the old command, the old command is +overwritten with the new data. + + +The function behaves as for wcheckPoint in that it flushes the client-side buffer and reports any uncleared +error - either by calling p_ieave or by returning the error number. + + +Only available in version 3.5 and upwards of the window server. + + +winformOn Enable the reception of WM_ON events +VOID wInformOn (VOID) ; + +Enable the reception of a wu_on event when the machine is switched on. + +The window server only sends a wy_on event to the foreground client. + + +On the HC, the window server is only informed of the machine being switched on after +p_setonevent (TRUE) has been called (normally by the shell). + + +Only available in version 3.5 and upwards of the window server. + + +winformOnAll Enable/disable the reception of WM_ON events + + +VOID wInformOnAll(UINT state); + + +Available in version 4 of the window server, this function is similar to wInformon. However, there are +some subtle differences. + + +If state is TRUE, it enables the reception of wu_on events; on the other hand, if state 1s FALSE, it disables +the reception of wm_on events. + + +When enabled by this call, wu_on events are delivered whenever the machine is switched on, regardless of +whether the calling client is in foreground or in background. + + +Disabling wu_on events with this call disables the reception of wu_on events regardless of whether they +were originally enabled by a call to wInformonall Or wInformon. + + +Capturing keys + + +wCaptureKey Capture a key +INT wCaptureKey(UINT keycode, UINT modifiers, UINT modifier_mask) ; +Send the specified key press(es) to the calling client, whether it is foreground or not. +Every time a key is pressed the window server evaluates +(key_pressed_code==keycode) && ((key_pressed_modifiersé&émodifier_mask) ==modifiers) +and if the result is TrRuz then the keyboard event is sent to the client that specified the capture. +For example: +wCaptureKey (W_SPECIAL_KEY|'a',W_PSION_MODIFIER, W_PSION_MODIFIER) ; +captures PSION+A, PSION+SHIFT+A, PSION+SHIFT+CTRL+A, and PSION+CTRL+A. Whereas: +wCaptureKey (W_SPECIAL_KEY| 'a',W_PSION_MODIFIER, W_PSION_MODIFIER|W_SHIFT_MODIFIER) ; + + +captures PSION+A and PSION+CTRL+A. + + +5-11 + + +WINDOW SERVER REFERENCE + + +Note from the above that it is possible for two different but similar key/modifier combinations to capture +the same key presses. This is significant if the two calls to wcapturekey came from different clients. +Where two key capture records select the same key press, the key event is delivered to the first client to +call wCaptureKey. + + +The function is useful for implementing "hotkeys" which select a particular task. However, you should +only capture relatively obscure key combinations which are not normally used by the tasks themselves +(capturing the unmodified A key, for example, would be disastrous). + + +The function returns zero if successful. Errors include E_GEN_NomeEmory and, if there is already a capture +record with a matching keycode, modifiers and modifier_mask (even as a result of a wcaptureKey from +another client), E_FILE_Ex1stT. The function either leaves or returns the error, depending on whether +wDisableLeaves has been called. + + +The window server automatically cancels any calls a client has made to wcaptureKey when that client +disconnects or terminates. + + +On an HC, an application can disable the window server's processing of the TASK key by capturing it with: +wCaptureKey (W_KEY_TASK,0,0); + + +Not available in version 2 of the window server. + + +wCancelCaptureKey Cancel key capture +INT wCancelCaptureKey(UINT keycode, UINT modifiers, UINT modifier_mask) ; + + +Cancel a key capture set up by wcapturekey, the keycode and masks must exactly match those used to +initiate the capture. + + +The function returns zero if successful. If the keycode/modifier combination is not marked as captured +then the function will leave or return E_FILE_NxIST. + + +Not available in version 2 of the window server. + + +Setting task switch keys + + +wSetTaskKey Set a task switch key +INT wSetTaskKey(UINT keycode, UINT modifiers, UINT modifier_mask) ; + + +Set the specified keypress(es) to move the foreground client to the end of the task list and bring the client +previously at position | (where the foreground process has position zero) to the foreground. + + +As for captured keys, every time a key is pressed the window server evaluates +(key_pressed_code==keycode) && ((key_pressed_modifiersémodifier_mask) ==modifiers) +and if the result is TRUE, the tasks are cycled. + + +The effect of setting the task key does not cease when the calling client disconnects or terminates. The +only way to stop the key press from being a task key is to call wcancelTaskKey. + + +Any number of task switch keys may be set. On the HC and MC, these operate in addition to the +W_KEY_TASK key (unless the w_KEy_TAs«K key has been captured). + + +The function returns zero if successful. If there is already a set task key record with a matching keycode, +modifiers and modifier_mask, the function leaves or returns E_FILE_EXIST. It can also fail with +E_GEN_NoMEmoRY. If there is already a capture record with a matching keycode, modifiers and +modifier_mask, the capture key record is cancelled and replaced by the task key record. + + +The shell on the S3 and S3a calls wSet TaskKey to assign SHIFT+SYSTEM as a task key. + + +Only available in version 3.5 upwards of the window server. + + +5-12 + + +5 EVENTS + + +wCancelTaskKey Cancel a task switch key +INT wCancelTaskKey(UINT keycode, UINT modifiers, UINT modifier_mask) ; +Cancel a task key setting, set up with wset TaskKey. + + +The function returns zero if successful. If the keycode/modifier combination is not marked as a task key +then the function will leave or return £_FILE_NXIST. + + +wSetBackTaskKey Set a back task switch key +INT wSetBackTaskKey(UINT keycode, UINT modifiers, UINT modifier_mask) ; + +Set the specified keypress(es) to bring the client furthest from the front to the foreground. + +Except that it cycles tasks in the opposite direction, wSetBackTaskKey is identical to wset TaskKey. + + +The shell on the S3 and S3a calls wsetBackTaskKey to assign SHIFT+PSION+SYSTEM to the "back-task" key +which brings the task furthest from the front to the foreground. + + +wCancelBackTaskKey Cancel a back task switch key +INT wCancelBackTaskKey (UINT keycode, UINT modifiers, UINT modifier_mask) ; +Cancel a back task key setting, set up with wSetBackTaskKey. + + +The function returns zero if successful. If the keycode/modifier combination is not marked as a back task +key then the function will leave or return E_FILE_NXIST. + + +Capturing the mouse + + +wCaptureMouse Capture the mouse + + +VOID wCaptureMouse(UINT wid); + + +Capture the mouse within window wid and all its descendants. This function does not capture with +respect to other clients' windows. + + +It is used, for example, by the dialog box that allows the user to click on it or any of its constituent +windows, but ignores clicks to other windows in the application (ie the menu bar and the application's +client window). + + +If mouse capture is already active in another window then the previous capture will be cancelled before +the new capture is activated. + + +If a window with capture is destroyed the mouse is automatically released. + + +wReleaseMouse Release the mouse + + +VOID wReleaseMouse (VOID) ; + + +Cancel the mouse capture, does nothing if there was no capture active. + + +WINDOW SERVER REFERENCE + + +The rubber band + + +The rubber band is only implemented on machines with a pointing device, such as on the MC200 and +MC400. + + +wRubberBand Rubber banding + + +VOID wRubberBand(UINT msg_window, UINT band_window, W_RUBBER_BAND *prubber) ; + + +Start the rubber band and return immediately where the result is returned later as a WA_RUBBER event +(which might just indicate that the parameters are illegal). + + +msg_window is the ID of the window to which the wM_RUBBER event will be sent. + + +band_window is the ID of the window in which the rubber band will be drawn, it is usually set to zero (the +whole screen). + + +The rubber band is displayed as specified by the w_RUBBER_BAND struct at address prubber where +W_RUBBER_BAND is defined as: + + +typedef struct +{ + + +P_EXTENT start; /* initial size and position */ +P_EXTENT outer; /* outer bounding rectangle */ +P_EXTENT inner; /* inner bounding rectangle */ +UWORD flags; + +UWORD minx; /* max and min size limits */ + + +UWORD miny; + +UWORD maxx; + +UWORD maxy; + +P_POINT grid_snap; /* x and y grid snap values */ +} W_RUBBER_BAND; + + +If flags is set to zero then the following default values will be used: + + +resizing Disabled. + +minx Not applicable when resizing disabled. +miny + +maxx + +maxy + +start The extent of msg_window. + +outer No outer bounds. + +inner The visible extent of band_window. +grid_snap (1,1) in the x and y directions. +complete on release Disabled. + + +Each of these defaults may be overridden by setting the following bits in flags: + + +W_BAND_RESIZE enables resizing of the rubber band, if this is selected the rubber band will +appear on screen with its resize triangles, if resizing is disabled the rubber +band appears as a rectangle. When resizing is enabled then minx, miny, maxx +and maxy (which determine the maximum and minimum sizes of the rubber +band) must be set. + + +W_BAND_START sets the start position and size to start. If this conflicts with inner, outer or +the maximum or minimum size limits then it will be modified appropriately. + + +W_BAND_INNER sets the inner rectangle to inner. The movement of the rubber band is +restricted such that part of the rubber band stays within this rectangle. + + +W_BAND_OUTER sets the outer rectangle to outer. The movement of the rubber band is +restricted such that no part of the rubber band extends outside this rectangle. + + +5-14 + + +5 EVENTS + + +W_BAND_GRID_SNAP sets the grid snap values to grid_snap. The rubber band will move/resize in +steps of grid_snap. + + +W_BAND_GRID_SNAP_SIZE aS for W_BAND_GRID_SNap except that only the size of the rubber band (and not +its position) is grid snapped. + + +W_BAND_COMPLETE_ON_UP causes the rubber band to complete on the first mouse up event. +The values in start, outer and inner are all relative to band_window. + + +If there is no legal position for the rubber band then the rubber band completes immediately with a +WM_RUBBER message with the state set to ww_BAND_ERROR. This could happen (say) if minx is greater than +maxx Or if inner does not intersect with outer. + + +WM_RUBBER events + + +The window server sends a wM_RUBBER message when the rubber banding completes. The format of the +WM_RUBBER message is: + + +typedef struct +{ +UWORD state; /* completion state */ +P_EXTENT extent; /* the selected extent */ +} WMSG_RUBBER; + + +Sstate is set to one of the following: + + +WM_BAND_NOMOVE the band position was selected without any moving or resizing, extent is the +same as set in wRubberBand. + + +WM_BAND_MOVE the rubber band moved but did not change size. extent is set to the new +position and the old height and width. + + +WM_BAND_RESIZE the rubber band has been resized (and perhaps also moved). extent contains +the new position and size. + + +WM_BAND_CANCEL the rubber band was cancelled. extent is undefined. +WM_BAND_ERROR the rubber band was not displayed because of illegal parameters in +wRubberBand. + + +Capturing mouse and keyboard events + + +The flag w_wIN_RUBBER_BAND_CAPTURE USed in the wSetWindow and wcreateWindow commands can be +used to capture all mouse and keyboard events to the rubber band from the moment the mouse was pressed +in the specified window. The first click in the window will be sent to the window as a +WM_RUBBER_BAND_INIT event and held in a buffer as a wu_mouse event (of type wM_MOoUSE_PRESS). +Subsequent mouse and keyboard events will also be buffered. When the rubber band becomes active it will +receive all the buffered events. The capture is cancelled on completion of the rubber band. + + +When a client receives a WM_RUBBER_BAND_INIT event it MUST call wRubberBand immediately. This is +because all clients will have all their mouse events and keys blocked. If the client decides that it does not +want to launch a rubber band then it should set the w_sanp_KILL_capTurE flag in flags and call +wRubberBand, this will cancel the mouse capture without actually launching a rubber band (all parameters +in the w_RUBBER_BAND Structure are ignored except that msg_window must be a valid window ID). + + +5-15 + + +CHAPTER 6 + + +WINDOW SERVER REFERENCE UPDATE + + +This document is a beta version and may be subject to change. + + +This chapter describes the changes and additions that have been made to the Window server as a result of +the introduction of the Siena and Series 3c machines into the SIBO range. + + +Note: Siena was codenamed Vine by Psion during development, hence the naming of some of the +constants given below. + + +Screen sizes + + +The true screen and pixel dimensions of the various LCD screens on all SIBO machines are as follows: + + +Machine type Screen Pixel pitch Pixel size Screen size Screen size +(pixels) (mm) (mm) (cm) (in) +HC 160x80 0.34x0.43 0.31x0.40 5.44x3.44 2.14x1.35 +S3 240x80 0.385x0.43 0.355x0.40 9.24x3.44 3.64x1.35 +Workabout 240x100 0.26x0.30 0.23x0.27 6.24x3.00 2.45x1.18 +Siena 240x160 0.25x0.25 0.23x0.23 6.00x4.00 2.36x1.57 +S3a 480x160 0.259x0.259 0.20x0.20 12.477x4.156 4.915x1.637 +S3c 480x160 0.26x0.26 0.20x0.20 12.478x4.158 4.915x1.637 +MC200 640x200 0.33x0.33 0.30x0.30 21.12x6.60 8.31x2.60 +MC400 640x400 0.33x0.33 0.30x0.30 21.12x13.20 8.31x5.20 + + +In the above table, the horizontal measure is shown before the vertical measure. The pixel pitch measures +the horizontal and vertical distance between the same points on adjacent pixels. The difference between +the pixel size and the pixel pitch gives the gap between pixels. + + +The Series 3c and the Siena screens support the use of grey in exactly the same way as for the Series 3a. + + +Keyboard + + +Except where stated below, the keycodes produced on the Series 3c and the Siena are identical to those +produced on the Series 3a. + + +The following table lists the additional and/or modified key codes produced by the special keys on the +Siena and the Series 3c, as listed in wskeys.h: + + +W_KEY_TAB (0x9 or Produced by TAB, with or without SHIFT or CTRL. On the HC and MC only, the +"\t') PSION key adds w_spEcIaL_kEy. On the Workabout, the PSION key (but not +SHIFT+PSION) converts the keypress to Ww_KEY_TASK. + + +On the Series 3c, the PSION key (including SHIFT+PSION) converts the keypress +tO W_KEY_IR_LINK (0x142). + + +6-1 + + +WINDOW SERVER REFERENCE + + +W_FUNC_MODIFIER +(0x80) + + +W_KEY_APP1 to +W_KEY_APP9 (0x131 to +0x139) + + +W_KEY_IR_BRING +(0x140) + + +W_KEY_IR_SEND +(0x141) + + +W_KEY_IR_LINK +(0x142) + + +W_KEY_CALC_CLEAR +(0x01b) + + +W_KEY_CALC_MEM_CLEAR +(0x150) + + +W_KEY_CALC_MEM_RECAL +L (0x151) + + +W_KEY_CALC_MEM_ MINUS +(0x152) + + +W_KEY_CALC_MEM_ PLUS +(0x153) + + +W_KEY_CALC_CHNG_SIGN +(0x154) + + +W_KEY_CALC_PERCENT +(0x155) + + +W_KEY_CALC_DECIMAL +(0x156) + + +W_KEY_CALC_MEM_INPUT +(0x158) + + +W_RUSSIAN_MODIFIER +(0x1000) + + +6-2 + + +On the Siena only, an FN modifier key is provided that produces this additional +modifier code. + + +Note that the same value is used for Mouse Down (w_mousE pown) on the Psion +MC range of machines. + + +On the Series 3 and Series 3a, key codes w_kEY_APP1 tO W_KEY_APP8 are +produced by the eight membrane keys (also called application keys) in order, +from left to right. + + +The Series 3c has a ninth membrane key, on the extreme right, that produces +W_KEY_APP9. + + +On the Siena only, this key code is produced by the IR receive key. + + +On the Siena only, this key code is produced by the IR send key. + + +On the S3c only, this key code is produced by the PSION + TAB key combination. + + +On the Siena only, this key code is produced by the ON/CE key. + + +On the Siena only, this key code is produced by FN + the ‘3’ key on the numeric +keypad. + + +On the Siena only, this key code is produced by FN + the ‘2’ key on the numeric +keypad. + + +On the Siena only, this key code is produced by FN + the ‘-’ key on the numeric +keypad. + + +On the Siena only, this key code is produced by FN + the ‘+’ key on the numeric +keypad. + + +On the Siena only, this key code is produced by FN + the ‘.’ key on the numeric +keypad. + + +On the Siena only, this key code is produced by FN + the ‘=’ key on the numeric +keypad. + + +On the Siena only, this key code is produced by the ‘.’ key on the numeric +keypad. + + +On the Siena only, this key code is produced by FN + the ‘1’ key on the numeric +keypad. + + +On the Russian variant Series 3a and Series 3c only, (for Psion internal use +only). + + +6 WINDOW SERVER REFERENCE UPDATE + + +Status windows +Series 3c + + +Status windows on the Series 3c are functionally identical to those on the Series 3a. Some minor cosmetic +changes have been made, including a new analog clock design for the wide status window. + + +Siena + + +Only a narrow status window is available on the Siena. A smaller font is used and the diamond list has +been reorganised, compared with that of the Series 3a, to maximise the space for displaying text. Despite + + +these changes, only four characters of the application name and up to five characters of each diamond list +item can be displayed. + + +Diamond list text items that contain more than five characters are automatically truncated. Since such +truncation may occur at an unsuitable point in the text, you should consider supplying truncated versions + + +of the diamond text for use in the status window, such as the four-character abbreviations for ‘Normal’ +and ‘Outline’ shown in the above illustration. + + +The following constants are defined in wlib.h: + + +WS_WIDTH_V4c 51 Normal status window width on Series 3c, in pixels; +this is not a new constant - it also exists on the Series 3a + + +WS_WIDTH_SMALL_V4c 32 Narrow status window width on Series 3c, in pixels; +this is not a new constant - it also exists on the Series 3a + + +WS_WIDTH_VINE 36 Narrow status window width on Siena, in pixels + + +6-3 + + +WINDOW SERVER REFERENCE + + +Clocks + + +The clock creation functions, for example, wscreateClock2, on the Siena and Series 3c support additional +clock styles. The new styles and their appearances and dimensions are given below. The associated +symbolic constants are defined in wlib.h. + + +Siena + + +The Siena supports one additional clock, of type ws_cLocK_VINE: + + +WS_CLOCK_VINE 0x06 + +WS_BITMAP_VINE_CLOCK_SIZE_X 70 Width of Siena analogue clock, in pixels +WS_BITMAP_VINE_CLOCK_SIZE_Y 69 Height of Siena analogue clock, in pixels +Series 3c + + +The Series 3c supports two additional clock types, ws_cLock_MEDIUM3 and ws_CLOCK_XL2_ANALOG: + + +WS_CLOCK_MEDIUM3 0x06 + +WS_BITMAP_MEDIUM3_CLOCK_SIZE_X 58 Width of Series 3c medium analogue clock, in pixels + +WS_BITMAP_MEDIUM3_CLOCK_SIZE_Y 51 Height of Series 3c medium analogue clock, in pixels + +WS_CLOCK_XL2_ANALOG 0x07 + +WS_BITMAP_XL2_CLOCK_SIZE_X 111 Width of Series 3c extra large analogue clock, in +pixels + +WS_BITMAP_XL2_CLOCK_SIZE_Y 110 Height of Series 3c extra large analogue clock, in +pixels + + +Window Server versions + + +The following values are contained in the version_id member of the w_sERVER_INFo Struct. The constants +and the struct are defined in wilib.h: + + +WS_TYPE_S3C 0x60 Series 3c window server + + +WS_TYPE_VINE 0x70 Siena window server + + +6-4 + + +INDEX + + +$WS_FL + + +environment variable, 1-2, 1-55, 1-56, 2-25 + + +$WS_FNTS + +environment variable, 1-2, 1-38, 2-10 +$WS_IF + +environment variable, 2-10, 3-16 +$WS_SD + +environment variable, 1-32 +$WS_SF + +environment variable, 1-38 +$WS_SF2 + +environment variable, 1-39 +$WS_SF4 + +environment variable, 1-39 +.pcex files + +from screen capture, 1-33 + +to bitmap PIC files, 1-31 +.ph files + +multi bitmap header file, 1-31 +.pic files + +checksum, 1-37 + +from a PCX file, 1-31 +.plk files + +multi bitmap files, 1-31 +activation + +event, 5-10 +add files + +embedded bitmap files, 1-37 +alert flag + +WS_ALERT_B, 1-3 +alerts + +asynchronous, 2-18 + +message display, 2-12 + +synchronous, 2-14 + +updating, 2-19 + +wsAlertW, 1-3 +animation + +bitmap sequences, 1-21, 3-14 + +sprites, 1-3, 1-23, 3-15 +application keys + +handler, 1-15 + + +W_KEY_APPn, 5-5 +wAppKeyHandler, 1-15 + + +area fill pattern + +gFillPattern, 4-13 +area filling + +modes, 4-12, 4-13 + +WLIB functions, 4-12 +arrow keys + +rubber band mode, 1-54 +arrows + +drawing, 4-10 +ascent + +fonts, 4-14 +asynchronous + +events, 5-2 +attached clients + +WLIB functions, 2-25 +attachment + +event, 5-8 +backed up windows + +bitmaps, 1-19 +background + +client, 1-14 + +client switch task order, 2-8 + +event, 5-6 +background modes + +window, 1-3 +backlight + +key code, 5-5 +baseline + +fonts, 4-14 +bitmaps + +capture screen to, 1-32 + + +converting from pcx with wspcx.exe, 1-31 + + +copying, 4-29, 4-30 + +creation of, 1-30, 4-26 + +drawables, 1-18 + +drawing from, 1-30, 4-31 + +drawing to, 1-31 + +embedded files, 1-37 + +files creating, 1-31 + +files creating with grey, 1-31 + +find in file gSetOpenAddress, 1-30 +freeing, 4-28, 4-32 + +freeing sequences, 3-15 + +from PCX files, 1-31 +G_TRMODE_CLR, 1-30 +G_TRMODE_INV, 1-30 +G_TRMODE_REPL, 1-30 +G_TRMODE_SET, 1-30 + +gCopyBit, 1-30 + +gDrawBit, 1-30 + +gFillPattern, 1-30 + +grey, 1-22 + +gSetOpenAddress, 1-30 + +header file for multi bitmap files, 1-31 +horizontal slice, 4-30 + +joining multiple from PLK file, 1-31 +loading, 4-27, 4-31 + +multiple, 4-30 + +open multiple bitmap file gInitBit, 1-30 +opening, 4-31 +overview, 1-30 + +pixel coordinates, 1-47 +reading, 4-30 + +redraws avoiding, 1-22 + + +WINDOW SERVER REFERENCE + + +redraws avoiding example code, 1-22 + +ROM-based grey, 1-30 + +saving, 4-28 + +screen capture, 1-31 + +sequences, 1-21, 3-14 + +storage of, 1-30 + +structure, 1-36 + +validating, 4-30 + +wFree, 1-30 + +WLIB functions, 1-2, 4-26 + +wsetWinBitmap, 1-30 +bitmaps copying + +gCopyBit, 4-29 + +gCopyRect, 4-30 +bitmaps create + +gCreateBit, 4-26 +bitmaps drawing from + +gDrawBit, 4-31 +bitmaps freeing + +wFree, 4-32 +bitmaps function + +wChangeWinBitmap, 3-15 + +wFree, 3-15 + +wsetWinBitmap, 3-14 +bitmaps loading + +gGetBit, 4-31 + +gOpenBit, 4-27 +bitmaps multi save end + +gEndMultiSave, 4-32 +bitmaps multiple initialise + +gInitMultiSave, 4-32 +bitmaps multiple saving + +gSaveMultiBit, 4-32 +bitmaps open + +embedded, 4-28 + +structure, 4-26, 4-27 +bitmaps opening + +gInitBit, 4-31 +bitmaps partial save + +gSaveMultiRect, 4-32 +bitmaps position + +gSetOpenAddress, 4-15 +bitmaps reading + +gPeekBit, 4-30 +bitmaps saving + +gSaveBit, 4-28 + +gSaveRect, 4-28 + +multiple, 4-32 +bitmaps sequences + +wChangeWinBitmap, 1-21 + +wFree, 1-21 + +wsetWinBitmap, 1-21 +bitmaps size get + +gQueryBit, 4-31 +bitmaps validating + +gCheckBitmapID, 4-30 +black + +plane, 1-3, 1-19, 3-8, 4-1, 4-13 +blind operations + +window server, 1-11 +body cell + +fonts, 4-14 +border + +WLIB function, 4-8 + + +ii + + +WLIB functions, 4-10 +border attribute +W_BORD_CORNER_1, 4-11 +W_BORD_CORNER_2, 4-11 +W_BORD_CORNER_4, 4-11 +W_BORD_CUSHION, 4-11 +W_BORD_OPEN, 4-11 +W_BORD_SHADOW_D, 4-11 +W_BORD_SHADOW_ON, 4-11 +W_BORD_SHADOW_S, 4-11 +border drawing +gBorder, 4-10 +gBorder2, 4-12 +gBorder2Rect, 4-10 +gBorderRect, 4-8 +types, 4-10 +box +WLIB function, 4-8 +buffered commands +window server, 1-11, 1-13, 2-5 +busy +message cancel, 2-12 +message display, 2-11 +busy message +window server option, 1-6 +button drawing +example code, 4-24 +button text +wDrawButton, 4-24 +wDrawButton2, 4-25 +cancelled +event, 5-6, 5-10 +capturing +keyboard events, 5-15 +keys, 1-51, 5-11 +mouse, 1-53, 5-13 +mouse events, 5-15 +screen to a bitmap file, 1-32 +checksum +font files, 1-46 +pic files, 1-37 +WLIB function, 4-32 +checksum get +gInquireChecksum, 4-32 +child +window, 1-18 +clear area +gClrRect, 4-12 +CLIB +library, 1-8 +startup module, 1-8, 2-1 +startup module MC, 1-10 +client +attach caller, 2-26 +attach caller to foreground, 2-26 +attached, 2-25, 5-8 +background, 1-14 +command event, 5-7 +command get, 5-10 +command send, 5-10 +de-iconised event, 5-8 +detach caller, 2-26 +detached, 2-26, 5-8 +foreground, 1-14 + + +INDEX + + +going deaf, 1-26 +iconised, 1-16 +iconised mark as, 2-9 +information get, 2-8 +list get, 2-10 +management, 1-17 +pause disable, 2-10 +pausing, 1-52 +pausing enable, 2-9 +priority, 1-16, 2-7 +system-modal, 1-17, 2-9 +task order, 2-8 +wCancelSystemModal, 2-9 +client commands +between window server clients, 1-6 +client window +background drawing, 1-18 +clients +window server, 1-13 +clients terminating +window server, 1-6 +client-side buffer +flushing, 1-13 +clipping +redrawing, 3-9 +windows, 1-25 +windows child, 1-18 +clock +creating, 3-17, 3-19 +example code, 3-18, 3-20, 3-21 +freeing, 3-22 +offset, 3-22 +Series 3c and Siena update, 6-4 +Series 3c update, 6-4 +Siena update, 6-4 +structure, 3-19 +WLIB functions, 3-16 +clock attribute +WS_CLOCK_AM_PM, 3-17, 3-20 +WS_CLOCK_BOX, 3-20 +WS_CLOCK_CENTERED, 3-17, 3-20 +WS_CLOCK_FORCE_ANALOG, 3-17, +3-20 +WS_CLOCK_FORCE_DIGITAL, 3-17, +3-20 +WS_CLOCK_FORMATTED, 3-19 +WS_CLOCK_GREY, 3-20 +WS_CLOCK_LARGE_ANALOG, 3-17, +3-19 +WS_CLOCK_MEDIUM, 3-17, 3-19 +WS_CLOCK_MEDIUM2, 3-19 +WS_CLOCK_SMALL_DIGITAL, 3-17, +3-19 +WS_CLOCK_WITH_DATE, 3-17, 3-20 +WS_CLOCK_WITH_SECONDS, 3-17, +3-20 +WS_CLOCK_XL_ANALOG, 3-19 +clock drawing +automatic, 1-6 +clock function +wFree, 3-22 +wsCreateClock, 3-17 +wsCreateClock2, 3-19 +wsSetClock, 3-22 + + +code +key, 1-51 +keys, 5-3 + + +command data get + +wGetCommand, 5-10 +compatibility mode + +S3 display mode, 2-6 + +Series 3, 1-12 + +status windows, 2-21 + +W_CTBY_S3, 2-6 + +W_CTBY_S3_SCR, 2-6 + +wInquireCompatibility, 2-7 +compute mode + +ending wEndCompute, 2-8 + +priority setting wStartCompute, 2-8 +configure + +font group, 4-18 + +window server, 2-24 +connect to + +window server, 2-1, 2-3 +CONNECT_INFO + +structure, 2-3 +console device + +channel to, 1-8 +coordinates + +pixel, 1-47 +copying bitmaps + +WLIB function, 4-29, 4-30 +corner type + +border attribute, 4-8 + +border attributes, 4-11 +count + +key repeat, 1-51 + +keys repeat, 5-3 +cursor + +flashing, 1-29 + +grey, 1-29 + +text, 3-12 + +text window, 1-29 + +wTextCursor, 1-29 +cursor attribute + +W_CURSOR_GREY, 3-12 +cursor function + +wDrawTextCursor, 3-13 + +wEraseTextCursor, 3-13 + +wTextCursor, 3-12 +cursor remove + +wEraseTextCursor, 1-29 +date changed + +event, 5-7 +DatStatusNamePtr + +magic static, 2-13 +deaf clients + +multi-tasking, 1-26 + +window server flag, 1-56 +de-iconise + +event, 5-8 +descent + +fonts, 4-14 +destroying + +windows, 1-27 +detachment + +event, 5-8 + + +iii + + +WINDOW SERVER REFERENCE + + +diamond key + +key code, 5-5 + +key press, 1-15 + +mode display, 2-20 +disable + +status window, 2-22 + +status window temporary, 2-22 +disconnect from + +window server, 2-5 +display + +brief message, 2-11 +display process + +SYS$CONS on MC, 1-7 +double pixel mode + +window, 1-12 +doubled sized pixels + +mode, 4-1 + +S3 display mode, 2-6 +drawable + +graphics context, 4-1 + +windows and bitmaps, 1-18, 1-50 +drawing + +arrows, 4-10 + +background client, 1-18 + +lines, 4-7 + +polygon, 4-7 + +shadowed text, 4-23 + +shadows, 4-10 + +text, 1-44 + +to bitmaps, 1-31 + +windows, 1-25 +drawing mode + +G_GC_FLAG_BOTH_PLANES, 4-3 + +G_GC_FLAG_DOUBLE, 4-3 + +G_GC_FLAG_GREY_PLANE, 4-3 +drawing region + +window, 1-19 +DYL graphics + +WLIB function, 4-33 +E_CONFIG + +structure, 3-16 +E_PRIORITY_BACK + +window server flag, 2-7 +E_PRIORITY_FORE + +window server flag, 2-7 +embedded + +font files, 1-47 +embedded bitmap files + +add file lists, 1-37 +enable + +status window temporary, 2-22 +end rubber band + +event, 5-10 +environment variable + +$WS_FL, 1-2, 1-55, 1-56, 2-25 + +$WS_FNTS, 1-2, 1-38, 2-10 + +$WS_IF, 2-10, 3-16 + +$WS_SD, 1-32 + +$WS_SF, 1-38 + +$WS_SF2, 1-39 + +$WS_SF4, 1-39 +EPOC + +operating system, 1-1 + +PC version, 1-59 + + +iv + + +error + + +cleaning up, 1-11 +handling window server, 2-7 +panic numbers window server, 1-12 + + +error handling + + +window server, 1-11 + + +escape-key + + +event, 5-8 + + +event + + +W_KEY_MODE, 1-2 +W_MOUSE_DOWN, 5-9 +W_MOUSE_OUTSIDE, 5-9 +WM_ACTIVE, 1-53, 5-10 +WM_ATTACHED, 2-25, 5-8 +WM_BACKGROUND, 5-6 +WM_CANCELLED, 1-28, 5-6, 5-10 +WM_COMMAND, 5-7 +WM_DATE_CHANGED, 1-3, 5-7 +WM_DEICONISE, 1-16, 2-8, 5-8 +WM_DETACHED, 2-25, 5-8 +WM_ESCAPE, 5-8 +WM_FOREGROUND, 2-25, 5-6 +WM_KEY, 1-15, 1-51, 5-3 +WM_KEYBOARD_STATE_CHANGE, +5-8 +WM_MOUSE, 1-52, 5-9 +WM_MOUSE_MOVE, 5-9 +WM_MOUSE PRESS, 5-9 +WM_MOUSE_RELEASE, 1-53, 5-9 +WM_ON, 5-7, 5-11 + +WM_REDRAW, 3-12, 5-6 +WM_RUBBER, 1-53, 5-10, 5-14 +WM_RUBBER_BAND_INIT, 1-54, 5-9 +WM_TASK_KEY, 1-15, 5-7 +WM_TASK_UPDATE, 5-7 +WM_USER_MSG, 5-7, 5-10 +WS_EVENT_UNION, 5-1 + + +event function + + +wCancelGetEvent, 5-10 +wGetEvent, 1-51 + +wGetEvent get async, 1-14 +wGetEventSpecial, 1-51 +wGetEventSpecial get async, 1-14 +wGetEventWait, 1-51 +wGetEventWait event get, 1-14 +wSendCommand, 5-10 +wUserMsg, 5-10 + + +event selected + + +WE_ESC, 5-2 +WE_KEY, 5-2 +WE_MOUSE, 5-2 +WE_NORMAL, 5-2 +WE_OTHERS, 5-2 +WE_REDRAW, 5-2 +WE_STATUS, 5-2 + + +event selected update + + +wGetEventUpdate, 5-2 + + +event types + + +described, 5-3 + + +events + + +activation, 5-10 +asynchronous, 1-28, 5-2 +attachment, 5-8 +background, 5-6 + + +cancelled, 5-6, 5-10 +client command, 5-7, 5-10 +date changed, 5-7 +de-iconise, 5-8 +detachment, 5-8 +end rubber band, 5-10 +escape-key, 5-8 +foreground, 5-6 +getting next, 5-1 +inform key handler, 5-7 +key, 1-14 +key presses, 1-51 +keyboard capturing, 5-15 +keyboard state change, 5-8 +large screen, 5-8 +machine on, 5-7 +mouse, 1-14, 1-52, 5-9 +non window server, 1-28 +other sources, 1-28 +process termination, 5-7 +redraw, 1-24, 5-6 +rubber, 5-15 +selected, 5-2 +start rubber band, 5-9 +synchronous, 5-1 +time-stamping, 1-14 +types, 5-3 +update selected, 5-2 +user, 5-10 +user message, 5-7 +waiting, 5-1 +wGetEvent async, 5-2 +wGetEventWait sync, 5-1 +window server clients, 1-14 +WLIB functions, 5-10 +events selected async +wGetEventSpecial, 5-2 +fast fonts +described, 1-38 +file format +bitmaps, 1-36 +fonts, 1-46 +files +bitmaps creating, 1-31 +font, 1-42 +fill area +gClrRect, 4-12 +filling areas +modes, 4-12, 4-13 +WLIB functions, 4-12 +flashing +cursor, 1-29 +FLK +font source file list file, 1-44 +flushing +client-side buffer, 1-13 +commands window server, 2-5 +window server, 1-11 +flushing commands +window server, 2-7 +FON +file, 1-42 +font group configure +gConfigureFonts, 4-18 + + +INDEX + + +font group header read +gReadFontGroupHeader, 4-19 +font header read +gReadFontHeader, 4-19 +font information +structure, 4-16 +font internal +wSetSystemFont, 4-17 +font loading +gOpenFont, 4-15 +font open index +gOpenFontIndex, 4-18 +font position +gSetOpenAddress, 4-15 +font style +G_FONT_FLAG_ASCII, 4-16 +G_FONT_FLAG_BOLD, 4-16 +G_FONT_FLAG_CP850, 4-16 +G_FONT_FLAG_ITALIC, 4-16 +G_FONT_FLAG_SERIF, 4-16 +G_STY_BOLD, 4-2 +G_STY_DOUBLE, 4-2 +G_STY_INVERSE, 4-2 +G_STY_ITALIC, 4-2 +G_STY_MONO, 4-2 +G_STY_NORMAL, 4-2 +G_STY_SUBSCRIPT, 4-2 +G_STY_SUBSCRIPT2, 4-3 +G_STY_SUPERSCRIPT, 4-2 +G_STY_SUPERSCRIPT2, 4-3 +G_STY_UNDERLINE, 4-2 +font system +wSetSystemFont, 4-17 +font type system +W_SYSTEM_FONT_INTERNAL_S3, 4-17 +W_SYSTEM_FONT_INTERNAL_S3B, +4-17 +W_SYSTEM_FONT_S3, 4-17 +W_SYSTEM_FONT_S3B, 4-17 +font width table +gGetWidthTable, 4-17 +fonts +ascent, 4-14 +baseline, 4-14 +bitmaps, 1-38 +body cell, 4-14 +compiler wsfcomp.exe, 1-43 +configure group, 4-18 +descent, 4-14 +fast, 1-38 +file structure, 1-46 +files, 1-42 +files checksum, 1-46 +files embedded, 1-47 +files p_cre, 1-46 +finding in file gSetOpenAddress, 1-42 +FON files, 1-42 +freeing, 4-16 +group, 4-18 +group header, 4-19 +HC, 1-39 +header, 4-19 +high character, 4-14 +horizontal leading, 4-14 + + +WINDOW SERVER REFERENCE + + +ID field, 4-3 +ID start WS_FONT_BASE, 1-38 +ID system WS_FONT_SYSTEM, 1-38 +information, 1-44, 4-16 +internal IDs, 4-17 +loading gOpenFont, 1-42 +loading gOpenFontIndex, 1-42 +low character, 4-14 +MC, 1-41 +monospaced, 1-38 +multiple, 4-18 +opening, 4-15, 4-18 +proportional, 1-38 +roman, 1-41 +ROM-based, 1-38, 4-3 +S3, 1-40 +S3a, 1-41 +source file list FLK file, 1-44 +source FSC file, 1-43 +structure, 1-46 +style, 1-45, 4-2 +style G_STY_BOLD, 1-45 +style G_LSTY_DOUBLE, 1-45 +style G_STY_INVERSE, 1-45 +style G_STY_ITALIC, 1-45 +style G_LSTY_MONO, 1-45 +style G_STY_NORMAL, 1-45 +style G_LSTY_UNDERLINE, 1-45 +swiss, 1-42 +system IDs, 4-17 +text, 1-38, 4-14 +vertical leading, 4-14 +width, 4-14 +width table, 4-17 +Workabout, 1-41 + +Fonts + + +ID system from W_SERVER_INFO, 1-38 + + +ID system S3/HC from $WS_SF, 1-38 + + +ID system S3a from $WS_SFNTS, 1-38 + + +information gFontInfo, 1-44 +fonts.h + +header file, 1-39, 1-41 +foreground + +client, 1-14 + +client switch task order, 2-8 + +event, 5-6 +freeing + +bitmap sequences, 3-15 + +bitmaps, 4-28, 4-32 + +clocks, 3-22 + +fonts, 4-16 + +mouse icon, 3-23 + +permanent graphics contexts, 4-5 + +sprites, 3-16 + +temporary graphics contexts, 4-6 +FSC file + +font source file, 1-43 +G_FONT_CONFIG + +structure, 4-18 +G_FONT_FLAG_ASCTI + +font style, 4-16 +G_FONT_FLAG_BOLD + +font style, 4-16 + + +vi + + +G_FONT_FLAG_CP850 + +font style, 4-16 +G_FONT_FLAG_ITALIC + +font style, 4-16 +G_FONT_FLAG_SERIF + +font style, 4-16 +G_FONT_INFO + +font information structure, 4-16 + +structure, 1-46 +G_GC + +plane flag, 1-3 + +structure, 3-9, 4-1 +G_GC_FLAG_BOTH_PLANES + +drawing mode, 4-3 +G_GC_FLAG_DOUBLE + +drawing mode, 4-3 + +graphics flag, 1-2 +G_GC_FLAG_GREY_PLANE + +drawing mode, 4-3 +G_SHADOW + +structure, 4-23 +G_STY_BOLD + +font style, 1-45, 4-2 +G_STY_DOUBLE + +font style, 1-45, 4-2 +G_STY_INVERSE + +font style, 1-45, 4-2 +G_STY_ITALIC + +font style, 1-45, 4-2 +G_STY_MONO + +font style, 1-45, 4-2 +G_STY_NORMAL + +font style, 1-45, 4-2 +G_STY_SUBSCRIPT + +font style, 4-2 +G_STY_SUBSCRIPT2 + +font style, 4-3 +G_STY_SUPERSCRIPT + +font style, 4-2 +G_STY_SUPERSCRIPT2 + +font style, 4-3 +G_STY_UNDERLINE + +font style, 1-45, 4-2 +G_TRMODE_CLR + +bitmap transfer mode, 1-30 + +text mode, 4-2 + +text transfer mode, 1-45 +G_TRMODE_INV + +bitmap transfer mode, 1-30 + +text mode, 4-2 + +text transfer mode, 1-45 +G_TRMODE_REPL + +bitmap transfer mode, 1-30 + +text mode, 4-2 + +text transfer mode, 1-45 +G_TRMODE_SET + +bitmap transfer mode, 1-30 + +text mode, 4-2 + +text transfer mode, 1-45 +gBorder + +graphics output, 1-49 + +WLIB function, 4-10 +gBorder2 + +graphics output, 1-49 + + +WLIB function, 4-12 +gBorder2Rect + +graphics output, 1-49 + +WLIB function, 4-10 +gBorderRect + +graphics output, 1-49 + +WLIB function, 4-8 +gCheckBitmapID + +WLIB function, 4-30 +gClrRect + +graphics output, 1-49 + +WLIB function, 4-12 +gConfigureFonts + +WLIB function, 4-18 +gCopyBit + +bitmap WLIB function, 1-30 + +graphics output, 1-49 + +WLIB function, 4-29 +gCopyRect + +graphics output, 1-49 + +WLIB function, 4-30 +gCreateBit + +bitmap WLIB function, 1-30 + +WLIB function, 4-26 +gCreateGC + +graphics context permanent, 1-50 + +WLIB function, 4-4 +gCreateGCO + +graphics context permanent, 1-50 + +WLIB function, 4-5 +gCreateTempGC + +graphics context temporary, 1-51 + +WLIB function, 4-5 +gCreateTempGCO + +graphics context temporary, 1-51 + +WLIB function, 4-6 +gDrawBit + +bitmap WLIB function, 1-30 + +graphics output, 1-49 + +WLIB function, 4-31 +gDrawBox + +graphics output, 1-49 + +WLIB function, 4-8 +gDrawLine + +graphics output, 1-49 + +WLIB function, 4-7 +gDrawObject + +graphics output, 1-49 + +WLIB function, 4-12 +gDrawPolyLine + +graphics output, 1-49 + +WLIB function, 4-7 +gEndMultiSave + +WLIB function, 4-32 +gFillPattern + +bitmap WLIB function, 1-30 + +graphics output, 1-49 + +WLIB function, 4-13 +gFontInfo + +fonts WLIB function, 1-44 + +WLIB function, 4-16 +gFreeTempGC + +graphics context free, 1-51 + +WLIB function, 4-6 + + +INDEX + + +gGetBit + +bitmap WLIB function, 1-30 + +WLIB function, 4-31 +gGetWidthTable + +WLIB function, 4-17 +gInitBit + +bitmap WLIB function, 1-30 + +WLIB function, 4-31 +gInitMultiSave + +WLIB function, 4-32 +gInquireChecksum + +WLIB function, 4-32 +gInvObloid + +graphics output, 1-49 + +WLIB function, 4-13 +gmode + +graphics modes, 4-2 +gOpenBit + +bitmap WLIB function, 1-30 + +WLIB function, 4-27 +gOpenFont + +fonts WLIB function, 1-42 + +WLIB function, 4-15 +gOpenFontIndex + +fonts WLIB function, 1-42 + +WLIB function, 4-18 +gOpenMouselcon + +WLIB function, 3-23 +gPeekBit, 1-35 + +WLIB function, 4-30 +gPrintBoxText + +graphics output, 1-49 + +text drawing WLIB function, 1-44 + +WLIB function, 4-20 +gPrintClipText + +graphics output, 1-49 + +text drawing WLIB function, 1-44 + +WLIB function, 4-20 +gPrintText + +graphics output, 1-49 + +text drawing WLIB function, 1-44 + +WLIB function, 4-20 +gQueryBit + +WLIB function, 4-31 +graphics + +adding output functions, 4-33 + +DYL, 4-33 + +G_GC_FLAG_DOUBLE flag, 1-2 + +output, 2-10 + +structures, 1-48 + +WLIB functions, 1-47 +graphics contexts + +current, 1-50 + +free gFreeTempGC, 1-51 + +free wEndRedraw, 1-51 + +gCreateGC, 4-4 + +gCreateGCO, 4-5 + +gCreateTempGC, 4-5 + +gCreateTempGCO0, 4-6 + +gFreeTempGC, 4-6 + +gSetGC, 4-6 + +gSetGCO, 4-7 + +overview, 1-50, 4-1 + +permanent, 1-50, 4-4 + + +WINDOW SERVER REFERENCE + + +permanent freeing, 4-5 +permanent gCreateGC, 1-50 +permanent gCreateGCO, 1-50 +set specific gSetGC, 1-50 +set specific gSetGCO, 1-50 +setting, 4-6 +temporary, 1-51, 4-5 +temporary & permanent, 1-50 +temporary freeing, 4-6 +temporary gCreateTempGC, 1-51 +temporary gCreateTempGCO, 1-51 +temporary wBeginRedrawGC, 1-51 +temporary wBeginRedrawGCo, 1-51 +temporary wBeginRedrawWinGC, 1-51 +temporary wBeginRedrawWinGCO, 1-51 +wFree, 4-5 +windows, 1-18 +graphics DYL call +wCallDYL, 4-33 +graphics DYL enquiry call +wCallDYLReply, 4-33 +graphics DYL load +wLoadDYL, 4-33 +graphics functions +not to current graphics context, 1-49 +to current graphics context, 1-49 +graphics modes +gmode, 4-2 +graphics objects +gDrawObject, 4-12 +type attributes, 4-12 +types, 4-12 +graphics output +gBorder, 1-49 +gBorder2, 1-49 +gBorder2Rect, 1-49 +gBorderRect, 1-49 +gClrRect, 1-49 +gCopyBit, 1-49 +gCopyRect, 1-49 +gDrawBit, 1-49 +gDrawBox, 1-49 +gDrawLine, 1-49 +gDrawObject, 1-49 +gDrawPolyLine, 1-49 +gFillPattern, 1-49 +gInvObloid, 1-49 +gPrintBoxText, 1-49 +gPrintClipText, 1-49 +gPrintText, 1-49 +gShadowText, 1-49 +gXPrintText, 1-49 +not to current graphics context, 1-49 +to current graphics context, 1-49 +wCancelBusyMsg, 1-49 +wDrawButton, 1-49 +wDrawButton2, 1-49 +wDrawTextCursor, 1-49 +wEraseTextCursor, 1-49 +wInfoMsg, 1-49 +winfoMsgCorner, 1-49 +wsAlertA, 1-50 +wsAlertCancel, 1-50 +wsAlertUpdate, 1-50 + + +viii + + +wsAlertW, 1-50 +wsCreateClock, 1-49 +wsCreateClock2, 1-49 +wscrollRect, 1-49 +wScrollWin, 1-49 +wsDisable, 1-50 +wsDisableTemp, 1-50 +wsEnable, 1-50 +wsEnableTemp, 1-50 +wsSetBusyMsg, 1-49 +wsSelectList, 1-50 +wsSetClock, 1-49 +wsSetList, 1-50 +wsStatusWindow, 1-50 +wsUpdate, 1-50 +wTextCursor, 1-49 +gReadFontGroupHeader +WLIB function, 4-19 +gReadFontHeader +WLIB function, 4-19 +grey +cursor, 1-29 +plane, 1-3, 1-19, 3-8, 4-1, 4-13 +gSaveBit +bitmap WLIB function, 1-31 +WLIB function, 4-28 +gSaveMultiBit +bitmap WLIB function, 1-31 +WLIB function, 4-32 +gSaveMultiRect +bitmap WLIB function, 1-31 +WLIB function, 4-32 +gSaveRect +bitmap WLIB function, 1-31 +WLIB function, 4-28 +gSetGC +graphics context specific, 1-50 +WLIB function, 4-6 +gSetGCO +graphics context specific, 1-50 +WLIB function, 4-7 +gSetOpenAddress +bitmap WLIB function, 1-30 +fonts WLIB function, 1-42 +WLIB function, 4-15 +gShadowText +graphics output, 1-49 +text drawing WLIB function, 1-44 +WLIB function, 4-23 +gTextCount +text layout WLIB function, 1-44 +WLIB function, 4-17 +gTextWidth +text layout WLIB function, 1-44 +WLIB function, 4-16 +gXPrintText +graphics output, 1-49 +text drawing WLIB function, 1-44 +WLIB function, 4-21 +HC +fonts, 1-39 +replacing the shell, 1-56 +shell example code, 1-56 +task switching, 1-15 + + +header file +for multi bitmap files, 1-31 +wlib.h, 1-8 +header files +fonts.h, 1-39, 1-41 +high character +fonts, 4-14 +hook notifier +process, 1-55 +window server option, 1-5 +horizontal leading +fonts, 4-14 +hotkeys +capturing, 5-12 +implementing, 5-12 +hot-spot +mouse icon, 1-52 +hung-up +redrawing delays, 1-26 +window server flag, 1-56 +icon ID +WS_DEFAULT_ICON, 1-3 +icon ID grey +WS_DEFAULT_ICON+1, 1-3 +iconised +client, 1-16 +client mark as, 2-9 +icons +mouse, 1-52, 3-22 +include file +key code wskeys.h, 6-1 +inform key handler +event, 5-7 +input +rubber band mode, 1-53 +internal fonts +IDs, 4-17 +invalidate function +wlInvalidateRect, 3-12 +wlInvalidateWin, 3-12 +invalidating +windows, 1-24 +WLIB function, 3-12 +invert obloid +gInvObloid, 4-13 +invisible window +wMakelnvisible, 1-28 +key +pause disable wDisablePauseKey, 1-52 +pause enable wEnablePauseKey, 1-52 +specific cancel wCancelCaptureKey, 1-51 +specific wCaptureKey, 1-51 +tasks setting, 1-52 +key capture +wCaptureKey, 5-11 +key capture off +wCancelCaptureKey, 5-12 +key code +diamond, 5-5 +Series 3c and Siena update, 6-1 +W_FUNC_MODIFIER, 6-2 +W_KEY_BACKLIGHT, 5-5 +W_KEY_CALC_CHNG_SIGN, 6-2 +W_KEY_CALC_CLEAR, 6-2 + + +INDEX + + +_CALC_DECIMAL, 6-2 +_CALC_MEM_CLEAR, 6-2 +_CALC_MEM_INPUT, 6-2 +_CALC_MEM_MINUS, 6-2 +_CALC_MEM_PLUS, 6-2 +_CALC_MEM_RECALL, 6-2 +_CALC_PERCENT, 6-2 +_CAPS_LOCK, 5-5 +_DELETE_LEFT, 5-4 + + +_HELP, 5-5 + + +MENU, 5-5 + + +qeidddddddddedeedeeeeeeeeeas + + +Sebi bie eb bii ibis bts bist tts + + +Me +Y_ +Y_ +Y_ +NX +Y_ +Y_LEFT, 5-4 +Mes +Y_ +Y +Y_' +Y_ +Y_PAGE_UP, 5-4 +Y + + +agceead + + +W_KEY_VOICE, 5-4 +W_RUSSIAN_MODIFIER, 6-2 +wskeys.h, 6-1 +key code applications +W_KEY_APPn, 5-5 +key modifier +W_CAPS_MODIFIER, 5-3, 5-9 +W_CTRL_MODIFIER, 5-3, 5-9 +W_NUM_LOCK_MODIFIER, 5-3, 5-9 +W_PSION_MODIFIER, 5-3, 5-9 +W_SHIFT_MODIFIER, 5-3, 5-9 +key press +diamond, 1-15 +keyboard +events capturing, 5-15 +input, 1-14, 1-51 +key press events, 1-51 +rubber band, 5-15 +Series 3c and Siena update, 6-1 +state change event, 5-8 +update for Series 3c and Siena, 6-1 +key-click +disable, 2-26 +enable, 2-26 +keys +application handler, 1-15 +cancel back task switch keys, 5-13 +cancel task switch keys, 5-12 +capturing, 1-51, 5-11 +code, 1-51, 5-3 + + +WINDOW SERVER REFERENCE + + +code - Series 3c and Siena update, 6-1 +code wskeys.h, 6-1 +count, 1-51, 5-3 +events, 1-14 +key press events, 1-51 +modifier, 5-3 +repeat count, 1-51, 5-3 +set back task switch keys, 5-13 +set task switch keys, 5-12 +large screen +event, 5-8 +LCD display resolution +by machine, 2-5 +leading horizontal +fonts, 4-14 +leading vertical +fonts, 4-14 +leaving +disable, 2-7 +enable, 2-7 +libraries +WLIB using, 1-8 +line drawing +gDrawBox, 4-8 +gDrawLine, 4-7 +gDrawPolyLine, 4-7 +WLIB functions, 4-7 +link paste +window server services, 1-6 +low character +fonts, 4-14 +machine on +event, 5-7 +machine type +from wConnect, 1-2 +magic static +DatStatusNamePtr, 2-13 +MC +fonts, 1-41 +task switching, 1-16 +wAttachToClient, 1-16 +wAttachToForegroundClient, 1-16 +MC200 +Fonts system ID, 1-39 +mouse, 5-9 +MC400 +Fonts system ID, 1-39 +mouse, 5-9 +message +cancel busy, 2-12 +display alerts, 2-12 +display brief, 2-11 +display busy, 2-11 +message constant +W_INFO_MSG_MAX_LEN, 2-11 +message flag +W_CORNER_BOTTOM_LEFT, 2-11 +W_CORNER_BOTTOM_RIGHT, 2-11 +W_CORNER_TOP_LEFT, 2-11 +W_CORNER_TOP_RIGHT, 2-11 +mode display +diamond key, 2-20 +mode list +status window, 2-23 + + +modifier +keys, 5-3 +monospaced fonts +sets, 1-38 +mouse +capturing, 1-53, 5-13 +event, 5-9 +events, 1-14, 1-52, 5-9 +freeing icon, 3-23 +grabbing, 1-53 +icons, 1-52, 3-22 +input, 1-52 +releasing, 5-13 +rubber band, 5-15 +mouse capture +wCaptureMouse, 5-13 +mouse icon +gOpenMouselcon, 3-23 +hot-spot, 1-52 +W_WIN_MI_STANDARD, 1-52 +wFree, 3-23 +mouse icon attribute +W_WIN_MI_CROSS, 3-22 + + +_MI_MARGIN, 3-23 +I_MOVE, 3-23 +_ NULL, 1-52, 3-22 +_PG_DOWN, 3-23 +_PG_UP, 3-23 +_PUSHER, 3-22 +_RESIZE, 3-23 +_RIGHT, 3-23 +_STANDARD, 3-22 +_TEXT, 3-22 +MI_TO_BIG, 3-23 +_MI_TO_SMALL, 3-23 +N_MI_VSLIDE, 3-23 +mouse icon position + +gSetOpenAddress, 4-15 +mouse release + +wReleaseMouse, 5-13 +multiple + +bitmaps, 4-30 + +fonts, 4-18 +multi-tasking + +redraw response, 1-26 + +window destroying and, 3-6 +normal + +plane, 1-3, 1-19, 3-8, 4-1, 4-13 +notifier + +hook the process, 1-55 + +window server option, 1-5 +notify + +process SYS$NTFY, 1-54 +obloid invert + +gInvObloid, 4-13 +on event enable + +winformOn, 5-11 + +winformOnAll, 5-11 +opening + +bitmaps, 4-31 + +fonts, 4-15, 4-18 + + +z +z + + +— + + +— + + +— + + +— + + +z'z'z'czzzzzz + + +— + + +— + + +— + + +eececccece +Ssscccaces + + +ZAZZAZLZAZLZAZLZLAZLZZ + + +z= +=i + + +F + + +p_cre +font files, 1-46 +function, 1-37 + + +p_enter + +window server, 1-11 +p_execc + +sub-process create, 1-26 +P_EXTENT + +structure, 1-48, 3-1 +P_FSIG + +structure, 1-37, 1-46 +p_iowait + +and window server events, 1-28 +p_leave + +window server, 1-11 +p_panic + +window server, 1-12 +P_POINT + +structure, 1-48, 3-1, 4-30 +P_RECT + +structure, 1-48, 4-29 +p_resume + +function, 1-14 +panic + + +W_PANIC_SPRITE, 3-16 + +W_PANIC_SPRITE_EXISTS, 3-16 +panic numbers + +window server, 1-12 +parent + +window, 1-18 +password support + +window server option, 1-6 +pause + +client disable, 2-10 + +client enable, 2-9 + + +pausing + +client, 1-52 +PC + +EPOC, 1-59 +PCX file + + +from screen capture, 1-33 + +to bitmap file, 1-31 +pcxsave.c + +example program screen capture, 1-33 +pcxScreenSave + +screen capture, 1-33 +permanent + +status window, 2-19 +PH file + +multi bitmap header file, 1-31 +PIC file + +from a PCX file, 1-31 +PIC_HEAD + +structure, 1-36 +pixel + +coordinates, 1-47 + +double sized mode, 4-1 + +screen resolutions, 2-5 +pixel coordinates + +bitmaps, 1-47 +plane + +black, 1-3, 1-19, 4-1 + +grey, 1-3, 1-19, 3-8, 4-1, 4-13 + +normal, 1-3, 1-19, 4-1, 4-13 + + +INDEX + + +plane flag + +in G_GC, 1-3 +PLIB + +library, 1-8 + +startup module, 1-9, 2-1 + +startup module MC, 1-10 +PLK file + +multi bitmap files, 1-31 +polygon drawing + +WLIB function, 4-7 + + +priority +changing clients, 2-7 +client, 1-16 + + +compute mode end wEndCompute, 2-8 +compute mode setting wStartCompute, 2-8 +redraw events, 1-27 +wEndCompute, 1-17 +wSetPriorityControl, 2-8 +wsStartCompute, 1-17 +process +SYS$FSRV, 1-54 +SYS$MANG, 1-54 +SYS$NTFY, 1-54 +SYS$NULL, 1-54 +SYS$SHLL, 1-15, 1-54 +SYS$WSRYV, 1-54 +wsystem, 1-55 +process termination +event, 5-7 +proportional fonts +sets, 1-38 +reading bitmaps +WLIB function, 4-30 + + +redraw +event, 5-6 +events, 1-24 + + +priority, 1-27 +priority bit W_WIN_PRIORITY, 1-27 +responsively, 1-26 +update region, 1-24 +validating before, 1-25 +redraw function +wBeginRedraw, 3-9 +wBeginRedrawGC, 3-9 +wBeginRedrawGC0, 3-10 +wBeginRedrawWin, 3-9 +wBeginRedrawWinGC, 3-10 +wBeginRedrawWinGC0O, 3-10 +wEndRedraw, 3-11 +redrawing +wBeginRedraw WLIB functions, 1-26 +windows, 1-24, 1-25 +windows variants, 3-8 +redraws +avoiding using bitmaps, 1-22 +avoiding using bitmaps example code, 1-22 +releasing mouse +WLIB function, 5-13 +repeat count +key, 1-51 +keys, 5-3 +reserved static +see magic static, 2-4 + + +WINDOW SERVER REFERENCE + + +ROM +built in grey bitmap, 1-30 +roman +fonts, 1-41 +ROM-based fonts +IDs, 4-3 +sets, 1-38 +root +window, 1-18 +rubber band +arrow keys, 1-54 +enter mode wRubberBand, 1-54 +input mode, 1-53 +keyboard events, 5-15 +mouse events, 5-15 +WLIB functions, 5-14 +rubber band attribute +W_BAND_COMPLETE_ON_UP, 5-15 +W_BAND_GRID_SNAP, 5-15 +W_BAND_GRID_SNAP_ SIZE, 5-15 +W_BAND_INNER, 5-14 +W_BAND_OUTER, 5-14 +W_BAND_RESIZE, 5-14 +W_BAND_START, 5-14 +rubber band flag +WM_BAND_CANCEL, 5-15 +WM_BAND_ERROR, 5-15 +WM_BAND_MOVE, 5-15 +WM_BAND_NOMOVE, 5-15 +WM_BAND_RESIZE, 5-15 +rubber band start +wRubberBand, 5-14 +83 +fonts, 1-40 +S3a +fonts, 1-41 +saving bitmaps +WLIB function, 4-28 +saving multiple bitmaps +WLIB function, 4-32 +scapt +screen capture example program, 1-36 +screen +coordinates, 1-18 +double pixel mode, 1-2 +event, 5-8 +screen capture +disabling, 1-32 +example code, 1-33 +HC, 1-33 +pexScreenSave function, 1-33 +scapt example program, 1-36 +to a bitmap, 1-31 +to bitmap file, 1-32 +to PCX file pexsave.c, 1-33 +screen resolution +by machine, 2-5 +by machine update, 6-1 +Series 3c and Siena update, 6-1 +screen sizes +by machine update, 6-1 +scrolling +rectangle, 3-7 +window, 3-7, 3-8 + + +xii + + +windows, 1-28 +windows continuous, 1-29 +selected events +WLIB function, 5-2 +Series 3 +compatibility mode, 1-12 +task switching, 1-15 +Series 3a +task switching, 1-15 +server +window server connecting to, 1-8 +setting graphics contexts +WLIB functions, 4-6 +shadowed text +WLIB functions, 4-23 +shadows +drawing, 4-10 +shell +event, 5-7 +HC replacing the shell, 1-56 +HC shell example code, 1-56 +process, 1-15, 1-54 +sibling +window, 1-18, 3-7 +sprite +structure, 3-15 +sprite attribute +W_SPRITE_CLIP_CHILDREN, 3-15 +sprite function +wCreateSprite, 3-15 +wFree, 3-16 +wsetSprite, 3-16 +sprites +animated bitmaps, 1-3 +animated graphics, 1-23 +animation, 3-15 +black plane, 1-23 +changing, 3-16 +creating, 3-15 +freeing, 3-16 +grey plane, 1-23 +normal plane, 1-23 +plane grey, 1-23 +W_SPRITE_CLIP_CHILDREN, 1-23 +wCreateSprite, 1-23 +wFree, 1-23 +wsetSprite, 1-23 +start rubber band +event, 5-9 +startup module + + +PLIB MC, 1-10 +start-up system +process, 1-54 +status window +compatibility mode, 2-21 +disable, 2-22 +drawing, 1-6 +extent get, 2-21 +mode list, 2-23 +overview, 2-19 +permanent, 2-19 + + +permanent enable, 2-21 + +permanent set state, 2-21 + +select position set, 2-23 + +Series 3c and Siena update, 6-3 + +Series 3c update, 6-3 + +Siena update, 6-3 + +state get, 2-23 + +temporary, 2-19 + +temporary disable, 2-22 + +temporary enable, 2-22 + +update displayed, 2-22 + +wsStatusWindow permanent, 2-21 +status window flag + + +W_STATUS_WIN_NO_DIAMOND, 2-23 + + +W_STATUS_WINDOW_BIG, 2-21 + + +W_STATUS_WINDOW_CTBY, 2-21 +W_STATUS_WINDOW_ICON, 2-23 + + +W_STATUS_WINDOW_OFF, 2-21 + + +W_STATUS_WINDOW_SMALL, 2-21 + + +structures +bitmap open, 4-26, 4-27 +clock, 3-19 +CONNECT_INFO, 2-3 +E_CONHIG, 3-16 +G_FONT_CONHIG, 4-18 +G_FONT_INFO, 1-46, 4-16 +G_GC, 3-9, 4-1 +G_SHADOW, 4-23 +graphics, 1-48 +P_EXTENT, 1-48, 3-1 +P_FSIG, 1-37 +P_POINT, 1-48, 3-1, 4-30 +P_RECT, 1-48, 4-29 +PIC_HEAD, 1-36 +sprite, 3-15 +W_SERVER_INFO, 1-38, 2-3 +W_SUPPORT_INFO, 2-26 +W_WINDATA, 3-1 +wMainGc, 2-2 +wMainWid, 2-2 +WMSG_KEY, 5-3 +WMSG_MOUSE, 5-9 +WMSG_RUBBER, 5-15 +WS_EV, 5-1 +WS_PIC_HEADER, 1-37 +WSERV_SPEC, 2-3 +wSpec, 2-2 +Structures +WS_FONT_FILE_HEADER, 1-46 +style +fonts, 1-45, 4-2 +sub-process +create p_execc, 1-26 +Swiss +fonts, 1-42 +synchronous +events, 5-1 +SYS$CONS +display process on MC, 1-7 +SYS$FSRV +process, 1-54 +SYS$MANG +process, 1-54 + + +INDEX + + +SYS$NTFY + + +process, 1-54 + + +SYS$NULL + + +process, 1-54 + + +sys$shll, 2-9 +SYS$SHLL + + +process, 1-54 + + +SYS$WSRV + + +process, 1-54 +window server process, 1-1 + + +system fonts + + +IDs, 4-17 + + +system modal + + +wCancelSystemModal, 1-17 +wsystemModal, 1-17 + + +system start-up + + +process, 1-54 + + +system type + + +from wConnect, 1-2 + + +system-modal + + +client, 1-17, 2-9 + + +task key + + +back set wSetBackTaskKey, 1-52 +cancel wCancelTaskKey, 1-52 +set wSetTaskKey, 1-52 + + +Task key + + +$3 and 3a, 1-52 + + +task key back cancel + + +wCancelBackTaskKey, 1-52 + + +task keys + + +setting, 1-52 + + +task order + + +client position, 2-8 + + +task switching + + +cancel back task switch keys, 5-13 +cancel task switch keys, 5-12 + +HC, 1-15 + +MC, 1-16 + +Series 3, 1-15 + +Series 3a, 1-15 + +set back task switch keys, 5-13 + +set task switch keys, 5-12 + +window server, 1-14 + + +task switching back cancel + + +wCancelBackTaskKey, 5-13 + + +task switching key cancel + + +wCancelTaskKey, 5-12 + + +task switching key set + + +wsetTaskKey, 5-12 + + +task switching set back + + +wsetBackTaskKey, 5-13 + + +temporary + + +text + + +status window, 2-19 + + +button, 4-24, 4-25 + +cursor, 1-29, 3-12 + +drawing, 1-44 + +fonts, 1-38, 4-14 + +transfer mode, 1-45, 4-2 + +transfer mode G_TRMODE_CLR, 1-45 +transfer mode G_TRMODE_INV, 1-45 +transfer mode G_TRMODE_REPL, 1-45 +transfer mode G_TRMODE_ SET, 1-45 +width, 4-16 + + +xiii + + +WINDOW SERVER REFERENCE + + +text count +gTextCount, 4-17 +text drawing +gPrintBoxText, 1-44 +gPrintClipText, 1-44 +gPrintText, 1-44 +gShadowText, 1-44 +gXPrintText, 1-44 +text mode +G_TRMODE_CLR, 4-2 +G_TRMODE_INV, 4-2 +G_TRMODE_REPL, 4-2 +G_TRMODE_SET, 4-2 +text output +WLIB functions, 4-19 +text print +boxed, 4-20 +clipped, 4-20 +embellishment, 4-21 +gPrintText, 4-20 +shadowed, 4-23 +text print boxed +gPrintBoxText, 4-20 +text print clipped +gPrintClipText, 4-20 +text print embellished +gXPrintText, 4-21 +text print shadowed +gShadowText, 4-23 +text width +gTextCount, 1-44 +gTextWidth, 1-44 +wGetWidthTable, 1-44 +text width get +gTextWidth, 4-16 +textmode +transfer mode, 1-45, 4-2 +time-stamp +events, 1-14 +top-level +window, 1-18 +transfer mode +text, 1-45, 4-2 +update event selection +WLIB function, 5-2 +update region +redrawing, 1-24 +user +event, 5-10 +user message +event, 5-7 +validate function +wValidateRect, 3-11 +wValidateWin, 3-11, 3-12 +validating +before drawing, 1-25 +WLIB function, 3-11 +version_id +window server, 2-4 +versions +window server, 1-1 +vertical leading +fonts, 4-14 + + +Xiv + + +visibility +window, 3-6 +visibility of +windows, 1-28 +visible window +wMakeVisible, 1-28 +W_BAND_COMPLETE_ON_UP +rubber band attribute, 5-15 +W_BAND_GRID_SNAP +rubber band attribute, 5-15 +W_BAND_GRID_SNAP_SIZE +rubber band attribute, 5-15 +W_BAND_INNER +rubber band attribute, 5-14 +W_BAND_OUTER +rubber band attribute, 5-14 +W_BAND_ RESIZE +rubber band attribute, 5-14 +W_BAND_START +rubber band attribute, 5-14 +W_BORD_CORNER_1 +border attribute, 4-11 +W_BORD_CORNER_2 +border attribute, 4-11 +W_BORD_CORNER_4 +border attribute, 4-11 +W_BORD_CUSHION +border attribute, 4-11 +W_BORD_OPEN +border attribute, 4-11 +W_BORD_SHADOW_D +border attribute, 4-11 +W_BORD_SHADOW_ON +border attribute, 4-11 +W_BORD_SHADOW_S +border attribute, 4-11 +W_CAPS_MODIFIER +key modifier, 5-3, 5-9 +W_CONNECT_AT_BACK +window server flag, 2-3 +W_CONNECT_CONNECTED +window server flag, 2-8 +W_CONNECT_DISABLE_LEAVES +window server flag, 2-3 +window server option, 1-11 +W_CONNECT_PRIORITY +window server flag, 2-3, 2-7, 2-8 +W_CONNECT_SYSTEM_MODAL +window server flag, 2-3, 2-8 +W_CONNECT_USER_FLAG +window server flag, 2-3, 2-8 +W_CORNER_BOTTOM_LEFT +message flag, 2-11 +W_CORNER_BOTTOM_RIGHT +message flag, 2-11 +W_CORNER_TOP_LEFT +message flag, 2-11 +W_CORNER_TOP_RIGHT +message flag, 2-11 +W_CTBY_S3 +compatibility mode, 2-6 +W_CTBY_S3_SCR +compatibility mode, 2-6 + + +W_CTRL_MODIFIER + +key modifier, 5-3, 5-9 +W_CURSOR_GREY + +cursor attribute, 3-12 +W_FUNC_MODIFIER + +key code, 6-2 +W_INFO_MSG_MAX_LEN + +message constant, 2-11 +W_KEY_APP1 + +application keys, 5-5, 6-2 +W_KEY_APP2 + +application keys, 5-5, 6-2 +W_KEY_APP3 + +application keys, 5-5, 6-2 +W_KEY_APP4 + +application keys, 5-5, 6-2 +W_KEY_APP5 + +application keys, 5-5, 6-2 +W_KEY_APP6 + +application keys, 5-5, 6-2 +W_KEY_APP7 + +application keys, 5-5, 6-2 +W_KEY_APP8 + +application keys, 5-5, 6-2 +W_KEY_APP9 + +application keys, 6-2 +W_KEY_APPn + +application keys, 5-5 +W_KEY_BACKLIGHT + +key code, 5-5 +W_KEY_CALC_CHNG_SIGN + +key code, 6-2 +W_KEY_CALC_CLEAR + +key code, 6-2 +W_KEY_CALC_DECIMAL + +key code, 6-2 +W_KEY_CALC_MEM_CLEAR + +key code, 6-2 +W_KEY_CALC_MEM_INPUT + +key code, 6-2 +W_KEY_CALC_MEM_MINUS + +key code, 6-2 +W_KEY_CALC_MEM_PLUS + +key code, 6-2 +W_KEY_CALC_MEM_RECALL + +key code, 6-2 +W_KEY_CALC_PERCENT + +key code, 6-2 +W_KEY_CAPS_LOCK + +key code, 5-5 +W_KEY_DELETE_LEFT + +key code, 5-4 +W_KEY_DELETE_RIGHT + +key code, 5-4 +W_KEY_DIAMOND + +key code, 5-5 +W_KEY_DOWN + +key code, 5-4 +W_KEY_END + +key code, 5-4 +W_KEY_ESCAPE + +key code, 5-4 +W_KEY_HELP + +key code, 5-5 + + +INDEX + + +W_KEY_HOME + +key code, 5-4 +W_KEY_INFO + +key code, 5-5 +W_KEY_IR_BRING + +key code, 6-2 +W_KEY_IR_LINK + +key code, 6-2 +W_KEY_IR_SEND + +key code, 6-2 +W_KEY_LCD + +key code, 5-5 +W_KEY_LCD_MINUS + +key code, 5-5 +W_KEY_LEFT + +key code, 5-4 +W_KEY_MENU + +key code, 5-5 +W_KEY_MODE + +event, 1-2 + +key code, 1-15, 5-5 +W_KEY_OFF + +key code, 5-6 +W_KEY_ON + +key code, 5-5 +W_KEY_PAGE_DOWN + +key code, 5-4 +W_KEY_PAGE_UP + +key code, 5-4 +W_KEY_RETURN + +key code, 5-4 +W_KEY_RIGHT + +key code, 5-4 +W_KEY_TAB + +key code, 5-4, 6-1 +W_KEY_TASK + +key code, 5-4 +W_KEY_UP + +key code, 5-4 +W_KEY_VOICE + +key code, 5-4 +W_MOUSE_DOWN + +events, 5-9 +W_MOUSE_OUTSIDE + +events, 5-9 +W_NUM_LOCK_MODIFIER + +key modifier, 5-3, 5-9 +W_PANIC_SPRITE + +panic, 3-16 +W_PANIC_SPRITE_EXISTS + +panic, 3-16 +W_PSION_MODIFIER + +key modifier, 5-3, 5-9 +W_RUSSIAN_MODIFIER + +key code, 6-2 +W_SERVER_INFO + +for system font ID, 1-38 + +structure, 1-38, 2-3 +W_SHIFT_MODIFIER + +key modifier, 5-3, 5-9 +W_SPRITE_CLIP_CHILDREN + +sprite attribute, 3-15 + +sprites, 1-23 + + +WINDOW SERVER REFERENCE + + +W_STATUS_WIN_NO_DIAMOND + +status window flag, 2-23 + +window status flag, 2-23 +W_STATUS_WINDOW_BIG + +status window flag, 2-21 +W_STATUS_WINDOW_CTBY + +status window flag, 2-21 +W_STATUS_WINDOW_ICON + +status window flag, 2-23 +W_STATUS_WINDOW_OFF + +status window flag, 2-21 +W_STATUS_WINDOW_SMALL + +status window flag, 2-21 +W_SUPPORT_CTBY_S3 + +window server flag, 2-26 +W_SUPPORT_GREY + +window server flag, 2-26 +W_SUPPORT_INFO + +structure, 2-26 +W_SYSTEM_FONT_INTERNAL_S3 + +font type system, 4-17 +W_SYSTEM_FONT_INTERNAL_S3B + +font type system, 4-17 +W_SYSTEM_FONT_S3 + +font type system, 4-17 +W_SYSTEM_FONT_S3B + +font type system, 4-17 +W_WIN_BACK_BITMAP + +window attribute, 1-19, 3-2 +W_WIN_BACK_CLR + +window attribute, 1-20, 1-25, 3-2 +W_WIN_BACK_CLR_NO_REDRAW + +window attribute, 1-21, 3-2 +W_WIN_BACK_GREY_BITMAP + +window attribute, 1-19, 3-2 +W_WIN_BACK_GREY_CLR + +window attribute, 1-20, 1-25, 3-2 + + +REDRAW +window attribute, 1-21 + + +window attribute, 1-21, 3-2 +W_WIN_DOUBLE_PIXEL +window attribute, 1-2, 3-3 + + +window attribute, 1-53, 3-3 +W_WIN_INPUT_ONLY +window attribute, 1-53, 3-3 + + +Xvi + + +W_WIN_MI_CROSS + +mouse icon attribute, 3-22 +W_WIN_MI_HSLIDE + +mouse icon attribute, 3-23 +W_WIN_MI_LEFT + +mouse icon attribute, 3-23 +W_WIN_MI_ MARGIN + +mouse icon attribute, 3-23 +W_WIN_MI_ MOVE + +mouse icon attribute, 3-23 +W_WIN_MI_ NULL + +mouse icon attribute, 1-52, 3-22 +W_WIN_MI PG_DOWN + +mouse icon attribute, 3-23 +W_WIN_MI_PG_UP + +mouse icon attribute, 3-23 +W_WIN_MI PUSHER + +mouse icon attribute, 3-22 +W_WIN_ML RESIZE + +mouse icon attribute, 3-23 +W_WIN_MIL RIGHT + +mouse icon attribute, 3-23 +W_WIN_MI STANDARD + +mouse icon, 1-52 + +mouse icon attribute, 3-22 +W_WIN_MI_ TEXT + +mouse icon attribute, 3-22 +W_WIN_MIL TO _BIG + +mouse icon attribute, 3-23 +W_WIN_MI_TO_SMALL + +mouse icon attribute, 3-23 +W_WIN_ML_ VSLIDE + +mouse icon attribute, 3-23 +W_WIN_MOUSE_DRAG +window attribute, 1-52, 3-3 +W_WIN_MOUSE_GRAB, 1-53 + +window attribute, 3-4 +W_WIN_MOUSE_MOVE +window attribute, 1-52, 3-3 +W_WIN_NO_MOUSE +window attribute, 1-52, 3-3 +W_WIN_NO_REDRAW + +window attribute, 1-20, 3-3 +W_WIN_PRIORITY + +redraw priority, 1-27 + +window attribute, 3-3 +W_WIN_RUBBER_ BAND +indow attribute, 3-4 + +window attribute_, 3-4 +W_WIN_RUBBER_BAND_ CAPTURE + +window attribute, 1-54 + + +iS +5 + + +W_WIN_RUBBER_BAND_COMPLETE_ON_ + + +RELEASE + +window attribute, 1-54 +W_WINDATA + +structure, 3-1 +wAppKeyHandler + +application keys, 1-15 +wAttachToClient + +MC, 1-16 + +WLIB function, 2-26 +wAttachToForegroundClient + +MC, 1-16 + +WLIB function, 2-26 + + +wBeginRedraw + + +redrawing WLIB functions, 1-25, 1-26 + + +WLIB function, 3-9 +wBeginRedrawGC + +graphics context temporary, 1-51 + +WLIB function, 3-9 +wBeginRedrawGCO + +graphics context temporary, 1-51 + +WLIB function, 3-10 +wBeginRedrawWin + +WLIB function, 3-9 +wBeginRedrawWinGC + +graphics context temporary, 1-51 + +WLIB function, 3-10 +wBeginRedrawWinGCO + +graphics context temporary, 1-51 + +WLIB function, 3-10 +wCallDYL + +WLIB function, 4-33 +wCallDYLReply + +WLIB function, 4-33 +wCancelBackTaskKey + +task key back cancel, 1-52 + +WLIB function, 5-13 +wCancelBusyMsg + +graphics output, 1-49 + +WLIB function, 2-12 +wCancelCaptureKey + +key specific cancel, 1-51 + +WLIB function, 5-12 +wCancelGetEvent + +and window server events, 1-28 + +WLIB function, 5-10 +wCancelSystemModal + +system modal cancel, 1-17 + +WLIB function, 2-9 +wCancelTaskKey + +task key cancel, 1-52 + +WLIB function, 5-12 +wCaptureKey + +specific key, 1-51 + +WLIB function, 5-11 +wCaptureMouse + +WLIB function, 5-13 +wChangeWinBitmap + +bitmap sequences, 1-21 + +WLIB function, 3-15 +wCheckPoint + +WLIB function, 2-7 +wCleanUp + +WLIB function, 2-7 +wClientIconised + +WLIB function, 2-9 +wClientInfo + +WLIB function, 2-8 +wClientPosition + +WLIB function, 2-8 +wCloseWindowTree + +windows destroying, 1-27 + +WLIB function, 3-6 +wCompatibilityMode + +S3 display mode, 2-6 +wConnect + +WLIB function, 1-8, 2-1, 2-3 + + +wCreateSprite + +sprites, 1-23 + +WLIB function, 3-15 +wCreateWindow + +window create, 1-18, 1-27 + +WLIB function, 3-1, 3-4 +wDetachClient + +WLIB function, 2-26 +wDisableKeyClick + +WLIB function, 2-26 +wDisableLeaves + +WLIB function, 2-7 +wDisablePauseKey + +pause key disable, 1-52 + +WLIB function, 2-10 +wDisconnect + +WLIB function, 2-5 +wDrawButton + +graphics output, 1-49 + +WLIB function, 4-24 +wDrawButton2 + +graphics output, 1-49 + +WLIB function, 4-25 +wDrawTextCursor + +graphics output, 1-49 + +WLIB function, 3-13 +WE_ESC + +event selected, 5-2 +WE_KEY + +event selected, 5-2 +WE_MOUSE + +event selected, 5-2 +WE_NORMAL + +event selected, 5-2 +WE_OTHERS + +event selected, 5-2 +WE_REDRAW + +event selected, 5-2 +WE_STATUS + +event selected, 5-2 +wEnablePauseKey + +pause key enable, 1-52 + +WLIB function, 2-9 +wEndCompute + +priority, 1-17 + +WLIB function, 2-8 +wEndRedraw + +graphics context free, 1-51 + +WLIB function, 3-11 +wEraseTextCursor + +cursor remove, 1-29 + +graphics output, 1-49 + +WLIB function, 3-13 +wFlush + +WLIB function, 2-5 +wFree + +bitmap free, 1-30 + +bitmap sequences, 1-21 + +sprites, 1-23 + + +WLIB function, 3-15, 3-16, 3-22, 3-23, 4-5, + + +4-16, 4-28, 4-32 +wGetCommand +WLIB function, 5-10 + + +WINDOW SERVER REFERENCE + + +wGetEvent + +event, 1-28, 1-51 + +event get async, 1-14 + +WLIB function, 5-2 +wGetEventSpecial + +event, 1-28, 1-51 + +event get async, 1-14 + +WLIB function, 5-2 +wGetEventUpdate + +WLIB function, 5-2 +wGetEventWait + +event, 1-51 + +event get, 1-14 + +WLIB function, 5-1 +wGetProcessList + +WLIB function, 2-10 +wGetWidthTable + +text layout WLIB function, 1-44 +wGetWindowPosition + +window position get, 1-27 + +WLIB function, 3-7 +width + +fonts, 4-14 +window + +attributes, 3-1 + +attributes get, 3-5 + +attributes set, 3-5 + +back up bitmaps, 1-19 + +back up bitmaps advantages, 1-19 + +back up bitmaps disadvantages, 1-19 + +back up bitmaps memory, 1-20 + +background field, 3-2 + +background modes, 1-3 + +child, 1-18 + +clipping, 1-25 + +creating, 1-27, 3-1, 3-4 + +destroying, 1-27, 3-6 + +drawing, 1-25 + +drawing region, 1-19 + +flicker free drawing, 1-25 + +flicker free redrawing, 1-25 + +inactive, 1-53 + +initialising, 1-27, 3-1 + +invisible function, 3-6 + +mouse only input, 1-53 + +no-redraw, 1-20 + +ownership, 1-18 + +parent, 1-18 + +position get wGetWindowPosition, 1-27 + +position set wWindowPosition, 1-27 + +root, 1-18 + +scrolling, 1-28, 3-7 + +scrolling optimised, 1-3 + +sibling, 1-18, 3-7 + +sibling position get, 3-7 + +sibling position set, 3-7 + +status, 2-19 + +top-level, 1-18 + +trees, 1-18, 3-5 + +visibility, 1-28, 3-6 + +visible function, 3-7 + +W_WIN_DOUBLE_PIXEL flag, 1-2 + +wInvalidateWin, 1-24 + + +XViii + + +Window +offset get, 3-6 +root reassign, 3-6 + +window attribute +W_WIN_BACK_BITMAP, 1-19, 3-2 +W_WIN_BACK_CLR, 1-20, 1-25, 3-2 +W_WIN_BACK_CLR_NO_REDRAW, + + +1-21, 3-2 +W_WIN_BACK_GREY_BITMAP, 1-19, +3-2 +W_WIN_BACK_ GREY _CLR, 1-20, 1-25, +3-2 + + +W_WIN_BACK_GREY_CLR_, 3-2 +W_WIN_BACK_GREY_CLR_NO_ +REDRAW, 1-21 +W_WIN_BACK_GREY_NONE, 1-25, 3-2 +W_WIN_BACK_GREY_NONE_, 3-2 +W_WIN_BACK_GREY_NONE_NO_ +REDRAW, 1-21 +W_WIN_BACK_GREY_SET, 1-20, 1-25, +3-2 +W_WIN_BACK_GREY_SET_, 3-2 +W_WIN_BACK_GREY_SET_NO_ +REDRAW, 1-21 +W_WIN_BACK_NONE, 1-25, 3-2 + + +1-21, 3-2 +W_WIN_DOUBLE_PIXEL, 3-3 + + +W_WIN_INACTIVE, 1-53, 3-3 +N_INPUT_ONLY, 1-53, 3-3 +IN_MOUSE_DRAG, 1-52, 3-3 +IN_MOUSE_GRAB, 3-4 +IN_MOUSE_MOVE, 1-52, 3-3 +IN_NO_MOUSE, 1-52, 3-3 +IN_NO_REDRAW,, 1-20, 3-3 +IN_PRIORITY, 3-3 +IN_RUBBER_BAND_, 3-4 +IN_RUBBER_BAND_CAPTURE, + + +Z + + +geececace +geeeeeez + + +25 +af + + +_WIN_RUBBER BAND_COMPLETE_ +ON_RELEASE, 1-54 +WS_WIN_BITMAP_GREY, 1-22 + +window create +wCreateWindow, 1-18, 1-27 + +window destroying +multi-tasking and, 3-6 + +window function +wCreateWindow, 3-1 +wInquireWindow, 3-1 +wSetWindow, 3-1 + +window invisible +wMakelInvisible, 1-28 + +window offset +wInquireWindowOffset, 1-18 + +window rectangle +wlInvalidateRect, 1-24 + +window scrolling +continuous, 1-29 + + +wscrollRect, 1-28 +wScrollWin, 1-28 +window server +buffered commands, 2-7 +changes, 1-1 +client information by process id, 2-8 +client list get, 2-10 +clients, 1-13 +configure, 2-24 +connect to, 1-8, 2-1, 2-3 +connecting to example code, 2-4 +disconnect from, 2-5 +error handling, 1-11, 2-7 +events and p_iowait, 1-28 +events and wCancelGetEvent, 1-28 +events and WM_CANCELLED, 1-28 +flag WSERV_FLAG_HOOK_NOTIFIER, +1-55 +flag WSERV_FLAG_HUNG_UP, 1-56 +flag WSERV_FLAG_LOW_BATTERY_ +WARNINGS, 1-56 +flag WSERV_FLAG_NO_NOTIFIER_ +REBOOT, 1-55 +flag +WSERV_FLAG_NO_PANIC_NOTIFY, +1-55 +introduction, 1-1 +process SYS$WSRYV, 1-1 +Series 3c and Siena update, 6-1 +supported features get, 2-26 +task switching, 1-14 +version 3, 1-7 +version 3.5, 1-5 +version 4, 1-2 +version from wConnect, 1-2 +version_id, 2-4 +versions, 1-1 +versions Series 3c and Siena update, 6-4 +versions Series 3c update, 6-4 +versions Siena update, 6-4 +W_CONNECT_DISABLE_LEAVES flag, +1-11 +wConnect WLIB function, 1-8 +WLIB functions, 2-1 +window server configuration +see WSERV_FLAG, 2-24 +window server constant +WS_LAST_CLIENT_POSITION, 2-8 +window server flag +E_PRIORITY_BACK, 2-7 +E_PRIORITY_FORE, 2-7 +W_CONNECT_AT_BACK, 2-3 +W_CONNECT_CONNECTED, 2-8 +W_CONNECT_DISABLE_LEAVES, 2-3 +W_CONNECT_PRIORITY, 2-3, 2-7, 2-8 +W_CONNECT_SYSTEM_MODAL, 2-3, +2-8 +W_CONNECT_USER_FLAG, 2-3, 2-8 +W_SUPPORT_CTBY_S3, 2-26 +W_SUPPORT_GREY, 2-26 +window server flags +see also WSERV_FLAG, 2-24 +window status flag +W_STATUS_WIN_NO_DIAMOND, 2-23 + + +INDEX + + +window tree +wlnitialiseWindowTree, 1-27 +window visible +wMakeVisible, 1-28 +windows +clipping child, 1-18 +drawables, 1-18 +graphics contexts, 1-18 +invalidating, 1-24 +overview, 1-18 +overview additional info, 1-27 +redrawing, 1-24, 1-25 +redrawing variants, 3-8 +windows and bitmaps +drawables, 1-18 +windows destroying +wCloseWindowTree, 1-27 +winfoMsg +graphics output, 1-49 +WLIB function, 2-11 +winfoMsgCorner +graphics output, 1-49 +WLIB function, 2-11 +winformOn +WLIB function, 5-11 +winformOnAll +WLIB function, 5-11 +wlnitialiseWindowTree +window tree, 1-27 +WLIB function, 3-5 +wInquireCompatibility +compatibility mode get, 2-7 +wInquireStatusWindow +WLIB function, 2-23 +wlInquireWindow +WLIB function, 3-1, 3-5 +wInquireWindowOffset +window offset, 1-18 +WLIB function, 3-6 +winvalidateRect +and invisible windows, 1-28 +window rectangle, 1-24 +WLIB function, 3-12 +winvalidateWin +and invisible windows, 1-28 +window, 1-24 +WLIB function, 3-12 +WLIB +header file, 1-8 +library with CLIB and PLIB, 1-8 +wLoadDYL +WLIB function, 4-33 +WM_ACTIVE +event, 1-53, 5-10 +WM_ATTACHED +event, 2-25, 5-8 +WM_BACKGROUND +event, 5-6 +WM_BAND_CANCEL +rubber band flag, 5-15 +WM_BAND_ERROR +rubber band flag, 5-15 +WM_BAND_ MOVE +rubber band flag, 5-15 + + +WINDOW SERVER REFERENCE + + +WM_BAND_NOMOVE +rubber band flag, 5-15 +WM_BAND_RESIZE +rubber band flag, 5-15 +WM_CANCELLED +and window server events, 1-28 +event, 1-28, 5-6, 5-10 +WM_COMMAND +event, 5-7 +WM_DATE_CHANGED +event, 1-3, 5-7 +WM_DEICONISE +event, 1-16, 2-8, 5-8 +WM_DETACHED +event, 2-25, 5-8 +WM_ESCAPE +event, 5-8 +WM_FOREGROUND +event, 2-25, 5-6 +WM_KEY +event, 1-15, 1-51, 5-3 +WM_KEYBOARD_STATE_ CHANGE +event, 5-8 +WM_MOUSE +event, 1-52, 5-9 +WM_MOUSE_MOVE +event, 5-9 +WM_MOUSE_PRESS +event, 5-9 +WM_MOUSE_RELEASE +event, 1-53, 5-9 +WM_ON +event, 5-7, 5-11 +WM_REDRAW +event, 3-12, 5-6 +WM_RUBBER +event, 1-53, 5-10, 5-14, 5-15 +WM_RUBBER_BAND_INIT +event, 1-54, 5-9 +WM_TASK_ KEY +event, 1-15, 5-7 +WM_TASK_UPDATE +event, 5-7 +WM_USER_MSG +event, 5-7, 5-10 +wMainGc +structure, 2-2 +wMain Wid +structure, 2-2 +wMakelnvisible +window WLIB function, 1-28 +WLIB function, 3-6 +wMake Visible +window WLIB function, 1-28 +WLIB function, 3-7 +WMSG_KEY +structure, 5-3 +WMSG_MOUSE +structure, 5-9 +WMSG_RUBBER +structure, 5-15 +Workabout +fonts, 1-41 +task switching, 1-15 + + +». ©. ¢ + + +wReassignRootWindow + +WLIB function, 3-6 +wReleaseMouse + +WLIB function, 5-13 +wRubberBand + +enter rubber band mode, 1-54 + +WLIB function, 5-14 +WS_ALERT_B + +alert flag, 1-3 +WS_CLOCK_AM_PM + +clock attribute, 3-17, 3-20 +WS_CLOCK_BOX + +clock attribute, 3-20 +WS_CLOCK_CENTERED + +clock attribute, 3-17, 3-20 +WS_CLOCK_FORCE_ANALOG + +clock attribute, 3-17, 3-20 +WS_CLOCK_FORCE_DIGITAL + +clock attribute, 3-17, 3-20 +WS_CLOCK_FORMATTED + +clock attribute, 3-19 +WS_CLOCK_GREY + +clock attribute, 3-20 +WS_CLOCK_LARGE_ANALOG + +clock attribute, 3-17, 3-19 +WS_CLOCK_MEDIUM + +clock attribute, 3-17, 3-19 +WS_CLOCK_MEDIUM2 + +clock attribute, 3-19 +WS_CLOCK_SMALL_DIGITAL + +clock attribute, 3-17, 3-19 +WS_CLOCK_WITH_DATE + +clock attribute, 3-17, 3-20 +WS_CLOCK_WITH_SECONDS + +clock attribute, 3-17, 3-20 +WS_CLOCK_XL_ANALOG + +clock attribute, 3-19 +WS_DEFAULT_ICON + +icon ID, 1-3 +WS_DEFAULT_ICON+1 + +icon grey ID, 1-3 +WS_EV + +structure, 5-1 +WS_EVENT_UNION + +events, 5-1 +WS_FONT_BASE + +define, 1-38 +WS_FONT_FILE_HEADERS + +structure, 1-46 +WS_FONT_SYSTEM + +define, 1-38 +WS_LAST_CLIENT_POSITION + +window server constant, 2-8 +WS_PIC_HEADER + +structure, 1-37 +WS_WIN_BITMAP_GREY + +window attribute, 1-22 +wsAlertA + +graphics output, 1-50 + +WLIB function, 2-18 +wsAlertCancel + +graphics output, 1-50 +wsAlertUpdate + +graphics output, 1-50 + + +WLIB function, 2-19 +wsAlertW + +alerts, 1-3 + +graphics output, 1-50 + +WLIB function, 2-14 +wsCreateClock + +graphics output, 1-49 + +WLIB function, 3-17 +wsCreateClock2 + +graphics output, 1-49 + +WLIB function, 3-19 +wscrollRect + +graphics output, 1-49 + +window scrolling, 1-28 + +WLIB function, 3-7 +wscrollWin + +graphics output, 1-49 + +window scrolling, 1-28 + +WLIB function, 3-8 +wsDisable + +graphics output, 1-50 + +WLIB function, 2-22 +wsDisableTemp + +graphics output, 1-50 + +WLIB function, 2-22 +wsEnable + +graphics output, 1-50 + +WLIB function, 2-21 +wsEnableTemp + +graphics output, 1-50 + +WLIB function, 2-22 +wsendCommand + +WLIB function, 5-10 +WSERV_FLAG + +HOOK_NOTIFIER, 2-24 + +HUNG_UP_SW, 2-25 + +LOW_BATTERY_WARNINGS, 2-25 + +NO_NOTIFIER_REBOOT, 2-24 + +NO_PANIC_NOTIFY, 2-24 + +NO_SHELL_REBOOT, 2-24 + +SW_NO_CAPS, 2-25 + +SW_NO_LINK, 2-25 + +SW_NO_LOW_BATTERY, 2-25 + +SW_NO_PACKS, 2-25 + +UPDATE_MSGS, 2-24 +WSERV_FLAG_HOOK_NOTIFIER + +window server flag, 1-55 +WSERV_FLAG_HUNG_UP + +window server flag, 1-56 +WSERV_FLAG_LOW_BATTERY_ +WARNINGS + +window server flag, 1-56 +WSERV_FLAG_NO_NOTIFIER_REBOOT + +window server flag, 1-55 +WSERV_FLAG_NO_PANIC_NOTIFY + +window server flag, 1-55 +WSERV_SPEC + +structure, 2-3 +wsetBackTaskKey + +task key back set, 1-52 + +WLIB function, 5-13 +wSetBusyMsg + +graphics output, 1-49 + +WLIB function, 2-11 + + +INDEX + + +wsetPriorityControl + +WLIB function, 2-8 +wsetSprite + +sprites, 1-23 + +WLIB function, 3-16 +wsSetSystemFont + +WLIB function, 4-17 +wsetTaskKey + +task key set, 1-52 + +WLIB function, 5-12 +wsetWinBitmap + +bitmap sequences, 1-21 + +bitmap WLIB function, 1-30 + +WLIB function, 3-14 +wsetWindow + +WLIB function, 3-1, 3-5 +wsfcomp.exe + +font file compiler, 1-43 +WSpcx.exe + +bitmap converter, 1-31 + +bitmap file converter, 1-31 +wSpec + +structure, 2-2 +wsScreenExt + +WLIB function, 2-21 +wsSelectList + +graphics output, 1-50 + +WLIB function, 2-23 +wsSetClock + +graphics output, 1-49 + +WLIB function, 3-22 +wsSetList + +graphics output, 1-50 + +WLIB function, 2-23 +wsStatus Window + +graphics output, 1-50 +wStartCompute + +priority, 1-17 + +WLIB function, 2-8 +wStartup + +WLIB function, 2-1 +wStatus Window + +status window permanent set, 2-21 +wsUpdate + +graphics output, 1-50 + +WLIB function, 2-22 +wsupportInfo + +WLIB function, 2-26 +wsystem + +process, 1-55 + +WLIB function, 2-24 +wsystemModal + +system modal, 1-17 + +WLIB function, 2-9 +wTextCursor + +cursor WLIB function, 1-29 + +graphics output, 1-49 + +WLIB function, 3-12 +wUserMsg + +WLIB function, 5-10 +wValidateRect + +WLIB function, 1-25, 3-11, 3-12 +wValidateWin + +WLIB function, 1-25, 3-11 + + +WINDOW SERVER REFERENCE + + +wWindowPosition +window position set, 1-27 +WLIB function, 3-7 + + +xxii + + diff --git a/docs/2-03 IO Devices Reference 2.30_djvu.txt b/docs/2-03 IO Devices Reference 2.30_djvu.txt new file mode 100755 index 0000000..d3ab4df --- /dev/null +++ b/docs/2-03 IO Devices Reference 2.30_djvu.txt @@ -0,0 +1,14945 @@ +SIBO 'C' Software Development Kit + + +I/O DEVICES REFERENCE + + +Version 2.30 + + +March 1, 1999 + + +(C) Copyright Psion PLC 1990-97 + + +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, Psion Series 3c, Psion Siena and Psion Workabout are trademarks of Psion PLC. + + +TopSpeed is a registered trademark of Clarion Software Corporation. Intel 8086 and 80286 are registered +trademarks of Intel 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 Introduction + + +Conventions used in this manual + + +2 Console + + +Introduction + + +Automatic opening of a console channel +Explicit opening of a console channel +P_FSET service call convention + +Panics + + +Console services + + +Open the console (p_open) + +Close the console (p_close) + +Write to the console (p_write) + +Read a keypress (P_LFREAD) + +Cancel an outstanding read (P_FCANCEL) + +Test for outstanding keypresses (P_FTEST) + +Flush keyboard buffer (P_FFLUSH) + +Edit a string (P_FEDIT) + +Sense console data (P_FSENSE) + +Set the console window size (P_FSET, P_SCR_WSET) +Scroll the window content (P_LSCR_SCROLL) + +Clear a rectangle (P_FSET, P_SCR_CLR) + +Position cursor to next line (P_FSET, P_SCR_NEL) + +Set the cursor position (absolute) (P_LFSET, P_SCR_POSA) +Set the cursor position (relative) (P_LFSET, P_SCR_POSR) +Turn the cursor on or off (P_FSET, P_SCR_CURSOR) +Set scroll lock (P_LFSET, P_LSCR_SLOCK) + +Set auto wrap (P_FSET, P_SCR_WLOCK) + +Set escape on or off (P_FSET, P_SCR_ESCAPE) + +Set compatibility on or off (P_FSET, P_LSCR_COMPATIBILITY) +Set the use of grey on or off (P_LFSET, P_LSCR_GREY) + + +Additional console services + + +Read an event (PLEVENT_READ) + +Test for outstanding event (P_LEVENT_TEST) + +Get console data (P_FINQ) + +Flush window server buffer (P_FWFLUSH) + +Set the console output rectangle (P_FSET, P_SCR_CSET) + +Set character attributes (P_FSET, P_SCR_ATTRB) + +Set the screen font (P_FSET, P_SCR_FONT) + +Set the last line wrap (P_FSET, P_SCR_LAST_LINE_WRAP) +Set window server flushing (P_FSET, P_SCR_FLUSH) +Disable reads (P_FSET, P_SCR_DISABLE READS) + +Bring to foreground (P_FSET, P_SCR_CLIENT_FOREGROUND) +Capture a key (P_LFSET, P_SCR_CAPTURE_KEY) + + +Cancel a key capture (P_LFSET, PLSCR_CANCEL_CAPTURE_KEY) +Example + + +3 Parallel Port + + +Introduction + + +Parallel port device names +Panics + + +Ww & +ae es + + +Parallel port services + + +Open a parallel port (p_open) + +Close a parallel port (p_close) + +Write to a parallel port (P_FWRITE) +Cancel a write request (P_FCANCEL) +Sense the input control lines (P_FSENSE) +Write the output control lines (P_FSET) + + +Example + + +Introduction + + +Serial port device names +Panics + + +Serial port parameters + + +Baud rate + +Character frame +Parity + +Handshaking + +Control flags +Terminator characters + + +Serial port errors +Serial port services + + +Open a serial port (p_open) + +Close a serial port (p_close) + +Read from the serial port (P_FREAD) + +Write to the serial port (P_FWRITE) + +Cancel any outstanding requests (P_FCANCEL) +Sense the serial port characteristics (P_FSENSE) +Set the serial port characteristics (P_FSET) +Flush the read buffer (P_FFLUSH) + +Test for received characters (P_FTEST) + +Test and set control lines (P_FCTRL) + +Inquire supported serial characteristics (P_FINQ) + + +Introduction + + +Sound on MC and HC machines +Sound on Series 3 machines +Sound on Series 3a machines +Panics + + +Sound services + + +Open the sound channel (p_open) + +Close the sound channel (p_close) + +Cancel a write request (P_FCANCEL) +Sense sound characteristics (P_FSENSE) +Set sound characteristics (P_FSET) +Write alarm note sequence (E_LFALARM) + + +HC, MC and Series 3a additional sound service + + +Write to voice n (E_LFSSOUNDCHANNELn) + + +Series 3 and Series 3a additional sound service + + +Write DTMF dial tones (E_FDIAL) + + +Example + + +1/0 DEVICES REFERENCE + + +WwW WW WW WwW W +WNHONNNR RR + + +4 Serial Port + + +5 Sound + + +NNANAAnAnNnaannannnnnann +r + + +ABRRBOBBWNNHNNHNNHNKRHR SEE + + +ii + + +CONTENTS + + +6 The Alarm Device Driver 6-1 +Introduction 6-1 + +Panics 6-2 + +Series 3, Series 3a and MC alarm services 6-2 + +Open the alarm channel (p_open) 6-2 + +Close the alarm channel (p_close) 6-2 + +Cancel an alarm request (P_FCANCEL) 6-2 + +Queue a timed alarm (A_FTIMED) 6-2 + +Queue an untimed alarm (A_FUNTIMED) 6-3 + +Series 3a additional alarm services 6-3 + +Queue a Series 3a timed alarm (A_FTIMED_X) 6-3 + +Queue a Series 3a untimed alarm (A_FUNTIMED_X) 6-4 + +7 The Free-Running Counter 7-1 +Introduction 7-1 + +FRC services 7-1 + +Open the FRC channel (p_open) 7-1 + +Close the FRC channel (p_close) 7-2 + +Cancel the FRC request (P_FCANCEL) 7-2 + +Start the free-running counter (A_FTIMED) 7-2 + +Read the elapsed time in ELFRC_COUNTING mode (P_FREAD) 7-2 + +Read the elapsed time in E_-FRC_REPEATING mode (P_FREAD) 7-3 + +8 The Series 3 World Database 8-1 +Introduction 8-1 + +Mode 8-1 + +Series 3 and Series 3a World database services 8-2 + +Open the World channel (p_open) 8-2 + +Close the World channel (p_close) 8-2 + +Cancel a World request (P_FCANCEL) 8-2 + +Find by city (WR_FIND_CITY) 8-2 + +Find by country (WR_FIND_COUNTRY) 8-2 + + +Find by city and country (WR_FIND_EXACT) 8-3 +Find next city (WR_NEXT) 8-3 +Find previous city (WR_BACK) 8-3 +Find home city (WR_GET_HOME) 8-3 +Set home city (WR_SET_HOME) 8-3 +Find default country (WR_GET_DEFAULT_COUNTRY) 8-4 +Set default country (WR_SET_DEFAULT_COUNTRY) 8-4 + + +Get dial string (WR_GET_DIAL_STRING) 8-4 +Open file for additional data (WR_SET_EXTRA) 8-5 +Modify additional data (WR_EXTRA) 8-5 +Read city data (WR_GET_CITY_DATA) 8-6 +Read city data (WR_GET_COUNTRY_DATA) 8-7 +Calculate distance, sunrise and sunset (WR_CALC) 8-8 +Read next city name (WR_NEXT_LOCK) 8-9 +World file types and their locations 8-9 +Main World file 8-9 +World Extension file 8-9 +World File format 8-9 +World Extension File format 8-10 +File header 8-10 +Data block 8-10 + + +iii + + +I/O DEVICES REFERENCE + + +9 Xmodem and Ymodem + + +Introduction +Data transfer protocols overview +One byte checksum +Two byte Cyclic Redundancy Check (CRC) +The Xmodem protocol +Link establishment +The data transfer phase +Link termination +Checksum data flow showing error recovery +The CRC variant +CRC data flow showing error recovery +The 1K variant +The 1K option data flow +Abandoning a transfer +The Ymodem protocol +Link establishment +The data transfer phase +Link termination +Ymodem file transfer data flow +The 1K variant +The G variant +Ymodem-G file transfer data flow +Abandoning a transfer +Protocol problems +Xmodem/Ymodem services +Open an Xmodem/Ymodem channel (p_open) +Close the Xmodem channel (p_close) +Connect to the remote computer (P_FCONNECT) +Disconnect from the remote computer P_FDISCONNECT) +Read data from the remote computer (P_FREAD) +Write data to the remote computer (P_FWRITE) + + +10 NCP and Link + + +iv + + +Introduction +Panics + +The Psion logical link layer protocol + +The SYS$NCP process +Connection establishment +Data transfer + +The LINK process + +NCP services +Open an NCP channel (p_open) +Close the NCP channel (p_close) +Connect to a remote process (P_FCONNECT) +Disconnect from the remote process (P_FDISCONNECT) +Read data from the remote process (P_LFREAD) +Write data to the remote process (P_FWRITE) +Cancel any outstanding request (P_FCANCEL) +Read supervisory information (P_FRSUPER) +Respond to a supervisory message (P_FINQ) +Sense the current channel activity (P_FSENSE) +Request the SYS$NCP terminate (P_FSTOP) + +Example + + +° +— + + +XO 0 0 O_O OO O_O SOO SO 0 XO +BBWWWWNNN DN RRR + + +Ne) +I I I I I I I +aN + + +KH HB woeomOUNUUADAUUY + + +So +Neo + + +11 Cradle and Docking Station + + +Introduction + +Cradle/Docking Station services +Open the device (p_open) +Close the channel (p_close) +Read from the device (P_FREAD) +Cancel a read (P_LFCANCEL) +Set the device type (P_FSET) +Sense the device type (P_FSENSE) + + +12 HC Magnetic Card Reader + + +Introduction +Open the MCR device (p_open) +Close the channel (p_close) +Read from the MCR device (P_FREAD) +Cancel a read (P_LFCANCEL) +Set the pull-up resistors (P_FSET) + + +13 HC Bar Code Reader + + +Hardware Description + +The Bar code reader interface module + +The bar code reader wand. + +Device drivers + +Bar code driver services +Open the bar code device (p_open) +Close the channel (p_close) +Read from the MCR device (P_FREAD) +Cancel a read (P_LFCANCEL) + + +14 HC Intelligent Bar Code Reader/RS232 Port + + +RS232/intelligent bar code reader module +The RS232 serial port interface +Power consumption +Powering the HC from an external power source +DSR auto wakeup switch +The bar code interface +Power consumption +Powering a bar code wand from the HC +Bar code symbologies +Code 128 +Codabar +Interleaved 2 of 5 +Code 39 +The UPC/EAN bar code formats +UPC E +UPC E + 2 digits +UPC E + 5 digits +EAN 8 bar code format +EAN 8 + 2 digits +EAN 8 + 5 digits +EAN 13 +EAN 13 + 2 digits +EAN 13 + 5 digits +UPC A +UPC A + 2 digits +UPC A + 5 digits + + +CONTENTS + + +I/O DEVICES REFERENCE + + +Bar code commands +Multiple options in a command +Issuing multiple commands +Serial intercharacter delay +Hard reset +Select bar code symbology +Check character options +Decoding options +Single read mode +Single read control +Set Interleaved 2 of 5 length +Set termination string +Code ID characters +Status request +Scanner enable + +RS232 port/bar code driver services +Open the device (p_open) +Close the channel (p_close) + + +Sense serial port characteristics (P_FSENSE) + + +Set serial port characteristics (P_FSET) +Read from device (P_FREAD) +Write to device (P_FWRITE) + +An example program + + +15 Introduction to Psion Infrared Communications + + +About this chapter +The IrDA protocol layer model +Introduction to Psion infrared communications +The Psion protocol layer model +The physical layer +Port geometry +Data transfer rate +Data link layer +Primary and secondary stations +IrLAP services +The network layer +IAS application logging +Discovery +Multiplexing +Link Control +The Psion IR Communications application +Third party applications +System resources +Keypresses +The IR printer port device driver + + +16 The AccessIr API + + +Using the AccessIr API +Prerequisites +Introduction to using the AccessIr API +Initialising the IR protocol stack + + +Opening and closing a channel to the IR device + + +Discovery + +Selection + +Connection + +Sending and accepting data +Disconnection + +Constants + + +CONTENTS + + +Opening and closing a channel to the IR device 16-3 +Open a channel to the IR device (p_open) 16-3 +Close a channel to the IR device (p_close) 16-4 + +Discovery, selection and connection 16-4 + +Discover IR enabled machines (P_FIRDISCOVER) 16-4 + +Select remote machine to connect to (P_FIRSELECT) 16-4 + +Connect to selected machine (P_FIRMAKECONNECT) 16-5 + +Wait for remote connect (primary) (P_FIRAWAITCONNECT) 16-5 + +Send and accept data 16-6 + +Accept data from selected remote machine (P_FREAD) 16-6 + +Send data to the selected remote machine (P_FWRITE) 16-6 + +Disconnection 16-6 + +Disconnect from remote machine (P_FIRDISCONNECT) 16-6 + +Example application 16-7 + +17 The IrMUX API 17-1 + +Using the IrMUX API 17-1 +Prerequisites 17-1 +Introduction to using the ITMUX API 17-1 +Initialising the IR protocol stack 17-1 +Logging on to and logging off from the ITMUX server 17-2 +Registering/unregistering applications with the LM-IAS server 17-2 +LM-IAS services 17-2 + +The IAS Get Value By Class message frame 17-3 +The IAS Get Value By Class reply frame 17-3 +Connectionless calls 17-3 +Reading and writing data 17-3 +Connection-oriented calls 17-3 +Discovery 17-4 +Connection - first time 17-4 +Disconnecting - first time 17-4 +Connection - second time 17-4 +Reading and writing data 17-4 +Disconnecting - second time 17-4 +Using Exclusive mode 17-4 +The IrMUX API 17-5 +IrMUX message format 17-5 +Log on to the IrMUX server (LM_Logon) 17-5 +Log off from the ITMUX server (LM_Logoff) 17-5 +Register a port number with the LM-IAS server (LM_RegisterPort) 17-5 +Free registered port with LM-IAS server (LM_UnRegisterPort) 17-6 +Queue a connectionless read request (LM_CLReadRequest) 17-6 +Queue a connectionless write request (LM_CLWriteRequest) 17-7 +Return info on in-range machines (LM_DiscoverDevicesRequest) 17-7 +Attempt to connect to a remote machine (LM_ConnectRequest) 17-7 +Wait for remote machine to connect (LM_WaitForConnection) 17-8 +Return the status of the link (LM_StatusRequest) 17-9 +Queue a read request on a connection (LM_ReadRequest) 17-9 +Queue a write request on a connection (LM_WriteRequest) 17-10 +Queue an unreliable read request (LM_UReadRequest) 17-10 +Queue an unreliable write request (LM_UWriteRequest) 17-11 +Obtain/release exclusive access (LM_AccessModeRequest) 17-11 +Place the connection into Idle/Active mode (LM_IdleRequest) 17-12 +Set retries on each data frame (LM_SetHandshakingLevel) 17-12 +Disconnect (LM_DisconnectRequest) 17-13 + + +1/0 DEVICES REFERENCE + + +18 Fast Charger + + +Introduction +Docking Station services + +HC/Workabout docking station fast charger services + +Fast charging batteries + +Measuring battery capacity +Rated charge capacity of standard Psion battery packs +Example calculations +Open the fast charger device (p_open) +Close the channel (p_close) +Set the battery charge mode (FCHG_SETCHARGEMODE) +Charging Psion battery packs +Charging custom battery packs +Read battery charge mode (FCHG_READCHARGEMODE) +Read the battery status (FCHG_READSTATUS) +Read the battery status asynchronously (FCHG_ASYNCHREAD) +Cancel an asynchronous read (FCHG_CANCEL) +Fast charge the main battery (FCHG_FASTCHARGE1) +Fast charge the spare battery (FCHG_FASTCHARGE2) +Discharge the main battery (FCHG_DISCHARGE1) +Example program + + +18-1 +18-1 +18-1 +18-2 +18-3 +18-3 +18-3 +18-3 +18-4 +18-4 +18-4 +18-5 +18-6 +18-6 +18-7 +18-7 +18-7 +18-7 +18-8 +18-8 + + +CHAPTER 1 + + +INTRODUCTION + + +This manual describes the I/O device drivers that have been written by Psion, except for the files device +driver and the the asynchronous timer device driver which are described in the Files and the Time, +Timers and Dates chapters of the PLIB Reference manual. + + +Before using any of the devices described in this manual the reader should be familiar with the contents of +the Asynchronous Requests and Semaphores and the I/O System chapters of the PLIB Reference manual. + + +Conventions used in this manual + + +I/O devices support a number of services, each specified by a function number of the form P_Fxxxx +(defined in p_file.h). For example, to write to a channel opened with a control block at *pcb, you may call: + + +p_ioc(pcb,P_FWRITE, additional parameters) ; +The notation p_ioc(P_FWRITE) or, more simply, P_FWRITE is used to refer to this function call. + + +All I/O function requests are asynchronous in principle. In practice, however, many I/O requests are +implemented synchronously, that is, the I/O operation will complete before the service call returns. For +example, the P_FCLOSE service is always implemented synchronously but the p_rREaD service is commonly +implemented asynchronously. + + +The description of a service that is implemented synchronously gives either the specific synchronous call +(such as p_open or p_close) or the p_iow service call prototype. Services implemented synchronously are +prototyped using only the p_iow I/O primitive, since there is no advantage in calling them +asynchronously. + + +A service that is implemented asynchronously may be called synchronously or asynchronously. The +description gives both the synchronous call (as described above) and the asynchronous p_ioc service call +prototype. Such a service may be called using the p_iow, p_ioc or p_ioa primitives. Note that the use of +p_ioc is in almost all cases preferable to the use of p_ioa (since the former will complete even in the +event of an error). + + +Note that smaller code will be generated by use of the primitives: + + +p_iow2, p_iow3, p_iow4, p_iow5, +p_ioc3, p_ioc4, p_ioc5d, +p_ioa3, p_ioa4, p_ioad. + + +Again the use of, for example, p_ioc3 is in almost all cases preferable to the use of p_ioa3. The same +statement applies to the other two variants of each function. + + +CHAPTER 2 + + +CONSOLE + + +Introduction + + +The console (con: ) device provides a basic set of screen and keyboard services, suitable for use by +relatively simple character-based C application programs. OPL programs automatically open a console +channel to provide support for the screen display and keyboard commands. + + +The console device is implemented differently on different machines in the SIBO range: +e on the HC and Series 3 machines the console device connects directly to the window server. + + +e onthe MC 200 and MC 400 machines the console device is implemented by an intermediate +sysscons display process. + + +There are also some differences in the services that are available on different machines. These differences +are stated in the description of the particular service to which they apply. + + +Some of the console functions use the P_PoINT, P_RECT and P_REcTP structures. They are defined in +p_graf.h (which is included by p_cons.h) as: + + +typedef struct +{ +WORD x; /* x coordinate */ +WORD y; /* y coordinate */ +} P_POINT; + + +typedef struct +{ +P_POINT tl; /* top left coordinates */ +P_POINT br; /* bottom right coordinates */ +} P_RECT; + + +typedef struct +{ +P_RECT r; /* rectangle */ +P_POINT p; /* point */ +} P_RECTP; + + +Co-ordinates are measured from the top left corner of the window (0, 0), and increment to the right (x) +and down (y). Co-ordinates are measured in character units. + + +When rectangles are specified the top left point is included in the rectangle and the bottom right corner is +just outside the rectangle. If a rectangle extends outside the console window then it is clipped to fit inside +the window (this feature may be used to save sensing the size of the window when a scroll or clear is +required up to the right/bottom edge of the window). + + +Versions of EPOC prior to version 2.32 do not support the opening of a console device when the +application program's total memory usage exceeds 32k. + + +I/O DEVICES REFERENCE + + +Automatic opening of a console channel + + +A channel to the console device is opened automatically during the start-up initialisation of a C program +built with the CLIB start-up module. This does not occur in the case of programs built with the PLIB +start-up module. + + +In PLIB programs, however, the console (if not already open) is opened automatically by the first use of +one of the PLIB simple console I/O functions (p_getch, p_printf, etc.) described in the //O System +chapter of the PLIB Reference manual. + + +The console channel handle of an automatically opened console device channel is stored in the pre- +defined static winHandle. + + +An automatically opened console is set to a size appropriate for the SIBO machine on which the +application is running. In a PLIB program you may, however, specify the window size of an automatically +opened console by setting the global p_REcT structure _DefScreenRect, as follows: + + +GLDEF_D _DefScreenRect; + + +_DefScreenRect.tl.x=0; +_DefScreenRect.tl.y=0; +_DefScreenRect.tl1.x=40; /* 40 columns */ +_DefScreenRect.tl.x=8; /* 8 rows */ + + +An automatically opened console is also set to the native mode of the machine. On the Series 3a machine +the console is opened in non-compatibility, with access to grey. In a PLIB program you may modify the +console mode by setting the global variable _pefscreenMode. The possible modes that may be set are: + + +use the native mode of the machine - this is the default value +compatibility mode, allowing Series 3 software to run on the Series 3a +non-compatibility mode, with grey enabled + +compatibility mode, but with grey enabled + + +WN FO + + +Thus, compatibility mode may be set as follows: + + +GLDEF_D INT _DefScreenMode; +_DefScreenMode=1; + + +Values that are not relevant to a particular type of machine are simply ignored. + + +If used, the values of _DefScreenRect and _DefScreenMode must be set before the first usage of any +function that causes the console to be opened. Ignore the ‘duplication’ message generated by the linker +when this code is included in your application. + + +In CLIB programs you can prevent the automatic opening of a console channel by defining the function +p_xwind in your code, as in the following example: + + +extern void *winHandle; + + +void p_xwind (void) +{ +winHandle=(void *)1; + + +} + + +int main(void) + + +{ + + +return (0); + + +} + + +You should ignore the warning, given during the linking of your program, that the symbol _p_xwind is +duplicated. + + +2 CONSOLE + + +If you use this technique, your CLIB program should not, of course, make any reference to stdin, stdout +or stderr, unless you have redirected them. Setting winHandle to | (an illegal value for a handle) will +guarantee that any such reference will fail with a panic. + + +Explicit opening of a console channel + + +In a PLIB program you may, if you wish, explicitly open a console channel by means of p_open. The +console channel handle must be stored in the pre-defined static winHandle that is used for an +automatically opened console channel. For example: + + +GLREF_D VOID *winHandle; +p_open (&winHandle, "CON:",-1); + + +This is particularly important if your program uses any of the PLIB simple console I/O functions. +Otherwise you may inadvertently attempt to open two console channels from the same process and your +process will be panicked. + + +After explicitly opening the console and before making any other use of its services you must make it +visible by setting its size with the p_rseEt service, using the p_scr_wset function code. + + +Compatibility mode and the availability of grey can be set by means of the p_Fset service, using the +P_SCR_COMPATIBILITY and p_scr_GRey function codes. + + +P_FSET service call convention + + +The p_rset function provides a number of services, determined by a function code. The function code is +assigned to a uworp whose address is passed as the third parameter to the p_iow function. The convention: + + +INT p_iow(VOID *pcb, P_FSET, &P_SCR_CLR, P_RECT *prect); +is used to denote this. It should be interpreted as: +UWORD function; + + +function = P_SCR_CLR; +p_iow (pcb, P_FSET, &function,prect) ; + + +or equivalent. + + +Panics + + +All services (with the exception of p_open) will cause the calling process to be panicked if the passed +channel handle is not valid. Other panics are described under the particular service to which they apply. + + +SSS ee +Console services + + +p_open(CON:) Open the console +INT p_open(VOID **ppcb, CON:, -1); + + +Open a channel to the console device, writing the channel handle to *ppcb if successful. The console +window is not made visible until its size has been set by the p_rset service with a function code of +P_SCR_WSET. + + +When first opened the console properties are: +e auto wrap on +e auto flushing on +e — scroll lock off +e cursor display off +e pause key sequence enabled +e exit key sequence enabled (escape on) + + +e last line wrap (not available on MC) off + + +I/O DEVICES REFERENCE + + +It is recommended that ppcb should be the address of the pre-defined static winHandle, as in the +following example: + + +GLREF_D VOID *winHandle; + + +LOCAL_D UWORD func; +LOCAL_D INT err; + + +if ((err=p_open (&winHandle, "CON:",-1)) !=0) +{ +fail: +p_notifyerr(err,"Failed to open console",NULL, NULL, NULL) ; +p_exit (0); +} + +/* set the screen size */ + +rect.tl.x = rect.tl.y = 0; + +rect.br.x 257 + +rect.br.y = 9; + +func = P_SCR_WSET; + +if ((err=p_iow4 (winHandle, P_FSET, &func, &rect) ) !=0) +{ + + +p_close(winHandle) ; + + +goto fail; +} + + +You should not open the console yourself if your program is built with the CLIB start-up module. +The calling process is panicked if it already has an open channel to the console. + + +Returns zero if successful, or the negative error E_FILE_ALLOc if it failed to allocate memory for the +channel control block. In versions of EPOC prior to version 2.32, p_open("con:") will fail (and return a +negative number) if the total application memory usage exceeds 32k. + + +p_close Close the console +INT p_close(VOID *pcb) ; +Close the channel to the console. + + +Returns zero. + + +p_write Write to the console + + +INT p_write(VOID *pcb, UBYTE *buf, UWORD len); + + +Write len bytes of data from buf to the screen, starting at the current column (x coordinate) in the current +line (y coordinate). The value of 1en must be less than or equal to 255. + + +The request will always return immediately (but the text may not appear immediately if auto flushing is +turned off) and there is no advantage in calling this service in any way other than with p_write. + + +Characters are printed directly on the screen unless they are one of: + + +BELL sound the bell (buzzer) + +TAB go to the next tab stop (tabs are every 8 characters) +BS backspace + +CR move the cursor to the beginning of the current line +LF, VT move the cursor down one line + +FF move the cursor down one screen + + +2 CONSOLE + + +If there are more characters in buf than will fit on the current line, the writing of the additional characters +depends on the auto wrap and scroll states as set by the p_rsEt service with function codes p_scR_WLOCK +and p_SCR_SLOCK: + + +e if auto wrap is on then any additional characters in buf are written from character position zero +in the following line. If this following line is off the screen then the screen will first be scrolled +up by one line, provided scroll lock is off. + + +e if auto wrap is off then the additional characters in buf successively overwrite the last character +in the line. On completion of the write request the last character in the row will therefore be the +final character in but. This assumes, of course, that there are no cursor movement characters in +buf. + + +The request cannot fail and so the function call always returns zero. + + +P_ FREAD Read a keypress + + +INT p_iow(VOID *pcb, P_FREAD, P_CON_KBREC *kbrec);_.VOID p_ioc(VOID *pcb, P_FREAD, WORD +*pstat, P_CON_KBREC *kbrec) ; + + +RRead a keypress record into the p_con_KBRECc struct pointed to by kbrec. The p_con_KBREC Struct is +defined in p_cons.h as: + + +typedef struct +{ + + +UWORD keycode; /* Code for the key pressed */ +UBYTE modifiers; /* State shift keys etc */ +UBYTE count; /* Used to accumulate auto-repeat counts */ + + +} P_CON_KBREC; + + +The content of modifiers is a set of bit flags indicating which modifier keys were held down when a key +was pressed: + + +W_SHIFT_MODIFIER SHIFT key down +W_CTRL_MODIFIER CONTROL key down +W_PSION_MODIFIER PSION key down +W_CAPS_MODIFIER Caps lock on + + +W_NUM_LOCK_MODIFIER Num lock on + + +The content of keycode for a standard keypress is simply its ASCII character code. There are also many +special values that the keycode can provide, corresponding to particular keypresses or keypress +combinations. These are fully described in the Events chapter of the Window Server Reference manual. + + +A P_FREAD request will not complete until either there is an outstanding keypress to read or the request is +cancelled. A synchronous request may therefore take an indefinitely long time to return. A prior +p_iow(P_FTEST) call will determine if there is an outstanding keypress. + + +The calling process is panicked if pcb is not a valid channel handle, or if there is an outstanding p_rFREAD +(Or P_EVENT_READ) request. + + +The completion status code is returned by the synchronous p_iow(P_FREAD) and written to *pstat by +asynchronous calls. The completion status code is zero if the p_rREAD request completed successfully, or +the negative error &_FILE_CANCEL if the request was cancelled by a p_FcaANCEL request. + + +P_FCANCEL Cancel an outstanding read +INT p_iow(VOID *pcb, P_FCANCEL) ; +Cancel an outstanding read; the request is harmless if there are no reads outstanding. + + +The request cannot fail and always returns zero. + + +P_FTEST Test for outstanding keypresses +INT p_iow(VOID *pcb, P_FTEST, UWORD *pflag); +Set *pflag to TRUE if there are any keypresses outstanding, otherwise set it to FALSE. + + +The request cannot fail and always returns zero. + + +1/0 DEVICES REFERENCE + + +P_FFLUSH Flush keyboard buffer +INT p_iow(VOID *pcb, P_FFLUSH) ; +Flush the keyboard buffer, all key presses held in the buffer are discarded. + + +The request cannot fail and always returns zero. + + +P_FEDIT Edit a string + + +INT p_iow(VOID *pcb, P_FEDIT, P_CEDIT *cedit, UWORD *plen); +Edit a string. The p_cepiT struct is defined in p_screen.h as: + + +typedef struct +{ + + +UBYTE cursorpos; /* not used */ + +UBYTE trap; /* trap input errors or not */ +UBYTE string[P_MAXEDITSTR]; /* string to edit */ + +} P_CEDIT; + + +Allows the user to edit the text in string. The cursor is initially positioned at the end of the string. The +user is not allowed to expand the string beyond *plen characters (string must be initially not more than +*plen characters in length). Since *plen does not include the terminating zero, its value must be Jess than +P_MAXEDITSTR (256). + + +Pressing the left or right arrow keys moves the cursor one character to the left or right in the string. The +HOME and END keys move the cursor to the start and end of the string. + + +Pressing Esc clears the content of the string. The value of trap determines what happens if Esc is pressed +when the string is already clear. If trap is TRUE, then the editing operation will complete with string +unchanged, if trap is FALSE then nothing will happen. + + +Returns zero, or E_LFILE_CANCEL if editing is terminated by pressing Esc. + + +P_FSENSE Sense console data + + +INT p_iow(VOID *pcb, P_FSENSE, P_RECTP *prectp) ; + + +Write the cursor position to (prectp->p.x,prectp->p.y) and write the window co-ordinates to prectp- +>x. The window co-ordinates are those specified by the most recent prior call to P_rsET with function code +P_SCR_WSET or P_SCR_CSET. + + +For example: + + +LOCAL_C VOID SenseConsole (VOID) + + +{ +P_RECTP rectp; +WORD x_pos, y_pos, width, height; + + +p_iow (winHandle, P_FSENSE, &rectp) ; +X_pos = rectp.p.x; + +y_pos = rectp.p.y; + +width = rectp.r.br.x - rectp.r.tl.x; +height = rectp.r.br.y - rectp.r.tl.y; + + +/* do something with the coordinates here */ + + +} + + +The request cannot fail and always returns zero. + + +2 CONSOLE + + +P_FSET, P_SCR_WSET Set the console window size + + +INT p_iow(VOID *pcb, P_FSET, &P_SCR_WSET, P_RECT *prect); + + +Set the console window size. A p_rEcT structure is used for historical reasons; in practice prect- +>rect .t1 should always be (0,0). For example, to set the console size to 9 lines high by 25 columns wide +(the full screen size for HC machines) you should use: + + +P_RECT rect; +UWORD func; + + +rect.tl.x rect.tl.y = 0; +rect.br.x = 25; + +rect.br.y = 9; + +func = P_SCR_WSET; + + +p_iow(winHandle, P_FSET, &func, &rect) ; + + +Returns zero if successful, otherwise the error =_GEN_NomEmory if unable to create a window of the new size. + + +P_FSET, P_SCR_SCROLL Scroll the window content + + +INT p_iow(VOID *pcb, P_FSET, &P_SCR_SCROLL, P_RECTP *pscrl)j; + + +Scroll the rectangle pscri->r by the vector amount (pscr1->p.x,pscrl->p.y). The area left behind the +trailing edge(s) is cleared. Scrolling a rectangle is not affected by setting or clearing the scroll lock. + + +pscrl->r describes the rectangle to scroll; +pscrl->p.x gives the horizontal distance to scroll (negative left, positive right); +pscrl->p.y gives the vertical distance to scroll (negative up, positive down). + + +For example: + + +LOCAL_C VOID scroll(WORD amnt_v, WORD amnt_h) + +/* scroll the whole window vertically amnt_v and horizontally amnt_h */ +{ +UWORD func; +P_RECTP scrl; + + +p_iow(winHandle, P_FSENSE, &scrl); + + +scrl.r.br.x -= scrl.r.tl.x; +scrilsr.br vy == serlar.tl.y; +scrl.r.tl.x = 0; +scrl.r.tl.y = 0; + +scrl.p.x = amnt_h; + +scrl.p.y = amnt_v; + +func = P_SCR_SCROLL; + + +p_iow(winHandle, P_FSET, &éfunc, &éscrl) ; +} + + +Returns zero. + + +P_FSET, P_SCR_CLR Clear a rectangle + + +INT p_iow(VOID *pcb, P_FSET, &P_SCR_CLR, P_RECT *prect); + + +Clear the rectangle *prect. If *prect extends outside the console window then it is clipped so that only +the part that intersects with the window is cleared. + + +For example: + + +LOCAL_C VOID clear(P_RECT *prect) +{ +INT func; + + +func = P_SCR_CLR; +p_iow(winHandle, P_FSET, &éfunc,prect) ; +} + + +Returns zero. + + +I/O DEVICES REFERENCE + + +P_ FSET, P_SCR_NEL Position cursor to next line + + +INT p_iow(VOID *pcb, P_FSET, &P_SCR_NEL) ; + + +Move the cursor position to the first column on the next line. If the current row is the bottom row then, +provided scroll lock is not set, the window image scrolls up. + + +Returns zero. + + +P_FSET, P_SCR_POSA Set the cursor position (absolute) + + +INT p_iow(VOID *pcb, P_FSET, &P_SCR_POSA, P_POINT *ppoint); + + +Position the cursor to the point *ppoint. If *ppoint is outside the window the cursor moves to the the +position in the window closest to *ppoint. + + +Returns zero. + + +P_FSET, P_SCR_POSR Set the cursor position (relative) + + +INT p_iow(VOID *pcb, P_FSET, &P_SCR_POSR, P_POINT *ppoint); + + +Position the cursor by adding the displacement *ppoint to its current co-ordinates. If *ppoint is outside +the window the cursor moves to the the position in the window closest to *ppoint. + + +Returns zero. + + +P_FSET, P SCR_CURSOR Turn the cursor on or off + + +INT p_iow(VOID *pcb, P_FSET, &P_SCR_CURSOR, UWORD *pflag); +Turn the cursor off if *pflag is FALSE, turn it on if *pflag is TRUE. + + +Turning the cursor on or off has no affect on the screen driver output other than enabling or disabling the +display of the cursor. + + +Returns zero. + + +P_FSET, P_ SCR_SLOCK Set scroll lock + + +INT p_iow(VOID *pcb, P_FSET, &P_SCR_SLOCK, UWORD *pflag); +Turn scroll lock off if *pflag is FALSE, turn it on if *pflag is TRUE. + + +When scroll lock is on scrolling of the console (caused by either P_scR_NEL or p_write) is disabled. It has +no effect on scrolling by means of P_rsET with function code P_SCR_SCROLL. + + +Returns zero. + + +P_FSET, P_SCR_WLOCK Set auto wrap + + +INT p_iow(VOID *pcb, P_FSET, &P_SCR_WLOCK, UWORD *pflag); +Turn auto wrap off if *pflag is FALSE, turn it on if *pflag 1s TRUE. + + +If auto wrap is off then character printing by p_write stops at the right margin, with further characters +successively overwriting the last character in the line. If auto wrap is on then trying to write a character +beyond the end of the line causes the cursor to move to the start of the next line. If the cursor is in the last +line of the window (and scroll lock is off) this will cause a scroll. + + +Returns zero. + + +2 CONSOLE + + +P_FSET, P_ SCR_ESCAPE Set escape on or off + + +INT p_iow(VOID *pcb, P_FSET, &P_SCR_ESCAPE, UWORD *pflag); +Turn escape handling off if *pf1ag is FALSE, turn it on if *pflag iS TRUE. + + +If escape handling is off then the user will not be able to use the exit key sequence to exit the console +application. The exit key sequence is PSION-ESC on HC and Series 3 machines, PSION-E on (English- +language) MC machines (PSION-? on foriegn language MCs, where ? is a character that depends on the +language). Additionally, on MC machines, the stop menu button will be disabled when escape is off. + + +Escape handling is initially on. + + +Returns zero. + + +P_FSET, P_SCR_COMPATIBILITY Set compatibility on or off + + +INT p_iow(VOID *pcb, P_FSET, &P_SCR_COMPATIBILITY, UWORD *pflag); +This function code is only available on machines that contain version 4, or later, of the window server. +Turn compatibility off if *pf1ag is FALSE, turn it on if *pflag iS TRUE. + +If compatibility is turned on, all drawing to the screen of the Series 3a is performed in double pixel mode. +On Series 3a machines, compatibility mode is initially on. + +Returns zero. + + +Note: A tru value of *pf1ag must be the value 1. Any other non-zero value may be interpreted differently +on future machines. + + +P_FSET, P_SCR_GREY Set the use of grey on or off +INT p_iow(VOID *pcb, P_FSET, &P_SCR_GREY, UWORD *pflag); + +This function code is only available on machines that contain version 4, or later, of the window server. +Turn the use of grey off if *pfiag 1s FALSE, turn it on if *pflag iS TRUE. + +On Series 3a machines, the use of grey is initially off. + + +Returns zero. + + +Additional console services + + +The following services have been implemented to support OPL/g on HC and Series 3 machines. They are +not available on machines in the MC range. + + +If your application is sufficiently complex to require these services it is recommended that you consider +writing it as a window server application rather than using the console device. + + +P_EVENT READ Read an event + + +INT p_iow(VOID *pcb, P_EVENT_READ, P_CON_KBREC *kbrec) ; +VOID p_ioc(VOID *pcb, P_EVENT_READ, WORD *pstat, P_CON_KBREC *kbrec) ; + + +RRead an event record (including keypress events) into the p_con_KBrREc struct pointed to by kbrec. The +P_CON_KBREC Struct is defined in p_cons.h as: + + +typedef struct +{ + + +UWORD keycode; /* Code for the key pressed */ +UBYTE modifiers; /* State shift keys etc */ +UBYTE count; /* Used to accumulate auto-repeat counts */ + + +} P_CON_KBREC; + + +I/O DEVICES REFERENCE + + +If the event was a keypress (a wM_KEy event) the result is exactly as for a P_FREAD request, described +earlier. + + +Other window server events result in one of the following values being written to keycode: + + +CONS_EVENT_FOREGROUND received a WM_FOREGROUND event +CONS_EVENT_BACKGROUND received a WM_BACKGROUND event +CONS_EVENT_ON_OFF received a WM_ON event +CONS_EVENT_COMMAND received a WM_COMMAND event + + +Future versions of the console device may report additional event types. Applications should be written to +ignore event types other than those listed above. + + +A P_EVENT_READ request will not complete until either an event is received or the request is cancelled. A +synchronous request may therefore take an indefinitely long time to return. A prior p_iow (P_EVENT_TEST) +call will determine if there is an outstanding event to be read. + + +The calling process is panicked if pcb is not a valid channel handle, or if there is an outstanding +P_EVENT_READ (or P_FREAD) request. + + +The completion status code is returned by the synchronous p_iow(P_EVENT_READ) and written to *pstat +by asynchronous calls. The completion status code is zero if the P_LEVENT_READ request completed +successfully, or the negative error E_LFILE_CANCEL if the request was cancelled by a P_FcANCEL request. + + +P_EVENT_ TEST Test for outstanding event + + +INT p_iow(VOID *pcb, P_EVENT_TEST, UWORD *pflag); + + +Set *pflag to TRUE if there are any events (including keypress events) outstanding, otherwise set it to +FALSE. + + +The request cannot fail and always returns zero. + + +P_FINQ Get console data + + +INT p_iow(VOID *pcb, P_FINQ, CONSOLE_INFO *pinfo); + + +Return information about the window server resources used by the console. coNSOLE_iInFo is defined in +p_cons.has: + + +typedef struct +{ + + +UINT window_handle; /* window server id of the console window */ + + +UINT font_handle; /* window server id of the console font */ +UINT line_height; /* pixel height of a console line - font height + leading */ +UINT char_width; /* pixel width of a monospaced console character */ + + +} CONSOLE_INFO; + + +Returns zero. + + +P_FWFLUSH Flush window server buffer + + +INT p_iow(VOID *pcb, P_FWFLUSH) ; +Flush the commands buffered to the window server - has no effect when auto flushing is on. + + +Returns zero. + + +P_FSET, P_SCR_CSET Set the console output rectangle + + +INT p_iow(VOID *pcb, P_FSET, &P_SCR_CSET, P_RECT *prect); + + +Set the console output rectangle. All subsequent output is restricted (and wrapped) to the rectangle +described by prect within the console window. + + +Returns zero if successful, or E_GEN_aRG if any part of prect is outside the console window (i.e. either of +prect->tl.x Or prect->t1.y is less than zero, or prect->br.x Of prect->br.y respectively exceed the +width or height of the console window). + + +2-10 + + +2 CONSOLE + + +P_FSET, P_SCR_ATTRB Set character attributes + + +INT p_iow(VOID *pcb, P_FSET, &P_SCR_ATTRB, UWORD *pattrib); + + +Set the character attributes (style) to be used to display future characters written to the console. This +service permits the mixing of a number of different styles in the console window. + + +The value of *pattrib may be +P_SCR_NORMAL No additional style + + +or any combination of the bit flags: + + +P_SCR_BOLD Bold +P_SCR_REVERSE Reverse video +P_SCR_UNDLINE Underlined +P_SCR_BLINK Blinking +P_SCR_ITALIC Italics + + +It is not guaranteed that all the above attributes are supported in all versions of the console for the HC and +Series 3, but unsupported attributes are harmlessly ignored. + + +Any attribute which would have the effect of changing the width of a displayed character (such as +P_SCR_BOLD in current machines) is ignored. At the time of writing, no machine supports p_scR_BLINK. + + +For example: + + +UWORD func; +UWORD attrib; + + +p_printf("This is normal"); + +func = P_SCR_ATTRB; + +attrib = P_SCR_UNDLINE; + +p_iow (winHandle, P_FSET, &func, &attrib) ; +p_printf("This is underlined"); + +attrib = P_SCR_NORMAL; + +p_iow (winHandle, P_FSET, &func, &attrib) ; +p_printf ("Back to normal text"); + + +Returns zero. + + +P_FSET, P SCR_FONT Set the screen font + + +INT p_iow(VOID *pcb, P_FSET, &P_SCR_FONT, P_SCR_SET_FONT *pfont); + + +Set the console font and style for the entire window to those specified by the content of the +P_SCR_SET_FONT Struct pointed to by pfont. The struct is defined in p_cons.h as: + + +typedef struct +{ +UWORD id; /* font id */ +UWORD style; /* font style */ +} P_SCR_SET_FONT; + + +The allowed values for the font ia and style are those that are appropriate for setting a window server +graphics context (see the Window Server Reference manual). Note that the font must be monospaced; if +you set id to be the font id of a proportional font you should also include G_sty_mono in style. + + +For example: + + +UWORD func; +P_SCR_SET_FONT font; + + +font.id = WS_FONT_BASE; + +font.style = G_STY_MONO|G_STY_DOUBLE; +func = P_SCR_FONT; +p_iow(winHandle, P_FSET, &func, &font) ; + + +Since the size of the console window may be altered by changing the font, a call to p_rserT with function +code p_scr_Font will automatically clear and resize the console. + + +I/O DEVICES REFERENCE + + +It is not possible to mix different fonts and/or styles in the console window by means of this service. +Certain aspects of the font style may be changed using the P_FsET service with function code +P_SCR_ATTRB. + + +Returns zero. + + +P_FSET, P_SCR_LAST_ LINE WRAP Set the last line wrap + + +INT p_iow(VOID *pcb, P_FSET, &P_LAST_LINE_WRAP, UWORD *pflag); +Turn last line wrap on if *pflag is TRUE, turn it off if *pflag is FALSE. + + +If last line wrap is off then the display immediately wraps and scrolls (provided wrapping and scrolling +are not disabled) when a character is printed to the bottom right position in the console. + + +Last line wrap is initially off. + + +Returns zero. + + +P_FSET, P_SCR_FLUSH Set window server flushing + + +INT p_iow(VOID *pcb, P_FSET, &P_SCR_FLUSH, UWORD *pflag); + +Disable auto-flushing if *pflag is FALSE, enable it if *pflag is TRUE. + +Auto-flushing is initially enabled. + +When auto-flushing is enabled each window server function call is flushed immediately. + + +If auto-flushing is disabled, one or more window server function calls may be buffered. Execution of a +window server function may therefore be deferred until after the initiating function call has returned. In +such a case a function may return a window server error that was caused by an earlier, but buffered, +function call. + + +Returns zero. + + +P_FSET, P_SCR_DISABLE_READS Disable reads + + +INT p_iow(VOID *pcb, P_FSET, &P_SCR_DISABLE_READS, UWORD *pflag) ; +Disable reads if *pflag is TRUE, enable reads if *pflag iS FALSE. + + +A console application which needs to receive events directly from the window server, by calling +wGetEvent, should first disable reads. Otherwise all events are preferentially reported to the console. + + +No P_FREAD Of P_EVENT_READ request should be outstanding when this service is called and no more reads +may be performed until reads are re-enabled. + + +Initially reads are enabled. + + +Returns zero. + + +P_FSET, P_SCR_CLIENT_FOREGROUND Bring to foreground + + +INT p_iow(VOID *pcb, P_FSET, &P_SCR_CLIENT_FOREGROUND, UWORD *pid); + + +Make the process with process ID *pid the foreground process. Use a value of zero for «pid to bring the +current process to the foreground. + + +The service does nothing if the process specified by *pid does not exist. + + +Returns zero. + + +2 CONSOLE + + +P_FSET, P_SCR_CAPTURE KEY Capture a key + + +INT p_iow(VOID *pcb, P_FSET, &P_SCR_CAPTURE_KEY, CONSOLE_CAPTURE_KEY *pcapt) ; +Specify a keypress that is to be sent to the calling process, irrespective of its foreground/background status. + + +The keypress combination to be captured is specified by the content of the consoLE_CAPTURE_KEY Struct, +defined in p_cons.h as: + + +typedef struct +{ +UWORD code; +UBYTE modifier_mask; +UBYTE dont_care_mask; +} CONSOLE_CAPTURE_KEY; + + +Every time a key is pressed the window server evaluates +(key_pressed==code) && ((key_pressed_modifiersédont_care_mask) ==modifier_mask) + + +and if the result is TRuz then the keyboard event is sent to the process that specified the capture. + + +For example, + + +UWORD func; +CONSOLE_CAPTURE_KEY capture; + + +capture.code = W_SPECIAL_KEY|'a'; + +capture.modifier_mask = W_PSION_MODIFIER; +capture.dont_care_mask = W_PSION_MODIFIER|W_SHIFT_MODIFIER; +func=P_SCR_CAPTURE_KEY; + +p_iow (winHandle, P_FSET, &func, &capture) ; + + +captures PSION+A and PSION+CTRL+A. + + +See also the equivalent window server function wcapturekey, described in the Window Server Reference +manual. The struct elements code, modifier_mask and dont_care_mask correspond to the wcaptureKey +parameters keycode, modifiers and modifier_mask respectively. + + +Returns zero if successful, or =_FILE_ExIst if the specified keycode/modifier combination is currently +captured by any process. + + +P_FSET, P_SCR_CANCEL_CAPTURE_KEY Cancel a key capture + + +INT p_iow(VOID *pcb, P_FSET, &P_SCR_CANCEL_CAPTURE_KEY, CONSOLE_CAPTURE_KEY *pcapt) ; + + +Cancel a key capture set up by p_rset with function code p_scR_caPTURE_KEY. The content of pcapt must +exactly match that used to initiate the capture. + + +Returns zero if successful, or E_F1LE_nx1st 1f the keycode/modifier combination is not marked as +captured. + + +I/O DEVICES REFERENCE + + +Example + + +The following short program exercises many of the services described above. It consists of two parts, the +first of which simply receives keys typed by the user and reports them by type on the screen. The second +part enables the user to scroll a part of the display and to set the console attributes (scroll lock, line wrap +etc) to see how they affect the way typed characters are displayed. + + +#include +#include +#include +GLREF_D VOID *winHandle; + + +LOCAL_D P_RECTP RectP; + + +#define CON_HEIGHT 9 +#define CON_WIDTH 25 + + +LOCAL_C VOID doSetMode (UWORD mode, VOID *al) + + +/* +Shell to P_FSET +Hf, + +{ + +INT err; + +if ((err=p_iow4 (winHandle, P_FSET, &mode, al) ) !=0) + + +p_notifyerr(err,"Set service failed",NULL,NULL, NULL) ; + + +LOCAL_C VOID clear_line (VOID) +/* +position cursor to begining of the line and clear the line +*/ +{ +P_RECTP rectp; + + +p_iow3 (winHandle, P_FSENSE, &rectp) ; +rectp.p.x = 0; + +doSetMode (P_SCR_POSA, &rectp.p) ; +rectp.r.tl.x = 0; + +rectp.r.br.x = CON_WIDTH; +rectp.r.tl.y = rectp.p.y; +rect.r.br.y = rectp.p.y + 1; +doSetMode (P_SCR_CLR, &rectp.r); + +} + + +LOCAL_C VOID ReportKey (VOID) +{ +P_CON_KBREC kbrec; + + +p_printf ("Press Any Key (ESC quits)\r\n"); +FOREVER +{ +p_iow3 (winHandle, P_FREAD, &kbrec) ; +clear_line(); +if (kbrec.modifiers&W_PSION_MODIFIER) +p_printf ("Psion key %x",kbrec.keycode) ; +else if (p_isprint (kbrec.keycode) ) +p_printf ("Normal key %c",kbrec.keycode) ; +else if (kbrec. keycode==W_KEY_ESCAPE) +break; +else +p_printf("Non printable key %x",kbrec.keycode) ; + + +LOCAL_C VOID TryModes (VOID) +{ +INT wrap_lock,scroll_lock, escape; +P_RECTP rectp; +P_CON_KBREC kbrec; + + +escape = TRUE; /* set toggle flags to default values */ +wrap_lock = TRUE; +scroll_lock = FALSE; + + +rectp.r.tl.x = 5; /* define a rectangle for scrolling */ +rectp.r.tl.y = 1; +rectp.r.br.x = 20; +rectp.r.br.y = 6; + + +FOREVER +{ +p_iow3 (winHandle, P_FREAD, &kbrec) ; +if (! (kbrec.modifiers&W_PSION_MODIFIER) ) +{ +if (p_isprint (kbrec.keycode) ) +p_putch (kbrec.keycode) ; +else if (kbrec.keycode==W_KEY_RETURN) +doSetMode (P_SCR_NEL, 0); +else if (kbrec.keycode=='\b') +/* make backspace destructive */ +p_print("\b \b"); +else if (kbrec.keycode==W_KEY_ESCAPE) + + +break; +} +else +{ +kbrec.keycodeé&=(~W_SPECIAL_KEY) ; +switch (kbrec. keycode) +{ +case W_KEY_LEFT: +rectp.p.x = (-1); +rectp.p.y = (-1); +scroll: doSetMode (P_SCR_SCROLL, &rectp) ; +break; +case W_KEY_RIGHT: +rectp.p.x = (1); +rectp.p.y = (1); + + +goto scroll; +case W_KEY_DOWN: +rectp.p.x = 1; +rectp.p.y = 0; +goto scroll; +case W_KEY_UP: +rectp.p.x = (-1); +rectp.p.y = 0; +goto scroll; +case 'w': /* PSION modifier always gives lower case key */ + + +wrap_lock = !wrap_lock; +doSetMode (P_SCR_WLOCK, &wrap_lock) ; +break; + +case 's': +scroll_lock = !scroll_lock; +doSetMode (P_SCR_SLOCK, &scroll_lock) ; +break; + +case 'q': +escape = !escape; +doSetMode (P_SCR_ESCAPE, &escape) ; +break; + +default: /* do nothing */ +break; + + +} + + +2 CONSOLE + + +I/O DEVICES REFERENCE + + +GLDEF_C INT main(VOID) +/* +Allow user to type characters etc +xf +{ +INT err; +P_RECT rect; + + +if ((err=p_open (&winHandle, "CON:",-1)) !=0) +{ +p_notifyerr(err,"No Console device",NULL, NULL, NULL) ; +p_exit (0); +} +rect.tl.x = rect.tl.y = 0; /* set the screen size */ +rect.br.x = CON_WIDTH; +rect.br.y = CON_HEIGHT; +doSetMode (P_SCR_WSET, &rect) ; + + +p_printf ("Simple console program") ; +ReportKey (); + + +p_putch(0x0c) ; /* form feed to clear screen */ +p_printf ("Type characters or:"); + +p_printf ("Psion <- scrolls left/up"); + +p_printf ("Psion -> scrolls rght/dn"); +p_printf("Psion Down scrolls down"); +p_printf("Psion Up scrolls up"); + +p_printf("Psion W toggles wrap lock"); +p_printf("Psion S toggles scrl lock"); +p_printf("Psion Q toggles escape"); + +TryModes () ; + + +p_close(winHandle) ; +return(0); + + +} + + +CHAPTER 3 + + +PARALLEL PORT + + +Pc 9 EEEEEEEEEEE—— Ss +Introduction + + +One or more standard centronics parallel ports are available on all SIBO machines, in the form of either a +dual serial/parallel expansion module (for example, the HC and MC ranges) or a parallel expansion +module (such as the parallel 3-link for the Series 3). The HC cradle provides a third parallel port. + + +Parallel port device names + + +Depending on the number and location of ports available, the port device names are "PAR:A", "PAR:B" and +"PAR:C". For example, the Series 3 recognises only "PaAR:a", but an MC fitted with two serial/parallel +expansion modules recognises "Ppar:a" (left hand module, looking from the front of the machine) and +"PAR:B" (right hand module, looking from the front of the machine). + + +The parallel port driver is an output-only device driver that does not support a read service. + + +Panics + + +All services (with the exception of p_open) will cause the calling process to be panicked if the passed +channel handle is not valid. Other panics are described under the particular service to which they apply. + + +Parallel port services + + +p_open(PAR:) Open a parallel port +INT p_open(VOID **pcb, TEXT *pname, -1); + + +Open a channel to the parallel port *pname, where pname points to the string "PAR:A", "PAR:B" OF +"PAR:C", writing the address of the channel control block to *pcb. + + +The parallel port lines are powered up and all control lines are cleared low. The port will continue to +consume power until the channel is closed. + + +Returns zero if successful, or one of the following negative error numbers: + + +E_FILE_ALLOC failed to allocate memory for the control block +E_FILE_DEVICE the port does not exist +E_FILE_LOCKED or the port is already open + + +E_GEN_INUSE + + +p_close Close a parallel port + + +INT p_close(VOID *pcb); + + +Power down the parallel port lines and close the port channel corresponding to the specified control block, +first cancelling any outstanding Pp_FwRITE request. + + +Returns zero. + + +1/0 DEVICES REFERENCE + + +P_FWRITE Write to a parallel port + + +INT p_iow(VOID *pcb, P_FWRITE, VOID *buf, UWORD *plen); +VOID p_ioc(VOID *pcb, P_FWRITE, WORD *pstat, VOID *buf, UWORD *plen)j; + + +Write *plen bytes of data from buffer buf to the parallel port. It is the user's responsibility to preserve the +data at *pbuf and *plen until the write request completes. + + +The write request will never complete if the parallel port is not physically connected to a functioning +receiver. It is therefore advisable always to write asynchronously to the parallel port, and to use a timer +that provides a timeout on each write, as illustrated in the example at the end of this chapter. + + +Panics if a P_FWRITE request is currently outstanding, or if pcb is not a valid channel handle. + + +The completion status code is returned by the synchronous p_iow(P_FWRITE) and written to *pstat by +asynchronous calls. The completion status code is zero if the P_FWRITE request completed successfully, or +one of the following negative error numbers: + + +E_FILE_WRITE failed to write + + +E_FILE_CANCEL the write was cancelled by a call to the P_FcANCcEL service + + +P_FCANCEL Cancel a write request + + +INT p_iow(VOID *pcb, P_FCANCEL) ; +Cancel any outstanding P_FwRITE request, causing it to complete with an E_FILE_CANCEL completion code. + + +If a write request is outstanding then an indeterminate amount of data will have been written to the +parallel port before the request is cancelled. + + +Performing a cancel is harmless if no write request is outstanding. + + +Returns zero. + + +P_FSENSE Sense the input control lines +INT p_iow(VOID *pcb, P_FSENSE, UWORD *port); + + +This service is not, at the time of writing, available for any version of either the Series 3 or the Series 3a. +It is only available for machines in the HC and MC ranges that contain EPOC with a version number of +2.30 or later. + + +Write the current values of the centronics port input control lines to *port (all control lines are cleared +low when the port is opened). + + +The input control line values are defined, in p_par.h, according to the following table, where the pin +numbers are those appropriate for a 25-way D-type connector. + + +Symbol Control line Pin number +S_BUSY Busy 11 + +S_ACK Acknlg 10 +S_ERROR Error 15 + +S_PE Paper error 12 + + +Following the call, the values of the remaining bits at *port are undefined. + + +Returns zero. + + +P_FSET Write the output control lines + + +INT p_iow(VOID *pcb, P_FSET, UWORD *type, UWORD *port); + + +This service is not, at the time of writing, available for any version of either the Series 3 or the Series 3a. +It is only available for machines in the HC and MC ranges that contain EPOC with a version number of +2.30 or later. + + +Set or clear the centronics output control lines (all control lines are cleared low when the port is opened). + + +3-2 + + +3 PARALLEL PORT + + +If *t ype is 1 then the control lines corresponding to the bits set in *port will be set high. +If *t ype is 0 then the control lines corresponding to the bits set in *port will be cleared low. + + +The output control line values are defined, in p_par.h, according to the following table, where the pin +numbers are those appropriate for a 25-way D-type connector. + + +Symbol Control line Pin number +S_SPARE === See below +S_INIT Init 16 +S_AUTOFD Autofeed 14 +S_SELECT Select 17 + + +Any other bits set in *port are ignored. + + +The s_sparz bit is not available on the centronics connector. It may be of use in custom hardware designs +as it corresponds to pin 42 of the Psion-specific custom peripheral chip, astcs5. Changing this bit will +have no effect on the standard RS232/parallel expansion module. + + +Returns zero. + + +EEE +Example + + +The following example copies one or more files to a parallel port. It uses many of the parallel port +services, and illustrates the use of a timer to provide a timeout in conjunction with the p_rwRITE service. + + +include +include +include +include + + +LOCAL_D VOID *fcb=NULL; +LOCAL_D VOID *pcb=NULL; +LOCAL_D VOID *tcb=NULL; + + +LOCAL_C VOID Report (INT err) + + +TEXT buf [E_MAX_ERROR_TEXT_SIZE]; + + +p_errs (&buf[0],err); +p_printf("%s", &buf[0]); +} + + +LOCAL_C INT BufToParallel (VOID) +{ +WORD len; +WORD pstat,tstat; +ULONG time; +TEXT buf [64]; + + +len=p_read(fcb, &buf[0], 64); +if (len>=0) +{ +p_ioc5 (pcb, P_FWRITE, &pstat, &buf[0],é&len) ; +time=50; /* 5 second timeout */ +p_ioc4 (tcb, P_FRELATIVE, &tstat, &time) ; +p_iowait (); +if (pstat==E_FILE_PENDING) /* timer timed out */ +{ +p_iow2 (pcb, P_FCANCEL) ; +p_waitstat (&pstat) ; +return (E_FILE_CANCEL) ; +} +p_iow2 (tcb,P_FCANCEL); /* cancel timer */ +p_waitstat (&tstat) ; +} +return (len); + + +} + + +1/0 DEVICES REFERENCE + + +LOCAL_C VOID FileToParallel (VOID) + + +{ +INT err; + + +if ((err=p_open(&pcb, "PAR:A",-1))<0) /* open parallel port */ + + +{ +Report (err) ; +return; +} +FOREVER + + +{ +if ((err=BufToParallel()) <0) + + +{ +if (err!=E_FILE_EOF) + + +Report (err) ; +break; +} +} +p_close (pcb); +pcb=NULL; +} + + +GLDEF_C INT main(VOID) +{ +INT err; +TEXT bb[P_FNAMESIZE]; + + +if ((err=p_open(&tcb,"TIM:",-1))<0) /* open timer for timeouts */ + + +{ +Report (err) ; +return (0); +} +while (p_getl("Enter file name: + + +{ +if ((err=p_open (&fcb, &bb[0],P_FOPEN|P_FSTREAM) ) <0) /* open a file */ + + +{ + +Report (err); +continue; + +} +FileToParallel(); +p_close(fcb); + +} +p_close(tcb); +return(0); + + +} + + +Note that this example is based on the assumption that the only two asynchronous events that can occur +are the completion of a write to the parallel port and the expiry of the timer. For further discussion of a +more general case, see the description of p_ioc in the PLIB Reference manual. + + +", &bb[0],P_FNAMESIZE) ) + + +CHAPTER 4 + + +SERIAL PORT + + +eee ————————>>>——EE—————>>>>eE~— Ss +Introduction + + +The serial driver in the EPOC operating system supports a fully interrupt driven industry-standard RS-232 +serial link. + + +The driver consists of two cooperating layers. The lower driver is a physical device driver (PDD). It +provides a set of services that hide any hardware dependencies from the upper layer. + + +The upper layer of the driver is a logical device driver (LDD). It provides the logical (hardware +independent) services that are described in this chapter. Incoming data is buffered at this level. +Serial port device names + + +The first serial port on a SIBO machine has the device name "Tty:a". Many machines in the SIBO range +have more than one serial port available; a second port has the device name "TTy:8". For example, a +Series 3 fitted with a 3 Link (RS232) recognises only "tty:a", but an MC fitted with two serial/parallel +expansion modules recognises "TTy:a" and "tTy:B" (left and right hand modules respectively, looking +from the front). HC machines have a third port, on the cradle, with the device name "TTy:c". + + +HC machines also support serial ports with TTL level signals with device names "TTY:D", "TTY:E", +"TTy:F" (direct TTL levels) and "tTv:c", "TTy:H", "TTY:1" (inverted TTL levels). These ports are not +described in this chapter. + + +Panics + + +All services (with the exception of p_open) will cause the calling process to be panicked if the passed +channel handle is not valid. Other panics are described under the particular service to which they apply. + + +eee +Serial port parameters + + +The serial port parameters are set and sensed with the aid of a p_sRcuar struct, defined in p_serial.h as: + + +typedef struct + + +UBYTE tbaud; /* transmit baud rate */ + +UBYTE rbaud; /* receive baud rate */ + +UBYTE frame; /* number of data, parity and stop bits */ +UBYTE parity; /* parity type */ + +UBYTE hand; /* handshake flags */ + +UBYTE xon; /* XON character */ + +UBYTE xoff; /* XOFF character */ + +UBYTE flags; /* controlling flags */ + +ULONG tmask; /* terminator mask */ + + +} P_SRCHAR; +The possible settings are described in the following subsections. + + +One of the major problems with serial communications is ensuring that both ends of a physical link are +using the same port parameters. Typically, if one or more of the parameters differ, some data may be +transferred successfully whilst other data may not. This can make it difficult to determine which +parameter is incorrect. + + +1/0 DEVICES REFERENCE + + +Baud rate (tbaud, rbaud) + + +The Baud rate is, strictly speaking, a measure of the electrical signalling rate (the frequency of electrical +impulses) of a communications link. In practice, however, it is used to specify the data transfer rate, in +bits per second. The Baud rate and the data transfer rate are equal if one bit of data is encoded in each +signalling period. + + +For back-to-back serial communications the Baud rate and the data transfer rate are equivalent. It is only +when considering data transfer over a modem that the Baud rate and data transfer rate may differ. +Typically, modems that transfer data at a rate higher than 1200 bits per second encode more than | bit of +data into a single signalling period. For such a modem the Baud rate will differ from the data transfer +rate. + + +The transmit and receive Baud rates (tbaud and rbaud respectively) may be set to one of the following +values, which are defined in p_serial.h: + + +P_BA +P_BA +P_BA +P_BA +P_BA +P_BA +P_BA +P_BA +P_BA +P_BA +P_BA +P_BA +P_BA +P_BA +P_BA +P_BA +P_BA +P_BA + + +D_50 +D_75 +D_110 +D_134 +D_150 +D_300 +D_600 +D_1200 +D_1800 +D_2000 +D_2400 +D_3600 +D_4800 +D_7200 +D_9600 +D_19200 +D_38400 +D_56000 + + +U +U +U +U +U +U +U +U +U +U +U +U +U +U +U +U +U +U + + +The default value for both tbaud and rbaud is P_BAuD_9600. None of the SIBO serial port hardware +currently supports split Baud rates (separate transmit and receive Baud rates). + + +All machines in the SIBO range support Baud of rates of P_BAUD_50 to P_BAUD_9600 inclusive. In addition +the MC 200, MC 400 and Series 3a machines support a rate of P_BAUD_19200. The HC and Series 3 +machines can also be set to use P_BAUD_19200. However, the clock speed on current machines is slightly +too slow to handle this rate of data transfer, and overrun errors occur fairly frequently. Error correcting +protocols (eg Link) will run on the HC and Series 3 at 19200 Baud but, because of the high number of +retransmissions, they are slower than if they were run at 9600 Baud. + + +At 19200 Baud an interrupt occurs approximately every 500 microseconds. The following table shows the +number of instruction cycles available on a range of machines between two interrupts occurring at this +rate. + + +Machine Clock speed Instruction cycles +HC 3.84MHz 480 +Series 3 3.84MHz 480 +Series 3a 7.68MHz 960 +IBM PC/AT 4.77MHz 596 +MC 200/400 7.68MHz 960 + + +Character frame (¢rame) + + +The basic unit of transmission is the RS-232 asynchronous character frame. This is a sequence of bits +which consists of one start bit, between five and eight data bits, an optional parity bit and one or two stop +bits. + + +The start and stop bits are used to synchronise the data transmission. + + +The number of data bits required largely depends on the nature of the data that is being transferred. For +example, eight data bits are needed to transmit arbitrary binary data bytes, but seven bits are sufficient to +transmit text, containing only ASCII character codes with values not exceeding Ox7F. + + +Including a parity bit provides for an elementary degree of error detection in the transmitted data. + + +4-2 + + +4 SERIAL PORT + + +The value of frame describes the character frame. It may contain one of one of the following values, +defined in p_serial.h: + + +P_DATA_5 5 data bits +P_DATA_6 6 data bits +P_DATA_7 7 data bits +P_DATA_8 8 data bits + + +The value in frame may be ored with any combination of: + + +P_TWOSTOP 2 stop bits if set, 1 if clear +P_PARITY parity bit is present if set + + +All SIBO machines support all of the above settings. The default value of frame is +P_DATA_8 +for eight data bits, one stop bit and no parity. + + +In the majority of cases the total number of bits needed to transmit a single character is close to ten (for +example, one start bit, seven data bits, one parity bit and one stop bit). As a result, a reasonable estimate +of the character transfer rate is usually found by dividing the Baud rate by ten. + + +Parity (parity) + + +If present, the parity bit may be set or cleared to ensure that the combined sum of the set data and parity +bits is either odd (odd parity) or even (even parity). Alternatively it may be always set (mark parity) or +always clear (space parity). If the p_parrty bit is set in fiela, then parity should be set to one of the +following values, defined in p_serial.h: + + +P_PAR_EVEN even parity +P_PAR_ODD odd parity +P_PAR_MARK mark parity +P_PAR_SPACE space parity + + +Provided that p_partty is set in frame, the parity bit is generated (for transmission) and verified (on +receipt) by the port hardware. Reporting of parity errors may be suppressed by setting p_IGNORE_PARITY in +flags (see below). + + +The default value of parity is zero. No machine in the SIBO range supports either mark or space parity. + + +Handshaking (xon, xoff, hand) + + +Handshaking (also called flow control or buffer control) is a mechanism by which either end of a +communications link can pause and restart data transmission from the other end. There are two basic +forms: + + +e software handshaking +e hardware handshaking + + +Handshaking is required to prevent one end from sending data faster than the receiving end can process it. +For example, you may be able to send data to a printer at 9600 Baud, but it is unlikely that the printer is +capable of printing 960 characters per second. The printer will use handshaking to suspend the +transmission of data from time to time (when its internal buffer becomes full) and restart it when it is able +to receive more characters (some buffer space becomes available). + + +Software handshaking involves the transmission of particular characters, one to suspend and one to +resume transmission. This is usually called XON/XOFF handshaking, since the characters normally +selected to suspend and resume transmission are XOFF (0x13, pc3) and XON (0x11, pDc1) respectively. +Other characters may be used, provided that both ends of the communications link agree. + + +Software handshaking can sensibly be used only to transfer data that has pure textual content. Arbitrary +binary data may include bytes with values equal to one or other of the handshaking control characters. +The remote end will not be able to distinguish between such a character being sent as data or as a +handshaking control. For example, a WordStar file may contain the binary value 0x13 (XOFF) as an +underscore range marker. On receipt of this character the remote end will not transfer any data until it +receives an XON and so the transfer process may hang. More importantly, the XOFF character will be +removed from incoming data, being interpreted as a control character rather than as data. Thus, in the +above example, underscore range markers will be lost during the transfer. + + +The character codes used to resume and suspend transmission in software handshaking are stored in xon +and xoff. The default values are DC1 (0x11) and DC3 (0x13) respectively. + + +I/O DEVICES REFERENCE + + +Hardware handshaking involves the setting of a particular electrical state on specific control lines. It +usually involves a pair of lines, the output from one end being the input to the other, and vice versa. A +common cause of failure of hardware handshaking is the use of an improperly wired cable. Various +control line combinations may be used, as listed below. + + +DSR/DTR This form of handshaking uses the RS-232 control lines Data Set Ready (DSR) +and Data Terminal Ready (DTR). These lines were not originally intended for +use as data flow control lines, but were meant to be used to indicate the +presence or absence of a remote machine. However, many printers use +DSR/DTR handshaking to control the flow of data from a computer. + + +The receiver's output line (DTR) is held inactive (-ve) to suspend data transfer +and set active (+ve) to resume data transfer. This signal is expected to arrive +on the remote (sending) machine's DSR input line. + + +RTS/CTS This form uses the RS-232 control lines Request To Send (RTS) and Clear To +Send (CTS). These lines are the ones originally intended for use to control data +flow from either end. RTS/CTS handshaking is normally used for hardware +handshaking with a modem, and the DSR and DTR lines are used for their +originally intended purposes of indicating that a remote machine exists and the +port is open. + + +The output line (RTS) is held inactive (-ve) to suspend data transfer and set +active (+ve) to resume data transfer. This signal is received by the remote +machine via the CTS input line (ie its now Clear To Send data). + + +The Data Carrier Detect (DCD) line is not a control of flow handshaking line as described above. It is a +condition indicator from a modem to indicate that a connection now exists with a remote modem. The +DCD signal is an input only signal and there is no corresponding output line. + + +The form of handshaking to be used is specified by the value of hana. It should contain a combination of +the following bits, defined in p_serial.h: + + +P_OBEY_XOFF If set, receipt of the characters specified in xoff and xon suspend and resume +data transmission. If clear, these characters are treated as ordinary data. This +controls input XON/XOFF handshaking, which is independent of output +XON/XOFF handshaking. + + +P_SEND_XOFF If set, the characters specified in xoff and xon are transmitted to the remote +device to suspend and resume data transmission from the remote device. This +controls output XON/XOFF handshaking, which is independent of input +XON/XOFF handshaking. + + +P_IGN_CTS If clear, the driver will set its RTS line inactive to suspend transmission from +the remote device, and transmission will be suspended when the remote device +sets its RTS (incoming CTS) line inactive (RTS/CTS handshaking). If set, then +RTS is permanently active and the state of the input CTS line is ignored. + + +P_OBEY_DSR If set, transmission will be suspended when the remote device sets its DTR +(incoming DSR) line inactive (DTR/DSR handshaking). If clear, the state of +the incoming DSR line is ignored. In all cases the DTR line is held +permanently active while the seial port is powered up and open. + + +P_FAIL_DSR This is ignored unless p_oBEY_pDsR is set. If P_FAIL_DsR is set and the remote +device sets its DTR line inactive then any outstanding P_FWRITE or P_FREAD +request is completed with an E_FILE_LINE error (rather than simply suspending +transmission). The CCITT recommendations state that a serial port should hold +its DTR line active while the port is powered up and active. Setting +P_FAIL_psR allows application code to detect that a conforming remote device +has been removed or the connection broken. + + +P_OBEY_DCD If set, then transmission is suspended if the remote device sets the incoming +DCD line inactive. If clear, the state of the DCD line is ignored. + + +P_FAIL_DCD This is ignored unless P_oBEY_pDcD is set. If P_FAIL_pcp is set and the remote +device sets the incoming DCD line inactive then any outstanding P_FWRITE or +P_FREAD request is completed with an &_FILE_LINE error (rather than simply +suspending transmission). + + +4 SERIAL PORT + + +The default value of hana is zero, setting RTS/CTS handshaking. + + +In addition to using the control lines for hardware data flow control (which is transparent to the +application code), the serial port services allow the explicit testing of the state of the control lines or, for +example, to wait for the DCD line to be driven by a modem. + + +Control flags (¢1ags) + + +The control flags specify how the device driver should handle certain events. At the time of writing there +is only one control flag, defined in p_serial.h: + + +P_IGNORE_PARITY The presence or absence of a parity bit in received data is not under the +receiver's control. Setting p_1GNoRE_PaRITy causes the serial driver to discard +any parity errors on received data. A character received with a parity error is +placed in the receive buffer and treated as a normal character, even though it +may be in error. + + +For future compatibility the remaining bits of £1ags should be zero. +The default value of £1ags is zero. + + +Terminator characters (tmask) + + +A receiver has no universally reliable way of knowing when the transmitter has no more data to send. +Once some data has been received, the receiver may be entitled to assume that a period (say, five seconds) +in which no data arrives means that no further data will arrive. Clearly, this is not foolproof. + + +This problem may be solved provided that the transmitter cooperates with the receiver to the extent of +sending mutually agreed terminating characters. + + +One or more terminating characters may be specified by setting one or more bits of tmask. This consists of +32 bit flags, each corresponding (in order, from bit zero to bit 31) to a terminating character code in the +range 0x00 to ox1f inclusive. + + +Thus, setting bit zero (0x00000001) selects character code 0x00 to be a terminating character and setting +bit 26 (0x04000000) selects crru—z. An important use is to set bit 13 and/or bit 10 to select cr and/or Lr. +This allows text to be read a line at a time from a serial port. + + +The default value of tmask is zero, to select no terminating characters. + + +Serial port errors + + +Several errors can arise from a serial port that do not occur elsewhere. They include: + + +E_FILE_PARITY A parity error means that the received electrical signal corresponding to the +parity bit does not match the parity value calculated from the received data +bits. This is typically caused by electrical noise and usually indicates that the +data has been corrupted in transmission. Parity error detection is not +particularly robust, since many errors pass undetected. + + +E_FILE_FRAME A framing error means that the received electrical signal does not match the +start and stop bits. This most commonly occurs if data is being sent at a Baud +rate which differs from that which the receiver is expecting. Alternatively it +may mean that the number of stop bits expected by the receiver is greater than +the number being sent by the transmitter. + + +E_FILE_OVERRUN An overrun error occurs when the received electrical signal does not match the +stop bits. Overrun and framing errors are very similar and it is often difficult to +differentiate between them. Some devices may not report them as different +errors. + + +E_FILE_LINE A line error is generated when the hardware detects an inactive signal on an +input control line that the receiver requires to be permanently active (see also +Handshaking in the Serial port parameters section). + + +I/O DEVICES REFERENCE + + +I a SS SS 8 tev oo _TT_|vam_J =] +Serial port services + + +p_open(TTY:) Open a serial port +INT p_open(VOID **ppcb, TEXT *pname,-1) ; + + +Open a channel to the serial port *pname, where pname points to a serial port device name, as specified +earlier. If successful, write the channel to *ppcb and return zero. + + +For example: + + +if (!p_open(&pSerial, "TTY:A",-1) ) +{ + + +p_close(pSerial); + + +} + + +If successful the port will be powered up and the DTR line will be driven active to indicate to a connected +remote device that the port is open. + + +When opened a serial port will adopt its default characteristics of +e =©Baud +e data bits, no parity, 1 stop bit +e ~=RTS/CTS handshaking +e DCl1 is the XON, DC3 is the XOFF character +e Parity errors are not ignored +e No terminator characters + + +These characteristics may be incorrect for the required usage. To ensure that no received data is lost from, +say, a buffered modem, the RTS line will not be driven active until either the first P_rFREAD request or the +setting of some serial characteristics. (This, of course, assumes that the remote device is using RTS/CTS +handshaking.) + + +The call to p_open returns zero if successful, or a negative error. Errors include: + + +E_GEN_NOMEMORY there is not enough memory available to open the device + +E_GEN_INUSE the specified port is currently in use + +E_FILE_DEVICE an illegal or non-existent device is specified + +E_FILE_LOCKED attempting to open too many channels to the device driver + +p_close Close a serial port + + +INT p_close(VOID *pcb) ; +Close the specified channel to the serial driver. + + +The internal receive data buffer is flushed. If a character is currently being transmitted, the P_FCLOSE +request waits until its transmission is complete. The transmit data register becomes empty. + + +Any outstanding serial driver P_FREAD or P_FWRITE requests are cancelled. + + +The RTS and DTR lines are set inactive to indicate that the serial port is no longer in use and the serial +port is powered down. + + +Returns zero. + + +4 SERIAL PORT + + +P_FREAD Read from the serial port + + +INT p_iow(VOID *pcb, P_FREAD, VOID *buf, UWORD *plen); +VOID p_ioc(VOID *pcb, P_FREAD, WORD *pstat, VOID *buf, UWORD *plen)j; + + +Read up to *pien bytes to *buf from the serial port. The supplied buffer is assumed to be at least *pien +bytes long. The only limit to the amount of data that can be received in one call is the size of the data +buffer at but. It is the user's responsibility to preserve the data space pointed to by buf and plen until the +P_FREAD request completes. + + +The p_rreap request will typically take a significant length of time to complete and should normally be +called asynchronously in a quality system. + + +The request will complete when one of the following occurs: + + +@ *plen bytes have been received and transferred to *but. The request completes with zero +completion status code. + + +e areceive error is detected. The number of bytes received before the the error occurred is written +to *plen and these bytes transferred to *buf. The request completes with a negative error +completion status code. + + +¢ one of the terminating characters specified by the tmask field of the serial characteristcs is +received. The number of bytes received, including the terminating character, is written to *plen +and these bytes transferred to *buf. The request completes with zero completion status code. + + +e the request is cancelled. The number of bytes so far transferred to *buf is written to *plen. +The request completes with the —_F1LE_caNcEL completion status code. + + +The buffering mechanism at the serial driver's logical device driver level means that, following a +P_FCANCEL request, more characters may be available that have not yet been transferred to *but. The user +should test for this by calling the p_rtEst service and, if necessary, calling the p_rREAD service +synchronously to extract the remaining characters, as in the following example. + + +len=100; +p_ioc(pSerial,P_FREAD, &stat, &buf[0],&len) ; + + +p_iow(pSerial, P_FCANCEL) ; +p_waitstat (&stat); /* use up P_FREAD signal */ + + +p_printf("Buf[] contains %d bytes",len); + + +p_iow(pSerial, P_FTEST, &len) ; +if (len) +p_read(pSerial,&buf[0],len); /* will complete immediately */ + + +p_printf("There are %d more bytes available",len); + + +The calling process is panicked if a p_FREaD request is already outstanding or if pcb is not a valid channel +handle. + + +The completion status code is returned by the synchronous p_iow(P_FREAD) and written to *pstat by +asynchronous calls. The completion status code is zero if the p_rREaD request completed successfully, +otherwise it is a negative error number. Errors include: + + +E_FILE_PARITY a parity error occurred while receiving a character. This error will only be +reported if the user has not set p_IGNORE_PARITY in the serial characteristics. +Otherwise the error is discarded and the character (although in error) will +simply be transferred to *buE. + + +E_FILE_FRAME a serial framing error has occurred. + +E_FILE_OVERRUN a serial overrun error has occurred. + +E_FILE_LINE a line failure has occurred. + +E_GEN_OVER the internal serial driver buffer has become full and further incoming + + +characters have been discarded. Some form of handshaking is required to slow +the transmitter down. + + +1/0 DEVICES REFERENCE + + +E_FILE_RECORD a terminator mask has been set, *plen bytes have been received and written +into *pbuf but no terminator character has been received. No characters have +been lost or received in error but the data format being received is not as +expected. This may or may not be regarded as an error, depending on the +application. + + +P_FWRITE Write to the serial port + + +INT p_iow(VOID *pcb, P_FWRITE, VOID *buf, UWORD *plen); +VOID p_ioc(VOID *pcb, P_FWRITE, WORD *pstat, VOID *buf, UWORD *plen)j; + + +Transmit *plen characters from the buffer at buf, obeying the currently selected handshaking. + + +The only limit to the amount of data that can be transmitted in one call is the size of the data buffer at buf. +A value of zero for *plen is permissible. It is the user's responsibility to preserve the data space pointed to +by buf and plen until the write request completes. + + +A P_FWRITE request will typically take a significant length of time to complete and should normally be +called asynchronously in a quality system. + + +A P_FWRITE request may be cancelled by using the P_FcANCEL service. The P_FWRITE request will complete +with the E_FILE_CANCEL completion status code. The serial driver does not report how many bytes have +been transmitted before the request was cancelled. + + +The P_FWRITE service can be used to wait for changes in hardware flow control lines. For example, a +physical link to a remote PC could be deemed to be established when the DSR line is set active. A +P_FWRITE request of zero bytes with handshaking set to P_OBEy_psR will only complete when the DSR line +is set active, as in the following example: + + +P_SRCHAR serChar; + + +p_iow(pSerial, P_FSENSE, &serChar) ; + +serChar.hand|=P_OBEY_DSR; + +p_iow(pSerial, P_FSET, &serChar) ; + +len=0; + +if (!p_iow(pSerial,P_FWRITE, &ébuf[0],é&len) ) +{ /* DSR now being driven */ +serChar.hand|=P_FAIL_DSR; +p_iow(pSerial,P_FSET, &serChar) ; + + +} +serChar.hand&=~ (P_OBEY. DSR|P FAIL_DSR) ; +p_iow(pSerial, P_FSET, &serChar) ; + + +In this example the serial handshaking is first set so that the first P_FWRITE request will wait until the +remote machine's DTR (incoming DSR) line is set active, at which time connection is deemed to have +been established. The handshaking is then set to cause any following read or write requests to fail if the +connection is lost (incoming DSR line set inactive). Finally, the handshaking is restored to its original +state. + + +The calling process is panicked if a P_FwRITE request is already outstanding, or if pcb is not a valid +channel handle. + + +The completion status code is returned by the synchronous p_iow(P_FWRITE) and written to *pstat by +asynchronous calls. The completion status code is zero if the P_FWRITE request completed successfully, +otherwise it is a negative error number. Errors include: + + +E_FILE_LINE a line failure has occurred. + + +P_FCANCEL Cancel any outstanding requests + + +INT p_iow(VOID *pcb, P_FCANCEL) ; + + +Cancel any outstanding P_FREAD and P_FWRITE requests, causing them to complete with the +E_FILE_CANCEL completion status code. + + +See the descriptions of the p_FREAD and P_FwRITE services for their behavior with respect to P_FCANCEL. +The p_FCANCEL service 1s harmless if no P_FREAD Or P_FWRITE requests are outstanding. + + +The P_FCANCEL service cannot fail and returns zero. + + +4-8 + + +4 SERIAL PORT + + +P_FSENSE Sense the serial port characteristics +INT p_iow(VOID *pcb, P_FSENSE, P_SRCHAR *pch) ; +Write the current serial characteristics to the p_sRcHar struct pointed to by pch. + + +The p_FSENSE service cannot fail and returns zero. + + +P_FSET Set the serial port characteristics +INT p_iow(VOID *pcb, P_FSET, P_SRCHAR *pch) ; +Set the serial port characteristics to those passed in the p_srcuar struct pointed to by pch. + + +An application which wishes to change the serial port characteristics will normally first sense the current +characteristics, using the p_rsENsE service. It will then make the required change and use the p_rsEt +service to apply the new characteristics. + + +The calling process is panicked if there is an outstanding Pp_FREAD or P_FWRITE request or if pcb is not a +valid channel handle. + + +Returns zero if the p_rsrET request completed successfully, otherwise a negative error. Errors include: + + +E_GEN_ARG one or more of the values specified in the p_srcuar struct is illegal. The +current characteristics are not changed. + + +E_GEN_NSUP one of the required characteristics is not supported by this particular driver. +The current characteristics are not changed. + + +E_FILE_LINE either DSR is inactive and p_ratL_psr has been specified or DCD is inactive +and p_rarL_pcp has been specified (or both). + + +P_FFLUSH Flush the read buffer + + +INT p_iow(VOID *pcb, P_FFLUSH) ; + + +Discard the current contents of the internal serial read buffer (at the logical device driver level) and clear +any outstanding error status. Any handshaking that has paused transmission from the remote device is +cleared so that the remote device is free to resume transmission. + + +The p_FFLuSH service cannot fail and returns zero. + + +P_FTEST Test for received characters +INT p_iow(VOID *pcb, P_FTEST, UWORD *plen); +Set *pien to the number of bytes that are currently available in the serial driver's internal buffer. + + +Following the call it is guaranteed that there are at least *p1en bytes available. These bytes may be read +synchronously, since a synchronous p_REaD request to read *pien bytes will complete immediately. + + +By the time the p_rrest request has completed there may be more than *pien bytes available, since data +is received under interrupt control. + + +The calling process is panicked if there is an outstanding p_rREaD request or if pcb is not a valid channel +handle. + + +The p_Ftest service cannot fail and returns zero. + + +P_FCTRL Test and set control lines + + +INT p_iow(VOID *pcb, P_FCTRL, UBYTE *pctrl); + + +Read the current state of the CTS, DSR and DCD input control lines to *pctr1 as a bit mask and, +optionally, set the DTR output control line. + + +I/O DEVICES REFERENCE + + +The following bit flags are defined in p_serial.h: + + +P_SRCTRL_CTS if set CTS is active, otherwise it is inactive +P_SRCTRL_DSR if set DSR is active, otherwise it is inactive +P_SRCTRL_DCD if set DCD is active, otherwise it is inactive + + +If the byte pointed to by * (pctr1+1) is non-zero it is used to set the state of the DTR output line. If non- +zero it should take one of the following values, defined in p_serial.h: + + +P_SRDTR_ON to set DTR active +P_SRDTR_OFF to set DTR inactive + + +Returns zero if the p_FcTRL request completed successfully, otherwise a negative error number. Errors +include: + + +E_GEN_NSUP this driver does not support the setting of the DTR line. All current SIBO +machines support the setting of the DTR line. + + +P_FINQ Inquire supported serial characteristics +INT p_iow(VOID *pcb, P_FINQ, UWORD *pmask) ; + + +Write three words, into *pmask, * (pmask+1) and * (pmask+2), containing the serial characteristics that the +driver supports. Each word consists of a set of bit flags with each bit set indicating a supported +characteristic. + + +The first word, at *pmask, indicates a combination of the following potentially supported Baud rates, +defined in p_serial.h: + + +P_SRINQ_50 +P_SRINQ_75 +P_SRINQ_110 +P_SRINQ_134 +P_SRINQ_150 +P_SRINQ_300 +P_SRINQ_600 +P_SRINQ_1200 +P_SRINQ_1800 +P_SRINQ_2000 +P_SRINQ_2400 +P_SRINQ_3600 +P_SRINQ_4800 +P_SRINQ_7200 +P_SRINQ_9600 +P_SRINQ_19200 + + +The serial driver in all SIBO machines reports that all the above Baud rates are suppported, however see +Baud rate in the earlier Serial port parameters section for a discussion of the use of 19200 Baud. + + +The second word, at * (pmask+1), indicates a combination of the following potentially supported Baud +rates, defined in p_serial.h: + + +P_SRINQ_38400 +P_SRINQ_56000 + + +SIBO machines do not currently support either of these Baud rates. + + +The third word, at * (pmask+2), indicates support for a combination of the following characteristics, +defined in p_serial.h: + + +P_SRINQ_DATAS supports 5 data bits +P_SRINQ_DATA6 supports 6 data bits +P_SRINQ_DATA7 supports 7 data bits +P_SRINQ_DATA8 supports 8 data bits +P_SRINQ_STOP2 supports sending 2 stop bits +P_SRINQ_PAREVEN supports even parity +P_SRINQ_PARODD supports odd parity +P_SRINQ_PARMARK supports mark parity + + +4 SERIAL PORT + + +P_SRINQ_PARSPACE supports space parity +P_SRINQ_SETDTR supports the setting of DTR +P_SRINQ_SPLIT supports the setting of split Baud rates + + +The SIBO machines support all of the above except p_sRINQ_PARMARK, P_SRINQ_PARSPACE and +P_SRINQ_SPLIT. + + +The p_Fing service cannot fail and returns zero. + + +ee +Example + + +The following example, which assumes that the serial port is connected to a modem, uses many of the +serial services described above. + + +After opening a console it sends a dialling string to the modem and waits for a connection to a remote +modem. It then receives text records transmitted by the remote modem and displays them in the console +window. This continues until the user exits the program by pressing the ESCAPE key. + + +include +include +include + + +define OPEN_TIMER 0 +define OPEN_PORT 1 +define DTR_HAND 2 +define DIALLING 3 +define LINE_FEED 0x0a + + +LOCAL_D VOID *pTimer=0; /* Timer channel handle */ +LOCAL_D WORD timStat; /* Timer completion status */ +LOCAL_D VOID *pSerial=0; /* Serial channel handle */ + + +LOCAL_D WORD serWriteStat; /* Serial write completion status */ +LOCAL_D WORD serReadStat; /* Serial read completion status */ + + +GLREF_D VOID *winHandle; /* Console channel handle */ + + +LOCAL_D WORD winStat; /* Console completion status */ + + +LOCAL_C VOID reportError(INT func, INT error) + + +UBYTE bb[100]; + + +switch (func) +{ +case OPEN_TIMER: +p_puts("Failed to open timer channel"); +break; +case OPEN_PORT: +p_puts("Failed to open serial port"); +break; +case DTR_HAND: +p_puts ("Modem not driving DSR"); +break; +case DIALLING: +p_puts ("Failed to connect to remote Modem") ; +break; +default: +p_puts ("Unknown function error"); +} +p_errs(&bb[0],error); +p_puts (&bb[0]); +p_close(pSerial) ; +p_close(pTimer) ; +p_exit (1); +} + + +I/O DEVICES REFERENCE + + +LOCAL_C VOID QueueTimer (ULONG timeout) +{ +p_ioc(pTimer,P_FREAD, &timStat, &timeout) ; +} + + +LOCAL_C VOID CancelTimer (VOID) +{ +p_iow(pTimer,P_FCANCEL) ; +p_waitstat (&timStat) ; +} + + +LOCAL_C VOID QueueSerialWrite(UBYTE *buf,UWORD *plen) + + +p_ioc(pSerial,P_FWRITE, &serWriteStat,buf,plen) ; + + +LOCAL_C VOID CancelSerialWrite (VOID) + + +p_iow(pSerial,P_FCANCEL) ; +p_waitstat (&serWriteStat) ; + + +LOCAL_C setHand(INT clrflag, INT setflag) + + +P_SRCHAR sch; + + +p_iow(pSerial,P_FSENSE, &sch) ; + +sch. hand&=clrflag; + +sch.hand|=set flag; + +return (p_iow(pSerial,P_FSET, &sch) ); +} + + +LOCAL_C VOID resetModem (VOID) +/* +Reset a modem by driving DTR low for 2 seconds +x +{ +UBYTE bb[2]; + + +bb [1]=P_SRDTR_OFF; +p_iow(pSerial,P_FCTRL, &bb[0]); +p_sleep(20L); + +bb [1]=P_SRDTR_ON; +p_iow(pSerial,P_FCTRL, &ébb[0]); +} + + +LOCAL_C dialNumber (VOID) +/* +Returns zero if successful, else -ve error number +ey. +{ +UWORD len; +INT ret; + + +len=11; +QueueSerialWrite ("ATD9, 123456", &len) ; +QueueTimer(50L); /* 5 secs to send dial string */ +p_iowait (); +if (serWriteStat !=E_FILE_PENDING) +{ /* sent dial string */ +CancelTimer(); +if (!serWriteStat) +{ /* sent dial string Ok */ +if ((ret=setHand(-1,P_OBEY_DCD) ) !=0) +return (ret); +len=0; +QueueSerialWrite("",&len); /* Wait for DCD */ +QueuveTimer(1200L); /* 2 mins to get through */ +p_iowait (); +if (serWriteStat !=E_FILE_PENDING) +{ +CancelTimer (); +if (!serWriteStat) +{ +if ((ret=setHand(-1,P_FAIL_DCD) ) !=0) +return (ret); + + +} +else +CancelSerialWrite(); + + +} + + +else /* timeout sending dial string */ +CancelSerialWrite(); +return (serWriteStat) ; + + +} + + +4 SERIAL PORT + + +I/O DEVICES REFERENCE + + +GLDEF_C main (VOID) +{ +INT ret; +UWORD len; +P_SRCHAR sch; +P_CON_KBREC kbrec; +UBYTE key[2]; +UBYTE buf [128+2]; + + +p_puts("Serial Driver Example"); /* opens a console */ + + +if ((ret=p_open (&pTimer, "TIM:",-1)) !=0) +reportError (OPEN_TIMER, ret) ; +if ((ret=p_open(&pSerial,"TTY:A",-1)) !=0) + + +reportError (OPEN_PORT, ret) ; +resetModem () ; + + +if ((ret=setHand(-1,P_OBEY DSR|P FAIL_DSR) ) !=0) +reportError (DTR_HAND, ret); +if ((ret=dialNumber () ) !=0) + + +reportError (DIALLING, ret) ; +p_iow(pSerial,P_FSENSE, &sch) ; +sch.tmask=(1< + + +LOCAL_C VOID PlaySound(VOID *pcb) +{ +WORD notesl1[] = {1048,24,524,12}; +WORD notes2[] = {1048,4,1320,4,1568,4,2092,4,1568,4,1320,4,1048,12}; +WORD sndstat1,sndstat2; +WORD lenl,len2; + + +INT i; +lenl = sizeof (notes1) /4; +len2 = sizeof (notes2) /4; + + +p_ioc5 (pcb, E_FSSOUNDCHANNEL1, ésndstat1, ¬es1[0],é&lenl); +p_ioc5 (pcb, E_FSSOUNDCHANNEL2, &ésndstat2, ¬es2[0],&len2) ; +i= -1; +do + +{ + +p_iowait (); + +itt; + +} while (sndstatl == E_FILE_PENDING && sndstat2 == E_FILE_PENDING) ; +if (sndstatl == E_FILE_PENDING) + +p_waitstat (&sndstatl); +else + +p_waitstat (&sndstat2) ; +while (i--) + +p_iosignal(); + + +} + + +GLDEF_C INT main(VOID) +{ +VOID *pcb; +E_SOUND sound; + + +p_open(&pcb, "SND:",-1); +p_iow (pcb, P_FSENSE, &sound) ; +p_iow (pcb, P_FSET, &sound) ; +PlaySound (pcb) ; + +p_close (pcb); + +return (0); + + +} + + +Series 3 and Series 3a additional sound service + + +This service is available only on Series 3 and Series 3a machines. + + +E FDIAL Write DTMF dial tones + + +VOID p_ioc(VOID *pcb, E_FDIAL, WORD *pstat, TEXT *pstr, E_DIAL *pdial); +INT p_iow(VOID *pcb, E_FDIAL, TEXT *pstr, E_DIAL *pdial); + + +Write a DTMF tone sequence from the zero terminated string *pstr, with timing as specified by the +content of the E_DIAL struct pointed to by pdial. This struct is defined in epoc.h as: + + +typedef struct +{ +UBYTE toneLengthTicks; /* tone length in 1/32 sec */ +UBYTE delayLengthTicks; /* inter-tone delay in 1/32 sec */ +UWORD pauseLengthTicks; /* pause length in 1/32 sec */ +} E_DIAL; + + +5 SOUND + + +DTMF tones are produced for the following valid characters: +e the digits 0 to 9 +e upper or lower case alphabetic characters in the range A to F +e the characters # (0x23) and * (0x2A) which are converted to F and E respectively. + + +Space and comma characters generate a pause of length specified by the &_p1at struct element +pauseLengthTicks. All other characters are ignored. + + +The string at pstr may be of any length, but the total number of valid tone and pause generating characters +characters in it may not exceed 26. + + +For example, assuming a dial-out code of 9, + + +E_DIAL dial; +TEXT digits[10]; + + +dial.toneLengthTicks=8; +dial.delayLengthTicks=8; +dial.pauseLengthTicks=48; + +p_scpy (&digits[0],"9,0711234") ; +p_iow(pcb,E_FDIAL, &digits[0],&dial) ; + + +will emit the DTMF dialling tones to dial the external number 071 1234. + + +Panics if an E_FDIAL Of E_FALARM request is currently outstanding, or if pcb is not a valid channel handle. + + +The completion status code is returned by the synchronous p_iow(E_FDIAL) service and written to *pstat +by an asynchronous call. The completion status code is zero if the E_Fp1aL request completed successfully, +or one of the following errors: + + +E_FILE_CANCEL the write was cancelled by a call to the p_rcancEL service +E_GEN_ARG the string contains too many valid characters + + +a ——— +Example + + +The following code implements a simple tone dialing system for HC, MC or Series 3a machines. +#include +#include +#include + + +GLREF_D VOID *winHandle; + + +LOCAL_D WORD tones1[] = +941,1,697,1,697,1,697,1,770,1,770,1,770,1, 852,1, 852,1,852,1,941,1,941,1}; + + +LOCAL_D WORD tones2[] = +1336,1,1209,1,1336,1,1447,1,1209,1,1336,1,1447,1,1209,1,1336,1,1447,1,1209,1,1477,1}; + + +LOCAL_C VOID dial(VOID *psoundcb, INT tone) + + +WORD len = 1; +WORD sl_status; +WORD *ptonel, *ptone2; + + +if(tone >= 0 && tone <= 11) +{ +ptonel = &tones1[0] + tone*2; +ptone2 = &tones2[0] + tone*2; +p_ioc5 (psoundcb, E_FSSOUNDCHANNEL1, &sl1_status,ptonel, &len) ; +p_iow4 (psoundcb, E_FSSOUNDCHANNEL2, ptone2, &len) ; +p_waitstat (&sl_status) ; +} + + +IEVICES REFERENCE + + +VOD + + +GLDEF_C INT main(VOID) +{ +INT c,tone,err; +VOID *psoundcb; +UWORD func; +P_RECT rect; +E_SOUND sound; + + +if ((err=p_open (&winHandle, "CON:",-1)) !=0) +{ +p_notifyerr(err,"No Console device",NULL, NULL, NULL) ; +p_exit (1); +} + + +rect.tl.x + + +rect.tl.y = 0; /* set the screen size */ +rect.br.x = 25; +rect.br.y = 9; +func = P_SCR_WSET; +p_iow4 (winHandle, P_FSET, &func, &rect) ; +p_printf ("Tone dial demo"); +if ((err=p_open (&psoundcb, "SND:",-1)) !=0) +{ +p_notifyerr(err,"Cannot open sound device",NULL, NULL, NULL) ; +p_close (winHandle) ; +p_exit (1); +} +sound.volume = 3; +sound.beatsPerMinute = 76; +p_iow3 (psoundcb, P_FSET, &sound) ; +FOREVER +{ +c = p_getch(); +if (c==W_KEY_RETURN) ; + + +break; +p_putch (c); +if (c=='"*') +tone = 10; +else if (c=='#"') +tone = 11; +else +tone =c - '0O'; + + +dial (psoundcb, tone) ; + +} +p_close (psoundcb) ; +p_printf("\r\nDemo finished"); +p_printf ("Press any key to exit"); +p_getch (); +p_close(winHandle) ; +return (0); + + +} + + +CHAPTER 6 + + +THE ALARM DEVICE DRIVER + + +Introduction + + +The atm: device driver supplied on Series 3, Series 3a and MC machines provides support for alarms +(as used in the Agenda application). A process may specify an alarm sound (Series 3a only), an alarm +message and an appointment time. + + +The following picture illustrates the screen display for an untimed alarm on a Series 3a machine. + + +Alarm (Agenda) 12:32:18 pm + + +Alarm: Mon 18th Oct + + +Finish the alarm server chapter ... + + +Clear alarm Snooze Silence + + +Note that the appointment date is displayed but not the appointment time. + + +The following picture illustrates the screen display for a timed alarm on a Series 3a machine. + + +Alarm (Agenda) 12:58:89 pm + + +Alarm: Mon 18th Oct 2:46 pm +Finish the alarm server chapter ... + + +Clear alarm Snooze Silence + + +—Enter_| + + +Both the time and the date of the appointment are displayed. + + +An alarm is set by sending an alarm request to the alarm device driver (atu: ). This request may be made +synchronously, using p_iow, or asynchronously, by using p_ioc, for example. + + +Note that the alarm server holds a copy of the data relating to an outstanding alarm request. An +outstanding alarm can therefore survive the termination of its parent, that is, the process that made the +alarm request. Such an alarm is referred to as an orphaned alarm. + + +An orphaned alarm is automatically reparented when an identical alarm request is made. This feaure is +used by, for example, the Agenda application. Thus, even if an Agenda file is repeatedly closed and +reopened, an entry with an alarm will not be marked with a large number of identical alarm requests.) + + +I/O DEVICES REFERENCE + + +Panics + + +An application will be panicked if it makes an alarm request before any previous alarm request from that +application has completed. All services (with the exception of p_open) will cause the calling process to be +panicked if the passed channel handle is not valid. + + +The #defines and structs for the alarm server device are in the header file hasrv.h. + + +Series 3, Series 3a and MC alarm services + + +The Series 3a also has additional services that are described in the following section. + + +Note that all alarm services are provided by the Time application that is built into Series 3 and Series 3a +machines, rather than being an integral part of the operating system. + + +p_open(ALM:) Open the alarm channel + + +INT p_open(VOID **pcb, "ALM:", -1); +Open a channel to the alarm device. +Returns zero if the alarm device is opened successfully, otherwise one of the following errors: + + +E_GEN_OPEN +E_GEN_NOMEMORY +E_FILE_NXIST + + +p_close Close the alarm channel + + +INT p_close(VOID *pcb); +Close the alarm device channel. + + +Returns zero. + + +P_FCANCEL Cancel an alarm request + + +INT p_iow(VOID *pcb, P_FCANCEL) ; +Cancel any outstanding alarm request. Performing a cancel is harmless if no alarm request is outstanding. + + +Returns zero. + + +A_FTIMED Queue a timed alarm + + +VOID p_ioc(VOID *pcb, A_FTIMED, WORD *pstat, A_DETAILS *pd, TEXT *pm) ; + + +Queue a timed alarm specified by a pointer to an A_DETAILS struct, and a pointer to a zero terminated text +message. + + +The A_DETAILS struct would be defined as follows: + + +typedef struct +{ +ULONG absTime; +ULONG dueTime; +} A_DETAILS; + + +¢ absTime is the alarm time as a system time. +¢ dueTime is the appointment time as a system time. +The appointment time should not be earlier than the time of the alarm. + + +The text message pointed to by pm should be a zero terminated string of not more than 65 characters +including the zero terminator. If no text message is required then pm should point to the null string. + + +The completion status is written to *pstat. The status is zero if the service completed successfully +otherwise a negative error number. + + +6-2 + + +6 THE ALARM DEVICE DRIVER + + +A_FUNTIMED Queue an untimed alarm + + +VOID p_ioc(VOID *pcb, A_FUNTIMED, WORD *pstat, A_DETAILS *pd, TEXT *pm); + + +Queue an untimed alarm specified by a pointer to an a_DETAILSs Struct, and a pointer to a zero terminated +text message. + + +This service is identical to a_rTIMED (see above) except that only the day and month of the appointment +time are displayed, the hours and minutes being omitted. + + +Series 3a additional alarm services + + +The services listed in this section are only available on the Series 3a machine. + + +A_FTIMED X Queue a Series 3a timed alarm +VOID p_ioc(VOID *pcb, A_FTIMED_X, WORD *pstat, AXDATA *pa, TEXT *pm); + + +Queue a timed alarm specified by a pointer to an axpata struct, and a pointer to a zero terminated text +message. + + +The axpara struct is defined in hasrv.h as follows: + + +typedef struct +{ +ULONG absTime; +ULONG dueTime; +SE_SND sound; +} AXDATA; + + +@ absTime 1s the alarm time as a system time. +@ dueTime is the appointment time as a system time. +® sound is the alarm sound (see below). + + +The se_swp struct defines the sound to be made and is defined in hasrv.h as follows: + + +typedef struct +{ +UBYTE len; +TEXT name[8]; +UBYTE zero_term; +} SE_SND; + + +¢ en is the length of the string in the name field. +¢ name specifies the name of the alarm sound (see below). +@ zero_term is the nuut character. +The element name in the sE_swp struct can have one of the following values: + + +e asingle byte containing a value between | and 16 inclusive. Currently only 1, 2 and 16 are used, +corresponding to the rings, chimes and silent alarms respectively. The contents of following +unused bytes are not significant. For example: + + +AXDATA axdata + + +axdata.sound.len=1; +axdata.sound.name[0]=1; + + +would set the rings sound. + + +I/O DEVICES REFERENCE + + +¢ anon-zero-terminated string specifying one of the .wve digital sound files resident in the ROM. +Currently these are: SYS$ALO/ for a 'Fanfare', SYS$AL02 for 'Soft bells' and SYS$AL03 for +‘Church bells’. For example: + + +AXDATA axdata + + +axdata.sound.len=8; +p_scopy (&axdata.sound.name[0],"SYSSAL03") ; + + +would set the 'Church bells' sound. + + +¢ anon-zero-terminated string specifying a .wve sound file resident in a local \wve\ directory. The +contents of following unused bytes are not significant. For example: + + +AXDATA axdata + + +axdata.sound.len=p_slen("mysound") ; +p_scopy (&axdata.sound.name[0],"mysound") ; + + +would set the sound to be that contained in a \wve\mysound.wve file. + + +The message pointed to by pm should be a zero terminated string of not more than 161 characters, +including the zero terminator. If no text message is required, then pm should point to a null string. + + +The completion status is written to *pstat. The status is zero if the service completed successfully +otherwise a negative error number. + + +A_FUNTIMED X Queue a Series 3a untimed alarm + + +VOID p_ioc(VOID *pcb, A_FUNTIMED_X, WORD *pstat, AXDATA *pa, TEXT *pm); +Queue an untimed alarm specified by a pointer to an axpata struct, and an associated text message. + + +This service is identical to the A_FTIMED_x service (see above) except that only the day and month of the +appointment time are displayed, the hours and minutes being omitted. + + +CHAPTER 7 + + +THE FREE-RUNNING COUNTER + + +Introduction + + +The Series 3a and Workabout machines are supplied with a device driver for a built in free-running +counter (FRC). This device driver may be accessed by applications and provides for the measurement of +elapsed time with an accuracy of +/- 2ppm (corresponding to 2.6 seconds per month) and a resolution of +1/1024 seconds. + + +The free-running counter device driver may be used in one of three ways: + + +e to provide a value that increments once every 1/1024 second, effectively a relative clock. An +application can read the value at any time, without resetting it. + + +e to trigger an event after a specified interval, in units of 1/1024 second. In effect this provides the +same function as a relative timer, except that the free-running counter works to a higher +resolution. + + +e to provide a value that increments once every specified time interval, in units of 1/1024 second. +This allows an application to create a relative clock, with the resolution tailored to the +application's requirements. The value is reset to zero each time that it is read. + + +As the FRC device driver can support only one process at any one time, applications should use it for no +longer than is absolutely necessary. + + +An application that only needs to work with time intervals with a resolution of 1/32 second or greater +should not use the FRC, but should use either a relative or an absolute timer: details of these timers can be +found in the Time, Timers and Dates chapter of the Plib Reference manual. + + +FRC services + + +The FRC: device driver is specific to the Series 3a and Workabout machines. + + +All services (with the exception of p_open) will cause the calling process to be panicked if the passed +channel handle is not valid. Other panics are described under the particular service to which they apply. + + +p_open(FRC:) Open the FRC channel +INT p_open(VOID **pcb, "FRC:", -1); + +Open a channel to the FRC device. + +Returns zero if the device was opened successfully, otherwise a negative error code. Errors include: +E_FILE_OPEN The device can not be accessed as it is in use. + + +E_GEN_NOMEMORY There is insufficient memory to allow a channel to be opened. + + +I/O DEVICES REFERENCE + + +p_close Close the FRC channel +INT p_close(VOID *pcb) ; +Close the device channel, first cancelling any outstanding read request. + + +Returns zero. + + +P_FCANCEL Cancel the FRC request + + +INT p_iow(VOID *pcb, P_FCANCEL) ; +Cancel any outstanding request. Performing a cancel is harmless if no request is outstanding. + + +Returns zero. + + +P_FSTART Start the free-running counter +INT p_iow(VOID *pcb, P_FSTART, UWORD *pmode, UWORD *pint); + +Start the free-running counter. + +The uworp pointed to by pmode must specify one of the following modes, defined in epoc.h: + + +E_FRC_COUNTING a counter increments every 1/1024 seconds from an initial value of zero. The +value of pint is ignored. + + +E_FRC_REPEATING a counter increments every *pint multiple of 1/1024 seconds, starting from +zero. The value of *pint should be in the range 10 to 65535, representing time +intervals approximately in the range of 0.01 to 64 seconds. + + +Any outstanding P_FREAD request will be cancelled and the counter reset to zero. + + +Returns zero if the request completed successfully, otherwise returns a negative error number. Errors +include: + + +E_GEN_NSUP an invalid mode was specified. + + +E_GEN_RANGE the specified repeat interval is not valid, i.e. it is in the range 0 to 9 inclusive. + + +P_ FREAD Read the elapsed time in E_ FRC_COUNTING mode + + +VOID p_ioc(VOID *pcb, P_FREAD, WORD *pstat, ULONG *argl); +INT p_iow(VOID *pcb, P_FREAD, ULONG *argl1); + + +Sense the current counter value, following a previous P_FSTART request that set E_LFRC_COUNTING mode. + + +The value written to *arg1 is the time, in units of 1/1024 seconds, since the last P_rsTarT request. The +value is not reset by the P_FREAD request. + + +The application will be panicked if an earlier P_FREAD request is outstanding. + + +The completion status is written to *pstat for p_ioc and returned by p_iow. It is zero if the request +completed successfully. Otherwise it is a negative error number. Errors include: + + +E_GEN_OVER the elapsed number of repeat intervals is too large to be written to *arg1. +E_FILE_CANCEL the P_FREAD request was cancelled before it completed. +E_FILE_READ either the counter was not running, or the machine was switched off while the + + +counter was running. + + +7 FRC + + +P_ FREAD Read the elapsed time in E_ FRC_REPEATING mode + + +VOID p_ioc(VOID *pcb, P_FREAD, WORD *pstat); +INT p_iow(VOID *pcb, P_FREAD) ; + + +Sense the current counter value, following a previous p_rstTarT request that set E_FRC_REPEATING mode. + + +The completion status value that results from a successful call to this service is the number of complete +time intervals (as specified by the earlier p_rstart request) that have elapsed since the last request for +either a P_FSTART Of a P_FREAD Service. The service will not complete until one time interval has elapsed, +otherwise completion is immediate. Time is not lost between successive P_FREAD requests, since the FRC +hardware is not reset. + + +The application will be panicked if an earlier p_rREaD request is outstanding. + + +The completion status is written to *pstat for p_ioc and returned by p_iow. It is a positive value if the +request completed successfully. Otherwise it is a negative error number. Errors include: + + +E_GEN_OVER the elapsed number of repeat intervals exceeds 32767. +E_FILE_CANCEL the p_FREAD request was cancelled before it completed. +E_FILE_READ either the counter was not running, or the machine was switched off while the + + +counter was running. + + +CHAPTER 8 + + +THE SERIES 3 WORLD DATABASE + + +Introduction + + +The World database is supported by all of the Series 3 range of machines. It stores a range of data for a +large number of countries - in practice only small or very recently created countries are not present. +Further data is stored for the larger cities in each country. + + +The wip: device driver allows an application to navigate the database by means of a number of search +services. A successful search sets the current city and/or country for other services that can access or +update the constituent data according to specific requirements. It supports multiple channels. + + +The services of this device driver are provided by the World application that is built into the ROM of all +machines in the Series 3 range. + + +The data stored in the database includes various codes required for dialling as follows: +e the national code for each country. +e the international prefix code for each country. +e the national prefix for long distance calls. +The database also includes the following data for each city: +e the deviation of the local time from Greenwich Mean Time. +e the times of sunset and sunrise expressed as a local time (these are actually calculated). +e the latitude and the longitude of the city. +e the coordinates of the city on the World map. +e the zone for daylight saving time (DST). +An application may also: +e set its home city. +e set its default country. + + +The database supports the creation of a file containing extra items which may be either new cities, or +replacement data for existing cities: only 32 extra items may be included in any one file. (A greater +number of extra items would significantly degrade the performance of the database search operations.) + + +Mode + + +A minority of services change the mode of the the database which can effect the operation of subsequent +services. Thus the wR_NEXT service moves to the next city if the database is in city mode. Otherwise the +WR_NEXT Service moves to the next country. + + +A service is assumed not to change the mode unless it is explictly stated to the contrary. + + +1/0 DEVICES REFERENCE + + +Series 3 and Series 3a World database services + + +Note that these services are provided by the World application that is built into Series 3 and Series 3a +machines, rather than being an integral part of the operating system. + + +p_open(WLD:) Open the World channel +INT p_open(VOID **ppcb, "WLD:", Oxffff); + +Open a channel to the World database and write the handle of the channel to «ppcb. + +Returns zero on success, otherwise a negative error code including the following: + + +E_FILE_ALLOC failed to allocate memory for the control block. + + +p_close Close the World channel +INT p_close(VOID *pcb) ; +Close the channel to the World database specified by pcb. + + +Returns zero on success. + + +P_FCANCEL Cancel a World request + + +INT p_iow(VOID *pcb, P_FCANCEL) ; + + +Cancel any outstanding World request on channel pcb and return zero - performing a cancel is harmless if +there is no outstanding request. + + +The P_FCANCEL request cannot fail. + + +WR_FIND_CITY Find by city + + +INT p_iow(VOID *pcb, WR_FIND_CITY, TEXT *match, WR_FIND_RES *result) ; + + +Find the first city that matches the string at address match writing the name of the matching city and the +associated country to the WR_FIND_RES struct pointed to by result - the matching is not case sensitive. + + +The WR_FIND_RES struct is defined as follows: +typedef struct + +{ +TEXT city [WR_MAX_NAME+1]; +TEXT country [WR_MAX_NAME+1]; +} WR_FIND_RES; + +The significance of the members of the WwR_FIND_RES struct is as follows: + +city the name of the matching city expressed as a zero terminated string. + + +country the name of the associated country expressed as a zero terminated string. + + +Returns WR_FOUND on success, Or WR_NOT_FOUND otherwise. + + +WR_FIND_COUNTRY Find by country + + +INT p_iow(VOID *pcb, WR_FIND_COUNTRY, TEXT *match, WR_FIND_RES *result); + + +Find the first country that matches the string at address match writing the name of the matching country +and its capital city to the wR_FIND_RES struct pointed to by result - the matching is not case sensitive. + + +8 SERIES 3 WORLD DATABASE + + +The wR_FIND_RES Struct is defined as follows: +typedef struct +{ +TEXT city [WR_MAX_NAME+1]; +TEXT country [WR_MAX_NAME+1]; +} WR_FIND_RES; +The significance of the members of the wR_FIND_REs struct is as follows: + + +city the name of the capital city of the matching country expressed as a zero +terminated string. + + +country the name of the matching country expressed as a zero terminated string. + + +Returns wR_FOUND on success, Or WR_NOT_FOUND otherwise. + + +WR_FIND_EXACT Find by city and country + + +INT p_iow(VOID *pcb, WR_FIND_EXACT, WR_FIND_RES *match) ; + + +Find the country that exactly matches the city specified in match->city, or if this is NuLL, the country +specified in match->country - the matching is not case sensitive. + + +For a description of the wR_FIND_REs Struct, see the above descriptions of the wR_Finp_crTy and +WR_FIND_COUNTRY Services. + + +Returns wR_FOUND on success, Or WR_NOT_FOUND otherwise. + + +WR_NEXT Find next city + + +VOID p_iow(VOID *pcb, WR_NEXT, WR_FIND_RES *result) ; + + +Write the names of the next city and the associated country, or the next country and its capital city, +depending on the mode, to the wR_FIND_REs struct pointed to by result. + + +The service is always successful. + + +WR_BACK Find previous city + + +VOID p_iow(VOID *pcb, WR_BACK, WR_FIND_RES *result); + + +Write the name of the previous city and the associated country, or the previous country and its capital city, +depending on the mode, to the wR_FIND_REs struct pointed to by result. + + +The service is always successful. + + +WR_GET_HOME Find home city + + +VOID p_iow(VOID *pcb, WR_GET_HOME, WR_FIND_RES *result); + + +Write the names of the home city and the associated country to the wR_FIND_REs struct pointed to by + + +result. + + +The service is always successful. + + +WR_SET HOME Set home city + + +INT p_iow(VOID *pcb, WR_SET_HOME) ; +Set the home city to the current city. +This is a system wide setting. + + +Returns zero on success, or WR_NOTVALID_ERR if the current city is no longer valid 1.e. the current city has +been deleted. + + +1/0 DEVICES REFERENCE + + +WR_GET_DEFAULT_ COUNTRY Find default country + + +VOID p_iow(VOID *pcb, WR_GET_DEFAULT_COUNTRY, WR_FIND_RES *result); +Write the name of the default country and its capital city to the wR_FIND_RES struct pointed to by result. +Note that the service sets the database to city mode. + + +The service is always successful. + + +WR_SET_ DEFAULT COUNTRY Set default country + + +INT p_iow(VOID *pcb, WR_SET_DEFAULT_COUNTRY) ; +Set the default country current country to the current country. +Note that the service sets the database to country mode. + + +Returns zero on success, Or E_GEN_UNDER if the current city is no longer valid i.e. the current country has +been deleted. + + +WR_GET_DIAL_STRING Get dial string + + +INT p_iow(VOID *pcb, WR_GET_DIAL_STRING, TEXT *inString, TEXT *outString); +Convert the string pointed to by inst ring into a dial string, written to the buffer pointed to by out string. + + +The output string may be played using the sound device: for futher details of tone dialling see the Sound +chapter of the I/O Devices Reference manual. + + +During the conversion, both spaces and hyphens are removed, but commas are left unchanged. A full stop +is interpreted as marking the end of the input string. For the significance of commas see the Sound +chapter of the //O Devices Reference manual. As an example, 0-171,123 4567.89 would be converted to +0171,1234567. + + +Returns zero on success, otherwise one of the following negative error codes: + + +E_GEN_ARG either the input string includes only one square bracket, or the country +specified in square brackets does not match a country in the database. + + +E_GEN_OVER at some stage in the conversion, the output string exceeded the maximum +allowed length of wR_MaAx_DIAL_STRING characters. + + +The conversion is illustrated by the following examples: +009 44 171 234 5678 + + +009 is an international access code which indicates that an international call is being made. The example +international access code is that of Denmark. In the United Kingdom the international access code is 001. + + +44 is a country code which indicates the destination country. The example country code is that of the +United Kingdom. + + +171 is an area code - in this case it is the Inner London code. +234 5678 is the local telephone number. + +For this example the service simply outputs 009441712345678. +009 44 (0) 171 234 5678 + + +(0) is the national prefix and is enclosed in brackets to indicate that it is not required for international +calls. + + +the other components are as described above. + + +the output string is 009441712345678. In this case the number corresponds to calling London from +Denmark. + + ++44 171 234 5678 + ++ is an abbreviation for the international access code. +44 is the country code for the United Kingdom. + +171 is the area code. + + +234 5678 is the local number. + + +8-4 + + +8 SERIES 3 WORLD DATABASE + + +the interpretation of the string depends on the home country. When this is Denmark, the service replaces +the plus character with the international access code of Denmark giving 009441712345678. On the other +hand, when the home country is the United Kingdom, the plus character and the country code are replaced +with the national prefix and the output string is 01712345678. + + +171 234 5678 [United Kingdom] + + +171 is the area code. +234 5678 is the local number. + + +[United Kingdom] is a convenient means of specifying the destination country: note the space between the +last digit and the first bracket and that the country is specified in full. + + +When the home country is Denmark, the output string is 009441712345678. +When the home country is the United Kingdom, the output string is 01712345678. +0 171 234 5678 + + +0 is the national prefix - sometimes referred to as the STD prefix - and is omitted on international calls. + + +the output string is 0171 234 5678. + + +WR_SET_EXTRA Open file for additional data + + +INT p_iow(VOID *pcb, WR_SET_EXTRA, WORD *flag, TEXT *name) ; + + +Open a file to store extra cities where name should point to the full file specification stored as a zero +terminated string and f1ag should always be set to p_FoPEN. + + +The filename is parsed with an extension of . wip. +The service will fail if the file does not exist. + + +Returns zero on success, otherwise £_GEN_1macE if the file is either badly formatted, or has a different +database version number, or a system error code. + + +WR_EXTRA Modify additional data + + +INT p_iow(VOID *pcb, WR_EXTRA, WORD *func, WR_EXTRA_DATA *data); + +Add, update or delete database entries in the file opened by the earlier wR_sET_ExTRa call. + +The service assumes that an extra World database file has been opened using the wR_sET_EXTRA Service. +The func argument may take one of the following values: + + +WR_EXTRA_ADD_CITY specifies that a city should be added to the World database - the data is read +from the wR_EXTRA_DATA union pointed to by data. The city must be in an +existing country. + + +The wR_EXTRA_DATA union is defined as follows: + + +typedef union +{ +WR_CITY_DATA ci; +WR_COUNTRY_DATA co; +} WR_EXTRA_DATA; + + +For further details of the wr_crTy_pata struct, see the description of the +WR_GET_CITY_DATA service. + + +WR_EXTRA_UPDATE_CITY specifies that a city in the World database should be updated - the new data is +read from the wR_EXTRA_DATA union pointed to by data. The city must be in an +existing country. + + +For details of the wR_ExTRA_DATA union see above. For details of the +WR_COUNTRY_DATA Struct see the description of the wR_GET_COUNTRY_DATA +service. + + +I/O DEVICES REFERENCE + + +WR_EXTRA_DELETE_CITY delete a city in the extra database file - the name of the city and the name of +the country are read from the wR_EXTRA_DATA union pointed to by data. + + +WR_EXTRA_UPDATE_COUNTRY — update a country in the World database - the data associated with the country is +read from the WR_EXTRA_DATA union pointed to by data. Renaming a country +does not delete or otherwise modify the member countries + + +On success, the service returns either zero or one of the following values: +WR_REVERTED the city has reverted to its original built-in data. +WR_DELETED the city has been deleted. + +Otherwise the service returns a negative error code which includes the following: + + +E_GEN_ARG tried to update a non-existent country, or specified a non-existent city as the +capital of a country. + + +WR_TOO_MANY_ERR attempted to exceed the maximum allowed number of items in the extra World +database file. The maximum number of allowed items is 32. + + +WR_DUPLICATE_ERR the new name for a city/country matches an already existing name. +WR_NOT_VALID attempted to delete a built-in city. +WR_DELHOME_ERR attempted to delete the home city. +WR_DEL_CAPITAL_ERR attempted to delete a capital city. + + +WR_GET_ CITY DATA Read city data + + +INT p_iow(VOID *pcb, WR_GET_CITY_DATA, WR_CITY_DATA *result); +Write data associated with the current city to the wR_cITy_pata struct pointed to by result. +The wR_c1tTy_pata struct is defined as follows: +typedef struct +{ +WR_FIND_RES f; +UBYTE units; +UBYTE DST; +WORD GMT; +LATL latl; +TEXT dial [WR_MAX_DIAL+1]; +TEXT STD[WR_MAX_CODE+1]; +P_POINT pos; +} WR_CITY_DATA; +The members of the wR_cr1Ty_pata struct have the following significance: + + +£ the names of the current city and the associated country: for further details see +the description of the WwR_FIND_CITY service. + + +units may be one of the following values: +WR_UNITS_MILES the units of distance are to be miles. +WR_UNITS_KILOMETERS the units of distance are to be kilometers. +WR_UNITS_NAUTICAL the units of distance are to be nautical miles. +DST may be one of the following values: +0x00 the daylight saving time is to be constant. +0x02 the daylight saving time is to be European. +0x04 the daylight saving time is to be American. + + +0x08 the daylight saving time is to be Southern. + + +8 SERIES 3 WORLD DATABASE + + +GMT the local time - this is expressed as a deviation from Greenwich Mean Time in +units of minutes. + + +latl the Lat struct is defined as follows: + + +typedef struct +{ +WORD iLat; +WORD iLong; +} LATL; + + +the iat member gives the latitude of the city in units of minutes of arc. +Positive values correspond to northern latitudes. + + +the iLtong member gives the longitude of the city in units of minutes of arc. +Positive values correspond to western longitudes. + + +dial the city dialling code - stored as a zero terminated string. + +STD the city area code - stored as a zero terminated string. + +pos the coordinates of the city on the World map: used, for example, by the World +application. + + +Returns zero on success, otherwise WR_NOTVALID_ERR if the item is no longer valid, for example, if the +current city has been deleted or renamed. + + +WR_GET_COUNTRY_DATA Read city data + + +INT p_iow(VOID *pcb, WR_GET_COUNTRY_DATA, WR_CITY_DATA *result); +Write the data for the current country to the wR_counTRY_pata Struct pointed to by result. +The wR_countRy_pata struct is defined as follows: + + +typedef struct +{ +WR_FIND_RES f; +UBYTE baseGMT; +UBYTE DST; +WORD GMT; +CO_DIAL dial; +} WR_COUNTRY_DATA; + + +The members of the wR_counrry_para struct have the following significance: + + +£ contains the names of the current country and the associated capital city: for +further details see the description of the wR_FIND_COUNTRY Service. + + +baseGMT reserved for internal use. + + +DST may be one of the following values: +0x00 the daylight saving time is to be constant. +0x02 the daylight saving time is to be European. +0x04 the daylight saving time is to be American. +oxos the daylight saving time is to be Southern. + + +GMT the local time - this is expressed as the deviation from Greenwich Mean Time +in units of minutes. + + +dial the country dialling code information (see below). +The co_prat struct is defined as follows: + + +typedef struct +{ +TEXT dialIntra[WR_MAX_INTRA+1]; +TEXT dialInter [WR_MAX_INTER+1]; +TEXT dial [WR_MAX_CODE+1; +UBYTE dummy; +} CO_DIAL; + + +1/0 DEVICES REFERENCE + + +The significant members of the co_p1at struct have the following meaning: + + +dialintra a zero terminated string of up to four digits, containing the national dialling +prefix. + +dialiInter a zero terminated string of up to four digits, containing the international +dialling prefix. + +dial a zero terminated string of up to eight digits, containing the national code. + + +Returns zero on success, otherwise WR_NOTVALID_ERR indicating that the current country is no longer +valid, for example, if the current country has been renamed. + + +WR_CALC Calculate distance, sunrise and sunset + + +VOID p_ioc(VOID *pcb, WR_CALC, WORD *pstat, WORD *state, WR_CALC_DATA *calc); +INT p_iow(VOID *pcb, WR_CALC, WORD *state, WR_CALC_DATA *calc); + +Obtain the distance of the target city from the home city and the local sunrise and sunset times. +The calculation proceeds in stages in order that it may be discontinued as and when required. + + +The first time the wR_catc service is called, *state must be set to WR_START_STATE. The service should +then be repeatedly called until *st ate is equal to WR_END_STATE indicating that the calculation is +complete. + + +The wR_cALc_paArTa struct is defined as follows: + + +typedef struct +{ +WR_CITY_DATA in; +WR_CALC_OUT out; +} WR_CALC_DATA; + + +The members of the wR_catc_pata struct have the following significance: + + +in specifies the data for the target city: for further details of the wR_cITy_paTa +struct see the description of the wR_GET_CITY_DATA service. + + +out the result of the calculation: the wR_caLc_out struct is defined as follows: + + +typedef struct +{ +WORD distance; +WORD sunRise; +WORD sunSet; +WORD always; +} WR_CALC_OUT + + +the distance member specifies the distance from the home city in the +specified units. + + +the sunRise member specifies the time of sunrise - this is a local time in units +of minutes. + + +the sunSet member specifies the time of sunset - this is a local time in units of +minutes. + + +the always member specifies whether the city is always dark (-1), always light +(1) or neither (0). + + +The completion status code is returned by the synchronous p_iow and written to *pstat by the +asynchronous p_ioc. + + +The completion status code is zero if the request completed successfully, otherwise a negative error code. + + +8 SERIES 3 WORLD DATABASE + + +WR_NEXT_ LOCK Read next city name + + +INT p_iow(VOID *pcb, WR_NEXT_LOCK, WR_FIND_RES *result); + + +Writes the name of the next city as a zero terminated string to the city member of the wR_FIND_REs struct +pointed to by result. + + +The name of the associated country is also written to the country member of the wR_FIND_REs struct +pointed to by result. + + +Returns zero on success, otherwise a negative error. + + +World file types and their locations + + +This section gives a summary of the file structures used by the World Server. The main bulk of the data is +stored using a complex compression algorithm. This cannot be duplicated realistically by a third party +developer, and the functionality is available through the World Server device driver, so it is not given in +detail. + + +Main World file + +The main World database file is stored in the ROM. For a single-language ROM it is: +ROM::WORLD.DAT + +For a multi-lingual ROM is: +ROM::WORLD._ + + +where lang is the language number selected as returned by p_get language, formatted as a 2-digit number, +left-filled with 0 if the language number is <10. + + +For English the filename of the World file in a multi-lingual ROM is ROM::WORLD.DAT. In a multi- +lingual ROM you are obviously going to have a number of such World files. + + +World Extension file + + +Users by default get an extension file World.dat created, but they can make their own world extension +files with different names. These files contain changes to the main data (city additions and changes, and +country changes), which the World Server reads to override the main world database file. + + +World File format + + +First 2 bytes The World file variant signature. This is a scrambled combination of the file version +and language. (Each language can have up to 15 versions; these correspond to new +releases.) + +Next 30 bytes 15 two-byte table pointers. These point to tables, or key positions within tables + +Remaining data Various tables, including a decode table, because all the data following is encoded. + + +I/O DEVICES REFERENCE + + +World Extension File format + +File header + +A World Extension File has a header of 32 bytes: + +First 16 bytes World Extension File signature worldFileType**<0x0> + + +17-18th bytes World file variant signature. On creation is copied from the main database file. Files +which are opened which do not match the main database file are rejected. + + +19-20th bytes Unsigned WORD containing size of extra data block +21st-32nd bytes Not used, filled with oxo bytes +Data block + + +The extra data block follows, which is a string of leading byte count data blocks. Each contains either +city or country alteration information. With the Series 3a and its newer brothers, there is a limit on the +number of blocks to 32 (excluding the final, empty, field). This data block is at least one byte long +(0x0, i.e. a leading byte count list terminator). + + +CHAPTER 9 + + +XMODEM AND YMODEM + + +Introduction + + +All Psion SIBO machines include an Xmodem/Ymodem device driver which implements the industry +standard Xmodem and Ymodem data transfer protocols. Only the data transfer protocols are implemented. +The applications perform the required file I/O. + + +The Psion SIBO Xmodem/Ymodem device driver is attached to a lower level driver which must support +the services provided by the Psion SIBO serial device driver. As it is an attached driver it can run over any +serial channel without modification. + + +There are numerous variations of both the Xmodem and the Ymodem protocols. The following are +supported: + + +e Xmodem Checksum +e Xmodem CRC + +e Xmodem CRC (1K) +e Ymodem + +e Ymodem (1K) + +e Ymodem-G + +e Ymodem-G (1K) + + +I _ +Data transfer protocols overview + + +The Xmodem and Ymodem protocols were established to allow two way error correcting data transfers +between remote computers. The protocols define the data as a series of data blocks each of which is +transmitted with a check for data corruption (a few other bytes are also added - see later sections). The +Xmodem/Y modem device driver supports either a one byte checksum or a two byte CRC data integrity +check. + + +One byte checksum + + +The one byte checksum is the sum of the bytes in the data block with the carries discarded. A one byte +checksum is not as reliable an integrity check as a two byte CRC. + + +Two byte Cyclic Redundancy Check (CRC) + + +The two byte CRC is the remainder after the datablock (treated as a large binary number) is divided by a +sixteen bit number. The supplied device driver uses the CRC sixteen bit divisor recommended by the +CCITT (in polynomial form this is x!° + x!? + x> + 1). The reader should be aware that other CRCs are +also in widespread use (the CRC-16 polynomial for example). + + +I/O DEVICES REFERENCE + + +The Xmodem protocol + + +The Xmodem data transfer protocol was developed in the late seventies as a 'quick hack' for transferring +data between dissimilar machines. It was written on and for machines that had eight bit UARTS +(Universal Asynchronous Receivers and Transmitters) and is thus an eight bit data transfer protocol. + + +The protocol is very simple and thus easy to port to other machines. This and the fact that the original +implementation was placed in the public domain very early in its life has meant that the Xmodem protocol +has become a defacto industry standard data transfer protocol. + + +The protocol lacks many features considered mandatory in modern data transfer protocols including full +duplex transfer and windowing. Worse still it is not robust: corruption of acknowledgement characters or +the data frame header characters can fool the protocol into adopting the wrong state. + + +The file transfer facilities provided by applications that use the protocol simply send the body of the file as +data in data frames. Since the protocol was originally developed on CP/M machines, text files should +consist of lines of printable ASCII terminated by the CRLF (0x0d 0x0a) character sequence, with the file +terminated with the SUB (0x1a) character. It is the responsibility of the application to perform the +required file translation. The SIBO filing system allows text files to be opened in 'stream' mode (i.e. as a +constant data stream with each text record delimited by CRLF characters), see the P_FSTREAM_TEXT +section within the Files chapter of the PLIB Reference Manual. The local filing system of machines in the +SIBO range store data in the same format as MSDOS. Thus a text file can be opened using the P_FsTREAM +mode and still present CRLF delimited data. However a remote filing system, that of the Macintosh for +example, would not necessarily store data in the same format. + + +Binary files can be transferred with the Xmodem protocol. In this case no format is implied. All the data +should be written to file as it is presented in the Xmodem data frames. + + +Link establishment + + +The Xmodem protocol does not define a distinct link establishment phase. The sender of the data waits for +a link establishment character (NAK) and then sends the first data frame. When the first data frame is +received the link is established and both sides are in the data transfer phase. + + +If the sender (receiver) does not receive the expected NAK character (data frame) within a reasonable time +(two minutes for example) it should quit. The receiver will continue sending NAK characters at regular +intervals until either the first data frame is received or the allowed time period has elapsed. + + +The data transfer phase + + +The sender transmits a series of Xmodem Checksum data frames. These consist of: + + +SOH the start of header character (0x01). + +Block number a one byte binary number labelling each data block. The number wraps to zero +at Oxff. + +oxff - block number the one's complement of the block number. This validates the block number. + +Data block a block of 128 data bytes. + +One byte checksum the sum of the data bytes with the carrys discarded. + + +Each frame must contain exactly 132 bytes. Thus when there is insufficient data to fill the data block +padding must be added. Typically the padding consists of end of file (SUB) characters, although NULL +characters would probably be better when sending binary files. + + +If the data and the block number have not been corrupted the receiver will send a positive +acknowledgement character (ACK) requesting the sender to transmit the next data frame. Otherwise the +receiver will transmit a negative acknowledgement character (NAK) requesting the sender to retransmit +the previous (corrupted) data frame. + + +Link termination + + +An Xmodem link termination phase does not exist separately to the data transfer phase. When the last +data frame has been transmitted the sender transmits a one byte EOT character that informs the receiver +that there is no more data. The receiver should acknowledge this in the same way that a normal data +frame is acknowledged, that is with either ACK or NAK characters. Once successfully acknowledged the +link has terminated. + + +9-2 + + +9 XMODEM AND YMODEM + + +Checksum data flow showing error recovery + + +Sender Receiver +NAK + +NAK + +SOH,0x01,0xFE,<128bytes>,CHK +NAK + +SOH,0x01,0xFE,<128bytes>,CHK +ACK + +SOH,0x02,0xFp,<128bytes>,CHK +ACK + +SOH,0x03,0xFc,<128bytes>,CHK + + + +SOH,0x03,0xFc,<128bytes>,CHK +ACK + +EOT +NAK + +EOT +ACK + + +The CRC variant + + +Xmodem CRC differs from the Xmodem Checksum protocol only in the data integrity check and the link +establishment character. + + +The Xmodem CRC protocol data frames include a two byte CRC data integrity check (with the high byte +being sent before the low byte) in place of the one byte checksum. This gives an improved data integrity +check at the expense of an extra byte of non-data - data frames are thus 133 bytes long. The PLIB function +p_crce will generate the required CRC. + + +The receiver establishes an Xmodem CRC link by sending a C (0x43) link establishment character. The +link establishment will fail if the sender does not support the CRC mode. + + +CRC data flow showing error recovery + + +Sender Receiver +C + +Cc + +SOH, 0x01,0xFE,<128 bytes>,CRCHI,CRCLO +ACK + +SOH,0x02,0xFD,<128 bytes>,CRCHI,CRCLO +NAK + +SOH,0x02,0xFpD,<128 bytes>,CRCHI,CRCLO + + + +SOH,0x02,0xFD,<128 bytes>,CRCHI,CRCLO +ACK + +EOT +ACK + + +The 1K variant + + +The 1K variant allows the sender to transmit 1024 bytes of data per data frame. Each 1K data frame starts +with an STX character (not an SOH character) and is otherwise identical to an Xmodem CRC data frame. +The link establishment, data transmission and link termination phases are the same as for the Xmodem +CRC protocol. + + +The 1K option allows 1024 byte data frames to be intermixed with 128 byte data frames, with the +restriction that a retransmitted frame must be the same size as the originally transmitted frame. + + +1K data frames are more sensitive to corruption (remember that the whole data block is destroyed by the +corruption of only one data byte). Thus 1K protocols should not be used when the transmission line is +noisy. + + +The 1K Xmodem variant supports only a two byte CRC data integrity check. It is inadvisable to use a one +byte checksum with 1K data frames and this option is not supported by the supplied driver. + + +I/O DEVICES REFERENCE + + +The 1K option data flow + + +Sender Receiver + +C +STX,0x01,0xFE,<1024 bytes>,CRCHI,CRCLO + +ACK +STX,0x02,0xFD,<1024 bytes>,CRCHI,CRCLO + +NAK +STX,0x02,0xFD,<1024 bytes>,CRCHI,CRCLO + + + +STX,0x02,0xFD,<1024 bytes>,CRCHI,CRCLO + +ACK +SOH,0x03,0xFc,<128 bytes>,CRCHI,CRCLO + +ACK +STX,0x04,0xFB,<1024 bytes>,CRCHI,CRCLO + +ACK +EOT + +ACK + + +Abandoning a transfer + + +The Xmodem specification does not explicitly provide for abandoning a data transfer session. In practice +various implementations will request link abandonment by sending a series of CAN (0x18) characters. +This method does not work well when the sender is currently transmitting a data frame. The safest option +is to continue sending the data frame and afterwards transmit the CAN characters. For a high quality +interface this alternative implies an unacceptable wait (for the 1K protocol with a 1200 baud transmission +rate the wait would be about eight seconds). The second alternative is to quit data frame transmission +immediately and send a series of CAN characters (which could be misinterpreted as belonging to the +abandoned data frame). Even if the receiver misinterprets some CAN characters the session will +eventually be abandoned. + + +When sending data the supplied driver will simply stop transmitting the current data frame and send a +CAN character immediately. + + +When receiving data the supplied driver will send a CAN character. + + +If a CAN character is received by the driver (except as part of a data frame) it will fail any outstanding +request with the E_FILE_CANCEL completion status. + + +The Ymodem protocol + + +The Ymodem protocol was developed from the realisation that the Xmodem protocol has several +weaknesses: + + +e Only one file can be transferred per command. The file name must be entered at both ends of the +link implying that the user has direct or indirect access to both computers (in addition to the +Xmodem link). + + +e The transferred files can contain up to 127 (or even 1023) useless bytes. These are added to pad +out the last data block. + + +e The time and date that the file was last modified are lost. + + +Some of the other weaknesses of the original specification had already been resolved by developing +variants of the Xmodem protocol. These variants (discussed in the previous section) allow for a more +sophisticated data integrity check (the CRC variant) and larger data frames (the 1K variant). + + +The three weaknesses in the above list are all concerned with file transfer rather than data transfer. Unlike +Xmodem, the Ymodem protocol is specifically designed for file transfer. + + +The Ymodem protocol does not attempt to overcome problems with or enhance the actual data flow +protocol. Thus Ymodem is subject to the same data corruption problems as Xmodem. + + +All Ymodem variants use CRCs. + + +9 XMODEM AND YMODEM + + +Link establishment + + +The Link establishment phase is identical to that for Xmodem CRC except that the first data frame +transmitted has a block number of zero rather than one. This block contains file information as follows: + + +e A zero terminated name. This is either the fully specified path name for the file to be transferred +or (more commonly) the file name with no path specified. In either case the name must be +acceptable to both the sender's and receiver's filing systems (in general machines that have +different filing systems will accept only the file name). This field is mandatory. + + +e = The file length. This is stored as a sequence of decimal digits immediately following the zero +terminated name. The receiver may use the file length to set the end of file position at the end of +the transfer. If further fields are present the file length must be present. If there are no further +fields the file length is optional. + + +e = The file modification date. This is stored as a sequence of octal digits specifying the time at +which the file was last modified in seconds from 00:00:00, January 1, 1970 (Unix time). A +single space character separates the file modification date from the file length. If further fields +are present the file modification date must be present. If there are no further fields the file +modification date is optional. + + +e The mode. This is stored as a sequence of octal digits and specifies the file mode. Unless the file +was sent from a Unix machine the mode is set to zero. Files sent from Unix machines that have +the mode set to 0x8000 are assumed to be a Unix type regular file. The mode field is separated +from the file modification date by a single space character. If further fields are present the mode +must be present. If there are no further fields the mode is optional. + + +e Serial number. This is stored as a sequence of octal digits and specifies the serial number of the +sender's software. The receiver's use of this number is optional. The serial number field is +separated from the mode field by a single space character. This field is optional. + + +All undefined fields, and the remaining bytes of the data frame, should be set to zero to allow for future +compatibility. + + +The following code fragment generates the first data frame containing the required Ymodem information +for filename, length and modification date. + + +p_bfil(&buf[0],128,0); +p_finfo(pFilename, &info) ; +p=p_scpy (&buf[0],pFilename) +1; +pt=p_gltob(p,info.size,10); +*ptt=" '; +pt=p_gltob(p,info.modst, 8); + + +When the first frame arrives the receiver should attempt to open the specified file. If the open request is +successful the receiver should send back an ACK to continue with the transfer, otherwise a CAN to cancel +the transfer. + + +When there are no more files to transfer the link connection should be re-established with a zero length +file name, after which the batch file transfer ends. + + +The data transfer phase +The data transfer phase is identical to the Xmodem CRC data transfer phase. + + +Link termination + + +The Ymodem file transfer termination phase does not exist separately from the data transfer phase. When +the file has been transmitted a one byte EOT character is sent to the receiver. The receiver should +acknowledge this in the same way that a normal data frame is acknowledged using either ACK or NAK +characters. The transfer of the file is now complete. When one or more additional files are to be sent the +sender must reestablish a link with the receiver and send the next file in exactly the same manner. When +all files have been sent the sender must send an initial (block number zero) data frame containing a zero +length file name. + + +I/O DEVICES REFERENCE + + +Ymodenm file transfer data flow + + +Sender Receiver + +C +SOH, 0x00,0xFF,,CRCHI,CRCLO + +ACK +SOH,0x01,0xFE,<128bytes>,CRCHI,CRCLO + +ACK +SOH,0x02,0xFD,<128bytes>,CRCHI,CRCLO + +ACK +EOT + +ACK + +C +SOH,0x00,0xf£,,CRCHI,CRCLO + +ACK +SOH,0x01,0xFE,<128bytes>,CRCHI,CRCLO + +ACK +SOH,0x02,0xFD,<128bytes>,CRCHI,CRCLO + +ACK +EOT + +ACK + +C +SOH,0x00,0xf£,,CRCHI,CRCLO + +ACK + + +The 1K variant + + +The 1K variant allows the sender to transmit 1024 bytes of data per frame. The 1K variant data frames are +identical to Xmodem 1K data frames (with the exception of the first frame as discussed earlier). + + +The G variant + + +The Ymodem-G protocol does not have any specified way of reporting an error to the sender, or more +specifically of requesting a re-transmission of a broken data frame. The only advantages over straight +ASCII transfer is that the receiver can detect errors (although nothing can be done about them) and +multiple files can be transferred. The design philosophy seems to have been that error correcting modems +guarantee that the files are not corrupted during transfer and that the inclusion of software error corection +severely reduces the modem's throughput. However error correcting modems only ensure that the data is +not corrupted during the transfer from one modem to another.They do not check for corruption of the data +while it is being sent from the computer to the modem, and vice versa. A typical problem can occur with +PCs connected to networks where some network software insists on disabling interrupts for extended +periods of time, certainly long enough to get serial overrun errors. The Ymodem-G protocol is highly +susceptible to such errors. + + +A Ymodem-G link is established by the receiver sending a G (0x47) character. + + +The Ymodem-G protocol only has acknowledgement characters after the first data frame (indicating that +the file was successfully opened) and after the EOT character (indicating that the file was successfully +closed). + + +The supplied device driver will send a CAN character if an error was detected while in Ymodem-G mode. +This will typically abort the entire transfer. + + +9 XMODEM AND YMODEM + + +Ymodem.-G file transfer data flow + + +Sender Receiver +G +SOH, 0x00,0xFr,,CRCHI,CRCLO +G +SOH,0x01,0xFE,<128bytes>,CRCHI,CRCLO +SOH,0x02,0xFp,<128bytes>,CRCHI,CRCLO +EOT +ACK +G +SOH,0x00,0xf£,,CRCHI,CRCLO +G +SOH,0x01,0xFE,<128bytes>,CRCHI,CRCLO +SOH,0x02,0xFpD,<128bytes>,CRCHI,CRCLO +EOT +ACK +G + + +SOH,o0x00,0xf£,,CRCHI,CRCLO + + +Abandoning a transfer + + +The Ymodem specification does not explicitly provide for abandoning a data transfer session. Various +implementations will send CAN (0x18) characters in an attempt to inform the remote computer that the +data transfer session should be abandoned. + + +When sending data the supplied driver will simply stop transmitting the current data frame and send a +CAN character immediately. + + +When receiving data the supplied driver will send a CAN character. + + +If a CAN character is received by the driver (except as part of a data frame) it will fail any outstanding +request with the E_FILE_CANCEL completion status. + + +Protocol problems + + +The primary task of any data transfer protocol is to ensure that the data sent is the same as the data +received. If the physical media being used could not corrupt the data then ASCII file transfer would be +ideal since no overheads are required in validating the data. + + +Although the Xmodem and Ymodem protocols address the majority of problems concerned various holes +in the error recovery have been pointed out. For example: + + +e Synchronisation will be lost if the NAK character sent by the receiver is corrupted to an ACK +character. The transfer will thus fail. + + +e = The use of different link establishment and acknowledgement characters for Xmodem, Ymodem +and Ymodem-G protocols can lead to confusion if the character is corrupted. For example, the +Ymodem protocol attempts to establish the link by sending a C character. Corruption of the +C to aG would fool the receiver into connecting in Ymodem-G mode. + + +e The use of anonymous acknowledgement characters for requesting data frame (re)transmission +can cause timing problems. For example, consider a receiver that sends an ACK or NAK +character requesting transmission of a data frame and finds that the sender is preoccupied. The +protocol allows for the receiver to wait for a specified time interval and then send another ACK +or NAK character. This will work fine unless the sender replies after transmission of the second +ACK or NAK character, and before its receipt. In this case the receiver will assume that the +transmitted data frame corresponds to the second ACK or NAK character and thus +synchronisation will be lost. + + +In actual field usage the Xmodem and Ymodem protocols perform more than adequately. + + +I/O DEVICES REFERENCE + + +ee en +Xmodem/Ymodem services + + +p_open(XMD:) Open an Xmodem/Ymodem channel + + +INT p_open(VOID **ppXmodem, "XMD:", —-1); + + +Attach the Xmodem/Ymodem driver to the open channel specified by ppxmodem. All I/O requests on that +channel will now be routed to the Xmodem/Ymodem device driver. + + +The passed channel is assumed to support the set of services provided by the serial driver. Currently only +the try: driver supports the serial services. + + +For example: +VOID *pcb; +if (!p_open(&pcb, "TTY:A",-1) ) +{ + + +if (!p_open(&pcb, "XMD:",-1) ) +{ + + +p_close (pcb); +} + +p_close (pcb) + +} + + +Note that two calls to p_close are required, one to close the channel to the Xmodem/Ymodem driver and +the second to close the channel to the serial driver. + + +The Xmodem/Ymodem driver senses the current serial driver's characteristics, removes any XON/XOFF +handshaking, sets the terminator mask to zero and sets the framing to eight bits, no parity and one stop +bit. The original serial characteristics are restored when the driver is closed. + + +Once a channel to the Xmodem/Ymodem driver has been opened, the application must connect to the +computer at the remote end. This done with the p_FconNECT service. + + +The calling process will be panicked if the serial driver to which the Xmodem/Ymodem driver is attached +has any outstanding requests on it. + + +Returns zero if the request completed successfully otherwise a negative error number. + + +p_close Close the Xmodem channel + + +INT p_close(VOID *pXmodem) ; + + +Close the Xmodem channel specified by pXmodem. The device driver should be closed when the file +transfer has completed. All I/O requests on the driver channel will then be routed to the underlying serial +driver. + + +Every outstanding request on the Xmodem/Ymodem driver will be completed, its completion status word +will be set to E_FILE_CANCEL and a signal will be generated. + + +The characteristics of the serial driver are restored to the values held before the Xmodem/Ymodem driver +was opened. + + +The p_FCLOSE request cannot fail and returns zero. + + +P_FCONNECT Connect to the remote computer + + +VOID p_ioc(VOID *pXmodem, P_FCONNECT, WORD *pstat, UWORD &type, UWORD &mode) ; +INT p_iow(VOID *pXmodem, P_FCONNECT, UWORD &type, UWORD &mode) ; + + +Obtain a connection to a computer assumed to be running some Xmodem/Ymodem software. +The connection type can be established as one of: +@ =P_XMDM_ACCP + + +e P_XMDM_INIT + + +9-8 + + +9 XMODEM AND YMODEM + + +where p_xmpmM_accp would be used to accept a connection (the application wishes to transmit a file or +files) and p_xmpM_1nrtT would be used to initiate the connection (the application wishes to receive a file or +files). + + +The connection mode determines the file transfer mode and can be one of: + + +P_XMDM_CRCORCHECKSuUM _ the connection should be established in either Xmodem checksum or Xmodem +CRC mode depending on which mode is supported by the remote computer. +The driver has a bias towards CRC mode. When transmitting connection +request characters it sends two CRC connection request characters (C,0x43) to +every checksum connection request character (NAK,0x15). When accepting a +connection it will throw away the first NAK character it receives while waiting +for a potential C character. + + +P_XMDM_CHECKSUMMODE the connection should be established in Xmodem checksum mode only. This +will connect to a remote computer that is using checksum mode faster than the +P_XMDM_CRCORCHECKSUM option. (If the remote computer is trying to establish a +connection in CRC mode a connection will still be established. This fact will +be reported to the caller.) + + +P_XMDM_CRCMODE the connection should be established in Xmodem CRC mode only. If the +remote computer does not support CRC mode no connection will be +established. + +P_YMODEM_MODE the connection should be established using the Ymodem batch protocol. + +P_YMODEM_G_MODE the connection should be established using the Ymodem-G batch protocol. + + +As an option on any of the protocols that support CRC error checking (Xmodem CRC and all the +Ymodem variants) the p_xmpM_onz_x flag can be ored into mode to indicate that data frames of size 1K +can be transmitted and received. + + +For example: +mode=P_XMDM_CRCMODE | P_XMDM_ONE_K; + + +When this flag is not set the Xmodem/Ymodem driver will refuse to accept 1K data frames and will +instead reply with NAK characters. This will eventually cause the data transfer to fail. + + +When a connection cannot be established, the reason for the failure will be written back to the completion +status word. + + +If the connection is successfully established the completion status word will contain zero and the actual +connection mode will be written back to mode. + + +For example: + + +type=P_XMDM_INIT; +mode=P_XMDM_CRCORCHECKSUM; +if (!p_iow(pXmodem, P_FCONNECT, &type, &mode) ) +{ +if (mode==P_XMDM_CRCMODE) +p_puts ("CRC mode") +else if (mode==P_XMDM_CHECKSUMMODE) +p_puts ("Checksum mode") + + +} +Note that the data space for mode must be preserved until the connection request completes. + + +In general the connection request will take an extended time. Thus the request should be made +asynchronously. The connection request can be cancelled with the p_FDISCONNECT service. + + +If the p_FconnEcT request was started successfully the I/O request returns either zero or a negative error +number. + + +The completion status word is returned by the synchronous p_iow request and written to *pstat by the +asynchronous p_ioc request. It is set to =_FILE_PENDING while the request is outstanding and zero on +successful completion. If the request fails to complete it is set to a negative error number. + + +The calling process will be panicked if there is an outstanding p_rcoNnNECcT request. + + +I/O DEVICES REFERENCE + + +Examples + + +To receive files using the Xmodem-CRC 1K protocol: + + +type=P_XMDM_INIT; + +mode=P_XMDM_CRCMODE | P_XMDM_ONE_K; + +if (!p_iow(pXmodem, P_FCONNECT, &type, &mode) ) +{ + + +} +To send files using the Ymodem batch protocol: + + +type=P_XMDM_ACCP; + +mode=P_YMODEM_MODE; + +if (!p_iow(pXmodem, P_FCONNECT, &type, &mode) ) +{ + + +} +To send files using the Ymodem-G 1K batch protocol: + + +type=P_XMDM_ACCP; + +mode=P_YMODEM_G MODE |P XMYM_ONE_K; + +if (!p_iow(pXmodem, P_FCONNECT, &type, &mode) ) +{ + + +P_FDISCONNECT Disconnect from the remote + + +INT p_iow(VOID *pXmodem, P_FDISCONNECT) ; +Disconnect from the remote computer. + + +The P_FDISCONNECT request can also be used to abandon the Xmodem/Ymodem session during the +connection establishment or data transfer phases. + + +If a connection has already been established then the p_rp1IscoNnNEcT request will cause a CAN character +to be transmitted to the remote computer. This may or may not be picked up by the remote +Xmodem/Ymodem implementation to indicate that the data transfer phase is being abandoned. The +Xmodem/Ymodem protocols do not have any standard mechanism for abandoning data transfer. + + +If no connection has been established yet, or if the transfer is now complete, no characters will be +transmitted to the remote computer. + + +Any outstanding asynchronous requests will be cancelled by the p_FpIsconnEcT request, and their +completion status words set to E_FILE_CANCEL. For each outstanding request a signal will be generated +and must be used up by the application. + + +Typically the p_FDISCONNECT request would be called synchronously. +The P_FDISCONNECT request can not fail and returns zero. + + +Example + + +type=P_XMDM_INIT; +mode=P_XMDM_CRCORCHECKSUM; +p_ioc (pXmodem, P_FCONNECT, &xStat, &type, &mode) ; +p_ioc(pConsole, P_FREAD, &kStat, &kbr) ; +p_iowait(); +if (xStat!=E_FILE_PENDING) + +{ /* Xmodem connect completed */ + + +} +else +{ /* key press occurred - cancel P_FCONNECT */ +p_iow (pXmodem, P_FDISCONNECT) ; +p_waitstat (&xStat); + + +9 XMODEM AND YMODEM + + +P_FREAD Read data from the remote computer + + +VOID p_ioc(VOID *pXmodem, P_FREAD, WORD *pstat, UBYTE *buffer, UWORD *plen)j; +INT p_iow(VOID *pXmodem, P_FREAD, UBYTE *buffer, UWORD *plen); + + +Read data from the remote computer. If the connection was not established with a type of p_xmpm_rntT the +request will fail with the negative error E_FILE_DISc. + + +When data is available it will be written to the buffer pointed to by buffer and the length of the data will +be written to *plen. + + +When the end of data indicator (EOT) from the remote computer is received the p_rreap request will be +completed with the (negative) z_F1ILE_zoF error number. + + +The application is responsible for supplying a buffer large enough to hold the largest data frame that can +arrive. If the p_xmpM_onz_k mode flag was set in the p_rconnecT request this is 1024 bytes otherwise it is +128 bytes. + + +If the Ymodem protocols are being used the first data frame read will contain the Ymodem file +information. + + +If the p_rREAD request was started successfully the synchronous I/O request returns zero otherwise it +returns a negative error number. + + +Whilst an asynchronous P_FREAD request is outstanding the completion status word is set to +E_FILE_PENDING. On completion the status word is set to zero if the read request completed successfully +otherwise a negative error number. In particular the completion code is set to E_F1LE_zoF if there is no +more data to read. + + +The calling process will be panicked if there is an outstanding p_rREapD request. + + +Examples + + +Receiving multiple files using the Ymodem protocol: + + +type=P_XMDM_INIT; +mode=P_YMODEM_G_MODE; +FOREVER +{ +if (ret=p_iow(pXmodem, P_FCONNECT, &type, &mode) ) +break; +if (ret=p_iow(pXmodem, P_FREAD, &fileinfo[0],élen) ) +break; +if (!p_slen(&fileinfo[0])) +{ /* finished multi-file receive */ +ret=0; +break; +} +p_open (&pFile, &fileinfo[0],P_FUPDATE|P_FSTREAM|P_FREPLACE) ; +while (! (ret=p_iow(pXmodem, P_FREAD, &buf[0],&len) ) ) +{ +if (ret=p_write (pFile, ébuf[0],1len) ) +break; +} +if (ret==E_FILE_EOF) +{ +/* Truncate the file as specified in fileinfo[] */ +} +p_close(pFile) ; +/* set the file modification date */ +if (ret!=E_FILE_EOF) +break; +} +p_iow (pXmodem, P_FDISCONNECT) ; +if (ret) +p_puts ("Error receiving files"); + + +I/O DEVICES REFERENCE + + +Receiving a single file using the Xmodem protocol: + + +type=P_XMDM_INIT; +mode=P_XMDM_CRCORCHECKSUM; +if (!p_iow(pXmodem, P_FCONNECT, &type, &mode) ) +{ /* Xmodem connect completed */ +p_open (&pFile, "temp.tmp", P_FUPDATE |P_FSTREAM|P_FREPLACE) ; +while (! (ret=p_iow(pXmodem, P_FREAD, &buf[0],&len) ) ) +{ +if (ret=p_write(pFile, ébuf[0],1len) ) +break; +} +p_close(pFile) ; +p_iow (pXmodem, P_FDISCONNECT) ; +if (ret!=E_FILE_EOF) +p_puts ("Error occurred"); + + +P_FWRITE Write data to the remote computer + + +VOID p_ioc(VOID *pXmodem, P_FWRITE, WORD *pstat, VOID *buffer, UWORD *plen); +INT p_iow(VOID *pXmodem, P_FWRITE, VOID *buffer, UWORD *plen); + + +Write data to the remote computer. If the connection was not established with a type of P_xmpM_accp the +request will fail with the negative error E_FILE_DISc. + + +Data can be written in buffers of 128 or 1024 bytes, although the device driver does not check whether or +not the connect request specified the p_xmpm_onE_x flag. If the receiver has not been set up to receive +1024 byte frames (the 1k option) it will in general fail to accept the data. + + +The 1K option specification allows the user to intermix the transmission of 128 and 1024 byte frames, this +driver conforms to that specification. + + +If the write request is for fewer than 128 bytes the internal transmit buffer is padded to 128 bytes with +SUB (0x1a) characters. If the request is for more than 128 but fewer than 1024 characters, the internal +buffer will similarly be padded with SUB characters. + + +As an exception to the above, if a write request of zero length is received this is taken to indicate that the +end of text marker should be transmitted to the remote computer, thus completing that data transfer. + + +Unlike for many device drivers the application does not have to preserve the data buffer or the length word +data spaces until data transmission has completed. + + +If the Ymodem protocols are being used the first data frame to be written is assumed to contain the +Ymodem file information. + + +If the p_rwRITE request was started successfully the I/O request returns zero otherwise it returns a negative +error number. + + +Whilst an asynchronous P_FWRITE request is outstanding the completion status word is set to +E_FILE_PENDING. On completion the status word is set to zero if the write request completed successfully +otherwise, it is set to a negative error number. + + +The calling process will be panicked if there is an outstanding P_FwRITE request. + + +9 XMODEM AND YMODEM + + +Examples + + +Sending a single file using the Xmodem protocol: + + +type=P_XMDM_ACCP; +mode=P_XMDM_CRCMODE; +if (!p_iow(pXmodem, P_FCONNECT, &type, &mode) ) +{ /* Xmodem connect completed */ +p_open (&pFile, "temp.tmp", P_FOPEN|P_FSTREAM|P_FSHARE) ; +while ((len=p_read(pFile, &ébuf[0],128) )>0) +{ +if (ret=p_iow(pXmodem, P_FWRITE, &buf[0],&len) ) +break; +} +if (!ret && (!len || len==E_FILE_EOF) ) +{ +len=0; /* Force EOT to be sent */ +p_iow (pXmodem, P_FWRITE, &buf[0],&len); +} +p_close(pFile) ; +p_iow (pXmodem, P_FDISCONNECT) ; +if (ret) +p_puts ("Error occurred") ; + + +Sending multiple files using the Ymodem protocol: + + +type=P_XMDM_INIT; +mode=P_YMODEM MODE |P XMDM_ONE_K; +FOREVER + +{ + +if (ret=p_iow(pXmodem, P_FCONNECT, &type, &mode) ) + + +break; +if (! (ret=getNextFileName (&name[0]) ) ) +break; /* gets Ymodem 1st frame info */ +len=128; +if (ret=p_iow(pXmodem, P_FWRITE, &name[0],&len); +break; + + +p_open (&pFile, gname[0],P_FOPEN|P_FSTREAM|P_FSHARE) ; +while ((len=p_read(pFile, &buf[0],1024) )>0) + + +if (ret=p_iow(pXmodem, P_FWRITE, &buf [0], &len) ) +break; + + +if (!ret && (!len || len==E_FILE_EOF) ) + + +len=0; /* Force EOT to be sent */ +p_iow (pXmodem, P_FWRITE, &buf[0],&len); + + +p_close(pFile); +if (ret) +break; +} +p_iow (pXmodem, P_FDISCONNECT) ; +if (ret) +p_puts ("Error sending files"); + + +CHAPTER 10 + + +NCP AND LINK + + +Introduction + + +This chapter describes the Psion Link application and the peer to peer data transfer services that are +provided to enable client server type applications to communicate with each other when the client and +server processes exist on different machines. + + +The basic Link application consists of two processes: LINK and syssncp. The Linx process varies from +machine to machine and provides only the user interface and one basic service. The syss$ncpP process is +identical on all machines and handles the physical connection and data transfer services. + + +The Link application is organised in four layers, each of which is responsible for a particular job: + + +e Physical Layer: for example the Serial Driver. This layer provides a set of services that hide any +hardware dependencies from the Logical Layer. + + +e Logical Link Layer. This layer provides the logical (hardware independent) services required by +the third layer. + + +e Data Transport and Multiplexing Layer +e = Application Layer + + +The first three layers are contained within the syssncp process, whose services are accessed via the NcP: +device driver. The syssncp process provides the data transport mechanism that allows client server +processes on different machines to communicate with each other. + + +There are many possible application layers, one of which is the LINK process. Client and server processes +are also examples of application layer processes. + + +Panics + + +All services (with the exception of p_open) will cause the calling process to be panicked if the passed +channel handle is not valid. Other panics are described under the particular service to which they apply. + + +The Psion logical link layer protocol + + +The Psion Link protocol provides the logical link layer services required by the syssncp process. The +services provided are fairly primitive. The syssncp process adds value to these services. A brief summary +of the protocol is presented here to aid in the explanation of the overall system. + + +The Psion Link protocol is a proprietary protocol based on the MNP protocol. It provides a symmetrical +‘error-free’ link between computers including: + + +e Full duplex data transmission. + +e 16 bit CRC error detection. + +e Multiple retransmissions. + +e Dataframe sequencing. + +e Variable dataframe size up to a maximum of 300 bytes per dataframe. + + +e A window size of one. + + +10-1 + + +I/O DEVICES REFERENCE + + +One of the major design criteria of the protocol was that it could be implemented in a very small amount +of code and required a small working set. Thus features such as large data frames (eg 1K) and windowing +were rejected. + + +The protocol is a data transfer protocol, not a file transfer protocol. The file transfer or more accurately +file access and management services are provided by application layer processes. + + +The SYS$NCP process + + +The two primary functions of the syssncp process are connection establishment and data transfer. +Connection establishment + + +A connection is established when the following criteria have been met: + +e A physical link has been established. + +e A logical link has been established. + +e The syssncp process has successfully exchanged logon messages with its remote counterpart. +If any of the above fail or the remote counterpart is not compatible a connection will not be established. + + +A physical link is deemed to have been established when the local machine detects that the remote +machine is driving the DTR (local machines DSR) hardware handshaking line (for further details see the +Serial Port chapter). + + +When establishing a modem link, a physical link is deemed to have been established when a modem +driver reports that an incoming call has arrived or that the dial request has been sucessful. + + +A logical link is deemed to have been established when the Pp_FconneEcT request on the link layer protocol +driver completes sucessfully. + + +The syssncp processes exchange logon messages that contain a version number and the time at which the +process was started. + + +The version numbers are checked to ensure compatibility (for possible future expansion). + + +The communicating sys$NncP processes exchange the time at which each was started so as to allow +connection re-establishment in the event of an error at either the logical or physical layer. The re- +establishment of the application layer connections (if present) will be transparent to the applications. + + +Data transfer + + +The syssncp process creates eight separate logical (software implemented) channels through which +applications can communicate. The first channel, channel zero, is used by the sys$ncp process, leaving +seven channels free for client server applications. When sending data the syssncp process multiplexes the +eight logical channels into one physical channel. Conversely, when receiving data the process +demultiplexes the data from one physical channel to eight logical channels. + + +The transferred data can be divided into control data and application data. + + +Control data is the data exchanged between communicating syssNcp processes that concerns application +connection, disconnection and data flow control. + + +Application data is the data exchanged between connected applications. It is transparent to the sys$ncP +process (which places no significance on any of the transferred bytes). Full 8 bit data transfer is available. +The syssncp process simply ensures that the data sent on a particular channel is routed to the correct +destination process. + + +The syssncp process removes a limitation of the logical link layer, namely the data frame size. The +SYSSNCP process will 'segment' application data such that the only frame size limitation is that of the +particular application. + + +10-2 + + +10 NCP AND LINK + + +The LINK process + + +The three primary tasks of the LINK process are: +e to provide a user interface for the Link application +e to respond to state changes in the syssncp process +e to set up the remote filing system, after successful connection establishment. + + +On both the Series 3 and the HC, the Link application has no visible user interface: the application is +started and stopped by the system process. For example, on the Series 3 the user turns the Link application +on or off and sets the baud rate by selecting the Remote link option on the Special menu. The system +process launches or terminates the application accordingly. + + +Since there is no user interface on the Series 3 and the HC, all state changes are handled without +prompting the user for a response. See the p_rFRsuPER and P_FINQ services described below. + + +When the syssncp informs the L1nx process that a connection has been established the L1nx process at +each end runs a process called syssrrsv (the remote file server process). The syssrrsv process provides +remote file access and management services. The L1nx process then adds the REM-:: filing system PDD +(Physical Device Driver) to the file server, thus creating a client server pair. + + +The 1nx process also sets itself up as an IPC (InterProcess Communication) message receiver. An +application may send the following messages to the LINK process: + + +LNKMSG_TERMINATE request that the Link application terminate. This involves removing the remote +file system client server pair, and informing the syssncp process that it should +terminate. Instead of sending a message directly an application can use the +p_pterminate system service to send this message indirectly. + + +LNKMSG_LOADREMOTE request that a message to load and run a specified process be sent to the remote +LINK process. The message is assumed to contain up to E_Max_NamE + 2 bytes. +The message consists of the name of the remote process that is to be loaded +followed by an optional leading byte count command line. If a command line +is required then the process name must be padded out to z_max_namE + 2 bytes +(with NULLS) for compatiblity purposes. The name is parsed with .JMG and +the resultant file name (no device or path) taken as the match pattern for a +search that will firstly look in the default directory of the remote LINK process +(typically LOC::M:\) then in the root directory of any devices that exist on the +remote machine and finally in the ROM. If a process is sucessfully loaded it +will be resumed immediately, the remote L1nx process will force a context +switch to allow the newly loaded process to run, typically for long enough to +open a channel on the nce: device. The resultant process id and full process +name are sent from the remote L1Nnx to the local tnx process. The local L1nk +process will write back the full process name into the buffer passed and +complete the IPC message send with the positive remote process id or negative +error number, very similar to the return values for p_execc. + + +LNKMSG_CONFIG request that the L1nx process inform the syssncp process to change its driver +configuration. The message parameter is the full pvrs struct to be passed to the +SYSSNCP process. + + +The tnxmsc_... message numbers can be found in link_def.h and the pvrs struct definition is in sys$ncp.h. + + +NCP services + + +p_open(NCP:) Open an NCP channel +INT p_open(VOID **ppNcp,"NCP:",-1); + + +Requests that a channel to the SYS$NCP process be opened and a channel allocated to the calling process +in preparation for connection to, and communication with, a remote process. + + +10-3 + + +I/O DEVICES REFERENCE + + +The nep: device driver is a root device driver, it does not require any opened channels to be passed to the +p_open request. All I/O requests on the allocated channel will be routed to the sys$ncp process by this +device driver automatically. + + +Opening a channel does not cause any data to be transferred to the remote machine. +A single process may open as many channels on the ncp: device as it likes. + + +If a process terminates for any reason without closing the channel to the ncp: device the syssNncP process +will tidy up, reporting to any remotely connected channel that this channel has now been closed. + + +Returns zero if the open request completed sucessfully otherwise a negative error number. A typical error +is that the syssncp process is not currently running in which case the E_FILE_NxIST error value will be +returned. + + +Example + + +if (!p_open(&pNcp, "NCP:",-1) ) +{ + + +p_close(pNcp) ; +} + + +p_close() Close the NCP channel +INT p_close(VOID *pNcp) ; +Requests that the currently opened channel to the syssncp process be closed. + + +Any outstanding I/O requests will be completed with the E_FILE_CANCEL completion status and a signal +will be generated. + + +If the process is still connected to a remote process the remote process will be informed that the +connection has been closed, any outstanding requests the remote process has will be completed with the +E_FILE_DIsc completion status. + + +The close request cannot fail and always returns zero. + + +P_FCONNECT Connect to a remote process + + +VOID p_ioc(VOID *pNcp, P_FCONNECT, WORD *pstat, UBYTE *pname, UWORD *plen); +INT p_iow(VOID *pNcp, P_FCONNECT, UBYTE *pname, UWORD *plen); + + +Requests that the channel be connected to a remote channel that has been opened by the named process. + + +In a typical client server application only the client process would make a p_FCoNNECT request. The server +process would typically open an nce: channel and queue a P_FREAD request awaiting its first command +from a client. + + +If both processes of an application attempt to obtain a connection they should ensure that their counterpart +is running and has an nce: channel open before making the P_FCONNECT request otherwise the request will +fail with the E_FILE_NxIstT completion status. Obviously if the connection request fails with the +E_FILE_NXIST completion status the request can be retried. The number of retries should, however, be +limited. + + +If an open channel is already connected to a remote channel the request will complete sucessfully. + + +In the Link application both of the L1nx processes attempt to obtain a connection. In this case both of +these processes will be running and have an ncp: channel open, since they launch the syssncpP process in +the first place. + + +The pname parameter is a pointer to a buffer containing the name of the remote process to connect with. +The name is used as the match parameter to the p_pidfind service on the remote machine. If that process +does not exist or does not have an opened syssncp channel the request will fail with the =_FILE_NxIsT +completion status. The data space pointed at is assumed to remain valid until the completion of the +P_FCONNECT request. + + +10-4 + + +10 NCP AND LINK + + +The plen parameter points to a word containing the length of the buffer at pname including the zero +terminator. The data space pointed at is not required to remain valid until the completion of the +P_FCONNECT request. + + +The p_Fconnect request will typically take a significant length of time and as such should be called +asynchronously in a quality system. + + +The p_FconnectT request may be cancelled by using the p_FcanceEt service, the original request will be +completed with r_FILE_CANCEL completion status and a signal generated. + + +How the remote process came to be running in the first place is of no concern to the syssncp process, it is +however of great concern to an application writer. + + +Three primary methods are available to get the remote process running: +e Inturnkey systems the remote process may be automatically loaded by the system initialisation. + + +e The user may be prompted to run the remote process from the command shell or system +applications. + + +e An application can request that the Linx process run the remote process on its behalf. +The latter of these three methods is the most general and is best explained by an example as given below. + + +The completion status is written to *pstat by an asynchronous request and returned by a synchronous +request. The status is zero if the service completed successfully, otherwise it is a negative error number. + + +Errors include: + + +E_FILE_NXIST the named process does not have a channel open on the remote syssncp. + +E_FILE_DISC the link is disconnected, there is no data path available to talk to the remote +SYSSNCP. + +E_FILE_LINE the link was disconnected whilst attempting to send data to the remote +SYSSNCP. + +E_FILE_RETRAN the retransmission threshold was reached because the link has been +disconnected. + +Example + + +Simple connection to a currently running remote process: + + +if ('!p_open(&pNcp, "NCP:",-1) ) +{ +len=8; /* incl zero terminator */ +if (!p_iow(pNcp, P_FCONNECT, "RPROC.*", &len) ) +{ + + +p_iow(pNcp, P_FDISCONNECT) ; +} + +p_close (pNcp) ; + +} + + +Connection to a remote process that is not currently running: + + +if ((linkPid=p_pidfind("LINK.*") ) <0) +p_exit (1); +p_scpy (&bb[0],"RPROC.IMG"); /* name only, no paths */ +p=(&bb[0]); +if (p_msendreceivew (linkPid, LNKMSG_LOADREMOTE, &p) <0) +p_exit (1); +len=p_slen(&bb[0])+1; /* full process name here now */ +if (!p_iow(pNcp, P_FCONNECT, &bb[0], &len) ) +{ + + +p_iow(pNcp, P_FDISCONNECT) ; +} + + +10-5 + + +I/O DEVICES REFERENCE + + +P_FDISCONNECT Disconnect from the remote process + + +INT p_iow(VOID *pNcp, P_FDISCONNECT) ; + + +Requests that the current connection to a remote process be broken. An application may use the channel to +connect to the same remote process or a different remote process if required. + + +Any outstanding P_FREAD or P_FWRITE requests will be completed with the E_FILE_CANCEL completion +status and a signal generated. + + +A P_FDISCONNECT request is harmless if no connection has been established or the current connection is +temporarily disconnected. + + +The p_FDISCONNECT request cannot fail and returns zero. + + +P_ FREAD Read data from the remote process + + +VOID p_ioc(VOID *pNcp, P_FREAD, WORD *pstat, UBYTE *buf, UWORD *plen); +INT p_iow(VOID *pNcp, P_FREAD, UBYTE *buf, UWORD *plen); + + +Requests that the next 'message' sent by the remote process be placed in the buffer provided, the length of +which be written to *plen. + + +A ‘message’ is the data sent by the remote application process in a P_FWRITE request. The contents of the +message and its format are entirely determined by the application using the ncp: channel. + + +The buffer provided must be large enough to hold the largest message that can be sent by the remote +application at this point in time (it does not necessarily follow that this is the largest possible message that +can be sent). The syssncp process does not check that the buffer provided is large enough, it simply writes +the message into the buffer. If the buffer is not large enough then other data will invaribly become +corrupted. + + +The data space pointed at by both the buf and plen parameters must be preserved until the P_FREAD +request completes. + + +The p_FREAD request will typically take a significant length of time and as such should be called +asynchronously in a quality system. + + +The p_FREAD request may be cancelled by using the P_FcaNcEt service, the original request will be +completed with E_FILE_CANCEL completion status and a signal generated. + + +A channel connection does not have to exist for a process to queue a P_FREAD request on the channel. In a +typical client-server application the client would run the remote server process which would open an NcP: +channel and queue a P_FREAD request. The client would queue a P_FCONNECT request and when complete +send the server any messages as required using the P_FWRITE service. + + +The calling process will be panicked if a p_FREAD request is currently outstanding or if pNcp is not a valid +channel handle. + + +The completion status is written to *pstat by an asynchronous request and returned by a synchronous +request. The status is zero if the service completed successfully, otherwise it is a negative error number. + + +Errors include: + + +E_FILE_LINE the physical link has failed. This is typically caused by the remote machine +or switching off or the pack doors being opened. The application process if a +E_FILE_RETRAN server Can re-queue a P_FREAD request awaiting the next message. Typically + + +the server should preserve the current state awaiting the next request. A client +would typically report the error and await user input before retrying the +operation. + + +E_FILE_DISC the channel has become disconnected because the remote application process +has terminated (either normally or abnormally). The application should tidy up +any resources and terminate. + + +E_GEN_RECEIVER the remote syss$NcpP process is terminating or a new one has attempted to +connect to the local syssncp process. The application should tidy up any +resources and terminate. + + +Example + + +See the client-server example at the end of this chapter. + + +10 - 6 + + +10 NCP AND LINK + + +P_FWRITE Write data to the remote process + + +VOID p_ioc(VOID *pNcp, P_FWRITE, WORD *pstat, UBYTE *buf, UWORD *plen); +INT p_iow(VOID *pNcp, P_FWRITE, UBYTE *buf, UWORD *plen)j; + + +Requests that the 'message' contained in the buffer of length *pien be sent to the connected process. +The data space pointed to by buf must be preserved until the p_rwriTE request completes. + + +The syssncp process contains a flow control mechanism such that if a process sends data to a connected +process faster than it can handle it, backwards pressure is applied to the sending process by the local +syssncp process. This mechanism is transparent to both the sender and receiver of the message. This flow +control is such that a sending process may send data as fast as it likes without the receiver ever being +swamped. + + +The amount of data that can be sent in one message is only restricted to the size of the sending processes +data space (64K less the stack, static variables and other allocated cells) however, the receiving process +must have a buffer as large as the largest message that can be sent. + + +A channel must be connected to a remote channel before a p_FwritTE request is made, if not the request +will complete with z_r1LE_p1sc completion status. + + +When the p_FwRITE request completes sucessfully this indicates that the remote process to which the +message has been sent has received that message. It does not indicate that the remote process has +sucessfully processed that message. + + +The p_FrwrRITE request will typically take a significant length of time and as such should be called +asynchronously in a quality system. + + +The p_FwrITE request may be cancelled by using the p_FcanceEt service, the original request will be +completed with &_FILE_CANCEL completion status and a signal generated. + + +The calling process will be panicked if a p_rwRitE request is currently outstanding or if pNcp is not a valid +channel handle. + + +The completion status is written to *pstat by an asynchronous request and returned by a synchronous +request. The status is zero if the service completed successfully, otherwise it is a negative error number. + + +Errors include £_FILE_LINE, E_FILE_RETRAN, E_FILE_DISsc and E_GEN_RECEIVER, all of which have the +same meaning as for the p_rREAD service. + + +Example + + +See the client-server example at the end of this chapter. + + +P_FCANCEL Cancel any outstanding request +INT p_iow(VOID *pNcp, P_FCANCEL) + + +Requests that any outstanding requests be cancelled, the outstanding requests will complete with the +E_FILE_CANCEL completion status and a signal be generated. It is indeterminate as to how much of the +message being sent to the remote process (using P_FWRITE) has actually been sent. + + +The p_rcancex request should typically only be used to cancel requests immediatly before the application +terminates. + + +The p_FcancEL request cannot fail and returns zero. + + +P_FRSUPER Read supervisory information +INT p_iow(VOID *pNcp, P_FRSUPER, NCLINK_INFO *pinfo, UWORD *plen); + +This function should only be called by a process that replaces the L1nxK process. + +Requests that the next state change be written back to the supplied buffer. + + +One process in the system is responsible for receiving the state change messages and responding to them. +In the supplied system this is the tnx process. In order for the process receiving the state change +messages to ensure that it does not miss any of the messages (and cause potential system deadlock) it +should have a process priority higher than that of the syssncp process. A priority of OxBO is adequate. + + +10-7 + + +I/O DEVICES REFERENCE + + +A connection does not have to exist (and infact should not exist before the first request is made) for this +request to be queued sucessfully. + + +Some state changes are purely informational and can be used as such as required, others require some +action before the syssNncp process can continue. The action may be hard coded into the LINK process +(typically the non user interface versions) or prompt the user for a solution to the new state. + + +The following informational state changes are reported: + + +PHYS_PHYS_LINK_ESTABLISHED, a physical link has been sucessfully established. The L1nx +process on the Series 3 and HC ignores this message. + + +PHYS_WAITING_FOR_CALL, the physical layer is waiting for an incoming call from the modem +driver in order to obtain a physical connection. The L1nx process on the Series 3 cannot receive +this status message as there is no modem driver available. On an HC the message is ignored. + + +PHYS_DIALLING_NUMBER, the physical layer is currently dialing a phone number in order to obtain +a physical connection. The phone number that is being dialled is in the 'phoneno' field of the +Dvrs struct. The LINK process on the Series 3 cannot receive this status message as there is no +modem driver available. On an HC the message is ignored. + + +PHYS_CONFIGURING_MODEM, the physical layer is currently waiting for the modem driver to finish +sending modem configuration commands. The Linx process on the Series 3 cannot receive this +status message as there is no modem driver available. On an HC the message is ignored. + + +PHYS_NCP_LINK_ESTAB_OK, a connnection to a remote sys$ncp process has been established or re +established if the physical or logical connections have previously failed. The L1Nx process on the +Series 3 and HC ignores this message. The connection details are contained in the pvrs struct. + + +PHYS_NCP_LINK_ESTAB_NEW_NCP, a connection to a remote sys$ncp process has been established, +however the remote sys$ncp is different to the one we were connected to earlier. The connection +details, eg port and baud rate are contained in the pvrs struct. The LINK process on the Series 3 +and HC should respond by sending a NCLINK_CTRL_NEW_NCP_OK response. + + +The following error state changes are reported, they all require some action, the response is sent back to +the syssncp process via the P_FINQ service. + + +10-8 + + +PHYS_NCP_LINK_ESTAB_INVALID_VER, the remote sys$ncp is version 1.0. We cannot continue +with the session since the operation of the two sys$ncp's is significantly different. There are very +few version 1.0 syssncp's. The local end should terminate by responding with the appropriate +p_FINQ message. + + +PHYS_NCP_LINK_END, the remote syssncp is terminating, the local end should either prompt for +continuation or termination and respond to the sys$ncpP with the appropriate p_FINQ message. + + +PHYS_SERCONFIG_FAILED, the physical layer has reported that the serial port the user has +specified does not exist. The local end should report the error to the user and typically terminate +by sending the appropriate p_FINQ message. + + +PHYS_CHARS_FAILED, the physical layer has reported that an attempt to set the serial +characteristics failed, presmably because the serial driver does not support the specified +configuration. The local end should report the error to the user and typically terminate by +sending the appropriate p_FINQ message. + + +PHYS_LINK_FAILED, the logical link layer driver has reported that the link has failed. If the +physical connection was over a modem link or a previous logical link connection has been made +the local end should ask the user for confirmation to re-try for a physical connection. If no link +has ever been established (no pHys_NCP_LINK_ESTAB_OK status message been received) the local +end should simply ask the syssNcp process to retry for a link. + + +PHYS_CONNECT_FAILED, the waiting for a physical connection has failed, typically this is caused +by a modem being removed from the serial port whilst waiting for an incoming call to arrive. +The local end should either exit or request the physical action be re-tried by sending the +appropriate P_FINQ response. + + +10 NCP AND LINK + + +@ PHYS_INIT_FAILED, the physical layer has reported that the initialisation of the modem failed, +presumably because of an invalid modem configuration string. The local end should either exit +or request the physical action be re-tried by sending the appropriate p_r1No response. + + +@ PHYS_DIAL_FAILED, the physical layer has reported that dialling the phone number failed. The +local end should either exit or request the physical action be re-tried by sending the appropriate +P_FINQ response. + + +@ PHYS_MDMCONFIG_FAILED, the physical layer has reported that sending additional modem +configuration strings has failed. The local end should either exit or request the physical action be +re-tried by sending the appropriate p_F1Nno response. + + +The p_FRsupPER request will typically take a significant length of time. In a high quality system it should +be called asynchronously. + + +The p_FRSUPER request may be cancelled by using the p_rcancet service. The original request will be +completed with k_FILE_CANCEL completion status and a signal generated. + + +All syssncp defines and structure definitions can be found in sys$ncp.h. + + +The calling process will be panicked if a p_rFRsuPER request is currently outstanding or if pNcp is not a +valid channel handle. + + +The p_rRsuPER request cannot fail and returns zero. + + +P_FINQ Respond to a supervisory message +INT p_iow(VOID *pNcp, P_FINQ, INT response, DVRS *pdvr) ; +This function should only be called by a process that replaces the LINK process. + + +In response to a P_FRSUPER event the state change process handler (typically L1nk) must send back a +response. + + +A response message may be one of the following: + + +@ NCLINK_CTRL_RETRY, to retry the action that failed. This would typically retry for a link +connection or a physical connection depending on which event occured earlier. The pdvr +parameter is irrelevant for this message type. + + +@ NCLINK_CTRL_EXIT, to request that all channels be closed, the local syssncp process inform the +remote syssncp process that it is about to terminate and actually break the physical and logical +connections. The pavr parameter is irrelevant for this message type. + + +@ NCLINK_CTRL_NEW_NCP_oK, to inform the syssncp process that the different remote syssncp +process is acceptable and that the controlling process (L1nx) has sorted out any channels that it is +responsible for (the remote filing system channels). The pdvr parameter is irrelevant for this +message type. + + +At any point in time a proces may inform the syssncp process that it should restart with new parameters +by sending it the following message + + +¢ NCLINK_CTRL_NEW_CONFIG, restart the syssncp process with the new configuaration as specified +in pavr. If any of the parameters are illegal or the request fails then a subsequent P_FRSUPER +request will received the failure state. + + +The p_ring request cannot fail and returns zero. + + +All syssncp defines and structure definitions can be found in sys$ncp.h. + + +10-9 + + +1/0 DEVICES REFERENCE + + +P_FSENSE Sense the current channel activity + + +INT p_iow(VOID *pNcp, P_FSENSE, NCLINK_SREC *prec); + + +If an application wishes to determine the channel activity occuring within the syssNncpP process the +statistical information contained in an NCLINK_sREC structure can be obtained. + + +The prec parameter is assumed to point to an aray of 8 NCLINK_SREC structures, one for each of the +possible channels that the syssncp process can handle. Channel 0 is used by the syssncp process and the +information in that array entry should be discarded. + + +All syssncp defines and structure definitions can be found in sys$ncp.h. + + +The P_FSENSE request cannot fail and returns zero. + + +P_FSTOP Request the SYS$NCP terminate + + +INT p_iow(VOID *pNcp, P_FSTOP); + + +If an application process wishes to terminate the syssncp process and all connected client server +applications it should use the P_FsTop service. + + +When the syssncp process receives this request it will fail all outstanding requests on all open channels +immediately with a E_FILE_D1Isc completion status then tell the remote syssncp process that it is about to +terminate. Any further requests made by any application proces on any channel will fail with the +E_GEN_NOPROC completion status. + + +The syssncp process will not terminate until all channels have been closed by all the application +processes. + + +Server processes will typically always have an outstanding P_FREAD request or be processing a request the +result of which is required to be sent back to the client. In both cases it will make a request on the ncP: +channel that will fail. If the error handling is as suggested in the P_rFREAD and P_FWRITE error section then +the server will terminate gracefully. + + +Client processes on the other hand tend not to make any requests until user input requires them to, hence +typically do not have any outstanding or make any requests on the ncp: channel. + + +In a high quality system the client should close its cp: channel as soon as it is informed that the syssncp +process is about to terminate. + + +If the client process is the one that makes the p_rstop request is not too much of a problem for it to know +to close its channel. + + +If the client does not make the request it will not know to close its channel. A solution to this is for a +client process to always have a P_FREAD request outstanding even though it may never read any data from +the remote process. If it does read data from the remote process (presumably after writing a request to the +remote process to make the data available) then it can still use the outstanding p_rReap to read this data. + + +nn EEE +Example + + +This example is for a client server application which allows a process to be run on a remote machine. The +full path name is specified. The connection establishment and data transfer phases are illustrated in as +simple a manner as is possible. For clarity the code does not implement the full error handling required in +a working application. + + +10 - 10 + + +The client side + + +GLDEF_C VOID main(VOID) +{ +WORD len,nlen, pid; +VOID *pNcp; +TEXT *p; +TEXT srvName [20]; +TEXT cmd[80] + + +if (pid=p_pidfind("LINK.*") ) <0) +p_exit (1); +if (p_open(&pNcp, "NCP:",-1) ) +p_exit (1); +p_scpy (&srvName[0],"EXECSRV") ; +p=(&srvName[0]); +if (p_msendreceivew (pid, LNKMSG_LOADREMOTE, &p) <0) +p_exit (1); +len=p_get1l("Name and command line", &cmd[0],80); +if (len) +{ +nlen=p_slen(&srvName[0])+1; +if (!p_iow(pNcp, P_FCONNECT, &ésrvName[0], &nlen) ) +{ +if (!p_iow(pNcp, P_FWRITE, &cmd[0], &len) ) +{ +if (!p_iow(pNcp, P_FREAD, &cmd[0], &len) ) +{ +pid=cmd[0]+(cmd[1]<<8); +if (pid>0) +p_printf("Remote pid %x",pid); +else +p_puts ("No such process"); + + +} +p_iow (pNcp, P_FDISCONNECT) ; +} +} +p_close(pNcp) ; +p_exit (0); +} + + +The server side + + +GLDEF_C VOID main(VOID) +{ +WORD len, pid; +VOID *pNcp; +TEXT *pname, *pcmd; +TEXT cmd[80] + + +if (p_open(&pNcp, "NCP:",-1) ) +p_exit (1); +if (!p_iow(pNcp,P_FREAD, &cmd[0], &len) ) +{ +pname=p_skipwh (&cmd[0]); +pcemd=p_skipch (pname) ; +if (*pcmd) +{ +*pcmd++=0; /* zero terminate proc name */ +pemd=p_skipch (pcmd) ; +} + + +pid=p_exec (pname, pcmd, p_slen(pcmd) ) ; + + +cmd [0]=pid; +cmd[1]=pid>>8; /* return pid or error */ +len=2; + + +p_iow(pNcp, P_FWRITE, &cmd[0],é&len) ; +} + +p_close(pNcp); + +p_exit (0); + +} + + +10 NCP AND LINK + + +10-11 + + +CHAPTER 11 + + +CRADLE AND DOCKING STATION + + +Introduction + + +This chapter refers to two units: the HC cradle and the docking station for HC and Workabout computers. +In this document the term ‘Cradle’ refers to the HC cradle, (which connects to the side pins of older HC +models). The term ‘Docking Station’ refers both to the HC docking station, (which connects to an HC LIF +interface fitted to the bottom of the HC), and to the Workabout docking station. The term ‘computer’ +refers to an HC or Workabout. + + +This chapter describes the services which are supported by the Cradle/Docking Station device driver +(crD:). The Fast Charger services provided by the Docking Station are described in the Fast Charger +chapter. + + +The Cradle/Docking Station device driver (cRD:) reports changes of state when a computer is inserted or +removed from the Cradle or Docking Station. It is supplied to allow a program to perform specific +operations automatically when the computer is inserted into the Cradle or Docking Station and to ‘tidy up' +when the computer is removed. + + +Notes: + + +1. the Cradle/Docking Station device does not have to be open to use the Cradle/Docking +Station expansion port. The operating system will automatically stop and start active devices +in the cradle. + + +2. the "Cradle/Docking Station in" signal is generated when the computer first touches the +connector, but software running on the computer must wait until the connection is fully +home before attempting to access any device in the Cradle/Docking Station. + + +If a user inserts the computer into the cradle slowly, EPOC may not recognise that the +Cradle/Docking Station expansion port is present. It such a case it may be prudent to open +and close an expansion device using the Cradle/Docking Station device as an indicator of the +connection state. If an attempt to open a device when the computer is inserted into the +Cradle/Docking Station fails, a retry can be attempted after a delay of, say, two seconds. + + +Cradle/Docking Station services + + +p_open(CRD:) Open the device +INT p_open(VOID **ppcb,"CRD:",-1); + + +Open a channel to the current Cradle or Docking Station device, as set by any previous call to the P_FsET +service. If there has been no previous call to this service, or if the machine has just been reset, it will open +a channel to the Cradle/Docking Station. + + +Returns zero if the device is opened successfully, otherwise a negative error. Errors include: + + +E_GEN_NOMEMORY failed to allocate memory for control block +E_FILE_LOCKED or port is already open or +E_GEN_INUSE in use + + +11-1 + + +I/O DEVICES REFERENCE + + +p_close Close the channel + + +INT p_close(VOID *pcb) + + +Close the channel. Returns zero. + + +P_FREAD Read from the device + + +VOID p_ioc(VOID *pcb, P_FREAD, WORD *pstat, UWORD *pcstate); +INT p_iow(VOID *pcb, P_FREAD, UWORD *pcstate) ; + + +Read a change of state from the Cradle/Docking Station, writing the new state to *pcstate. + + +When called for the first time after opening the device it will complete immediately, reporting the current +state. Thereafter it will complete whenever the computer is removed from or inserted into the +Cradle/Docking Station. + + +On completion *pcstate is TRUE if the computer is currently in the Cradle/Docking Station and Fats if +the computer is out of the Cradle/Docking Station. + + +Panics if a P_FREAD request is currently outstanding, or if pcb is not a valid channel handle. + + +The completion status code is returned by the synchronous p_iow(P_FREAD) and written to *pstat by +asynchronous calls. The completion status code is zero if the P_FREAD request completed successfully, or +E_FILE_CANCEL if the read was cancelled. + + +P_FCANCEL Cancel a read + + +INT p_iow(VOID *pcb,P_FCANCEL) ; + + +Cancel any outstanding P_FREAD request. Performing a cancel is harmless if no read request is +outstanding. + + +Returns zero. + + +P_FSET Set the device type + + +INT p_iow(VOID *pcb,P_FSET,WORD *pctype) ; + + +If *pctype 1s TRUE, sets all future cRD: operations to apply to the Docking Station and all accesses to port +C and related ports to apply to any expansion fitted into the Docking Station. It will also check that a valid +Docking Station expansion is fitted to the bottom of the HC. Since this call requires use of the high speed +serial channel on the bottom if the HC and affects all port C devices, it will fail with E_cEN_1nusE if +anything is open on port B or port C. + + +If *pctype is FALSE, sets all future cRD: operations to apply to the Cradle and all accesses to port C and +related ports to apply to any expansion fitted into the Cradle. Since this call affects all port C devices, it +will fail with E_cEN_InusE if anything is open on port C. + + +Note: This setting will remain even after the crp: device is closed. It will remain in force until it is +changed by another call to p_FsEt, or until the machine is reset. It is envisaged that one call will be made +to this function when an application first runs, and that this will set the device type for the life of the +application. + + +E_GEN_NOMEMORY failed to allocate memory for the control block +E_GEN_INUSE the port is in use (e.g. TT Y:B is open when trying to set to the Docking Station, +or TTY:C in the Docking Station is open when trying to set to the Cradle) + + +P_FSENSE Sense the device type + + +INT p_iow(VOID *pcb,P_FSENSE,WORD *pctype) ; + + +The current device type is returned in *pctype. If set to TRUE then the Docking Station is the current type, +if set to FALSE then the Cradle is the current type. + + +Note: This service does not check if the hardware is actually present (e.g. if an HC LIF interface is fitted) +and therefore may be called at any time. To check if the hardware is present, use the P_FSET service. + + +Returns zero. + + +11-2 + + +CHAPTER 12 + + +HC MAGNETIC CARD READER + + +Introduction + + +The HC Magnetic Card Reader (vcr: ) device driver is built into the HC's operating system. + + +The MCR interface may be fitted to the top (wcr:a) or bottom (Mcr:8B) of the HC, or in the cradle (wcr:c). + + +MCR services + + +p_open(MCR:) Open the MCR device +INT p_open(VOID **ppcb, "MCR:A",-1); +Open a channel to a Magnetic Card Reader device. + + +Returns zero if the device was opened successfully, otherwise a negative error. Errors include: + + +E_GEN_NOMEMORY failed to allocate memory for control block + +E_FILE_DEVICE no interface found in specified slot + +E_FILE_NAME invalid device name + +E_FILE_LOCKED or port is already open or + +E_GEN_INUSE in use + +p_close Close the channel + + +INT p_close(VOID *pcb) +Close the Magnetic Card Reader device channel. + + +Returns zero. + + +P_FREAD Read from the MCR device + + +VOID p_ioc(VOID *pcb, P_FREAD, WORD *pstat, UBYTE *bufl, UBYTE *buf2); +INT p_iow(VOID *pcb, P_FREAD, UBYTE *bufl, UBYTE *buf2); + + +Read either or both tracks of a card. Track 1 is read into *bufi and track 2 into *buf2, where each buffer +must be at least 256 bytes long. The data in each buffer is written as leading byte count ASCII text. The +leading byte count is zero if the read was not successful. + + +Either buf1 or buf2 may be passed as NULL to disable reading of the relevant track. For example, to read +only track 2: + + +UWORD stat; +UBYTE buf[256]; + + +p_ioc(pcb, P_FREAD, &stat, NULL, &buf[0]); +p_waitstat (&stat); + + +I/O DEVICES REFERENCE + + +Track 1 usually contains alphanumeric data (card holder's name and account number) while track 2 +contains numeric data only. The most common MCRs read only track 2. + + +Panics if a P_FREAD request is currently outstanding, or if pcb is not a valid channel handle. + + +The completion status code is returned by the synchronous p_iow(P_FREAD) and written to *pstat by +asynchronous calls. The completion status code is zero if the P_FREAD request completed successfully, or +one of the following negative error numbers: + + +E_FILE_READ an error was detected decoding the data +E_GEN_OVER device driver buffer overflow +E_FILE_CANCEL the read was cancelled + + +P_FCANCEL Cancel a read + + +INT p_iow(VOID *pcb,P_FCANCEL) ; + + +Cancel any outstanding P_FREAD request. Performing a cancel is harmless if no read request is +outstanding. + + +Returns zero. + + +P_FSET Set the pull-up resistors +VOID p_iow(VOID *pcb, P_FSET, UWORD *mask); + +This service is only available in EPOC versions 2.32 or later. + +Set the programmable pull-up/pull-down resistors on the five MCR reader lines. + + +The MCR device contains programmable 100k ohm pull-up/pull-down resistors on each of the reader +lines DATA1, CLK1, DATA2, CLK2 and cus. By default when the MCR device is opened these are set to pull +down. + + +The resistor on each line is controlled by a bit in «mask. If the bit is set to 1 the resistor is programmed to +pull-up, if the bit is cleared to 0 the resistor is programmed to pull-down. + + +The bits which control each line should be defined in the application source file, according to the +following table: + + +Symbol Value (binary) Line + +M_DATA1PU 00000001 Track 1 data +M_CLK1PU 00000010 Track 1 clock +M_DATA2PU 00000100 Track 2 data +M_CLK2PU 00001000 Track 2 clock +M_CLSPU 00010000 Card present signal + + +All other bits are ignored. + + +12-2 + + +CHAPTER 13 + + +HC BAR CODE READER + + +Hardware Description + + +The Bar code reader interface module + + +The bar code interface module is a grey plastic moulding which is designed to fit into one of the slots at +either end of the HC. To insert the module you will need to open the rear door of the HC, and unlock one +of the interface slots to remove the existing module or blank. Place the bar code reader module into the +slot and gently ease it home making sure it fits snugly. Once this is done you will need to lock the module +in place by moving the black switch into the locked position. After this close the door again otherwise the +HC will refuse to switch on. + + +The interface may be fitted to the top (BaR:a) or bottom (BaR:8B) of the HC. + +The bar code reader wand. + +The bar code wand is supplied with a locking mini-din plug which fits into the mini-din socket in the top +of the bar code module. Simply lining up the grooves and pushing the plug home will lock the plug into +place. The locking plug type is used so that if the HC is accidentally suspended by the bar code reader +cable, the machine will not come off the connector. To remove the wand from the module grip the plastic + + +moulding which surrounds the plug and pull gently. The plastic cover will slide back slightly releasing its +grip on the module. From there the plug should easily slide out. + + +[Me a Sees +Device drivers + + +At the time of writing, there is no bar code device driver or decoding software built into the HC's +operating system. Bar code readers are supported by separate device driver files which must be loaded by +the application code, by means of either the PLIB p_toadida function or the OPL DevLoadLpp call. + + +There are currently five combined decoder/device drivers: + + +BAREAN . LDD supports EAN8, EAN13, UPC and UPCE decoding +BARC39.LDD supports CODE 39 decoding + +BARITF.LDD supports Interleaved 2 of 5 (ITF) decoding +BAR128.LDD supports CODE 128 decoding + +BARMPLES . LDD supports Modified Plessey decoding + +BARRAW. LDD supports raw decoding + + +None of the currently available drivers supports auto discrimination of bar codes. + + +Installing the LDD optional component of the SDK copies these files into the \sibosdkNlib directory. The +required LDD must be copied into the appropriate directory on the HC using MCLINK. + + +A device driver may be loaded, for example, by: +p_loadldd("BARC39.LDD") ; + +To remove the device (and free the memory it uses) you should call +p_devdel ("BAR") ; + +or the equivalent OPL DevDelete call. + + +The bar code device driver software is updated from time to time; update information is available from +Psion Support. + + +13-1 + + +1/0 DEVICES REFERENCE + + +SSS ee | +Bar code driver services + + +p_open(BAR:) Open the bar code device +INT p_open(VOID **ppcb, "BAR:",-1); +Open a channel to a bar code device by means of a previously loaded bar code device driver. + + +Returns zero if the device was opened successfully, otherwise a negative error. Errors include: + + +E_GEN_NOMEMORY failed to allocate memory for control block +E_FILE_DEVICE no interface found in specified slot +E_FILE_NAME invalid device name + +E_FILE_LOCKED or port is already open or in use + + +E_GEN_INUSE + + +p_close Close the channel +INT p_close(VOID *pcb) +Close the bar code device channel. + + +Returns zero. + + +P_FREAD Read from the MCR device + + +VOID p_ioc(VOID *pcb, P_FREAD, WORD *pstat, UBYTE *buf); +INT p_iow(VOID *pcb, P_FREAD, UBYTE *buf) ; + + +Read a bar code into *buf, which must be at least 256 bytes long. The data is written as leading byte count +ASCII text. The leading byte count is zero if the read was not successful. The first character of the text +indicates the type of the bar code: + + +EAN8 or EAN13 +UPC + +Code 39 + +ITF + +Code 128 +Modified Plessey +UPCE + + +az 7t0aNwS + + +The remainder of the text is the decoded bar code data. +Panics if a P_FREAD request is currently outstanding, or if pcb is not a valid channel handle. + + +The completion status code is returned by the synchronous p_iow(P_FREAD) and written to *pstat by +asynchronous calls. It is zero if the P_FREAD request completed successfully, or one of the following +negative error numbers: + + +E_GEN_OVER device driver buffer overflow +E_FILE_CANCEL the read was cancelled + + +P_FCANCEL Cancel a read + + +INT p_iow(VOID *pcb,P_FCANCEL) ; + + +Cancel any outstanding p_FREAD request. Performing a cancel is harmless if no read request is +outstanding. + + +Returns zero. + + +13-2 + + +CHAPTER 14 + + +HC INTELLIGENT BAR CODE READER/RS232 PORT + + +See the HC Bar Code Reader chapter, for the description of the device driver for an alternative HC bar +code reader expansion module. + + +RS232/intelligent bar code reader module + + +The RS232/intelligent bar code reader is an expansion module which contains an intelligent bar decoding +micro controller. The module is fully compatible with the HC, HC-DOS and RWAN series of computers. + + +The expansion module provides one serial port connection to the HC computer, and this port is shared +between the two interfaces. The serial port may be configured by software to open a channel either to the +PC-AT style RS232 interface, or to the intelligent bar code scanner interface; both interfaces cannot be +used simultaneously. This module has been designed to allow an HC computer to read bar code labels, +using a wand attached to the bar code reader interface. Data collected from bar code scans may then be +transferred to an external computer (such as an IBM PC-AT compatible machine) from the HC computer, +via the RS232 serial port interface. + + +The bar code reader interface contains an intelligent micro controller that will automatically read and +decode data from a bar code wand (or a wand emulator) connected to the expansion module. The unit can +read and automatically discriminate between the following bar code formats: + + +e EAN/JAN 8 +e EAN/JAN 13 +e UPCA + +e UPCE + +e Codabar + +© Code 128 + + +e Interleaved 2 of 5 +e Code 39 (standard or extended) + + +The interface may be programmed to verify scanned data against check digits/characters on bar code +labels and to read, or to ignore any supplement digits in a bar code, as required. + + +The micro controller will transmit bar code data to the HC computer as an ASCII string of characters: + +i.e. each digit or character read from a bar code label will be transmitted to the HC computer as one +ASCII-coded character. The order of the bar code data will always be transmitted to the HC computer in +the correct order (i.e. reading from left to right across the bar code label), irrespective of the direction that +the bar code label was actually scanned. By default, the end of each complete bar code scan will be marked +by a single ASCII carriage return character. + + +The micro controller inside the expansion module is programmable. It may be instructed to decode only a +subset of the bar code symbologies that it recognises, to transmit check digits and check characters with +each bar code scan, read or ignore supplement digits, as well as many other bar code symbology-specific +options. The micro controller can also be programmed to mark the end of each scan with a customised +ASCT terminating string of up to four characters, in place of the default carriage return termination +character. This document contains detailed information on how to program the micro controller from + +C, and from OPL programs. + + +14-1 + + +I/O DEVICES REFERENCE + + +You may connect this expansion module either to the top slot, or to the bottom slot of an HC computer. + +When the expansion module has been plugged into the top slot on the computer, the RS232 port can be + +accessed by opening TTy:a, and the bar code interface may be accessed by opening TTy:p; if the module +has been connected to the bottom slot on the computer, then the RS232 port can be accessed by opening +TTy:B and the bar code interface may be accessed by opening TTyY:E. + + +The bar code interface communicates to the host computer at the following (standard HC Comms) +settings: + + +e Baud +e data bits +e — stop bit + + +e Xon/Xoff handshaking (No hardware handshaking) + + +The expansion module possesses two, male 9-pin D-type connectors: the RS232 connector is a standard +PC-AT type connector!; the bar code interface connector is a standard click-lock D-type connector for a +bar code wand. + + +To reduce power consumption, the bar code interface and the RS232 port interface are only powered up +when the channel to the serial port is open. + + +The RS232 serial port interface + + +The RS232 interface provides standard RS232 level signals to a 9-pin D-type male connector. The +connector is PC-AT compatible, although pin 9 (normally the Rr pin) is not driven by the interface. When +the interface unit has been connected to the top slot of the HC, then the RS232 port may be accessed by +opening the try:a device. If the unit has been connected to the bottom slot of the HC, then the RS232 port +may be accessed by opening TTY:B. + + +The table below displays the pinout for the PC-AT type RS232 serial port. + + +DCD input + +RX input + +TX output + +DTR output + +Ground (ov) + +DSR input + +RTS output + +CTS input + +Optional vsup connection + + +OMANDNKRWNKH + + +Power consumption + + +The RS232 port is only powered up when the appropriate channel is open. The interface will draw +approximately 10mA, plus the current drawn by the device connected to the other end of the RS232 cable. +If the remote device is a PC-AT type computer, then the total current drawn by the interface will typically +be 20mA, although this figure may vary from one PC to another. + + +When the HC computer is also powering an external device through the RS232 port, then that external +device should not draw more than: + + +e =250mA from the HC if no other expansion modules are attached to the HC, or +e 200mA from the HC if another expansion module is attached to the HC and is powered up. + + +Please note also that external device will draw current from the HC computer even when the HC computer +has been switched off. Consequently, the external device ought to have its own on/off switch, and to avoid +excessive battery drain, the external device should be switched off when it is not in use. + + +'The ringing indicator (Rt) pin has not been implemented on the RS232 port. It may, however, be +connected permanently to the HC computer vsup power supply rail, if required. This action will allow an +external unit such as an infrared laser scanner to have power supplied to it through the RI connection in +the serial link cable, from the HC computer. + + +14-2 + + +14 HC INTELLIGENT BAR CODE READER/RS232 PORT + + +Powering the HC from an external power source + + +The HC computer may be powered by an external source through pin 9 of the RS232 interface. To do this, a +2-pin header on the RS232/bar code interface expansion module PCB should be shorted together with a jumper. +(The 2-pin header is located at the extreme bottom left-hand side of the PCB, if the expansion module is oriented +so that the electrical components are uppermost and the two D-type connectors face upwards.) + + +This alteration will route the vsup main power supply rail from pin 9 of the serial port to the HC +computer. The external vsup power supply should be in the range of 7-10v. The external power supply +should be diode-isolated from the HC to prevent any power drain from the HC computer. + + +Please note that the main battery inside the HC computer will not be charged if power is supplied to the +HC from the RS232 port. + + +DSR auto wakeup switch + + +If required, the interface and HC computer may be woken up by an external device whenever the psp pin +of the RS232 link is asserted. To enable this facility, move the PCB switch (located at the bottom left-hand +corner of the circuit board) to the left-hand position. (If you hold the module with the component side of +the PCB facing you and the D-type connectors facing upwards, the switch is located to the bottom left +hand corner of the PCB.) + + +The bar code interface + + +The bar code reader interface contains a Hewlett-Packard HBCR-1610 series bar decoding micro +controller which is capable of reading and discriminating between the following bar code formats: +EAN/JAN 8, EAN/JAN 13, UPC A, UPC E, Codabar, Code 128, Interleaved 2 of 5 and standard or +extended Code 39 bar labels. + + +The interface possesses a 9-pin D-type click-lock male connector which may be attached to many standard +digital wands and wand emulating scanner units. However undecoded laser scanners (HHLC) are not +supported by this interface. + + +When the interface unit has been connected to the top slot of the HC, then the bar code port may be +accessed by opening the rry:p device. If the unit has been connected to the bottom slot of the HC, then the +bar code port may be accessed by opening trv:&. To conserve power, the bar code interface is only +powered up while the serial port is open. + + +The bar code interface communicates to the host computer with the following settings: +e Baud +e data bits, no parity and 1 stop bit +e Parity errors are not ignored + + +These are the default serial port settings for the HC computer. However, in addition, the bar code port +must also be set up so that: + + +e the tmask parameter of the serial port characteristics identifies the last character in the +terminating string for each incoming message, from the bar code interface. The default +terminating string is a single carriage return character: i.e. tmask=2000. + + +e the cts/rts handshaking protocol is disabled, by setting the 1cn_cts flag. + + +Full details are given later in this section, which describe how tmask and 1cN_cts may be set from within +a C or an OPL program. Please note that these two settings are only required to configure the bar code +ports Try:p and rry:& for the bar code interface; they do not apply to the RS232 ports rry:a and Try:B. + + +The table below displays the pinout for the two expansion module ports. + + +DCD input + +Bar data input + +Not connected + +Switched vsup output + +DSR input + +DTR output + +Ground (ov) + +Ground (ov) + +Switched 5v regulated output + + +OMDANANDNHRWNF + + +I/O DEVICES REFERENCE + + +Power consumption + + +External units should not draw more than: +e =250mA from the HC if no other expansion modules are attached to the HC, or +e 200mA from the HC if another expansion module is attached to the HC, and is powered up. + + +The bar code port draws an idle current of 1OmA, and typically 24mA when a scan is in progress. This +figure does not include the additional current drawn by the wand, or scanner, attached to the interface. To +conserve power, the RS232 interface is only powered up while the serial port is open. + + +Powering a bar code wand from the HC + + +The HC computer can supply a 5v ( +5%) regulated supply and a vsup (6-10v) supply to an external bar +code wand, or a wand emulating device (such as an RS232 laser scanner). These two power supplies are +available on pin 9 and pin 4, respectively, on the bar code interface connector. + + +To allow the HC to supply power an external unit a simple adjustment must be made to the expansion +module: a 2-pin header on the PCB of the RS232/bar code interface expansion module must be shorted +together with a jumper. (The 2-pin header is located at the extreme bottom left-hand side of the PCB, if +the expansion module is oriented so that the electrical components are uppermost and the two D-type +connectors are facing upwards.) + + +The two power supply outputs on the bar code interface (and the decoding IC) are switched on only when +the port is open. As a result, the power will be switched off when the HC computer powers down - if it is +left unused for longer than the timeout period. Please note that all of the custom settings programmed into +the bar code interface with escape sequences will be lost when the port is closed, or if the HC auto-powers +down. + + +Please note that the 2-pin header should only be taken if the external unit must be powered by the HC, or +if the HC must be powered by the external device. + + +[eyeee TS +Bar code symbologies + + +The bar code reader interface will transmit data from each bar code scan as a stream of ASCII text data. +Each data stream will be terminated by the default termination string (a carriage return character, 00d). +Alternatively, the interface may be programmed to terminate each stream of scan data with a custom +termination string of up to four characters. + + +Bar code data will always be transmitted to the host computer in the correct order (i.e. from left to right), +irrespective of the direction in which the bar label was originally scanned. Bar code labels containing +supplement digits can only be scanned in the forwards direction (i.e. from left to right); all other bar code +labels may be scanned either forwards or backwards. The interface may be programmed to include, or +strip out, check characters and ID characters in the transmitted data, as desired. The maximum scanning +rate for any bar code format is 30 ips + + +The remainder of this section will now describe each bar code format that may be scanned by the +interface. In each case, the programmable options that are associated with each format will also be +described. + + +Code 128 + + +Code 128 labels contain a variable number of digits, and one check character. There are three types of +Code 128 bar code labels that may be decoded by the bar code interface: code A, code B and code C. Both +Code A and Code B labels may contain a maximum of 31 characters; Code C labels may contain a +maximum of 62 characters. + + +No user-definable options are available to alter Code 128 bar code data. The bar code reader interface will +always check the label data against the check character on the bar code label, but the check character will +never be transmitted as part of the scanned data. + + +14-4 + + +14 HC INTELLIGENT BAR CODE READER/RS232 PORT + + +Codabar + + +Codabar labels contain one start character, a number of digits and one stop character. Only one user- +definable option exists with Codabar format data: the bar code reader interface may be programmed to +transmit, or to ignore any start and stop characters in the label data. + + +The start and stop characters may be any of the following four upper case characters: 'A', 'B', 'C’, or 'D'. A +start character does not have to be the same as the stop character. + + +The table below illustrates the effect that each Codabar option will have on the output data from the bar +code interface. + + +Start/stop chars Input label data Output data +Transmit A123456B 123456 +Ignore A123456B A123456B + + +Interleaved 2 of 5 + + +An Interleaved 2 of 5 bar code will always contain an even number of digits (including the check digit) +and no characters. It may also contain a number of additional check sum digits also. The maximum +number of digits that may be contained within a label is 32; the minimum number is 2. The interface may +be programmed to read either: + + +e any Interleaved 2 of 5 labels containing any even number of digits within the range of 2 and 32 +digits, +e only Interleaved 2 of 5 labels containing 6 or 14 digits, or + + +e only Interleaved 2 of 5 labels containing a preset, even number of digits. + + +There will always be one check digit at the end of the bar code label. The bar code scanner interface may +be programmed to verify the scanned data against this check digit, and it may also be programmed either +to transmit the check digit as part of the output data string, or to omit the check digit from the output data. + + +In the table below, 123456 represents a bar code scan containing the valid check digit 6 and 123457 +represents a scan that contains the invalid check digit 7. The output generated by the bar code interface is +displayed in the right-hand column. + + +Input data Verify the check Transmit the check digit ? Output data +digit? +23456 No Yes or No 23456 +123457 No Yes or No 23457 +123456 Yes No 2345 +123457 Yes No No output +23456 Yes Yes 23456 +123457 Yes Yes No output +Code 39 + + +A Code 39 bar code label may contain a minimum of one character and a maximum of 32 characters. It +will contain no digits. The bar code reader interface may be programmed to verify the label check +character, and to transmit the check character in the output data message, or strip the check character +from the output data. + + +In the following table, ancx represents a Code 39 label containing the valid check character x, and the +string apcp represents a Code 39 label containing an invalid check character p. + + +14-5 + + +1/0 DEVICES REFERENCE + + +Input label data Verify the check Transmit the check Output data +character? character +ABCD No Yes or No ABCD +ABCX No Yes or No ABCX +ABCD Yes No No output +ABCX Yes No ABC +ABCD Yes Yes No output +ABCX Yes Yes ABCX + + +The user interface may be programmed in Code 39 scans may be converted as character pairs (as defined +by the Code 39 symbology) or alternatively, each character in the scan may be decoded individually. + + +The UPC/EAN bar code formats + + +The UPC/EAN bar code family all contain a fixed number of digits, and all contain one check digit. The +bar code reader interface may be programmed to verify this check digit against the rest of the scanned +data. The interface may also be programmed to transmit the check digit as part of the bar code, or to omit +the check digit from the output data. + + +There twelve variants in the UPC/EAN family of bar codes. Note that JAN 8 labels are equivalent to EAN +8 format labels and JAN 13 labels are equivalent to EAN 13 format labels. + + +UPC E + + +The UPC E bar code label format contains a leading ID character, one number system digit, six data digits +and one check digit. The leading ID character must be an ASCII 'E’. The check digit will be followed by 2 +supplement digits in UPC E + 2 digit labels, and with 5 supplement digits in UPC E + 5 digit labels. + + +The bar code interface may be programmed to remove the ID character, or the check digit from the data +transmitted to the host computer. UPC E bar code label data may also be expanded into UPC A bar code +format automatically by the interface unit - in which case the six existing data digits will be expanded to +ten digits, and the leading ID character will become an ASCII'A'. Refer to the UPC A section in this +chapter for more information about this label format. + + +The following table displays the four different user-definable options available for modifying the output +data from UPC E scans. + + +Transmit ID char Transmit check digit Standard output (UPC E) Expanded output (UPC A) + + +No No dddddd ndddddddddd + +Yes No Endddddd Andddddddddd + +No Yes dddddd nddddddddddc + +Yes Yes Endddddd Anddddddddddc +where + + +gE = an ID character 'E' (0x45) +a =an ID character 'A' (0x41) +d= one data digit + +n = one number system digit + + += one check digit + + +Q + + +a + + += one supplement digit + + +14 HC INTELLIGENT BAR CODE READER/RS232 PORT + + +UPC E + 2 digits + + +As its name suggests, the UPC E + 2 bar code label format contains a leading ID character, one number +system digit, six data digits, one check digit and two supplement digits. The leading ID character must be +an ASCIL'E'. UPC E bar code label data may also be expanded into UPC A bar code format automatically +by the interface unit - in which case the six existing data digits will be expanded to ten digits, and the +leading ID character will become an ASCII 'A’. + + +The bar code interface may be programmed to remove the ID character, or the check digit from the output +data transmitted to the host computer. The following table displays the four different options available: + + +Transmit ID char Transmit check digit Standard output (UPC E) Expanded output (UPC A) + + +No No ddddddss nddddddddddss + +Yes No Enddddddss Anddddddddddss + +No Yes ddddddss nddddddddddcss + +Yes Yes Enddddddss Anddddddddddcss +where: + + +gE = an ID character 'E' (0x45) +a =an ID character 'A' (0x41) +a = one data digit + +n = one number system digit +c = one check digit + + +s = one supplement digit + + +UPC E + 5 digits + + +As its name suggests, the UPC E + 5 bar code label format contains a leading ID character, one number +system digit, six data digits, one check digit and five supplement digits. The leading ID character must be +an ASCII 'E'. UPC E bar code label data may also be expanded into UPC A bar code format automatically +by the interface unit - in which case the six existing data digits will be expanded to ten digits, and the +leading ID character will become an ASCII 'A’. + + +The bar code interface may be programmed to remove the ID character, or the check digit from the output +data transmitted to the host computer. The following table displays the four different options available: + + +Transmit ID char Transmit check digit Standard output (UPC E) Expanded output (UPC A) + + +No No ddddddsssss nddddddddddsssss + +Yes No Enddddddsssss Anddddddddddsssss + +No Yes ddddddsssss nddddddddddesssss + +Yes Yes Enddddddsssss Anddddddddddcsssss +where: + + +gE = an ID character 'E' (0x45) +a=an ID character 'A' (0x41) +d = one data digit + +n = one number system digit +c = one check digit + + +s = one supplement digit + + +14-7 + + +I/O DEVICES REFERENCE + + +EAN 8 bar code format + + +The EAN 8 bar code label format contains the following components: two leading ID characters, two flag +digits, five data digits and one check digit. The two leading ID characters will be the upper case string: +"ER w t. + + +The bar code interface may be programmed to remove the two ID characters, or the check digit from the +output data transmitted to the host computer. The following table displays the four different options +available: + + +Transmit ID chars Transmit check digit Output + + +No No ffddddd + +Yes No FFf£fddddd + +No Yes ffddddde + +Yes Yes FF £fdddddc +where: + + +F = an ID character 'F' (0x46) +f = one flag digit + +d = one data digit + +c = one check digit + + +EAN 8 + 2 digits + + +The EAN 8 + 2 bar code label format contains the following components: two leading ID characters, two +flag digits, five data digits, one check digit and two supplement digits. The two leading ID characters will +be the upper case string "FF". + + +The bar code interface may be programmed to remove the two ID characters, or the check digit from the +output data transmitted to the host computer. The following table displays the four different options +available: + + +Transmit ID chars Transmit check digit Output + + +No No ffdddddss + +Yes No FFf£fdddddss + +No Yes ffdddddess + +Yes Yes FFf£fdddddcss +where: + + +F = an ID character 'F' (0x46) +£ = one flag digit + +d = one data digit + +c = one check digit + + +s = one supplement digit + + +EAN 8 + 5 digits + + +The EAN 8 + 5 bar code label format contains the following components: two leading ID characters, two +flag digits, five data digits, one check digit and five supplement digits. The two leading ID characters will +be the upper case string "FF". + + +14 HC INTELLIGENT BAR CODE READER/RS232 PORT + + +The bar code interface may be programmed to remove the two ID characters, or the check digit from the +output data transmitted to the host computer. The following table displays the four different options +available: + + +Transmit ID chars Transmit check digit Output + + +No No ffdddddsssss + +Yes No FFffdddddsssss + +No Yes ffdddddcsssss + +Yes Yes FFf£ffdddddcsssss +where: + + +Fr = an ID character 'F' (0x46) +f = one flag digit + +a = one data digit + +c = one check digit + + +s = one supplement digit + + +EAN 13 + + +The EAN 13 bar code label format contains the following components: a leading ID character, two flag +digits, ten data digits and one check digit. The leading ID character will be an ASCII upper case 'F’. + + +The bar code interface may be programmed to remove the ID character, or the check digit from the output +data transmitted to the host computer. The following table displays the four different options available: + + +Transmit ID char Transmit check digit Output + + +No No ffdddddddddd + +Yes No Fff£dddddddddd + +No Yes ffddddddddddc + +Yes Yes Ff fdddddddddde +where: + + +Fr =an ID character 'F' (0x46) +f = one flag digit + +ad = one data digit + +c = one check digit + + +EAN 13 + 2 digits + + +The EAN 13 + 2 bar code label format contains the following components: a leading ID character, two +flag digits, ten data digits, one check digit and two supplement digits. The leading ID character will be an +ASCII upper case 'F’. + + +The bar code interface may be programmed to remove the ID character, or the check digit from the output +data transmitted to the host computer. The following table displays the four different options available: + + +Transmit ID char Transmit check digit Output + + +No No ffddddddddddss +Yes No Fffddddddddddss +No Yes ffddddddddddess +Yes Yes Fffddddddddddecss + + +14-9 + + +I/O DEVICES REFERENCE + + +where: +F = an ID character 'F' (0x46) +£ = one flag digit +d = one data digit +c = one check digit + + +s = one supplement digit +EAN 13 + 5 digits + + +The EAN 13 + 5 bar code label format contains the following components: a leading ID character, two +flag digits, ten data digits, one check digit and five supplement digits. The leading ID character will be an +ASCII upper case 'F’. + + +The bar code interface may be programmed to remove the ID character, or the check digit from the output +data transmitted to the host computer. The following table displays the four different options available: + + +Transmit ID chars Transmit check digit Output + + +No No ffddddddddddsssss + +Yes No Fffddddddddddsssss + +No Yes ffddddddddddesssss + +Yes Yes Fffddddddddddesssss +where: + + +F = an ID character 'F' (0x46) +f = one flag digit + +d = one data digit + +c = one check digit + + +s = one supplement digit +UPCA + + +The UPC A bar code label format contains a leading ID character, one number system digit, ten data +digits and one check digit. The leading ID character must be an ASCII 'A’. + + +The bar code interface may be programmed to remove the ID character, or the check digit from the output +data transmitted to the host computer. The following table displays the four different options available: + + +Transmit ID chars Transmit check digit Output + + +No No ndddddddddd + +Yes No Andddddddddd + +No Yes ndddddddddde + +Yes Yes Anddddddddddc +where: + + +a=an ID character 'A' (0x41) +n = one number system digit +d = one data digit + + +c = one check digit + + +14-10 + + +14 HC INTELLIGENT BAR CODE READER/RS232 PORT + + +UPC A + 2 digits + + +The UPC A + 2 bar code label format contains a leading ID character, one number system digit, ten data +digits, one check digit and two supplement digits. The leading ID character must be an ASCII 'A’. + + +The bar code interface may be programmed to remove the ID character, or the check digit from the output +data transmitted to the host computer. The following table displays the four different options available: + + +Transmit ID chars Transmit check digit Output + + +No No nddddddddddss + +Yes No Anddddddddddss + +No Yes nddddddddddcss + +Yes Yes Anddddddddddcss +where: + + +a =an ID character 'A' (0x41) +n = one number system digit +a = one data digit + +c = one check digit + + +s = one supplement digit + + +UPC A + 5 digits + + +The UPC A +5 bar code label format contains a leading ID character, one number system digit, ten data +digits, one check digit and five supplement digits. The leading ID character must be an ASCII 'A’. + + +The bar code interface may be programmed to remove the ID character, or the check digit from the output +data transmitted to the host computer. The following table displays the four different options available: + + +Transmit ID chars Transmit check digit Output + + +No No nddddddddddsssss + +Yes No Anddddddddddsssss + +No Yes nddddddddddesssss + +Yes Yes Anddddddddddcsssss +where: + + +a=an ID character 'A' (0x41) +n = one number system digit +d = one data digit + +c = one check digit + + +s = one supplement digit + + +Bar code commands + + +This section describes the commands that may be used to program the HC bar code reader interface. + + +The bar code interface is programmed by writing an escape sequence to the interface unit via a serial port. +With two exceptions, each escape sequence consists of a short text string in the following format: + + +-y + + +14-11 + + +I/O DEVICES REFERENCE + + +1. is the escape character (0x1b) + +2. - isa'-' character (0x2d) + +3. y isa'y' character (0x79) or a'y' character (0x59) +4 + + + is a parameter to the command, consisting of sequence of one to three numeric digit, +representing a decimal number between zero and 255. + + +5. is an upper case alphabetic character identifying the command to be executed. +The two exceptions are the hard reset command: +E + + +and the command to set the data termination string, which includes additional text following the letter +that identifies the command: + + +-y +In all cases the escape sequence must not contain any embedded spaces. + + +Commands to the bar code reader interface do not have to be issued individually. The /ssuing multiple +commands section in this chapter describes how several commands may be issued as a multiple escape +sequence, within one text string. + + +Multiple options in a command + + +Many of the bar code interface commands offer more than one option, selected by the value. To +select multiple options from a single command, simply sum all the required individual values +together, and then pass this summed value as the value within the escape sequence. + + +For example, the Select bar code symbology command -yF (described later in this chapter) +contains options to select five different bar code formats. For example, a value of | selects Code + +39, a value of 4 selects Codabar and a value of 8 selects UPC/EAN. You can select all three formats in a +single command by setting the value to 1+4+8 = 13, as follows: + + +-y13F + + +Issuing multiple commands + + +Several individual escape sequence commands may be concatenated together and be transmitted to the bar +code interface as a single escape sequence. To do this, append one or more additional +character sequences to the end of a standard, single, escape sequence. + + +When issuing multiple commands, all of the intermediate ASCII characters must be lower case +letters, and the terminating character must be an upper case ASCII character. + + +As with a single command, the escape sequence must not contain any embedded spaces. + + +For example, following three commands: + + +-y13F Select Codabar, UPC/EAN and Code 39 symbologies +-y2H Do not transmit Codabar start and stop characters +-y1D Insert a 10 ms delay between each data character + + +may be concatenated into a single escape sequence: +-y13£2h1D + + +The order of issuing commands is usually not important, so that the following three escape sequences are +all functionally identical: + + +-y13f£2h1D +-y2h1d13F +-y1d13£2H + + +Exceptions to this rule are mentioned explicitly in the following descriptions of the individual commands. + + +14-12 + + +14 HC INTELLIGENT BAR CODE READER/RS232 PORT + + +Serial intercharacter delay -yD + + +Enable or disable a ten millisecond delay between the transmission of each data character in the bar code +data string. + + + Option +0 No delay +1 Turn 10 millisecond delay on + + +The default value is equivalent to the command -yop. + + +Hard reset E +Perform a hard reset and run a self-test. + + +A hard reset will take approximately one second to complete. During this time, the bar code reader +interface will not react to any further commands that may be written to it. + + +All previous escape sequence commands sent to the bar code interface will be aborted when a hard reset is +executed. After the reset has taken place, all of the interface options will revert to their default values. + + +If the interface has failed its self-test, it will immediately transmit one of the following four messages: +ROM SELF TEST FAILED +PROCESSOR SELF TEST FAILED +LOWER RAM SELF TEST FAILED +UPPER RAM SELF TEST FAILED +No message will be issued if the interface has passed the self-test. + + +Note that the diagnostic messages will always be terminated by a carriage return (0x0d) and line feed +(0x0a) character pair, regardless of any previous command to set the termination characters. + + +All subsequent messages from the interface will be terminated with a (default) single carriage return +character. + + +A Hard Reset will not normally be issued as part of a multiple instruction escape sequence, because it will +cause all prior commands to be overridden by default settings, and all subsequent commands within the +escape sequence to be ignored by the bar code reader interface while it resets itself. + + +Select bar code symbology -yF +Set the barcode reader to recognise one or more barcode formats, as indicated in the following table: + Enable bar code format: + +1 Code 39 + +2 Interleaved 2 of 5 + +4 UPC/EAN + +8 Codabar + +16 Code 128 + + +For example, to read Code 39 and UPC/EAN bar codes only, use: +-y5F + + +If a bar code format has not been enabled, then the bar code reader will ignore all scans in that code +format. + + +The default setting for this option is equivalent to the command -y31F. + + +Note that it may be necessary to set additional interface options to enable the interface to read certain bar +code formats. + + +14 - 13 + + +1/0 DEVICES REFERENCE + + +Check character options -yG + + +Enable or disable verification/check digits and check characters within bar code scans. The precise action +of this command is dependent upon the bar code format being scanned, as indicated below. + + +The default state corresponds to the command -y0c. +Code 39 and Interleaved 2 of 5 + + +For Code 39 and Interleaved 2 of 5 bar codes, the bar code reader may be programmed to verify, or to +ignore check characters in the bar code scan. In addition, the bar code reader may be programmed to +transmit, or to omit the verification character from the scan data when it is transmitted to the host +computer. + + + Option + +0 Do not verify check characters + +1 Verify Code 39 check characters + +2 Verify Interleaved 2 of 5 check characters + +8 Transmit Code 39 and Interleaved 2 of 5 check characters + + +UPC/EAN + + +The contents of UPC/EAN bar code scans are always checked against the check digit. However, the bar +code reader may be programmed to transmit, or to omit the check digit when the scan data is transmitted +to the host computer. Note that the check digit in a UPC E bar code is never transmitted to the host +computer. + + +The bar code reader may also be programmed to decode UPC E 0 bar codes, or it may be programmed to +automatically discriminate between UPC E 0 and UPC E 1 version bar codes. + + + Option + +0 Read UPC E 0 only, transmit UPC/EAN check digit + +32 Do not transmit UPC/EAN check digit + +64 Read both UPC E 0 and UPC E 1 + +Decoding options -yH + + +This command provides several assorted programming options to the programmer. For UPC/EAN bar +code scans, the bar code reader may be programmed to accept (zero, two or five) supplemental digits in +the code, and to expand UPC E bar codes automatically into a UPC A code format, if required. + + +The bar code reader may also be programmed using this command to decode Code 39 bar codes in +standard, or in extended mode. If the extended option is selected, then the bar code reader will encode +each character pair into the corresponding ASCII characters; if standard mode is selected, then each +character in the scan data is decoded individually. + + +The bar code reader may also be programmed to retain (or discard) Codabar start and stop characters in +the scan data it transmits to the host computer. + + + Option + +1 Extended Code 39 + +0 Standard Code 39 + +2 Do not transmit Codabar start and stop characters +0 Transmit Codabar start and stop characters + +4 Read UPC bar codes only + +0 Read both UPC and EAN bar codes + +8 Decode UPC/EAN 2 digit supplement data + +0 Do not decode UPC/EAN 2 digit supplement data +16 Decode UPC/EAN 5 digit supplement data + +0 Do not decode UPC/EAN 5 digit supplement data + + +32 Expand UPC E bar codes into UPC A bar codes + + +14-14 + + +14 HC INTELLIGENT BAR CODE READER/RS232 PORT + + +0 Do not expand UPC E bar codes + +64 Auto discriminate UPC/EAN supplementals +0 Require UPC/EAN supplementals + +128 Transmit UPC/EAN ID characters + +0 Do not transmit UPC/EAN ID characters + + +The default setting is equivalent to the command -y0H. + + +Notes + + +When the option is set to decode UPC/EAN 2 digit (or 5 digit) supplement data, then the bar code label +must be scanned in the forwards direction only. + + +Only UPC/EAN bar codes containing supplement digits may be read by the interface if either, or both of +these options has been enabled. Both the 2 digit and 5 digit options may be enabled together to allow both +types of bar code scans to be read by the interface, if required. + + +If the supplement digit options are not enabled by this command, then bar code labels containing +supplement digits may still be scanned, and they may be scanned in both directions (i.e. forwards or +backwards). However the supplement digit data is not transmitted to the host computer. + + +Single read mode -yJ + + +This command will force the bar code reader to abort any current scan and not transmit that scan data to +the HC. + + +Enabling Single read mode means that the bar code reader will read a single bar code label each time a +Single read control command is issued. + + +When Single read mode is disabled, the bar code reader will attempt to read a bar code label whenever a +label is scanned. + + + Option +1 Single read mode is enabled +0 Single read mode is disabled + + +The default value is equivalent to the command -you. + + +Single read control -yK + + +This command will force the bar code reader to abort any current scan and not transmit that scan data to +the HC. + + +When Single read mode has been enabled (see above), the-Single read control may be used to enable the +bar code reader, so that it then will read one scan. + + + Option +1 Read next scan +Set Interleaved 2 of 5 length -yM + + +This command presets the length of Interleaved 2 of 5 bar code read by the bar code reader. + + +There are three length checking options available: + + + Option + +0 The bar code may have a variable length, between 4 and 32 digits +1..32 The bar code is digits long (even values only) + +33 The bar code may only contain either 6 or 14 digits + + +The default setting is equivalent to the command -yom. + + +14-15 + + +I/O DEVICES REFERENCE + + +Notes + + +Although the Interleaved 2 of 5 bar code length may be set to the minimum setting (i.e. two digits), short +Interleaved 2 of 5 bar codes may well appear in other, longer bar codes. As a result, false readings may be +given when other formats of bar code label are scanned, which may be misinterpreted as two digit +Interleaved 2 of 5 labels. Consequently, the minimum setting of 2 digits in this option is not +recommended. + + +An Interleaved 2 of 5 bar label must contain an even number of digits. If is set to an odd number +between one and thirty one, then the micro controller will automatically round up the value to the next +higher even number. + + +Set termination string -yO + + +This command will force the bar code reader to abort any current scan and not transmit that scan data to +the HC. + + +Append the termination string to the end of every bar code data message transmitted to the +HC computer by the micro controller, to mark the end of that message. + + +The default termination string is a single carriage return character (0x0a). However, a user-defined +termination string may be defined with this command, which will be used to terminate all subsequent +message transmitted by the bar code reader interface. An example escape sequence, which substitutes the +characters "stop" as the terminating string in place of the default value, is: + + +-y4Ostop + + +A termination string may contain a maximum of four characters and a minimum of zero characters. The +total number of characters contained within the termination string must be passed as the argument +of the escape sequence. + + +The default termination string transmitted by the bar code reader is a single carriage return character +(0x0d). + + +Unlike all other sequence commands described in this document, the ASCII characters for the termination +string follow the command identifier character that normally terminates a command. As a result this +command must be positioned last, if issued within an escape sequence that contains more than one +command (even if the terminating string contains zero characters). + + +For example, consider the commands: + +-y4Ostop Set the termination string to "stop" + +-y1D Insert a 10 ms delay between each data character + +If these commands are combined in a single escape sequence, that sequence must be: + + +-yl1d40stop + + +Code ID characters -yQ + + +Instruct the bar code reader to add a lower case ID character to the data message transmitted to the HC, to +identify the symbology of the bar code. This ID code character is transmitted before the bar label data. + + +The following values will enable, and disable this option: + + + Option +1 Transmit ID characters +0) Do not transmit ID characters + + +The table below displays which lower case ASCII character ('a' - 'e') is used to identify each type of bar +code label: + + +ID character Bar code format + + +Code 39 +Interleaved 2 of 5 +UPC/EAN/JAN +Codabar + +Code 128 + + +o0oaadaas ow + + +The default state is equivalent to the command -y0o. + + +14 - 16 + + +14 HC INTELLIGENT BAR CODE READER/RS232 PORT + + +Status request -yS + + +This command will force the bar code reader to abort any current scan and not transmit that scan data to +the HC. + + +Return a data string to the host computer, containing information about the status of the firmware inside +the bar code reader. + + + Option + +1 Transmit the status message + +The status message that is transmitted back to the HC in response to this instruction is: +HBCR-161X Version 15.x + + +followed by the current termination string, where "15.x" represents the present revision level of the +firmware inside the bar code reader interface. + + +Scanner enable -yW + + +This command will force the bar code reader to abort any current scan and not transmit that scan data to +the HC. + + +Enable or disable the bar code reader. + + +When disabled, the bar code scanner will not read data from any bar code labels. + + + Option +1 Enable the bar code scanner +0 Disable the bar code scanner + + +The default is for the bar code scanner to be enabled. + + +RS232 port/bar code driver services + + +The RS232 port/bar code device driver supports all the services that are described in the Serial Port +chapter of this manual. This section describes only those services that provide modified or additional +behaviour when used with the bar code reader interface. These include services to open the port, write +data to the bar code interface and read data from a bar code wand connected to the port. + + +p_open(TTY:) Open the device +INT p_open(VOID **ppcb, "TTY:B",-1); +Open a channel to the RS232 port/bar code device. + + +The table below displays which device should be accessed to open the RS232 port or the bar code reader +interface, when the expansion module has been inserted into either of the the top and bottom slots of the HC. + + +Slot RS232 port _Bar code port +Top TTY:A TTY2¢ +Bottom TTY:B TTY:D + + +On opening a channel, RS232 port, the bar code reader interface and any connected wand or scanner will +all be powered up automatically. + + +Returns zero if the device was opened successfully, otherwise a negative error. + + +For example, the following code fragment illustrates the opening of a channel to the bar code interface +with the device in the top slot of the HC. + + +LOCAL_D VOID *pHandle; +INT result; + + +result=p_open (&pHandle, "TTY:D",-1); + + +14-17 + + +1/0 DEVICES REFERENCE + + +p_close Close the channel +INT p_close (VOID *pcb) + +Close the channel to the RS232 port/bar code device. + +Returns zero. + + +Closing the channel will also cause the RS232 port/bar code interface to be powered down. To save battery +power, a device should be closed as soon as it is no longer required. + + +Note that when the device is closed, or when the HC automatically powers down, all of the information +programmed into the bar code interface will be lost. If you do not wish to use the default settings of the +bar code reader interface, then you will need to reprogram your custom settings back into the interface +when the device is next opened. + + +P_FSENSE Sense serial port characteristics + + +INT p_iow(VOID *pcb, P_FSENSE, P_SRCHAR *pserial); + + +Sense the serial port characteristics, writing them to the P_sRcuar struct (defined in p_serial.h) pointed to +by pserial. + + +The P_FSENSE service cannot fail and returns zero. + + +If using the bar code interface, the serial port characteristics must be altered once a channel is opened, to +allow the interface to communicate successfully with the HC. See the description of the P_Fset service for +further details. + + +P_FSET Set serial port characteristics +INT p_iow(VOID *pcb, P_FSET, P_SRCHAR *pserial); + +Set the serial port characteristics from the P_sRcHar struct (defined in p_serial.h) pointed to by pserial. +Returns zero if the P_FSET service completed successfully, otherwise returns a negative error. + + +If using the bar code interface, the serial port characteristics must be altered once a channel is opened, to +allow the interface to communicate successfully with the HC. Since the bar code interface does not use +RTS/cTS handshaking, the cts line in the serial port must be disabled. + + +The following code fragment illustrates the use of the P_FsENSE and P_FSET services to disable RTS/cTS +handshaking: + + +#include + + +LOCAL_D P_SRCHAR srChar; +LOCAL_D VOID *pHandle; + + +f_leave (p_open (&pHandle, "TTY:D",-1)); + +p_iow(pHandle,P_FSENSE,&srChar); /* read default settings into srChar */ +srChar.hand=P_IGN_CTS; /* suspend RTS/CTS handshaking */ + +p_iow (pHandle, P_FSET, &srChar) ; /* set up port with new settings */ + + +Note that this code assumes that it is called under the protection of p_enter. + + +P_FREAD Read from device + + +VOID p_iow (VOID *pcb, INT P_FREAD,VOID *buf,UINT *plen)j; +VOID p_ioc (VOID *pcb, INT P_FREAD,WORD *pfstat,VOID *buf,UINT *plen)j; + + +Read up to *plen bytes of data from the device into the buffer pointed to by buf. The buffer is assumed to +be of sufficient length to receive the data. If using an asynchronous P_FREAD service, it is the caller's +responsibility to preserve the data space pointed to by buf and plen until the service completes. + + +The result is returned by a call to p_iow and written to *pfstat by the asynchronous call. The result is +zero if the service completed successfully, otherwise it is a negative error. + + +14 - 18 + + +14 HC INTELLIGENT BAR CODE READER/RS232 PORT + + +A read operation may take an indefinite time to complete and it should therefore be executed +asynchronously within a quality system. For clarity, the following example code uses synchronous reads. + + +define MAX_BARCODE 128 +define TERMINATE_CHAR 0x0d + + +VOID *pHandle; + +TEXT *p; + +NT len; + +UINT count; + +TEXT buf [MAX_BARCODE+2]; + + +len=0; +count=1; +p=ébuf [0]; +FOREVER + + +{ + +p_iow(pHandle,P_FREAD,p, &count) ; + +lent+=1; + +if ( (*p++==TERMINATE_CHAR) | | (len>=MAX_BARCODE_LEN) ) +{ + + +*--p=0; /* convert to a zero-terminated string */ +len-=1; +break; +} +} + + +p_printf("Bar code is %s, containing %d bytes", &ébuf[0],len); + + +P_FWRITE Write to device + + +INT p_iow(VOID *pcb, INT P_FWRITE,VOID *buf,UINT *plen); +VOID p_ioc(VOID *pcb, INT P_FWRITE,WORD *pfstat,VOID *buf,UINT *plen); + + +Write up to *pien bytes of data from the buffer pointed to by buf to the device. If using an asynchronous +P_FWRITE Service, it is the caller's responsibility to preserve the data space pointed to by buf and plen +until the service completes. + + +The result is returned by a call to p_iow and written to *pfstat by the asynchronous call. The result is +zero if the service completed successfully, otherwise it is a negative error. + + +A write operation may take an indefinite time to complete and should therefore be executed +asynchronously within a quality system. For clarity, the following example uses a synchronous write. + + +The following code fragment transmits the escape sequence —y1d24f2u to the bar code reader +interface: + + +#define MAX COMMAND 64 + + +VOID *pHandle; +UINT len; +UBYTE command [MAX_COMMAND+2]; + + +p_scpy (&command[0],"\033-y1d24f£2H") ; + + +len=p_slen(&command[0]) ; +p_iow (pHandle, &command [0], &len) ; + + +14-19 + + +I/O DEVICES REFERENCE + + +An example program + + +The program listed below will operate a bar code interface connected to either the top, or the bottom of the +HC. The program will read scanned bar code data from the reader interface, display that information on +the screen and then await a key press. The scanning operation may be repeated as many times as required. +Press the X key after a scan to exit the program; pressing the V key will display the firmware status of the +software inside the bar code interface. + + +This program is only given here as a simple example of how to program the micro controller and read +scan data: a quality system should carry out more rigorous testing for errors, and should also use +asynchronous operations to read and write the data. + + +#include +#include + + +#define MAX _STRING 128 +LOCAL_D VOID *pHandle; + + +GLDEF_C INT main (void) +{ +P_SRCHAR srChar; +INT len, onebyte,result, reply; +TEXT buffer [MAX_STRING+2]; +/* Try to open a port */ +if (p_open(&pHandle, "TTY:D",-1) <0) +{ +if ((result=p_open (&pHandle, "TTY:E",-1) ) <0) +p_panic(result); +} + +/* Set up serial port characteristics */ +p_iow (pHandle, P_FSENSE, &srChar) ; +srChar.hand=P_IGN_CTS; +p_iow (pHandle, P_FSET, &srChar) ; +buffer[0]='\0'; +onebyte=1; +do + +{ + +/* Display menu on screen */ +p_printf(" BAR CODE SCANNER") ; +p_printf("%s",buffer) ; +p_printf("\npress V for Version,"); + + +p_printf Le X to eXit"); +p_printf (* or any other key"); +p_printf Cy to scan a label"); + + +reply=p_tofold(p_getch()); + + +if (reply=='V') +p_write (pHandle, "\033-y1S",5); +if (reply!='X"') +{ /* Read input from the bar code interface */ +len=0; +do +{ +p_iow (pHandle, P_FREAD, &buffer[len],é&onebyte) ; +} while (buffer[lent+]!=13 && len + + +ifndef EPOC +GLREF_D P_DEVICE p_serial,p_file,p_keyb,p_timer; + + +endif + +LOCAL_D VOID *pIr; + +LOCAL_D UBYTE buf[256]; + +LOCAL_D TEXT connData[64]=" "; + +LOCAL_D TEXT printstring[24]="Welcome to IR printing!"; +LOCAL_D UWORD slots; + +LOCAL_D INT readlen,writelen,ret,i; + +LOCAL_D UBYTE devName [24]; + +LOCAL_D ULONG devAddr; + + +LOCAL_C HANDLE LoadIrdaServer (TEXT *name) +INT err; + +TEXT serverPath[P_FNAMESIZE]; +HANDLE serverPid=NULL; + + +/* Start the IRDA stack as a separate process and store its pid */ +p_printf ("Trying to start %s",name) ; +if ((serverPid=p_pidfind(name) ) ==E_FILE_NXIST) +{/* Try to load irda from M first */ +f_fparse (name, "LOC: :M:\\", &serverPath[0],NULL) ; +if ((serverPid=p_execc(&serverPath[0], +(UBYTE *)&serverPid, sizeof (serverPid) ) ) <0) +{/* Try to load irda from ROM */ +f_fparse (name, "ROM::\\",&serverPath[0],NULL) ; +if ((serverPid=p_execc(&serverPath[0], +(UBYTE *)&serverPid, sizeof (serverPid) ) ) <0) +{/* Error ! No irda */ +return (0); +} +} +if ((err=p_presume (serverPid) ) <0) +return (0); +} +p_sleept (5L); /* Give irda a chance to get going */ +return (serverPid) ; + + +} + + +LOCAL_C VOID PrintMenu () +{ +D2 PLEINCE (MAREE ARE RES REA A ERIN) 7 +p_printf ("Press \'p\' to make station primary"); +p_printf ("Press \'s\' to make station secondary"); +p_printf ("Press \'q\' to quit"); + + +Pp DLLME ECU AREER EAR ARR RRR EAE HRI MY ; + + +} + + +16-7 + + +1/0 DEVICES REFERENCE + + +LOCAL_C INT DiscoverDevices () + +{ + +p_printf ("Doing a discovery"); + +slots=6; + +p_iow(pIr, 6, &buf[0],&slots); /* P_FIRDISCOVER */ + +p_printf ("Devices found = %d",slots); + +if (slots>0) +{/* We have discovered at least one device */ +devAddr= *((ULONG *) (&buf[4])); +/* Discovery nickname is last 23 bytes of info */ +p_bcpy (devName, &buf[12],23); + + +i=0; +while (devName[i]>=0x20 && i<23) +itt+; +devName[i]='\0'; +p_printf ("Remote devAddr = 0x%08X",devAddr) ; +p_printf ("Remote device = %s",devName) ; + + +return (0); +} + + +else + + +p_printf ("Trying again"); +return (-1); + + +LOCAL_C INT ConnectToFirstDevice() +{ +p_printf ("Selecting machine"); +ret=p_iow(pIr,7,&devAddr); /* P_FIRSELECT */ +p_printf ("Connecting to machine %08X",devAddr) ; +if ((ret=p_iow(pIr,8,"Test",&connData[0]) ) <0) /* P_FIRMAKECONNECT */ +{ +p_printf("Connect failed with ret = %d",ret); +p_getch(); +return (0); +} + + +p_printf ("Successfully connected machine") ; + + +} + + +LOCAL_C VOID TransmitData() +{ +INT ret; +p_printf ("Writing keypresses to IR port - ESC to cancel"); +writelen=1; +while ((ret=p_getch()) !=27) +{/* OK as long as not escape */ +buf [0]=ret; +p_iow(pIr,2, &buf[0],&writelen) ; /* P_FWRITE */ +p_print ("%s", &buf[0]); +} + + +LOCAL_C INT WaitForConnect () + +{ + +INT ret; + +p_printf ("Connecting as a secondary"); + +if ((ret=p_iow(pIr,5,"Test",&connData[0])) <0) /* P_FIRAWAITCONNECT */ +{ +p_printf ("Wait for connect failed with ret = %d",ret); +p_getch (); +return(-1); +} + +p_printf ("Accepted a connection"); + + +} + + +16-8 + + +16 THE ACCESSIR API + + +LOCAL_C INT ReadData() + +{ + +readlen=1; + +if ((ret=p_iow(pIr,1,é&buf[0],&readlen) ) <0) /* P_FREAD */ +{ +p_printf ("Error on reading"); +if (ret==DisconnectErr) + +p_printf ("Primary has disconnected") ; + +return (ret); +} + +p_print ("%s", &buf[0]); + +return (1); + + +} + + +LOCAL_C VOID Disconnect () + + +p_printf ("Disconnecting") ; +p_iow(pIr,4); /* P_FIRDISCONNECT */ + + +GLDEF_C INT main(VOID) + + +TEXT servername[20]="SYSSIRDA.IMG"; + + +#ifndef EPOC +p_inst (&p_file, &ép_serial, &p_keyb, &p_timer, NULL) ; +#endif + + +p_printf("Psion Software (c) October 1996"); +PUPBENEL (MAA AAAAAAAK AAA RAK AKA RAK KAA RA RAK ARE RARE ) - + + +p_printf("Starting simple AccessIr beaming app"); +if ((ret=LoadIrdaServer (servername) ) ==NULL) +{ +p_printf ("Problem loading Irda stack"); +p_getch(); +return (0); +} +p_printf ("Successfully kicked open the irda stack as separate process"); +if ((ret=p_open(&pIr, "AIR:",-1)) <0) +{ +p_printf ("Cannot open AccessIr driver ret = %d",ret); +p_getch(); +return (0); +} +p_printf ("Successfully opened AccessIr driver"); +startLoop: +PrintMenu () ; +ret=p_getch(); + + +switch (ret) + +{ + +case 'p!: + +case 'P'; +/* PRIMARY STATION - TRANSMITTER */ +if ((ret=DiscoverDevices ()) <0) + +goto startLoop; + +ConnectToFirstDevice () ; +TransmitData(); +Disconnect (); +break; + + +16-9 + + +1/0 DEVICES REFERENCE + + +case 's!': +case 'S': +/* SECONDARY STATION - RECEIVER */ +if ((ret=WaitForConnect () ) <0) +break; + + +while ((ret=ReadData())>0) +/* Keep reading until failure */ ; +break; +case 'q': +case 'Q': +p_printf ("Terminating program") ; +break; +default: +goto startLoop; +break; +} +p_close(pIr); /* This also kills the IrDA process */ +p_printf("End of program — Hit key to esc"); +p_getch(); +return (0); + + +} + + +16 - 10 + + +CHAPTER 17 + + +THE IRMUX API + + +Using the IrMUX API + + +Prerequisites + + +It is essential that the Introduction to Psion Infrared Communications chapter has been read before this +chapter. + + +Introduction to using the IrMUX API + + +The IrMUX API facilitates Infrared communication between two Psion machines (Series 3c and/or Siena). + + +This section explains how to use each call that can be made to the IrMUX server using IPC on a SIBO +(EPOC/16) based computer system. This API is more difficult to use than the AccessIr API, but +potentially gives more flexibility. For simple IR communication applications it is recommended that the +AccessIr API is used. + + +With the IrMUX API connectionless or connection-oriented calls are available. + + +This set of protocols uses machine addresses and port IDs (rather than application names as for the +AccessIr API). + + +The packets of data used must be exactly the right size, there is no error correction and there is no +guarantee of transfer. +Initialising the IR protocol stack + + +Before the IR protocol stack can be used it must be initialized, by doing a p_execc. The protocol stack is +started as a separate process. This is done in exactly the same way as when using the AccessIr API. When +the last application has logged off, the protocol stack will clean up and terminate itself automatically. + + +17-1 + + +I/O DEVICES REFERENCE + + +The argument *name is SySSIRDA. IMG in the example code segment below: + + +LOCAL_C HANDLE loadIRDAserver (TEXT *name) +{ +INT err; +TEXT serverPath[P_FNAMESIZE]; +HANDLE server_pid=NULL; +/* Start the IR process & store its server_pid in property */ +if (E_FILE_NXIST==(server_pid=p_pidfind (name) ) ) +{ /* Load from M, then from wherever we are... */ +f_fparse (name, "LOC: :M:\\", &serverPath[0],NULL) ; +if ((server_pid=p_execc(&serverPath[0], +(UBYTE*) &server_pid, +sizeof (server_pid) ) ) <0) +{ +f_fparse (name, "ROM::\\",&serverPath[0],NULL) ; +if ((server_pid=p_execc(&serverPath[0], +(UBYTE*) &Server_pid, +sizeof (server_pid) )) <0) +{ /* Error...no irda! */ +return (0); +} +} +if (0!=(err=p_presume (server_pid) ) ) +return (0); +} +p_sleept (5L); /* Give IRDA a chance to get going! */ +return (server_pid); + + +} + + +Logging on to and logging off from the IrMUX server +Before an application can use IrMUX services it must log on. When it has finished it must log off. + + +Logging on to the IrMUX server + + +The LM_Logon function call is used to log on to the ITMUX server. + + +Logging off from the IrMUX server + + +The tm_Logof¢ function call is used to log off from the IrMUX server. + + +Registering/unregistering applications with the LM-IAS server +This is independent of the process of sending or receiving data. An application can either: + +e register iself in the LM-IAS database + +¢ unregister iself from the LM-IAS database +Registering the port with the LM-IAS server +The tM_RegisterPort function call is used to register the application with the LM-IAS server. +Unregistering the port with the LM-IAS server + + +The LM_UnRegisterPort function call is used to unregister the application with the LM-IAS server. + + +LM-IAS services + + +The LM_GetValueByClass message has not been implemented as a direct IPC service, but an IAS Get +Value By Class frame must be passed from the LM-IAS server of the primary station to the LM-IAS +server of the secondary station. The secondary station replies with another specially formatted frame of +data. + + +The LM-IAS server on a remote machine is reached by starting a connection to the remote machine, +(using the LM_connectRequest function), with a remote port of zero. + + +17-2 + + +17 THE IRMUX API + + +The IAS Get Value By Class service can only be used with a connection to a remote LM-IAS server. +Direct read and write access to a remote LM-IAS port has not been blocked in order to allow future +expansion. A client should not attempt to send frames directly to a remote LM-IAS connection (other than +the Get Value By Class message) without a full understanding of the implications of such actions. +Developers should study the IrDA IrLMP specification. + + +The IAS Get Value By Class message frame + + +The format of the frame that must be sent from the primary station is: + + +byte 0x84 + +byte name length + +n bytes application name, not including zero terminator +byte 0x12 + +byte “IrDA: IrLMP:LsapSel” + + +The IAS Get Value By Class reply frame + + +The format of the frame returned by the LM-IAS server on the secondary station is: + + +byte AND with ox3r and compare with 4; if not equal to 4, failed +byte 0 + +byte non-zero + +byte don’t care + +byte don’t care + +byte don’t care + +byte 1 + +byte 0 + +word 0 + +byte port number + + +Connectionless calls + +Data may either be sent or received in a connectionless manner. This process involves one step: +e Queue a connectionless read or write request + +The first application to read the transmitted data is the one that gets it. + + +Reading and writing data + + +The LM_cLReadRequest function call is used to queue a connectionless read request. + + +The LM_cLwriteRequest function call is used to queue a connectionless write request. + + +Connection-oriented calls +The steps in the process for a secondary station are: +1. Register the application with the secondary station’s LM-IAS server +2. Wait for the primary station to connect +The steps in the process for a primary station are: +1. Discover and log the remote machines +2. Connect to the LM-IAS server on the selected remote machine + + +3. Ask for a particular registered application (by preparing and sending a LM_GetvalueByClass +message) + + +4. Wait for the reply (the secondary station returns a port ID for the required application) +5. Close the LM-IAS connection + + +17-3 + + +I/O DEVICES REFERENCE + + +6. Reconnect using the port ID previously returned for the required application on the +secondary station + + +7. Send or accept data (either reliably or unreliably) +8. Disconnect +Discovery + + +The LM_DiscoverDevicesRequest function call is used by the primary station to return information about +machines within transmission range. + + +Connection - first time + + +The bm_connectRequest function call is used by the primary station (with a remote port of zero) to +attempt to connect to the LM-IAS server of the remote machine. + + +If successful the primary station sends an IAS Get Value By Class frame to the secondary station. The +secondary station sends back a frame containing the ID of the port for the application required (previously +registered by the secondary station with its LM-IAS server). + + +Disconnecting - first time + + +The LM_DisconnectRequest function call is used by the primary station to disconnect the two +communicating machines, before subsequent reconnection. + + +Connection - second time + + +The bm_connectRequest function call is used by the primary station to attempt to re-connect to the remote +machine, using the port ID for the required application, returned previously. + + +Reading and writing data + + +Reading and writing data may be done either reliably or unreliably. If unreliable red/write is used then the +data is only sent once. + + +The LM_ReadRequest function call is used to queue a connection-oriented read request. + +The LM_writeRequest function call is used to queue a connection-oriented write request. + +The tM_UReadRequest function call is used to queue an unreliable connection-oriented write request. +The bM_UwriteRequest function call is used to queue an unreliable connection-oriented write request. + + +Disconnecting - second time + + +The bM_DisconnectRequest function call is used by the primary station to disconnect the two +communicating machines. + + +Using Exclusive mode + + +If an application on the primary station wants to be sure of control over the link then it should use +Exclusive mode. A call to bM_AccessModeRequest gives exclusive access to ITMUX. This means that only +that one application can talk, and all other applications are blocked. + + +If you want to stop other applications from placing IrMUX into Exclusive mode, then the connection +(which always starts in Idle mode) can be put into Active mode, by using the LM_IdleRequest function +call. This should only be done during critical periods of communication. The connection should be put +back in Idle mode when the critical period has finished, by using another call to LM_tdleRequest. + + +When in Exclusive mode, if the client application is not responding to incoming data quickly enough, the +number of retries to be used on each data frame can be changed (from the default of 1), using the +LM_SetHandshakingLevel function call. The number of retries must be set back to 1 when IrMUX leaves +Exclusive mode. + + +When exclusive use of IrMUX is no longer required, another call to bm_AccessModeRequest should be +made. + + +The current status of the link can be found with a call to tM_statusRequest. + + +17-4 + + +17 THE IRMUX API + + +The IrMUX API + + +IrMUX message format + + +The muxmessace struct has the format shown below. + + +typedef struct +{ + + +E_MESSAGE Mess; // Message Control +VOID * MessConn; // Connection Handle +VOID * MessArgl; // Argument 1 + +VOID * MessArg2; // Argument 2 + +UINT MessArg3; // Argument 3 + + +} MUXMESSAGE + +The £_messace struct has the format shown below. + +typedef struct message + +{ +struct message next; +UBYTE *status; +UINT type; // Message Number +HANDLE pid; +} E_MESSAGE; + + +The Message Number specified for each function below should be used as the type 1n an E_MESSAGE +struct, itself used as the mess field of a muxmEssacE struct. + + +Argument 1, Argument 2 and Argument 3 refer to the three muxmessace fields MessArg1, MessArg1 and +MessArgl. + + +For a full description of how to use these structs with the server function p_mreceive, see the chapter +Processes and Inter-Process Messaging in the PLIB Reference manual, and also the chapter Inter-Process +Communication in the OLIB Reference manual. + + +Unless specified below the argument values are unchanged when the function call returns. + + +Errors from IrLAP (returned in the status element of the z_messace struct) are documented in the IrDA +Serial Infrared Link Access Protocol (IrLAP) standard document. + + +LM_Logon Log on to the IrMUX server +Message Number 1 + + +Use this function call to log on to the IrMUX server. + + +LM_Logoff Log off from the IrMUX server +Message Number 2 + + +Use this function call to log off from the ITMUX server. This will stop any connections still held open by +the client. + + +LM_RegisterPort Register a port number with the LM-IAS server +Message Number 10 +Use this function call to register an application with the LM-IAS server. + + +The application name must be less than twenty five characters in length and zero terminated. + + +17-5 + + +1/0 DEVICES REFERENCE + + +Arguments + +Connection Handle Pointer to a vorp*; on return contains the LM- +IAS entry handle + +Argument 1 Pointer to a buffer containing the application +name + +Argument 2 Irrelevant + +Argument 3 The port number + +Value of status in the E_MESSAGE struct on return: + +OKAY Register successful + +E_GEN_NOMEMORY No memory to complete request + +E_GEN_RANGE Errors from IrLAP + +LM_UnRegisterPort Free registered port with LM-IAS server + + +Message Number 11 + + +Use this function call to free a registered port number with the LM-IAS server. + + +Arguments + +Connection Handle Entry handle + +Argument | Pointer to buffer containing class name +Argument 2 Irrelevant + +Argument 3 Irrelevant + +LM_CLReadRequest Queue a connectionless read request +Message Number 4 + + +Use this function call to queue a connectionless read request. + + +It should be noted that in the case of all reads, if a frame is received which is longer than the requested +data size the frame will be truncated and data will be lost. If a received frame is smaller than the length +requested the actual amount of data received will be placed into the urnt pointed to by argument2. + + +Arguments + +Connection Handle Irrelevant + +Argument | Pointer to a buffer to receive the data; on return +contains the received data + +Argument 2 Pointer to a uInT containing the number of +bytes required; on return the urnt contains the +actual amount of data returned + +Argument 3 Irrelevant + + +Value of status in the = _mMEeSSAGE Struct on return: + + +OKAY Read complete +E_GEN_INUSE Read already queued +E_MUX_ABORT IrMUX has been destroyed + + +17 - 6 + + +LM_CLWriteRequest +Message Number 5 + + +17 THE IRMUX API + + +Queue a connectionless write request + + +Use this function call to queue a connectionless write request. + + +Arguments +Connection Handle +Argument 1 +Argument 2 + + +Argument 3 + + +Value of status in the E_MESSAGE struct on return: + + +OKAY +E_GEN_NOMEMORY + + +(various) + + +LM_DiscoverDevicesRequest +Message Number 6 + + +Irrelevant +Pointer to a buffer containing the data to send; + + +Pointer to a uInT containing the number of +bytes to send + + +Irrelevant + + +Write successful +No memory to complete request + + +Errors from IrLAP + + +Return info on in-range machines + + +Use this function call to return information about machines within transmission range. + + +IrMUX will either instruct IrLAP to perform a discovery operation or will return the results of a previous + + +discovery. +Arguments +Connection Handle + + +Argument 1 + + +Argument 2 + + +Argument 3 + + +Value of status in the E_MESSAGE struct on return: + + +MUX_DISCOVERY_COMPLETE +MUX_CACHE_USED +E_GEN_NOMEMORY + + +E_MUX_ABORT + + +LM_ConnectRequest +Message Number 9 + + +Irrelevant + + +Pointer to a buffer of size at least +slots*sizeof (DISCOVERY_LOG) ; on return +contains the discovery log + + +Pointer toa urnT containing the number of +slots; on return contains the number of +discoveries + + +Irrelevant + + +Discovery complete +Results of previous discovery used +Could not complete request + + +IrMux has been destroyed + + +Attempt to connect to a remote machine + + +Use this function call to attempt to connect to a remote machine. Supplying a home Port number of -1 will +cause IrMUX to generate one for you. A remote port number of zero is used to connect to the remote LM- +IAS server. See the appropriate IrDA IrLAP document for details of the connect_stRuct and how to set + + +port numbers and other connection parameters. + + +17-7 + + +1/0 DEVICES REFERENCE + + +Arguments + +Connection Handle Pointer to a vorp* to receive the connection +handle on return + +Argument | Pointer to a CONNECT_STRUCT containing +connect parameters; on return the +CONNECT_STRUCT contains the actual connection +parameters + +Argument 2 Pointer to a buffer of 60 bytes of connection +data; on return the buffer contains connection +data from the other machine + +Argument 3 Irrelevant + + +Value of status in the E_MESSAGE struct on return: + + +OKAY Connection complete + +E_GEN_NSUP Unsupported parameters or port number + +E_GEN_INUSE Port number in use by another client + +E_MUX_BUSY A discovery is in process + +E_MUX_EXCLUSIVE Another connection already has exclusive +access to IrMUX + +E_GEN_NOMEMORY Insuffient Memory to make connection + +E_MUX_REMOTEDISCONNECT Remote forced disconnection + +E_MUX_TIMOUTDISCONNECT Forced disconnection, timout + +E_MUX_LOGOFFDISCONNECT Forced disconnection, client logoff + +E_MUX_USERDISCONNECT User cancelled connection + +E_MUX_LAP IrLAP cannot complete this request + +LM_WaitForConnection Wait for remote machine to connect + + +Message Number 8 + + +Use this function call to get a remote machine to wait for connection through a specified port number. + + +Arguments + +Connection Handle Pointer to vorp* to receive connection handle +on return + +Argument | Pointer to a CONNECT_STRUCT containing +connect parameters; on return the +CONNECT_STRUCT contains the actual connection +parameters + +Argument 2 Pointer to a buffer of 60 bytes of connection +data; on return the buffer contains connection +data from the other machine + +Argument 3 Irrelevant + + +17-8 + + +Value of status in the E_MEeSSAGE Struct on return: + + +OKAY + +E_GEN_NSUP + +E_GEN_INUSE +E_GEN_NOMEMORY +E_MUX_REMOTEDISCONNECT +E_MUX_TIMOUTDISCONNECT +E_MUX_LOGOFFDISCONNECT + + +E_MUX_USERDISCONNECT + + +LM_StatusRequest +Message Number 21 + + +17 THE IRMUX API + + +Connection complete + +Unsupported parameters or port number +Port number in use by another client +Insuffient memory to make connection +Remote forced disconnection + +Forced disconnection, timout + +Forced disconnection, client logoff + + +User cancelled connection + + +Return the status of the link + + +Use this function call to return the status of the link and where abouts IrLAP is holding un-ACKed data. + + +Arguments +Connection Handle + + +Argument 1 + + +Argument 2 + + +Argument 3 + + +Value of status in the E_MESSAGE struct on return: + + +OKAY + + +E_MUX_NOCONNECTION + + +LM_ReadRequest +Message Number 24 + + +Connection handle + + +Pointer to an rntT to hold the link quality on +return + + +Pointer to an int to hold the number of un- +ACKed frames on return + + +Irrelevant + + +Request complete + + +Connection handle invalid or connection +removed by other end + + +Queue a read request on a connection + + +Use this function call to queue a read request on a connection. + + +This function will panic the client process if a read is already queued on that connection. + + +Arguments +Connection Handle +Argument 1 +Argument 2 + + +Argument 3 + + +Connection handle +Pointer to a buffer to receive the data on return + + +Pointer to a uINT containing the number of +bytes required; on return the urnt contains the +amount of data returned + + +Irrelevant + + +17-9 + + +1/0 DEVICES REFERENCE + + +Value of status in the = _mMesSAGE Struct on return: + + +OKAY Read complete + +E_MUX_REMOTEDISCONNECT Remote forced disconnection + +E_MUX_TIMOUTDISCONNECT Forced disconnection, timout + +E_MUX_LOGOFFDISCONNECT Forced disconnection, client logoff + +E_MUX_USERDISCONNECT User cancelled connection + +E_MUX_NOCONNECTION Connection handle invalid or connection +removed by other end + +E_MUX_ABORT IrMUX has been destroyed + +LM_WriteRequest Queue a write request on a connection + +Message Number 25 + + +Use this function call to queue a write request on a connection. + + +The maximum length of a data frame that can be sent is returned as part of the connection +parameters from a connect request. Do not exceed this length. + + +Arguments + +Connection Handle Connection handle + +Argument | Pointer to a buffer containing the data to send + +Argument 2 Pointer to a uInT containing the number of +bytes to send + +Argument 3 TRUE if more data is to follow + + +Value of status in the = _mMesSAGE Struct on return: + + +OKAY Write successful +E_GEN_NOMEMORY No memory to complete request +E_MUX_NOCONNECTION Connection handle invalid or connection + + +removed by other end + + +(various) Errors from IrLAP +LM_UReadRequest Queue an unreliable read request +Message Number 26 + + +Use this function call to queue an unreliable read request on a connection. +In unreliable reading, data is sent only once. + + +This function will panic the client process if a read is already queued on that connection. + + +Arguments + +Connection Handle Connection handle + +Argument | Pointer to a buffer to receive the data on return + +Argument 2 Pointer to a urnT containing the number of +bytes required; on return the urnt contains the +actual amount of data returned + +Argument 3 Irrelevant + + +17 - 10 + + +17 THE IRMUX API + + +Value of status in the = _mMesSSAGE Struct on return: + + +OKAY Read complete + +E_MUX_REMOTEDISCONNECT Remote forced disconnection + +E_MUX_TIMOUTDISCONNECT Forced disconnection, timout + +E_MUX_LOGOFFDISCONNECT Forced disconnection, client logoff + +E_MUX_USERDISCONNECT User cancelled connection + +E_MUX_NOCONNECTION Connection handle invalid or connection +removed by other end + +E_MUX_ABORT IrMUX has been destroyed + +LM_UWriteRequest Queue an unreliable write request + +Message Number 27 + + +Use this function call to queue an unreliable write request on a connection. + + +In unreliable writing, data is sent only once. + + +Arguments + +Connection Handle Connection handle + +Argument | Pointer to a buffer containing the data to send + +Argument 2 Pointer to a uInT containing the number of +bytes to send + +Argument 3 TRUE if more data to follow + + +Value of status in the = _MESSAGE Struct on return: + + +OKAY Write successful +E_GEN_NOMEMORY No memory to complete request +E_MUX_NOCONNECTION Connection handle invalid or connection + + +removed by other end + + +(various) Errors from IrLAP +LM_AccessModeRequest Obtain/release exclusive access +Message Number 22 + + +Use this function call to obtain/release exclusive access to ITMUX. + + +Arguments + +Connection Handle Connection handle + +Argument 1 LM_ExclusiveMode to obtain exclusive access or +LM_Mult iplexMode to release exclusive access +to IrMUX + +Argument 2 Irrelevant + +Argument 3 Irrelevant + + +17-11 + + +1/0 DEVICES REFERENCE + + +Value of status in the = _MESSAGE Struct on return: + + +OKAY Request complete + +E_GEN_MEMORY Not enough memory to complete the request + +E_GEN_INUSE Unable to enter exclusive mode + +E_MUX_BUSY Another client is attempting to enter exclusive +mode + +E_MUX_EXCLUSIVE Another client already has exclusive access + +E_MUX_NOCONNECTION Connection handle invalid or connection +removed by other end + +E_MUX_ABORT IrMUX is being destroyed + +E_GEN_NSUP Argument | does not contain either + + +LM_ExclusiveMode Of LM_MultiplexMode + + +E_MUX_REMOTEDISCONNECT Remote forced disconnection +E_MUX_TIMOUTDISCONNECT Forced disconnection, timout +E_MUX_LOGOFFDISCONNECT Forced disconnection, client logoff +E_MUX_USERDISCONNECT User cancelled connection +LM_IdleRequest Place the connection into Idle/Active mode +Message Number 23 + + +Use this function call to place the connection into Idle/Active mode. + + +This implementation does not follow the IrMUX specification in that communication can be carried out in +both Active and Idle modes. Being in active mode simply acts as a block to other clients placing IIMUX +into Exclusive mode. + + +A connection always starts in Idle mode. To stop other clients gaining exclusive access to I1MUX by +entering Active mode, a client must put its own connection into Active mode. It is recommend that Active +mode is only used during critical periods of data communication. + + +Arguments + +Connection Handle Connection handle + +Argument 1 Irrelevant + +Argument 2 Irrelevant + +Argument 3 TRUE for Idle mode, ratse for Active mode + + +Value of status in the E_MESSAGE struct on return: + + +OKAY Mode change successful +E_MUX_BUSY Connection busy +E_MUX_NOCONNECTION Connection handle invalid or connection + + +removed by other end + + +LM_SetHandshakingLevel Set retries on each data frame +Message Number 28. + + +Use this function call to set the number of retries on each data frame, if the client application is not +responding to incoming data quickly enough. + + +This should only be enabled when in Exclusive mode. When use of exclusive mode has finished +LM_SetHandshakingLevel should be used to reset the number of retries to 1. + + +17 - 12 + + +Arguments +Connection Handle +Argument 1 +Argument 2 +Argument 3 + + +LM_DisconnectRequest +Message Number 20 + + +17 THE IRMUX API + + +Connection handle +Irrelevant +Irrelevant + + +The number of times to resend each frame, +0 (zero) for inactive. + + +Disconnect + + +Use this function call to disconnect. This will cancel any requests on the connection. + + +Arguments + +Connection Handle + +Argument 1 + +Argument 2 + +Argument 3 + +Value of status in the = _mMEesSSAGE Struct on return: +OKAY + + +E_MUX_NOCONNECTION + + +E_MUX_BUSY + + +Connection handle +Irrelevant +Irrelevant + + +Irrelevant + + +Disconnect complete + + +Connection handle invalid or connection +removed by other end + + +IrMUX is busy. The application shoul wait a +short time and try again. May be ignored if +logging off. + + +17 - 13 + + +CHAPTER 18 + + +FAST CHARGER + + +Introduction + + +This chapter describes Fast Charger services for the HC and Workabout docking stations. + + +In this document the term ‘Docking Station’ refers both to the HC docking station, (which connects to an +HC LIF interface fitted to the bottom of the HC), and to the Workabout docking station. The term +‘computer’ refers to an HC or Workabout. + + +Docking Station services + + +There are two variants of the docking station: one model has been designed for the HC computer and one +model has been designed for the Workabout computer. The docking station may be used to fast charge the +battery inside the "docked" computer. + + +The docking station Fcc: device driver may be used to charge (or discharge) the main battery under the +direct control of an HC/Workabout computer which has been inserted in the docking station holster. The +device driver may also be used to supply that computer with information about the battery charge status. + + +Notes: +1. the HC/Workabout docking station expansion port cannot be used whilst using the (Fcc:). + + +2. the HC/Workabout docking station will charge batteries without any external software +control from a docked computer. + + +See also the Cradle and Docking Station chapter for details of the cradle device driver crp:. + + +Using the Docking Station +Use of the Docking Station is complicated by the fact that one high speed serial channel is used to +communicate to three possible interfaces. + +1. The interface in the bottom of the HC (1.e. Barcode, RS232 etc.) + +2. The electronics in the device + +3. Any expansion fitted to the device. + + +As a result of this, only one interface at a time can be opened on this channel, 1.e. either the RS232 in the +HC bottom expansion (port TTY:B) or the RS232 in the Docking Station expansion slot (port TTY:C). + + +HC/Workabout docking station fast charger services + + +The Fcc: device driver will allow a C application running on a machine in the docking station holster to +monitor and control the state of the docking station fast charger circuitry. The docking station is capable +of charging , discharging and performing a capacity check of the main battery inside the computer in a +variety of operating modes. It may also be used to charge (but not discharge) a spare battery installed in +the spare battery compartment of the docking station. + + +Important note: the fast charger circuit in the docking station will charge batteries automatically without +requiring any explicit calls to the rcc: device driver; only in a few circumstances should it actually be + + +18-1 + + +I/O DEVICES REFERENCE + + +necessary to use FCG: (as described in this chapter) to give implicit instructions to the docking station. In +normal circumstances, it is not necessary to run software on the SIBO machine to control or monitor the +battery charging/discharging process. + + +There are two variants of the fast charger device driver, where each driver is tailored for use with one +specific SIBO computer and docking station. The fast charger device driver which may be used with an +HC computer is called sys$chgh.ldd; the fast charger device driver which may be used with a Workabout +computer is called sys$fchg.ldd. Both device drivers may be found in the path \sibosdk\lib\ on installation +of the relevant SIBO C Software Development Kit optional components onto your PC (from the /dd.zip +file). + + +The library file fcharge.h (located in the path \sibosdk\include\) contains C constant declarations which +may be used with either the sys$chgh.ldd or the sys$fchg.ldd device driver. + + +The fast charger does not allow a direct measurement of the status of each battery. As a result, the Fcc: +device drive will determine the status of each battery indirectly by measuring the charge pulses applied +by the charger circuitry to the battery pack over a short period of time. For this reason, some of the Fcc: +I/O operations may take a number of seconds to complete. + + +The fast charger device driver will only run if the Psion computer is resting in the docking station holster. + + +Fast charging batteries + + +The docking station may be used to charge the battery inside the "docked" computer, or a battery located +in the spare battery compartment on the top of the docking station. Only one battery pack can be charged +at any one time. + + +The fast charge circuitry possesses four modes of charging: + + +fast charge charge the battery pack with a preset current, and for a preset charge period (or +shorter, depending upon the charge status of the battery). + + +top off the battery pack is now 90-95% fully-charged; supply a lower current (typically C/10) +after completion of the fast charge, to fully-charge the cells + + +trickle charge supply a small charge current (typically C/30) to maintain the charge in a fully- +charged battery pack + + +discharge discharge the main battery at a fixed discharge current + + +If you wish to control the fast charger explicitly from a C program running on the "docked" Psion +computer, then the program should carry out the following steps: + + +1. open a channel to the fast charger device driver with the call p_open(voID **ppcb, +"PCG:A",-1); + + +2. set up the charge current and maximum charging time period with a call to +FCHG_SETCHARGEMODE (if this step is omitted, then default settings will be used). + + +3. instruct the device driver to charge the main battery (or the spare battery) with +FCHG_FASTCHARGEx. This command will commence the charging of the battery at a default +current and over a default time period. + + +4. close the channel to Fcc: with p_close (VOID *pcb) + + +Whilst the Fcc: channel is open, the C program may also monitor the progress of the charging process, if +required. Calls to FCHG_FASTCHARGEx may be omitted if the C program wishes only to monitor the progress +of the charging process. + + +The maximum charge time period set with a FCHG_SETCHARGEMODE call is used as a backup safety feature +to ensure that the fast charging process terminates before any damage can occur to the battery pack. For +this reason, it is essential that the charge time is set correctly, in relation to the charge rate which +you wish to use. The two main terminators used by the fast charge circuitry to detect the end of the +charging process are voltage and temperature slope. These two terminators are managed by the fast +charger hardware. + + +IMPORTANT: Never charge a standard Psion battery pack with a charge rate that exceeds 1C + + +without first contacting the battery supplier for advice. High charge rates in excess of 1C will +reduce the life of the battery pack and may create a risk of explosion or fire. + + +18 -2 + + +18 FAST CHARGER + + +Measuring battery capacity + + +The Fcc: device driver may be used to determine the charge capacity of a battery pack. If the time taken to +fully-discharge a fully-charged battery pack is measured, then the relative battery charge capacity may be +determined from the following equation: + + +M=(10* T, *I-)/(*C,) +where: +e M-= the reduction in battery charge capacity of the battery under test (%) +e Ty, = measured discharge time (minutes) +e I. =discharge current (mA) +e C, =rated battery capacity of battery under test (mAh) + + +Rated charge capacity of standard Psion battery packs + + +The rated charge capacity for the standard Psion HC and Workabout battery packs is displayed in the +table below. This table also contains the standard discharge time and the standard discharge current for +each variant of the docking station. . + + +Docking station Rated capacity C; (mAh) Discharge time T,, (mins) Discharge current I, + + +(mA) +HC 650 130 300 +Workabout 845 175 290 + + +Example calculations + + +Example 1: If a fully-charged HC battery pack takes 100 minutes to discharge, at the (fixed) discharge +current of 300mA, then the measured capacity of that HC battery pack is 77%. + + +ie. M= (10 * T,)* 1,)/ (6 * C. ) = (10 * 100 * 300) / (6 * 650) = 77% + + +Example 2: If a fully-charged Workabout battery pack takes 120 minutes to discharge, at the (fixed) +discharge current of 290mA, then the measured capacity of that Workabout battery pack is 69%, + + +Le. M=(10 * 120 * 290) / (6 * 845) = 69% + + +The charge capacity of custom batteries may also be determined using the same equation. Care must be +taken to use the correct value of I, in the equation, where I, is defined by the docking station variant that +is being used to discharge the custom battery pack. + + +p_open(FCG:A) Open the fast charger device +INT p_open(VOID **ppcb,"FCG:A",-1); +Open a channel to the docking station fast charger device. + + +Returns zero if the device is opened successfully, otherwise a negative error. The p_open operation will +fail if the docking station is not present. + + +If the channel is opened successsfully, the charging current and charging time will be preset to the default +settings. The device driver will then immediately begin polling the status of the battery. This polling +operation may take up to forty seconds to complete. + + +Errors include: + + +E_GEN_NOMEMORY failed to allocate memory for control block +E_FILE_LOCKED port is already open + +E_GEN_INUSE port in use + +E_FILE_DEVICE device does not exist + + +1/0 DEVICES REFERENCE + + +p_close Close the channel +INT p_close (VOID *pcb) ; + +Close the fast charger device channel. + +Any outstanding FCHG_xxx operations will be cancelled by p_close. + + +Returns zero. + + +FCHG_SETCHARGEMODE Set battery charge mode + + +#include “fcharge.h” +INT p_iow(VOID *pcb,FCHG_SETCHARGEMODE, WORD *pmode) ; + + +Set the charge current and the maximum charging time period. + +Two pieces of information must be passed to the docking station fast charger circuitry (in pmode): +e the current which will be used to charge the battery +e the maximum period of time which the battery will be charged. + + +The contents of pmode should contain a value which is constructed from two integers. The three least +significant bits in pmode should identify the charge time period; the four most significant bits in pmode +should identify the charge current. (The present charge mode may be read by calling the +FCHG_READCHARGEMODE function.) + + +This information may be selected from the fixed options that are supported by the docking station. The +minimum charging current that one could select should not be less than a quarter of the battery capacity +(unless the battery pack is known to be already partially charged). + + +Example: The capacity of the standard Workabout battery is 850mA. The minimum charging current that +one could use is 0.25 X 850 = 212mA (approx. 200mA = FcHG_ccLow2). + + +Please refer to the tables below for information about the discrete charge currents which may be supplied +by the docking station. This table also contains the names of the C constants, defined in fcharge.h, that +are associated with each charge current setting for the docking station. + + +Charging Psion battery packs + + +The following tables display suggested combinations of charge current and charge times that are suitable +for the standard Psion HC and Workabout battery packs: + + +Charge period Charge current for standard Charge current for standard +Psion HC battery pack Psion Workabout battery pack + +1C 700mA 850mA + +C/2 350mA 500mA + +C/4 175mA 200mA + + +The above charge period/charge currents correspond to the following C constants in fcharge.h: + + +Charge period Charge current for standard Charge current for standard +Psion HC battery pack Psion Workabout battery pack + +FCH_CTIME1C FCHG_DEFAULTCC FCHG_DEFAULTCC + +FCH_CTIMEC2 FCH_CC350mA FCH_CC500mA + +FCH_CTIMEC4 FCH_CCLOW2 FCH_CCLOW2 + + +High charging currents should only be selected in situations where special, high capacity, fast charge +battery packs are being used. Lower charging currents are recommended in circumstances where the +ambient temperature is above 35°C, or where lower capacity battery packs are used. + + +The minimum charging current that may be selected should not be less than a quarter of the battery +capacity (unless the battery pack is known to be already partially-charged). Incorrect settings will result in +under-charge or damage to batteries. + + +18-4 + + +18 FAST CHARGER + + +Charging custom battery packs + + +The docking station may also be used to charge custom battery packs with different charge-current +requirements. + + +The fast charger device driver and docking station support the following charge times: + + +Charge period Jfcharge.h constant Maximum charge period (minutes) +2C FCHG_CTIME2C 45 + +1C FCHG_CTIME1C 90 + +C/2 FCHG_CTIMEC2 180 + +C/4 FCHG_CTIMEC4 360 + + +The fast charger device driver and docking station support the following charge currents: + + +fcharge.h constant HC docking station current Workabout docking station current +FCHG_CCLOW1 100mA 130mA +FCHG_CCLOW2 175mA 200mA +FCHG_CC350mA 350mA 350mA +FCHG_CC500mA 500mA 500mA +FCHG_CC650mA 650mA 650mA +FCHG_DEFAULTCC 700mA 850mA +FCHG_CC850mA 850mA 850mA +FCHG_CC1000mA 1A 1A +FCHG_CC1100mA LIA LIA +FCHG_CCHIGH1 1.2A 1.3A +FCHG_CCHIGH2 1.4A 1.5A + + +IMPORTANT: Never charge a standard Psion battery pack with a charge rate that exceeds 1C + + +without first contacting the battery supplier for advice. High charge rates in excess of 1C will +reduce the life of the battery pack and may create a risk of explosion or fire. + + +Notes: + + +1. The standard power supply that is provided with the Workabout docking cradle has a +maximum current rating of 1A. As a result, battery charge currents in excess of 850 mA +cannot be supported by the standard power supply provided with the docking station. + + +If you wish to fast charge batteries using currents greater than 850 mA, a 2A power supply +must be used with the Workabout docking station. Suitable power supplies are available +from Psion; for further details please contact the Psion Sales staff. + + +The HC docking station is provided with a 2A power supply and hence is capable of +handling the entire charge current range supported by the device driver. + + +2. Charging currents below or equal to 200mA have a tolerance of + 30% and +currents greater then 300mA have a tolerance of + 15%. + + +18-5 + + +I/O DEVICES REFERENCE + + +FCHG_READCHARGEMODE Read battery charge mode + + +#include “fcharge.h” +INT p_iow(VOID *pcb,FCHG_READCHARGEMODE,WORD *pmode) ; + + +Read the charge current and the maximum charging time period settings. +The present charge rate and the required charging period will be returned to pmode. + + +The contents of pmode will contain a value which is constructed from two integers. The three least +significant bits in pmode will identify the charge time period; the four most significant bits in pmode will +identify the charge current. The charge mode may be altered by calling the FcHc_SETCHARGEMODE function. + + +The table that appears in the FcHG_SETCHARGEMODE section (above) contains all of the valid combinations +of charge current/charge period settings for HC and Workabout machines. + + +Zero is returned if the FcHG_SETCHARGEMODE request completed successfully, or a negative value if an error +has occurred. + + +FCHG_READSTATUS Read the battery status + + +#include “fcharge.h” +INT p_iow(VOID *pcb, FCHG_READSTATUS,WORD *pstatel,WORD *pstate2); + + +Read the present charge status of each battery from the docking station device, writing the new charge +states to pstatel and pstate2. + + +The status of the main battery inside the computer held in the holster is returned in pst ate1; if a spare +battery has been inserted in the spare battery compartment of the docking station, then the status of this +battery will be returned to pstate2. + + +On completion, pstate1 and pstate2 may contain one of the following integer values: +FCHG_UNKNOWN the battery is in an unknown state + + +FCHG_NOTCHARGING the battery is not charging. +If the docking station has been instructed to discharge the main battery, then +FCHG_READSTATUS will return a FCHG_NOTCHARGING value to indicate that the +battery is indeed being discharged + + +FCHG_FASTCHARGING The battery is fast charging + + +FCHG_TOPPINGOFF The battery is now charged to 90-95% of its maximum capacity and it is now +being topped off by the fast charger circuitry + + +FCHG_TRICKLE The battery is being trickle charged + + +The Fcc: device driver calculates the present charge status of a battery by measuring the duration of +charge pulses that the battery receives from the docking station. A charge pulse from the docking station +may last 40 seconds; as a result, it is possible that a call to FcHc_READSTATUS may not be able to determine +the present charge status of a battery at the precise moment in time when the call is made. + + +In this situation, a FCHG_UNKNowN status message will be returned for the status of that battery. This does +not mean that the battery charge status is indeterminate; another FCHG_READSTATUS call in the future may, +however, be able to return a valid status value for the charge status of that battery. + + +Zero is returned if the FcHG_READSTATUS request completed successfully, or a negative value if an error has +occurred. + + +18 - 6 + + +18 FAST CHARGER + + +FCHG_ASYNCHREAD Read the battery status asynchronously + + +#include “fcharge.h” +INT p_ioc(VOID *pcb,FCHG_ASYNCHREAD, WORD *pstatel,WORD *pstate2); + + +Read the present charge status of each battery from the docking station device asynchronously, writing the +new charge states to pstate1 and pstate2 when the charge status of either battery alters. + + +The rFcHG_ASYNCHREAD operation may be cancelled at any time by a call to FcHG_CANCEL. + + +FCHG_ASYNCHREAD Will return immediately after initiating a request to receive battery status information +when the status of either battery changes. At some time in the future, the new status of the main battery +inside the computer in the holster will be returned in pstate1; if a spare battery has been fitted inside the +compartment in the top of the docking station, then the status of this battery will be returned to pstate2. + + +Panics if pcb is not a valid channel handle, or if an FcHG_ASYNCHREAD operation is outstanding. + + +Returns zero if the rcHG_ASYNCHREAD request completed successfully, or a negative value if an error has +occurred. + + +FCHG_CANCEL Cancel an asynchronous read + + +#include “fcharge.h” +INT p_iow(VOID *pcb,FCHG_CANCEL) ; + + +Cancel any outstanding rcHG_ASYNCHREAD request. Performing a cancel is harmless if no read request is +outstanding. + + +Returns zero. + + +FCHG_FASTCHARGE1 Fast charge the main battery + + +#include “fcharge.h” +INT p_iow(VOID *pcb, FCHG_FASTCHARGE1) ; + + +Begin fast charging the main battery that is inside the computer fitted to the docking station holster. + + +The present settings for the charge current and charge time period (as set by p_open or +FCHG_SETCHARGEMODE) will be used by the fast charger circuitry to charge the battery. + + +FCHG_FASTCHARGE1 will return zero if it completes successfully, or a negative value if an error occurs. + + +Please note: only one battery may be charged at any one time; 1.e. the main battery cannot be charged +while a battery in the spare battery compartment is being charged. + + +If you wish to charge the main battery and the spare battery, then the software which calls rce: should +charge one battery, sense when that battery is charged sufficiently, and then charge the second battery. + + +FCHG_FASTCHARGE2 Fast charge the spare battery + + +#include “fcharge.h” +INT p_iow(VOID *pcb, FCHG_FASTCHARGEZ2) ; + + +Begin fast charging the battery that is in the spare battery compartment of the docking station. + + +The present settings for the charge current and charge time period (as set by p_open or +FCHG_SETCHARGEMODE) will be used by the fast charger circuitry to charge the battery. + + +FCHG_FASTCHARGE2 will return zero if it completes successfully, or a negative value if an error occurs. + + +Please note: only one battery may be charged at any one time; i.e. a battery in the spare battery +compartment cannot be charged while the main battery is being charged. + + +If you wish to charge the main battery and the spare battery, then the software which calls rce: should +charge one battery, sense when that battery is charged sufficiently, and then charge the second battery. + + +Note: if the main battery is charging and the spare battery is waiting, then the rcuc_FASTCHARGE2 function +will over-ride the status of the main battery and start charging the spare battery instead. + + +18 -7 + + +I/O DEVICES REFERENCE + + +FCHG_DISCHARGE1 Discharge the main battery + + +#include “fcharge.h” +INT p_iow(VOID *pcb, FCHG_DISCHARGE1) ; + + +Begin discharging the main battery fitted inside the computer fitted to the docking station holster. + + +The FCHG_DISCHARGE1 command will initiate a sequence of operations which will take a few seconds to +complete. If any additional calls are made to Fcc: in this period, those commands will return a negative +completion code and the instructions will be ignored. + + +The discharging current is fixed by the fast charger circuitry and may therefore not be altered by software. +The discharge current for the HC docking station is set to 300 mA +3%. The discharge current for the +Workabout docking station is set to 290 mA +3%. + + +FCHG_DISCHARGE1 will return zero if it completes successfully, or a negative value if an error occurs. +Notes: + + +1. when the docking station has been instructed to discharge a battery, subsequent +FCHG_READSTATUS operations will each return a FCHG_NOTCHARGING status code - which +should be interpreted as meaning that the battery is discharging (as expected). + + +2. The spare battery cannot be discharged by Fce:. + + +Example program + + +An example C application may be found in the file path \sibosdk\wkdemo\, on installation of this SDK +onto your PC. + + +charger.c is a Workabout computer program which monitors and controls the fast charger circuitry in the +docking station. This program allows the main battery, or spare battery to be charged, or the main battery +to be discharged, and the status of both batteries to be monitored. + + +Note: This program will only run if the Workabout computer has been placed into the holster of a docking +station. + + +/* Fastcharger for Workabout */ +/* Example application */ +/* (C) Copyright Psion Software PLC 1997 */ + + +include +include +include +include +include + + +include "fcharge.h" + + +GLREF_D VOID *winHandle; + + +LOCAL_C VOID State(WORD Val) + + +switch (Val) +{ + +case 0: +p_printf(" Unknown") ; +break; + +case l: +p_printf(" Not Charging") ; +break; + +case 2: +p_printf(" Fast Charging"); +break; + +case 3: +p printf (" Topping Off"); +break; + +default: +p_printf(" Trickle"); + + +18-8 + + +GLDEF_C VOID main(VOID) + + +/* + + +{ +VOID *pcb; +WORD One, OldOne; +WORD Two, OldTwo; +WORD KStat,Disch; +WORD LogOne[100]; +WORD LogTwo[100]; +WORD P1=0,P2=0, Temp; +ULONG TTime; +P_CON_KBREC Key; +TEXT X1Str[1l]; +WORD X1=0; +ULONG XE=0,DischTime; +TEXT *X1Ptr; +INT Item; +for (Item=0; Item<100; Item++) +{ +LogOne [Item] =0; +LogTwo [Item] =0; +} + + +p_devdel ("FCG",E_LDD) ; + +p_printf ("Loading"); + +if (p_loadldd("m:\\sys$fchg.1dd") <0) +p_panic(0); + +p_printf ("Opening test"); + +if (p_open (&pcb, "FCG:A",-1) <0) +p_panic(1); + +p_printf ("Closing test"); + +if (p_close (pcb) <0) +p_panic(2); + +p_printf ("Opening test part II"); + +if (p_open (&pcb, "FCG:A",-1) <0) +p_panic (3); + +p_printf ("Cant remove test"); + +if (p_devdel ("FCG:",E_LDD) >=0) +p_panic(4); + +p_printf ("Setting the charge Mode"); + + +p_iow (pcb, P_FCHG_READCHARGEMODE, &One) ; +if (One!=(P_FCHG_DEFAULTCC | P_FCHG_CTIME1C) ) + + +p_panic(5); +p_printf ("Test the charge Mode"); + + +if (p_iow (pcb, P_FCHG_SETCHARGEMODE, &One) !=0) + + +p_panic(6); +p_printf("Set Rubbish charge Mode"); +One=-1; + + +if (p_iow (pcb, P_FCHG_SETCHARGEMODE, &One) ==0) + + +p_panic(7); + + +p_iow (pcb, P_FCHG_READSTATUS, &One, &Two) ; + + +p_print ("Battery one:"); +State (One) ; +p_print ("Battery two:"); +State (Two) ; + + +p_printf("Asynch test1"); + + +p_iow (pcb, P_FCHG_ASYNCHREAD, &One, &Two) ; + + +p_print ("Battery one:"); +State (One) ; +p_print ("Battery two:"); +State (Two) ; +p_printf("Asynch test2"); + + +p_iow (pcb, P_FCHG_ASYNCHREAD, &One, &Two) ; + + +p_print ("Battery one:"); +State (One) ; + +p_print ("Battery two:"); +State (Two) ;* + + +18 FAST CHARGER + + +18-9 + + +1/0 DEVICES REFERENCE + + +18 - 10 + + +p_ioc4 (winHandle, P_FREAD, &KStat, &Key) ; +TTime=p_date(); +Disch=0; +DischTime=0; +FOREVER +{ + + +if (KStat!=E_FILE_PENDING) /* Was it the keyboard */ + + +{ + + +p_iowait(); /* not really the way to do this -oh well */ + + +if (Key.keycode=='Q' | | Key. keycode=='q' +p_exit (0); + + +|| Key.keycode==27) + + +else if (Key.keycode=='D' | | Key. keycode=='d"') + + +{ + +p_printf ("Start discharge"); + +TIime=p_date(); + +if (p_iow(pcb,P_FCHG_DISCHARGE) ) +p_panic(8); + +Disch=1; + +} + + +else if (Key.keycode=='F' || Key.keycode=='f') + + +p_printf("Start Fastchargel") ; +TTime=p_date(); + +if (p_iow(pcb,P_FCHG_FASTCHARGE1) ) +p_panic (9); + + +else if (Key. keycode=='G' | | Key. keycode=='g') + + +p_printf("Start Fastcharge2") ; +TTime=p_date(); + +if (p_iow(pcb,P_FCHG_FASTCHARGEZ2) ) +p_panic(9); + + +else if (Key. keycode=='C'! | | Key. keycode=='c"') + + +p_getl("Current: ",&X1Str[0],10); +X1Ptr=&X1Str[0]; +p_stoi(&X1Ptr,&X1); + +} + + +else if (Key.keycode=='/' | | Key. keycode=='?') + + +{ +if (Disch==1) + + +p_printf("Discharging: %d", (p_date()-TTime) ); + + +else + + +{ + + +p_printf("Discharge Time: %d1",DischTime) ; + + +if (X1>0 && DischTime>0) +{ +XE= (850*60*60*10) /X1; +XE= (DischTime*100*10) /XE; + + +p_printf("Capacity (Cell) %d%%", (UWORD) (XE) ); + + +} + + +} + + +else if (Key. keycode=='1') +{ +p_printf("Battery one Log"); +Temp=0; +while (Temp0) +State (LogOne[Temp-1]); +} +else if (Key. keycode=='2') +{ +p_printf ("Battery two Log"); +Temp=0; +while (Temp0) +State (LogTwo[Temp-1]); + + +18 FAST CHARGER + + +else if (Key.keycode=='H' | | Key.keycode=="'h' | | Key. keycode==290 | | +Key. keycode==291) +{ +p_printf£(""); +p_printf("C...Enter Discharge current"); +p_printf("D...Start Discharge"); +p_printf("F...Fastcharge Batteryl"); +p_printf("G...Fastcharge Battery2"); +p_printf("?...Show Discharge time"); +p_printf("1...Show Batteryl Log"); +p_printf("2...Show Battery2 Log"); +poipraent ft ((C"On-. 2QUrt™): 3. +p_printf£(""); +} +p_ioc4 (winHandle, P_FREAD, &KStat, &Key) ; +} +OldOne=One; +OldTwo=Two; +p_iow (pcb, P_FCHG_READSTATUS, &One, &Two) ; +if (OldOne!=One || OldTwo!=Two) +{ +if (OldOne==1 && Disch==1 && One!=1) +{ +Disch=0; +DischTime=(p_date()-TTime) ; +p_printf ("Discharge Time: %d",DischTime) ; +} +p_printf("Time: %d", (p_date()-TTime) ); +if (One!=O0ldOne) +{ +if (P1>50) +P1=0; +LogOne [P1++]=One; +} + + +if (Two!=OldTwo) + +{ + +if (P2>50) + +P2=0; + +LogTwo [P2++]=Two; + +} +p_print ("Battery one:"); +State (One) ; +p_print ("Battery two:"); +State (Two) ; +} + + +18 - 11 + + +INDEX + + +.wve files + +digital sound files, 5-1 +A_FTIMED + +alarm device, 6-2 +A_FTIMED_X + +alarm device, 6-3 +A_FUNTIMED + +alarm device, 6-3 +A_FUNTIMED_X + +alarm device, 6-4 +AccessIr + +infrared API, 16-1 +AccessIr API + +infrared, 15-4 +AIR: + +infrared device, 15-4, 16-1, 16-2 + +loading on Siena, 16-1 +alarm + +device I/O introduction, 6-1 + +note sequence SND: device, 5-3 +alarm device + +A_FTIMED, 6-2 + +A_FTIMED_X, 6-3 + +A_FUNTIMED, 6-3 + +A_FUNTIMED_X, 6-4 + +ALM: introduction, 6-1 + +p_close, 6-2 + +P_FCANCEL, 6-2 + +p_open(ALM:), 6-2 + +panics, 6-2 + +services additional S3a, 6-3 + +services $3 S3a & MC, 6-2 +alarm services + +time application $3 S3a, 6-2 +ALM: device + +introduction, 6-1 + +see alarm device, 6-1 +asynchronous + +I/O functions, 1-1 +bar code + +Codabar start and stop characters, 14-5 + +maximum scanning rate, 14-4 + +supplement digits, 14-4 +bar code command syntax + +HC bar code/RS232 module, 14-11 +bar code commands + +HC bar code/RS232 module, 14-11 +bar code formats UPC/EAN + +HC bar code/RS232 module, 14-6 +bar code interface + +comms settings, 14-2 + +HC bar code/RS232 module, 14-3 + + +bar code symbologies +HC bar code/RS232 module, 14-4 +bar code wand connector +HC bar code/RS232 module, 14-2 +BAR: device +see HC bar code reader, 13-1 +battery capacity +docking station fast charger, 18-3 +HC, 18-3 +Workabout, 18-3 +baud rates +infrared, 15-3 +beaming +infrared communications application, +15-6 +bottom slot +HC bar code/RS232 module, 14-2 +CLIB +programs CON: device use of, 2-1 +Codabar +start and stop characters, 14-5 +communications +infrared application, 15-6 +CON: device +automatic opening, 2-1 +CLIB based programs, 2-1 +example code, 2-14 +explicit opening, 2-3 +handle of, 2-2 +introduction, 2-1 +OPL programs, 2-1 +PLIB based programs, 2-2 +see console device, 2-1 +Condor chip +serial infrared, 15-3 +connection +second time (LM-IAS server) +infrared, 17-4 +connection first time (LM-IAS server) +infrared, 17-4 +connectionless calls +infrared, 17-3 +connectionless read request +infrared, 17-3 +connectionless write request +infrared, 17-3 +connection-oriented calls +infrared, 17-3 +console device +automatic opening of CON: device, 2-1 +example code, 2-14 +explicit opening of CON: device, 2-3 +handle of, 2-2 +I/O, 2-1 +p_close, 2-4 +P_EVENT_READ, 2-9 +P_EVENT_TEST, 2-10 +P_FCANCEL, 2-5 +P_FEDIT, 2-6 +P_FFLUSH, 2-6 +P_FINQ, 2-10 +P_FREAD, 2-5 +P_FSENSE, 2-6 + + +1/0 DEVICES REFERENCE + + +P_FSET service call convention, 2-3 +P_FTEST, 2-5 +P_FWFLUSH, 2-10 +p_open(CON:), 2-3 +P_SCR_ATTRB, 2-11 +P_SCR_CANCEL_CAPTURE_KEY, +2-13 +P_SCR_CAPTURE KEY, 2-13 +P_SCR_CLIENT_FOREGROUND, 2-12 +P_SCR_CLR, 2-7 +P_SCR_COMPATIBILITY, 2-9 +P_SCR_CSET, 2-10 +P_SCR_CURSOR, 2-8 +P_SCR_DISABLE_READS, 2-12 +P_SCR_ESCAPE, 2-9 +P_SCR_FLUSH, 2-12 +P_SCR_FONT, 2-11 +P_SCR_GREY, 2-9 +P_SCR_LAST_LINE_WRAP, 2-12 +P_SCR_NEL, 2-8 +P_SCR_POSA, 2-8 +P_SCR_POSR, 2-8 +P_SCR_SCROLL, 2-7 +P_SCR_SLOCK, 2-8 +P_SCR_WLOCK, 2-8 +P_SCR_WSET, 2-7 +p_write, 2-4 +panics, 2-3 +services, 2-3 +services additional, 2-9 +cradle device +introduction, 11-1 +introduction HC, 11-1 +p_close(CRD:), 11-2 +P_FCANCEL, 11-2 +P_FREAD, 11-2 +P_FSENSE, 11-2 +P_FSET, 11-2 +p_open(CRD:), 11-1 +services, 11-1 +CRC +XYmodem device, 9-1 +CRD: device +introduction, 11-1 +see cradle device, 11-1 +services, 11-1 +data transfer +link I/O, 10-1 +database +world application services $3 S3a, 8-2 +device driver +FCG: docking station, 18-2 +infrared accessir.ldd, 16-1 +serial port LDD, 4-1 +serial port PDD, 4-1 +Siena infrared printing, 15-7 +devices +AJR: infrared, 15-4, 16-1, 16-2 +alarm I/O introduction, 6-1 +ALM: introduction, 6-1 +BAR: introduction, 13-1 +CON: introduction, 2-1 +console I/O, 2-1 + + +ii + + +CRD: introduction, 11-1 +FCG: docking station, 18-1 +FRC: I/O introduction, 7-1 +FRC: introduction, 7-1 +HC bar code reader I/O introduction, 13-1 +HC bar code/RS232 module, 14-1 +HC cradle I/O introduction, 11-1 +HC docking station I/O introduction, 11-1 +HC intelligent bar code Reader, 14-1 +HC magnetic card reader I/O, 12-1 +I/O introduction, 1-1 +I/O Introduction, 1-1 +IRP: infrared printing, 15-7 +MCR: introduction, 12-1 +NCP I/O introduction, 10-1 +PAR: introduction, 3-1 +parallel port I/O, 3-1 +serial port I/O introduction, 4-1 +SIR: infrared, 15-2, 15-3 +SND: introduction, 5-1 +sound I/O introduction, 5-1 +TTY: introduction, 4-1 +WLD: introduction, 8-1 +Workabout docking station I/O +introduction, 11-1 +world database I/O introduction, 8-1 +XMD: introduction, 9-1 +Xmodem I/O introduction, 9-1 +Ymodem I/O introduction, 9-1 +dial tones +sound device DTMF, 5-4 +disconnecting first time (LM-IAS server) +infrared, 17-4 +disconnecting second time +infrared, 17-4 +discovery +infrared, 15-5, 17-4 +DISCOVERY_LOG +structure infrared, 15-5 +docking station +battery capacity calculations, 18-3 +device introduction HC, 11-1 +device introduction Workabout, 11-1 +fast charger, 18-1 +FCG: device, 18-1 +FCG: device driver, 18-2 +FCHG_ASYNCHREAD, 18-7 +FCHG_CANCEL, 18-7 +FCHG_DISCHCHARGE, 18-8 +FCHG_FASTCHARGE 1, 18-7 +FCHG_FASTCHARGE2, 18-7 +FCHG_READCHARGEMODE, 18-6 +FCHG_READSTATUS, 18-6 +FCHG_SETCHARGEMODE, 18-4 +p_close, 18-4 +p_open, 18-3 +docking station device +p_close(CRD:), 11-2 +P_FCANCEL, 11-2 +P_FREAD, 11-2 +P_FSENSE, 11-2 +P_FSET, 11-2 +p_open(CRD:), 11-1 + + +INDEX + + +services, 11-1 +DTMF +sound device dial tones, 5-4 +E_FALARM +sound device, 5-3 +E_FDIAL +sound device, 5-4 +E_FSSOUNDCHANNELn +sound device, 5-3 +E_MESSAGE struct +structure infrared, 17-5 +example application +infrared transfer, 16-7 +example program +fast charger Workabout, 18-8 +infrared transfer, 16-7 +exclusive mode +infrared, 17-4 +expansion module +HC bar code/RS232 module, 14-2 +extension file +world database, 8-9 +fast charger +docking station, 18-1 +example program Workabout, 18-8 +FCHG_ASYNCHREAD, 18-7 +FCHG_CANCEL, 18-7 +FCHG_FASTCHARGE I, 18-7 +FCHG_FASTCHARGE2, 18-7 +FCHG_FASTDISCHARGE I, 18-8 + + +FCHG_READCHARGEMODE, 18-6 + + +FCHG_READSTATUS, 18-6 + +FCHG_SETCHARGEMODE, 18-4 + +introduction, 18-1 + +p_close(FCG:A), 18-4 + +p_open(FCG:A), 18-3 + +services, 18-1 +FCG: + +device, 18-1 +FCHG_ASYNCHREAD + +fast charger, 18-7 +FCHG_CANCEL + +fast charger, 18-7 +FCHG_FASTCHARGE1 + +fast charger, 18-7 +FCHG_FASTCHARGE2 + +fast charger, 18-7 +FCHG_FASTDISCHARGE1 + +fast charger, 18-8 +FCHG_READCHARGEMODE + +fast charger, 18-6 +FCHG_READSTATUS + +fast charger, 18-6 +FCHG_SETCHARGEMODE + +fast charger, 18-4 +file format + +world database, 8-9 + +world database extension, 8-10 +FRC: device + +I/O introduction, 7-1 + +introduction, 7-1 + +p_close, 7-2 + +P_FCANCEL, 7-2 + + +P_FREAD, 7-2, 7-3 +P_FSTART, 7-2 +p_open(FRC:), 7-1 +services $3a & Workabout, 7-1 +free running counter +see FRC: device, 7-1 +get value by class frame +infrared, 17-2 +infrared IAS, 17-3 +get value by class reply frame +infrared IAS, 17-3 +handshaking level +infrared, 17-4 +HC +battery capacity calculation, 18-3 +HC bar code device +p_close, 13-2 +P_FCANCEL, 13-2 +P_FREAD, 13-2 +p_open(BAR:), 13-2 +HC bar code reader +device driver, 13-1 +hardware description, 13-1 +interface module, 13-1 +services, 13-2 +wand, 13-1 +HC bar Code reader +device I/O introduction, 13-1 +HC bar code/RS232 module +2-pin header, 14-3, 14-4 +5v regulated power supply, 14-4 +auto power-off HC, 14-4 +bar code command syntax, 14-11 +bar code commands, 14-11 +bar code formats UPC/EAN, 14-6 +bar code symbologies, 14-4 +bar code wand connector, 14-2 +bottom slot, 14-2, 14-3 +charging the main battery, 14-3 +CTS input, 14-2 +DCD input, 14-2, 14-3 +device introduction, 14-1 +diode isolation, 14-3 +DSR auto wakeup switch, 14-3 +DSR input, 14-2, 14-3 +DTR output, 14-2, 14-3 +example code, 14-20 +expansion module, 14-2 + + +HBCR-1610 series micro controller, 14-3 + + +idle current of interface, 14-4 + + +IGN_CTS serial port characteristic, 14-3 + + +interface comms settings, 14-3 + + +losing micro controller program data, + + +14-4 + +maximum output current, 14-2 +optional Vsup connection, 14-2 +p_close, 14-18 + +P_FREAD, 14-18 + +P_FSENSE, 14-18 + +P_FSET, 14-18 + +P_FWRITE, 14-19 +p_open(TTY:), 14-17 + +power consumption, 14-2 + + +1/0 DEVICES REFERENCE + + +power consumption wand, 14-4 +powering an external device, 14-4 +programming, 14-1 + +RI pin of the RS232 port, 14-2 +RS232 port pinout table, 14-2 +RTS output, 14-2 + + +RTS/CTS handshaking protocol, 14-3 + + +RX input, 14-2 + + +scanning current for the interface, 14-4 + + +services, 14-17 + +switched Sv regulated output, 14-3 +switched Vsup output, 14-3 +switching off the external unit, 14-2 + + +tmask serial port characteristics, 14-3 + + +top slot, 14-2, 14-3 + +TTY:A, 14-2 + +TTY:B, 14-2 + +TTY:D, 14-2, 14-3 + +TTY:E, 14-2, 14-3 + +TX output, 14-2 + +undecoded laser scanners, 14-3 + + +Vsup input voltage supply range, 14-3 + + +wand emulator, 14-1 +Xon/Xoff handshaking, 14-2 +HC cradle device +introduction, 11-1 +see cradle device, 11-1 +HC docking station +device introduction, 11-1 +HC intelligent bar code reader +device introduction, 14-1 +see HC bar code/RS232 module, 14-1 +HC magnetic card device +introduction, 12-1 +p_close, 12-1 +P_FCANCEL, 12-2 +P_FREAD, 12-1 +P_FSET, 12-2 +p_open(MCR:), 12-1 +services, 12-1 +HC magnetic card reader +device I/O, 12-1 +HWIM +infrared applications, 15-6 +I/O devices +introduction, 1-1 +see devices, 1-1 +I/O function +asynchronous, 1-1 +p_ioc, 1-1 +p_ioca, 1-1 +p_iow, 1-1 +synchronous, 1-1 +TAS +infrared, 15-4 +idle mode +infrared, 17-4 +include file +infrared constants p_file.h, 16-2 +infrared +AccessIr API, 15-4, 16-1 +AIR: device, 15-4, 16-1, 16-2 +AIR: device on Siena, 16-1 + + +iv + + +baud rates, 15-3 + +beaming communications application, +15-6 + +communications AccessIr API, 16-1 +communications application, 15-6 +communications IrMUX API, 17-1 +Condor serial chip, 15-3 + +connection first time (LM-IAS server), +17-4 + +connection second time (LM-IAS server), +17-4 + +connectionless calls, 17-3 +connectionless read request, 17-3 +connectionless services IrLAP, 15-4 +connectionless write request, 17-3 +connection-oriented calls, 17-3 +connection-oriented services IrLAP, 15-4 +constant P_FIRAWAITCONNECT, 16-3 +constant P_FIRDISCONNECT, 16-3 +constant P_FIRDISCOVER, 16-3 +constant P_ FIRMAKECONNECT, 16-3 +constant P_FIRSELECT, 16-3 + +constant P_FREAD, 16-3 + +constant P_FWRITE, 16-3 + +constants p_file.h, 16-2 + +device driver accessir.ldd, 16-1 +disconnecting first time (LM-IAS server), +17-4 + +disconnecting second time, 17-4 +discovery, 15-5, 17-4 + +example application, 16-7 + +exclusive mode, 17-4 + +handshaking level, 17-4 + +HWIM applications, 15-6 + +TAS, 15-4 + +IAS get value by class frame, 17-2, 17-3 +IAS get value by class reply frame, 17-3 +idle mode, 17-4 + +IPCS methods, 17-1 + +IrDA protocol model, 15-1 + +IrDA standard, 15-1 + +IrLAP, 15-1 + +IrLAP layer, 15-2, 15-3 + +IrLAP services, 15-4 + +IrLMP, 15-1, 15-4 + +IrLMP layer, 15-3 + +IrMUX API, 15-4, 17-1 + +IrMUX message format, 17-5 + +IrMUX server logoff, 17-2 + +IrMUX server logon, 17-2 + +ISO OSI layers, 15-1 + +link control, 15-6 + +link paste, 15-6 +LM_AccessModeRequest, 17-4, 17-11 +LM_CLReadRequest, 17-6 +LM_CLWriteRequest, 17-7 +LM_ConnectRequest, 17-2, 17-4, 17-7 +LM_DisconnectRequest, 17-4, 17-13 +LM_DiscoverDevicesRequest, 17-4, 17-7 +LM_GetValueByClass, 17-2 +LM_IdleRequest, 17-12 + +LM_Logoff, 17-2, 17-5 + +LM_Logon, 17-2, 17-5 + + +INDEX + + +LM_ReadRequest, 17-4, 17-9 +LM_RegisterPort, 17-2, 17-5 +LM_SetHandshakingLevel, 17-4, 17-12 +LM_StatusRequest, 17-9 +LM_UnRegisterPort, 17-2, 17-6 +LM_UReadRequest, 17-4, 17-10 +LM_UWriteRequest, 17-4, 17-11 +LM_WaitForConnection, 17-8 +LM_WriteRequest, 17-4, 17-10 +LM-IAS, 15-4 + +LM-IAS server registering, 17-2 +LM-IAS server unregistering, 17-2 +LM-MUxX, 15-4 + +loadIRDAserver() example code, 16-2 +message number | (IrMUX), 17-5 +message number 10 (IrMUX), 17-5 +message number 11 (rMUX), 17-6 +message number 2 (IrMUX), 17-5 +message number 20 (IrMUX), 17-13 +message number 21 (IrMUX), 17-9 +message number 22 (IrMUX), 17-11 +message number 23 (IrMUX), 17-12 +message number 24 (IrMUX), 17-9 +message number 25 (IrMUX), 17-10 +message number 26 (IrMUX), 17-10 +message number 27 (IrMUX), 17-11 +message number 28 (IrMUX), 17-12 +message number 4 (IrMUX), 17-6 +message number 5 (IrMUX), 17-7 +message number 6 (IrMUX), 17-7 +message number 8 (IrMUX), 17-8 +message number 9 (IrMUX), 17-7 +multiplexing, 15-6 + +MUXMESSAGE structure, 17-5 +OSI layers, 15-1 + +p_close, 16-2, 16-4 +P_FIRAWAITCONNECT, 16-3, 16-5 +P_FIRDISCONNECT, 16-3, 16-6 +P_FIRDISCOVER, 16-2, 16-4 +P_FIRMAKECONNECT, 16-3, 16-5 +P_FIRSELECT, 16-2, 16-4 +P_FREAD, 16-3, 16-6 + +P_FWRITE, 16-3, 16-6 + +p_mreceive, 17-5 + +p_open(AIR:), 16-2, 16-3 + +primary station, 15-4 + +printer IRP: device, 15-7 + +printer IRP: device Siena, 15-7 +protocol stack - initializing, 17-1 +protocol stack example code, 17-2 +protocol stack SYS$IRDA.IMG, 16-2, +17-2 + +Psion protocol model, 15-2 + +read request, 17-4 + +read request unreliable, 17-4 + +retries, 17-4 + +secondary station, 15-4 + +SIR, 15-1 + +SIR: device, 15-2, 15-3 +SYS_IR_POWER_LEVEL, 15-6 +SYS_PRINTER_IR, 15-6 + +unreliable read request, 17-4 + + +unreliable write request, 17-4 +write request, 17-4 +write request unreliable ), 17-4 +infrared communication +introduction to Psion IR, 15-1 +IPCS +infrared methods, 17-1 +IrDA +infrared protocol model, 15-1 +standard, 15-1 +IrLAP +infrared, 15-1 +infrared layer, 15-2, 15-3 +IrLAP services +infrared, 15-4 +IrLMP +infrared, 15-1, 15-4 +infrared layer, 15-3 +IrmMUxX +infrared API, 17-1 +IrMUX API +infrared, 15-4 +IrMUX message format +infrared, 17-5 +IrMUX server +infrared logoff, 17-2 +infrared logon, 17-2 +IRP: +infrared printer device, 15-7 +ISO OST layers +infrared, 15-1 +key code +W_KEY_IR_BRING, 15-6 +W_KEY_IR_LINK, 15-6 +W_KEY_IR_SEND, 15-6 +Link +data transfer, 10-1 +example code, 10-10 +inter-process messages, 10-3 +panics, 10-1 +process, 10-1 +protocol, 10-1 +protocol I/O introduction, 10-1 +LINK +process, 10-3 +link control +infrared, 15-6 +link paste +infrared, 15-6 +LM_AccessModeRequest +infrared, 17-4, 17-11 +LM_CLReadRequest +infrared, 17-6 +LM_CLWriteRequest +infrared, 17-7 +LM_ConnectRequest +infrared, 17-2, 17-4, 17-7 +LM_DisconnectRequest +infrared, 17-4, 17-13 +LM_DiscoverDevicesRequest +infrared, 17-4, 17-7 +LM_GetValueByClass +infrared, 17-2 + + +I/O DEVICES REFERENCE + + +LM_IdleRequest +infrared, 17-12 +LM_Logoff +infrared, 17-2, 17-5 +LM_Logon +infrared, 17-2, 17-5 +LM_ReadRequest +infrared, 17-4, 17-9 +LM_RegisterPort +infrared, 17-2, 17-5 +LM_SetHandshakingLevel +infrared, 17-4, 17-12 +LM_StatusRequest +infrared, 17-4, 17-9 +LM_UnRegisterPort +infrared, 17-2, 17-6 +LM_UReadRequest +infrared, 17-4, 17-10 +LM_UWriteRequest +infrared, 17-4, 17-11 +LM_WaitForConnection +infrared, 17-8 +LM_WriteRequest +infrared, 17-4, 17-10 +LM-IAS +infrared, 15-4 +LM-IAS server + + +LM-MUX +infrared, 15-4 +loadIRDAserver() + + +infrared example code, 16-2 + + +magic static + + +CON: device handle winHandle, 2-2 + + +magnetic card device + + +see HC magnetic card device, 12-1 + + +main world file +location, 8-9 + +maximum scanning rate +bar codes, 14-4 + +MCR: device +introduction, 12-1 + + +see HC magnetic card device, 12-1 + + +multiplexing + +infrared, 15-6 +MUXMESSAGE structure +infrared, 17-5 +NCP +panics, 10-1 + + +NCP device + +I/O introduction, 10-1 +NCP: device + +example code, 10-10 +p_close, 10-4 +P_FCANCEL, 10-7 +P_FCONNECT, 10-4 + + +P_FDISCONNECT, 10-6 + + +P_FINQ, 10-9 +P_FREAD, 10-6 + + +infrared registering, 17-2 +infrared unregistering, 17-2 + + +process SYS$NCP, 10-1 + + +P_FRSUPER, 10-7 +P_FSENSE, 10-10 +P_FSTOP, 10-10 +P_FWRITE, 10-7 +p_open(NCP:), 10-3 +process SYS$NCP, 10-2 +services, 10-3 +note sequence +SND: device, 5-3 +OPL +CON: device use of, 2-1 +OSI layers +infrared, 15-1 +p_close +alarm device, 6-2 +console device, 2-4 +FRC: device, 7-2 +HC bar code device, 13-2 +HC bar code/RS232 module, 14-18 +HC magnetic card device, 12-1 +infrared, 16-2, 16-4 +NCP: device, 10-4 +parallel port, 3-1 +serial port, 4-6 +sound device, 5-2 +world device, 8-2 +XYmodem device, 9-8 +p_close(CRD:) +close device, 11-2 +p_close(FCG:A) +fast charger device, 18-4 +P_EVENT_READ +console device, 2-9 +P_EVENT_TEST +console device, 2-10 +P_FCANCEL +alarm device, 6-2 +cancel read from device, 11-2 +console device, 2-5 +FRC: device, 7-2 +HC bar code device, 13-2 +HC magnetic card device, 12-2 +NCP: device, 10-7 +parallel port, 3-2 +serial port, 4-8 +sound device, 5-2 +world device, 8-2 +P_FCONNECT +NCP: device, 10-4 +XYmodem device, 9-8 +P_FCTRL +serial port, 4-9 +P_FDISCONNECT +NCP: device, 10-6 +XYmodem device, 9-10 +P_FEDIT +console device, 2-6 +P_FFLUSH +console device, 2-6 +serial port, 4-9 +p_file.h +infrared constants, 16-2 + + +INDEX + + +P_FINQ + +console device, 2-10 + +NCP: device, 10-9 + +serial port, 4-10 +P_FIRAWAITCONNECT + +infrared, 16-3, 16-5 + +infrared constant, 16-3 +P_FIRDISCONNECT + +infrared, 16-3, 16-6 + +infrared constant, 16-3 +P_FIRDISCOVER + +infrared, 16-2, 16-4 + +infrared constant, 16-3 +P_FIRMAKECONNECT + +infrared, 16-3, 16-5 + +infrared constant, 16-3 +P_FIRSELECT + +infrared, 16-2, 16-4 + +infrared constant, 16-3 +P_FREAD + +console device, 2-5 + +FRC: device, 7-2, 7-3 + +HC bar code device, 13-2 + +HC bar code/RS232 module, 14-18 + +HC magnetic card device, 12-1 + +infrared, 16-3, 16-6 + +infrared constant, 16-3 + +NCP: device, 10-6 + +read from device, 11-2 + +serial port, 4-7 + +XYmodem device, 9-11 +P_FRSUPER + +NCP: device, 10-7 +P_FSENSE + +console device, 2-6 + +HC bar code/RS232 module, 14-18 + +NCP: device, 10-10 + +parallel port, 3-2 + +sense the device type, 11-2 + +serial port, 4-9 + +sound device, 5-2 +P_FSET + +HC bar code/RS232 module, 14-18 + +HC magnetic card device, 12-2 + +parallel port, 3-2 + +serial port, 4-9 + +service call convension, 2-3 + +set the device type, 11-2 + +sound device, 5-2 +P_FSTART + +FRC: device, 7-2 +P_FSTOP + +NCP: device, 10-10 +P_FTEST + +console device, 2-5 + +serial port, 4-9 +P_FWFLUSH + +console device, 2-10 +P_FWRITE + +HC bar code/RS232 module, 14-19 + +infrared, 16-3, 16-6 + +infrared constant, 16-3 + +NCP: device, 10-7 + + +parallel port, 3-2 + +serial port, 4-8 + +XYmodem device, 9-12 +p_ioc + +I/O function, 1-1 +p_ioca + +I/O function, 1-1 +p_iow + +I/O function, 1-1 +p_mreceive + +infrared, 17-5 +p_open(AIR: + +infrared) + +infrared, 16-2 + +p_open(AIR:) + +infrared, 16-3 +p_open(ALM:) + +alarm device, 6-2 +p_open(BAR:) + +HC bar code device, 13-2 +p_open(CON:) + +console device, 2-3 +p_open(CRD:) + +open device, 11-1 +p_open(FCG:A) + +fast charger device, 18-3 +p_open(FRC:) + +FRC: device, 7-1 +p_open(MCR:) + +HC magnetic card device, 12-1 +p_open(NCP:) + +NCP: device, 10-3 +p_open(PAR:) + +parallel port, 3-1 +p_open(SND:) + +sound device, 5-2 +p_open(TTY:) + +HC bar code/RS232 module, 14-17 + +serial port, 4-6 +p_open(WLD:) + +world device, 8-2 +p_open(XMD:) + +XYmodem device, 9-8 +P_SCR_ATTRB + +console device, 2-11 +P_SCR_CANCEL_CAPTURE_KEY + +console device, 2-13 +P_SCR_CAPTURE KEY + +console device, 2-13 +P_SCR_CLIENT_FOREGROUND + +console device, 2-12 +P_SCR_CLR + +console device, 2-7 +P_SCR_COMPATIBILITY + +console device, 2-9 +P_SCR_CSET + +console device, 2-10 +P_SCR_CURSOR + +console device, 2-8 +P_SCR_DISABLE_READS + +console device, 2-12 +P_SCR_ESCAPE + +console device, 2-9 + + +I/O DEVICES REFERENCE + + +P_SCR_FLUSH + +console device, 2-12 +P_SCR_FONT + +console device, 2-11 +P_SCR_GREY + +console device, 2-9 +P_SCR_LAST_LINE_WRAP + +console device, 2-12 +P_SCR_NEL + +console device, 2-8 +P_SCR_POSA + +console device, 2-8 +P_SCR_POSR + +console device, 2-8 +P_SCR_SCROLL + +console device, 2-7 +P_SCR_SLOCK + +console device, 2-8 +P_SCR_WLOCK + +console device, 2-8 +P_SCR_WSET + +console device, 2-7 +p_write + +console device, 2-4 +panics + +alarm device, 6-2 + +console device, 2-3 + +Link, 10-1 + +NCP, 10-1 + +parallel port device, 3-1 + +serial port device, 4-1 + +sound device, 5-1 +PAR: device + +example code, 3-3 + +introduction, 3-1 + +see parallel port, 3-1 +parallel port + +device I/O, 3-1 + +example code, 3-3 + +p_close, 3-1 + +P_FCANCEL, 3-2 + +P_FSENSE, 3-2 + +P_FSET, 3-2 + +P_FWRITE, 3-2 + +p_open(PAR:), 3-1 + +panics, 3-1 +parity errors + +HC bar code/RS232 module, 14-3 +PC-AT style RS232 port + +HC bar code/RS232 module, 14-1 +PLIB + +programs CON: device use of, 2-2 +power consumption + +HC bar code/RS232 module, 14-4 +primary station + +infrared, 15-4 +printer device + +IRP: infrared, 15-7 +protocol + +Link introduction, 10-1 +protocol stack + +infrared - initializing, 17-1 + + +Psion infrared +protocol model, 15-2 +read request +infrared, 17-4 +read request unreliable +infrared, 17-4 +retries +infrared, 17-4 +RI pin of the RS232 port +HC bar code/RS232 module, 14-2 +RS232 device +see serial port, 4-1 +RS232 port pinout table +HC bar code/RS232 module, 14-2 +secondary station +infrared, 15-4 +serial infrared +Condor chip, 15-3 +serial port +baud rate, 4-2 +character frame, 4-2 +control flags, 4-5 +device driver LDD, 4-1 +device driver PDD, 4-1 +device I/O introduction, 4-1 +errors, 4-5 +example code, 4-11 +handshaking, 4-3 +HC TTL levels, 4-1 +p_close, 4-6 +P_FCANCEL, 4-8 +P_FCTRL, 4-9 +P_FFLUSH, 4-9 +P_FINQ, 4-10 +P_FREAD, 4-7 +P_FSENSE, 4-9 +P_FSET, 4-9 +P_FTEST, 4-9 +P_FWRITE, 4-8 +p_open(TTY:), 4-6 +panics, 4-1 +parameters, 4-1 +parity, 4-3 +services, 4-6 +terminator characters, 4-5 +Siena infrared +printer IRP: device driver, 15-7 +SIR +infrared, 15-1 +SIR: +infrared device, 15-2, 15-3 +SND: device +example code, 5-5 +introduction, 5-1 +see sound device, 5-1 +sound +buzzer emulator, 5-1 +buzzer piezo, 5-1 +device I/O introduction, 5-1 +digital files, 5-1 +HC machines, 5-1 +MC machines, 5-1 + + +INDEX + + +S3 machines, 5-1 + +S$3a machines, 5-1 +sound device + +E_FALARM, 5-3 + +E_FSSOUNDCHANNEL1, 5-3 + +example code, 5-5 + +p_close, 5-2 + +P_FCANCEL, 5-2 + +P_FSENSE, 5-2 + +P_FSET, 5-2 + +p_open(SND:), 5-2 + +panics, 5-1 + +services, 5-2 + +services additional HC MC S3a, 5-3 + +services additional S3 S3a, 5-4 + +SND: introduction, 5-1 +structures + +DISCOVERY_LOG infrared, 15-5 + +E_MESSAGE infrared, 17-5 + +MUXMESSAGE infrared, 17-5 +supplement digits + +bar codes, 14-4 +synchronous + +I/O functions, 1-1 +SYS$IRDA.IMG + +infrared protocol stack, 16-2, 17-2 +SYS$NCP + +process, 10-1, 10-2 +SYS_IR_POWER_LEVEL + +infrared, 15-6 +SYS_PRINTER_IR + +infrared, 15-6 +time application + +alarm services $3 S3a, 6-2 +top slot + +HC bar code/RS232 module, 14-2 +TTY: device + +example code, 4-11 + +introduction, 4-1 + +parameters, 4-1 + +see serial port, 4-1 +TTY:A + +HC bar code/RS232 module, 14-2 +TTY:B + +HC bar code/RS232 module, 14-2 +TTY sD + +HC bar code/RS232 module, 14-2 +TTY:E + +HC bar code/RS232 module, 14-2 +unreliable read request + +infrared, 17-4 +unreliable write request + +infrared, 17-4 +W_KEY_IR_BRING + +key code, 15-6 +W_KEY_IR_LINK + +key code, 15-6 +W_KEY_IR_ SEND + +key code, 15-6 +wand emulator + +HC bar code/RS232 module, 14-1 +winHandle + +magic static CON: device handle, 2-2 + + +WLD: device +introduction, 8-1 +see world device, 8-1 +Workabout +battery capacity calculation, 18-3 +Workabout docking station +device introduction, 11-1 +see docking station device, 11-1 +world application +database S3 S3a, 8-2 +world database +contents, 8-1 +file extension, 8-9 +file format, 8-9 +file format extension file, 8-10 +file types and locations, 8-9 +see also world device, 8-1 +world database device +see world device, 8-1 +world device +database contents, 8-1 +file extension, 8-9 +file format, 8-9 +file format extension file, 8-10 +file types and locations, 8-9 +I/O introduction, 8-1 +introduction, 8-1 +mode, 8-1 +p_close, 8-2 +P_FCANCEL, 8-2 +p_open(WLD:), 8-2 +services, 8-2 +WR_BACK, 8-3 +WR_CALC, 8-8 +WR_EXTRA, 8-5 +WR_FIND_CITY, 8-2 +WR_FIND_COUNTRY, 8-2 +WR_FIND_EXACT, 8-3 +WR_GET_CITY_DATA, 8-6 +WR_GET_COUNTRY_DATA, 8-7 +WR_GET_DEFAULT_COUNTRY, 8-4 +WR_GET_DIAL_STRING, 8-4 +WR_GET_HOME, 8-3 +WR_NEXT, 8-3 +WR_NEXT_LOCK, 8-9 +WR_SET_DEFAULT_COUNTRY, 8-4 +WR_SET_EXTRA, 8-5 +WR_SET_HOME, 8-3 +world file +extension, 8-9 +format, 8-9 +format extension file, 8-10 +main, 8-9 +world.dat +location, 8-9 +WR_BACK +world device, 8-3 +WR_CALC +world device, 8-8 +WR_EXTRA +world device, 8-5 +WR_FIND_CITY +world device, 8-2 + + +ix + + +I/O DEVICES REFERENCE + + +WR_FIND_COUNTRY + +world device, 8-2 +WR_FIND_EXACT + +world device, 8-3 +WR_GET_CITY_DATA + +world device, 8-6 +WR_GET_COUNTRY_DATA + +world device, 8-7 +WR_GET_DEFAULT_COUNTRY + +world device, 8-4 +WR_GET_DIAL_STRING + +world device, 8-4 +WR_GET_HOME + +world device, 8-3 +WR_NEXT + +world device, 8-3 +WR_NEXT_LOCK + +world device, 8-9 +WR_SET_DEFAULT_COUNTRY + +world device, 8-4 +WR_SET_EXTRA + +world device, 8-5 +WR_SET_HOME + +world device, 8-3 +write request + +infrared, 17-4 +write request unreliable + +infrared), 17-4 +XMD: device + +introduction, 9-1 + +see XYmodem device, 9-1 +Xmodem device + +I/O introduction, 9-1 + +see XYmodem device, 9-1 +Xon/Xoff handshaking + +HC bar code/RS232 module, 14-2 +XYmodem device + +checksum CRC, 9-1 + +checksum one byte, 9-1 + +device driver, 9-1 + +device I/O, 9-1 + +example connect code, 9-10 + +example disconnect code, 9-10 + +example file receive code, 9-11 + +example file recieve code, 9-12 + +example file send code, 9-10, 9-13 + +p_close, 9-8 + +P_FCONNECT, 9-8 + +P_FDISCONNECT, 9-10 + +P_FREAD, 9-11 + +P_FWRITE, 9-12 + +p_open(XMD:), 9-8 + +protocol problems, 9-7 + +protocols, 9-1 + +services, 9-8 + +Xmodem protocol, 9-2 + +Ymodem protocol, 9-4 +Ymodem device + +I/O introduction, 9-1 + +see XYmodem device, 9-1 + + diff --git a/docs/2-04 The SIBO Debugger 2.10_djvu.txt b/docs/2-04 The SIBO Debugger 2.10_djvu.txt new file mode 100755 index 0000000..95dc1b0 --- /dev/null +++ b/docs/2-04 The SIBO Debugger 2.10_djvu.txt @@ -0,0 +1,3286 @@ +THE SIBO DEBUGGER + + +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. + + +LES SSS ae ee ee eS ee ee ea +Contents + + +—_— —__ ror —— + + +TD AM OGUCHON 6 2.c025nitiecnoban eects wdtaciyngctececoduceiessceasahee he Oeseee eete Ree vee cece 1 +DEBUG OINGINOGES S. Cinicursonautatiane tostoesetune satid eewcaaess ides tee naaeet eer ocaibne eae 1 +SIBO