PNG  IHDRX cHRMz&u0`:pQ<bKGD pHYsodtIME MeqIDATxw]Wug^Qd˶ 6`!N:!@xI~)%7%@Bh&`lnjVF29gΨ4E$|>cɚ{gk= %,a KX%,a KX%,a KX%,a KX%,a KX%,a KX%, b` ǟzeאfp]<!SJmɤY޲ڿ,%c ~ع9VH.!Ͳz&QynֺTkRR.BLHi٪:l;@(!MԴ=žI,:o&N'Kù\vRmJ雵֫AWic H@" !: Cé||]k-Ha oݜ:y F())u]aG7*JV@J415p=sZH!=!DRʯvɱh~V\}v/GKY$n]"X"}t@ xS76^[bw4dsce)2dU0 CkMa-U5tvLƀ~mlMwfGE/-]7XAƟ`׮g ewxwC4\[~7@O-Q( a*XGƒ{ ՟}$_y3tĐƤatgvێi|K=uVyrŲlLӪuܿzwk$m87k( `múcE)"@rK( z4$D; 2kW=Xb$V[Ru819קR~qloѱDyįݎ*mxw]y5e4K@ЃI0A D@"BDk_)N\8͜9dz"fK0zɿvM /.:2O{ Nb=M=7>??Zuo32 DLD@D| &+֎C #B8ַ`bOb $D#ͮҪtx]%`ES`Ru[=¾!@Od37LJ0!OIR4m]GZRJu$‡c=%~s@6SKy?CeIh:[vR@Lh | (BhAMy=݃  G"'wzn޺~8ԽSh ~T*A:xR[ܹ?X[uKL_=fDȊ؂p0}7=D$Ekq!/t.*2ʼnDbŞ}DijYaȲ(""6HA;:LzxQ‘(SQQ}*PL*fc\s `/d'QXW, e`#kPGZuŞuO{{wm[&NBTiiI0bukcA9<4@SӊH*؎4U/'2U5.(9JuDfrޱtycU%j(:RUbArLֺN)udA':uGQN"-"Is.*+k@ `Ojs@yU/ H:l;@yyTn}_yw!VkRJ4P)~y#)r,D =ě"Q]ci'%HI4ZL0"MJy 8A{ aN<8D"1#IJi >XjX֔#@>-{vN!8tRݻ^)N_╗FJEk]CT՟ YP:_|H1@ CBk]yKYp|og?*dGvzنzӴzjֺNkC~AbZƷ`.H)=!QͷVTT(| u78y֮}|[8-Vjp%2JPk[}ԉaH8Wpqhwr:vWª<}l77_~{s۴V+RCģ%WRZ\AqHifɤL36: #F:p]Bq/z{0CU6ݳEv_^k7'>sq*+kH%a`0ԣisqにtү04gVgW΂iJiS'3w.w}l6MC2uԯ|>JF5`fV5m`Y**Db1FKNttu]4ccsQNnex/87+}xaUW9y>ͯ骵G{䩓Գ3+vU}~jJ.NFRD7<aJDB1#ҳgSb,+CS?/ VG J?|?,2#M9}B)MiE+G`-wo߫V`fio(}S^4e~V4bHOYb"b#E)dda:'?}׮4繏`{7Z"uny-?ǹ;0MKx{:_pÚmFמ:F " .LFQLG)Q8qN q¯¯3wOvxDb\. BKD9_NN &L:4D{mm o^tֽ:q!ƥ}K+<"m78N< ywsard5+вz~mnG)=}lYݧNj'QJS{S :UYS-952?&O-:W}(!6Mk4+>A>j+i|<<|;ر^߉=HE|V#F)Emm#}/"y GII웻Jі94+v뾧xu~5C95~ūH>c@덉pʃ1/4-A2G%7>m;–Y,cyyaln" ?ƻ!ʪ<{~h~i y.zZB̃/,雋SiC/JFMmBH&&FAbϓO^tubbb_hZ{_QZ-sύodFgO(6]TJA˯#`۶ɟ( %$&+V'~hiYy>922 Wp74Zkq+Ovn錄c>8~GqܲcWꂎz@"1A.}T)uiW4="jJ2W7mU/N0gcqܗOO}?9/wìXžΏ0 >֩(V^Rh32!Hj5`;O28؇2#ݕf3 ?sJd8NJ@7O0 b־?lldщ̡&|9C.8RTWwxWy46ah嘦mh٤&l zCy!PY?: CJyв]dm4ǜҐR޻RլhX{FƯanшQI@x' ao(kUUuxW_Ñ줮[w8 FRJ(8˼)_mQ _!RJhm=!cVmm ?sFOnll6Qk}alY}; "baӌ~M0w,Ggw2W:G/k2%R,_=u`WU R.9T"v,<\Ik޽/2110Ӿxc0gyC&Ny޽JҢrV6N ``یeA16"J³+Rj*;BϜkZPJaÍ<Jyw:NP8/D$ 011z֊Ⱳ3ι֘k1V_"h!JPIΣ'ɜ* aEAd:ݺ>y<}Lp&PlRfTb1]o .2EW\ͮ]38؋rTJsǏP@芎sF\> P^+dYJLbJ C-xϐn> ι$nj,;Ǖa FU *择|h ~izť3ᤓ`K'-f tL7JK+vf2)V'-sFuB4i+m+@My=O҈0"|Yxoj,3]:cо3 $#uŘ%Y"y죯LebqtҢVzq¼X)~>4L׶m~[1_k?kxֺQ`\ |ٛY4Ѯr!)N9{56(iNq}O()Em]=F&u?$HypWUeB\k]JɩSع9 Zqg4ZĊo oMcjZBU]B\TUd34ݝ~:7ڶSUsB0Z3srx 7`:5xcx !qZA!;%͚7&P H<WL!džOb5kF)xor^aujƍ7 Ǡ8/p^(L>ὴ-B,{ۇWzֺ^k]3\EE@7>lYBȝR.oHnXO/}sB|.i@ɥDB4tcm,@ӣgdtJ!lH$_vN166L__'Z)y&kH;:,Y7=J 9cG) V\hjiE;gya~%ks_nC~Er er)muuMg2;֫R)Md) ,¶ 2-wr#F7<-BBn~_(o=KO㭇[Xv eN_SMgSҐ BS헃D%g_N:/pe -wkG*9yYSZS.9cREL !k}<4_Xs#FmҶ:7R$i,fi!~' # !6/S6y@kZkZcX)%5V4P]VGYq%H1!;e1MV<!ϐHO021Dp= HMs~~a)ަu7G^];git!Frl]H/L$=AeUvZE4P\.,xi {-~p?2b#amXAHq)MWǾI_r`S Hz&|{ +ʖ_= (YS(_g0a03M`I&'9vl?MM+m~}*xT۲(fY*V4x@29s{DaY"toGNTO+xCAO~4Ϳ;p`Ѫ:>Ҵ7K 3}+0 387x\)a"/E>qpWB=1 ¨"MP(\xp߫́A3+J] n[ʼnӼaTbZUWb={~2ooKױӰp(CS\S筐R*JغV&&"FA}J>G֐p1ٸbk7 ŘH$JoN <8s^yk_[;gy-;߉DV{c B yce% aJhDȶ 2IdйIB/^n0tNtџdcKj4϶v~- CBcgqx9= PJ) dMsjpYB] GD4RDWX +h{y`,3ꊕ$`zj*N^TP4L:Iz9~6s) Ga:?y*J~?OrMwP\](21sZUD ?ܟQ5Q%ggW6QdO+\@ ̪X'GxN @'4=ˋ+*VwN ne_|(/BDfj5(Dq<*tNt1х!MV.C0 32b#?n0pzj#!38}޴o1KovCJ`8ŗ_"]] rDUy޲@ Ȗ-;xџ'^Y`zEd?0„ DAL18IS]VGq\4o !swV7ˣι%4FѮ~}6)OgS[~Q vcYbL!wG3 7띸*E Pql8=jT\꘿I(z<[6OrR8ºC~ډ]=rNl[g|v TMTղb-o}OrP^Q]<98S¤!k)G(Vkwyqyr޽Nv`N/e p/~NAOk \I:G6]4+K;j$R:Mi #*[AȚT,ʰ,;N{HZTGMoּy) ]%dHء9Պ䠬|<45,\=[bƟ8QXeB3- &dҩ^{>/86bXmZ]]yޚN[(WAHL$YAgDKp=5GHjU&99v簪C0vygln*P)9^͞}lMuiH!̍#DoRBn9l@ xA/_v=ȺT{7Yt2N"4!YN`ae >Q<XMydEB`VU}u]嫇.%e^ánE87Mu\t`cP=AD/G)sI"@MP;)]%fH9'FNsj1pVhY&9=0pfuJ&gޤx+k:!r˭wkl03׼Ku C &ѓYt{.O.zҏ z}/tf_wEp2gvX)GN#I ݭ߽v/ .& и(ZF{e"=V!{zW`, ]+LGz"(UJp|j( #V4, 8B 0 9OkRrlɱl94)'VH9=9W|>PS['G(*I1==C<5"Pg+x'K5EMd؞Af8lG ?D FtoB[je?{k3zQ vZ;%Ɠ,]E>KZ+T/ EJxOZ1i #T<@ I}q9/t'zi(EMqw`mYkU6;[t4DPeckeM;H}_g pMww}k6#H㶏+b8雡Sxp)&C $@'b,fPߑt$RbJ'vznuS ~8='72_`{q纶|Q)Xk}cPz9p7O:'|G~8wx(a 0QCko|0ASD>Ip=4Q, d|F8RcU"/KM opKle M3#i0c%<7׿p&pZq[TR"BpqauIp$ 8~Ĩ!8Սx\ւdT>>Z40ks7 z2IQ}ItԀ<-%S⍤};zIb$I 5K}Q͙D8UguWE$Jh )cu4N tZl+[]M4k8֦Zeq֮M7uIqG 1==tLtR,ƜSrHYt&QP윯Lg' I,3@P'}'R˪e/%-Auv·ñ\> vDJzlӾNv5:|K/Jb6KI9)Zh*ZAi`?S {aiVDԲuy5W7pWeQJk֤#5&V<̺@/GH?^τZL|IJNvI:'P=Ϛt"¨=cud S Q.Ki0 !cJy;LJR;G{BJy޺[^8fK6)=yʊ+(k|&xQ2`L?Ȓ2@Mf 0C`6-%pKpm')c$׻K5[J*U[/#hH!6acB JA _|uMvDyk y)6OPYjœ50VT K}cǻP[ $:]4MEA.y)|B)cf-A?(e|lɉ#P9V)[9t.EiQPDѠ3ϴ;E:+Օ t ȥ~|_N2,ZJLt4! %ա]u {+=p.GhNcŞQI?Nd'yeh n7zi1DB)1S | S#ًZs2|Ɛy$F SxeX{7Vl.Src3E℃Q>b6G ўYCmtկ~=K0f(=LrAS GN'ɹ9<\!a`)֕y[uՍ[09` 9 +57ts6}b4{oqd+J5fa/,97J#6yν99mRWxJyѡyu_TJc`~W>l^q#Ts#2"nD1%fS)FU w{ܯ R{ ˎ󅃏џDsZSQS;LV;7 Od1&1n$ N /.q3~eNɪ]E#oM~}v֯FڦwyZ=<<>Xo稯lfMFV6p02|*=tV!c~]fa5Y^Q_WN|Vs 0ҘދU97OI'N2'8N֭fgg-}V%y]U4 峧p*91#9U kCac_AFңĪy뚇Y_AiuYyTTYЗ-(!JFLt›17uTozc. S;7A&&<ԋ5y;Ro+:' *eYJkWR[@F %SHWP 72k4 qLd'J "zB6{AC0ƁA6U.'F3:Ȅ(9ΜL;D]m8ڥ9}dU "v!;*13Rg^fJyShyy5auA?ɩGHRjo^]׽S)Fm\toy 4WQS@mE#%5ʈfFYDX ~D5Ϡ9tE9So_aU4?Ѽm%&c{n>.KW1Tlb}:j uGi(JgcYj0qn+>) %\!4{LaJso d||u//P_y7iRJ߬nHOy) l+@$($VFIQ9%EeKʈU. ia&FY̒mZ=)+qqoQn >L!qCiDB;Y<%} OgBxB!ØuG)WG9y(Ą{_yesuZmZZey'Wg#C~1Cev@0D $a@˲(.._GimA:uyw֬%;@!JkQVM_Ow:P.s\)ot- ˹"`B,e CRtaEUP<0'}r3[>?G8xU~Nqu;Wm8\RIkբ^5@k+5(By'L&'gBJ3ݶ!/㮻w҅ yqPWUg<e"Qy*167΃sJ\oz]T*UQ<\FԎ`HaNmڜ6DysCask8wP8y9``GJ9lF\G g's Nn͵MLN֪u$| /|7=]O)6s !ĴAKh]q_ap $HH'\1jB^s\|- W1:=6lJBqjY^LsPk""`]w)󭃈,(HC ?䔨Y$Sʣ{4Z+0NvQkhol6C.婧/u]FwiVjZka&%6\F*Ny#8O,22+|Db~d ~Çwc N:FuuCe&oZ(l;@ee-+Wn`44AMK➝2BRՈt7g*1gph9N) *"TF*R(#'88pm=}X]u[i7bEc|\~EMn}P瘊J)K.0i1M6=7'_\kaZ(Th{K*GJyytw"IO-PWJk)..axӝ47"89Cc7ĐBiZx 7m!fy|ϿF9CbȩV 9V-՛^pV̌ɄS#Bv4-@]Vxt-Z, &ֺ*diؠ2^VXbs֔Ìl.jQ]Y[47gj=幽ex)A0ip׳ W2[ᎇhuE^~q흙L} #-b۸oFJ_QP3r6jr+"nfzRJTUqoaۍ /$d8Mx'ݓ= OՃ| )$2mcM*cЙj}f };n YG w0Ia!1Q.oYfr]DyISaP}"dIӗթO67jqR ҊƐƈaɤGG|h;t]䗖oSv|iZqX)oalv;۩meEJ\!8=$4QU4Xo&VEĊ YS^E#d,yX_> ۘ-e\ "Wa6uLĜZi`aD9.% w~mB(02G[6y.773a7 /=o7D)$Z 66 $bY^\CuP. (x'"J60׿Y:Oi;F{w佩b+\Yi`TDWa~|VH)8q/=9!g߆2Y)?ND)%?Ǐ`k/sn:;O299yB=a[Ng 3˲N}vLNy;*?x?~L&=xyӴ~}q{qE*IQ^^ͧvü{Huu=R|>JyUlZV, B~/YF!Y\u_ݼF{_C)LD]m {H 0ihhadd nUkf3oٺCvE\)QJi+֥@tDJkB$1!Đr0XQ|q?d2) Ӣ_}qv-< FŊ߫%roppVBwü~JidY4:}L6M7f٬F "?71<2#?Jyy4뷢<_a7_=Q E=S1И/9{+93֮E{ǂw{))?maÆm(uLE#lïZ  ~d];+]h j?!|$F}*"4(v'8s<ŏUkm7^7no1w2ؗ}TrͿEk>p'8OB7d7R(A 9.*Mi^ͳ; eeUwS+C)uO@ =Sy]` }l8^ZzRXj[^iUɺ$tj))<sbDJfg=Pk_{xaKo1:-uyG0M ԃ\0Lvuy'ȱc2Ji AdyVgVh!{]/&}}ċJ#%d !+87<;qN޼Nفl|1N:8ya  8}k¾+-$4FiZYÔXk*I&'@iI99)HSh4+2G:tGhS^繿 Kتm0 вDk}֚+QT4;sC}rՅE,8CX-e~>G&'9xpW,%Fh,Ry56Y–hW-(v_,? ; qrBk4-V7HQ;ˇ^Gv1JVV%,ik;D_W!))+BoS4QsTM;gt+ndS-~:11Sgv!0qRVh!"Ȋ(̦Yl.]PQWgٳE'`%W1{ndΗBk|Ž7ʒR~,lnoa&:ü$ 3<a[CBݮwt"o\ePJ=Hz"_c^Z.#ˆ*x z̝grY]tdkP*:97YľXyBkD4N.C_[;F9`8& !AMO c `@BA& Ost\-\NX+Xp < !bj3C&QL+*&kAQ=04}cC!9~820G'PC9xa!w&bo_1 Sw"ܱ V )Yl3+ס2KoXOx]"`^WOy :3GO0g;%Yv㐫(R/r (s } u B &FeYZh0y> =2<Ϟc/ -u= c&׭,.0"g"7 6T!vl#sc>{u/Oh Bᾈ)۴74]x7 gMӒ"d]U)}" v4co[ ɡs 5Gg=XR14?5A}D "b{0$L .\4y{_fe:kVS\\O]c^W52LSBDM! C3Dhr̦RtArx4&agaN3Cf<Ԉp4~ B'"1@.b_/xQ} _߃҉/gٓ2Qkqp0շpZ2fԫYz< 4L.Cyυι1t@鎫Fe sYfsF}^ V}N<_`p)alٶ "(XEAVZ<)2},:Ir*#m_YӼ R%a||EƼIJ,,+f"96r/}0jE/)s)cjW#w'Sʯ5<66lj$a~3Kʛy 2:cZ:Yh))+a߭K::N,Q F'qB]={.]h85C9cr=}*rk?vwV렵ٸW Rs%}rNAkDv|uFLBkWY YkX מ|)1!$#3%y?pF<@<Rr0}: }\J [5FRxY<9"SQdE(Q*Qʻ)q1E0B_O24[U'],lOb ]~WjHޏTQ5Syu wq)xnw8~)c 쫬gٲߠ H% k5dƝk> kEj,0% b"vi2Wس_CuK)K{n|>t{P1򨾜j>'kEkƗBg*H%'_aY6Bn!TL&ɌOb{c`'d^{t\i^[uɐ[}q0lM˕G:‚4kb祔c^:?bpg… +37stH:0}en6x˟%/<]BL&* 5&fK9Mq)/iyqtA%kUe[ڛKN]Ě^,"`/ s[EQQm?|XJ߅92m]G.E΃ח U*Cn.j_)Tѧj̿30ڇ!A0=͜ar I3$C^-9#|pk!)?7.x9 @OO;WƝZBFU keZ75F6Tc6"ZȚs2y/1 ʵ:u4xa`C>6Rb/Yм)^=+~uRd`/|_8xbB0?Ft||Z\##|K 0>>zxv8۴吅q 8ĥ)"6>~\8:qM}#͚'ĉ#p\׶ l#bA?)|g g9|8jP(cr,BwV (WliVxxᡁ@0Okn;ɥh$_ckCgriv}>=wGzβ KkBɛ[˪ !J)h&k2%07δt}!d<9;I&0wV/ v 0<H}L&8ob%Hi|޶o&h1L|u֦y~󛱢8fٲUsւ)0oiFx2}X[zVYr_;N(w]_4B@OanC?gĦx>мgx>ΛToZoOMp>40>V Oy V9iq!4 LN,ˢu{jsz]|"R޻&'ƚ{53ўFu(<٪9:΋]B;)B>1::8;~)Yt|0(pw2N%&X,URBK)3\zz&}ax4;ǟ(tLNg{N|Ǽ\G#C9g$^\}p?556]/RP.90 k,U8/u776s ʪ_01چ|\N 0VV*3H鴃J7iI!wG_^ypl}r*jɤSR 5QN@ iZ#1ٰy;_\3\BQQ x:WJv츟ٯ$"@6 S#qe딇(/P( Dy~TOϻ<4:-+F`0||;Xl-"uw$Цi󼕝mKʩorz"mϺ$F:~E'ҐvD\y?Rr8_He@ e~O,T.(ފR*cY^m|cVR[8 JҡSm!ΆԨb)RHG{?MpqrmN>߶Y)\p,d#xۆWY*,l6]v0h15M˙MS8+EdI='LBJIH7_9{Caз*Lq,dt >+~ّeʏ?xԕ4bBAŚjﵫ!'\Ը$WNvKO}ӽmSşذqsOy?\[,d@'73'j%kOe`1.g2"e =YIzS2|zŐƄa\U,dP;jhhhaxǶ?КZ՚.q SE+XrbOu%\GتX(H,N^~]JyEZQKceTQ]VGYqnah;y$cQahT&QPZ*iZ8UQQM.qo/T\7X"u?Mttl2Xq(IoW{R^ ux*SYJ! 4S.Jy~ BROS[V|žKNɛP(L6V^|cR7i7nZW1Fd@ Ara{詑|(T*dN]Ko?s=@ |_EvF]׍kR)eBJc" MUUbY6`~V޴dJKß&~'d3i5h-3LL

HOME


5h-3LL 1.0
DIR: /srv/http/vyvoj.adent.cz/vyvoj/moodle_esf_vz/mod/hotpot/template
/srv/http/vyvoj.adent.cz/vyvoj/moodle_esf_vz/mod/hotpot/template/
Upload File:
Current File : /srv/http/vyvoj.adent.cz/vyvoj/moodle_esf_vz/mod/hotpot/template/v6.php
<?PHP 

class hotpot_xml_quiz_template extends hotpot_xml_template_default {

    // constructor function for this class
    function hotpot_xml_quiz_template(&$parent) {

        $this->parent = &$parent;
        
        $get_js = optional_param('js', false);
        $get_css = optional_param('css', false);

        if (!empty($get_css)) {
            // set $this->css
            $this->v6_expand_StyleSheet(); 

        } else if (!empty($get_js)) {
            // set $this->js
            $this->read_template($this->parent->draganddrop.$this->parent->quiztype.'6.js_', 'js');

        } else {
            // set $this->html
            $this->read_template($this->parent->draganddrop.$this->parent->quiztype.'6.ht_', 'html');
        }

        // expand special strings, if any
        $pattern = '';
        switch ($this->parent->quiztype) {
            case 'jcloze':
                $pattern = '/\[(PreloadImageList)\]/';
                break;
            case 'jcross':
                $pattern = '/\[(PreloadImageList|ShowHideClueList)\]/';
                break;
            case 'jmatch':
                $pattern = '/\[(PreloadImageList|QsToShow|FixedArray|DragArray)\]/';
                break;
            case 'jmix':
                $pattern = '/\[(PreloadImageList|SegmentArray|AnswerArray)\]/';
                break;
            case 'jquiz':
                $pattern = '/\[(PreloadImageList|QsToShow)\]/';
                break;
        }
        if (!empty($pattern)) {
            $this->expand_strings('html', $pattern);
        }
    }

    // captions and messages

    function v6_expand_AlsoCorrect() {
        return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',also-correct');
    }
    function v6_expand_CapitalizeFirst() {
        return $this->bool_value('hotpot-config-file,'.$this->parent->quiztype.',capitalize-first-letter');
    }
    function v6_expand_CheckCaption() {
        return $this->parent->xml_value('hotpot-config-file,global,check-caption');
    }
    function v6_expand_CorrectIndicator() {
        return $this->js_value('hotpot-config-file,global,correct-indicator');
    }
    function v6_expand_Back() {
        return $this->int_value('hotpot-config-file,global,include-back');
    }
    function v6_expand_BackCaption() {
        return $this->parent->xml_value('hotpot-config-file,global,back-caption');
    }
    function v6_expand_ClickToAdd() {
        return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',click-to-add');
    }
    function v6_expand_ClueCaption() {
        return $this->parent->xml_value('hotpot-config-file,global,clue-caption');
    }
    function v6_expand_Clues() {
        return $this->int_value('hotpot-config-file,'.$this->parent->quiztype.',include-clues');
    }
    function v6_expand_Contents() {
        return $this->int_value('hotpot-config-file,global,include-contents');
    }
    function v6_expand_ContentsCaption() {
        return $this->parent->xml_value('hotpot-config-file,global,contents-caption');
    }
    function v6_expand_GuessCorrect() {
        return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',guess-correct');
    }
    function v6_expand_GuessIncorrect() {
        return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',guess-incorrect');
    }
    function v6_expand_Hint() {
        return $this->int_value('hotpot-config-file,'.$this->parent->quiztype.',include-hint');
    }
    function v6_expand_HintCaption() {
        return $this->parent->xml_value('hotpot-config-file,global,hint-caption');
    }
    function v6_expand_IncorrectIndicator() {
        return $this->js_value('hotpot-config-file,global,incorrect-indicator');
    }
    function v6_expand_LastQCaption() {
        return $this->parent->xml_value('hotpot-config-file,global,last-q-caption');
    }
    function v6_expand_NextCorrect() {
        $value = $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',next-correct-part');
        if (empty($value)) { // jquiz
            $value = $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',next-correct-letter');
        }
        return $value;
    }
    function v6_expand_NextEx() {
        return $this->int_value('hotpot-config-file,global,include-next-ex');
    }
    function v6_expand_NextExCaption() {
        return $this->parent->xml_value('hotpot-config-file,global,next-ex-caption');
    }
    function v6_expand_NextQCaption() {
        return $this->parent->xml_value('hotpot-config-file,global,next-q-caption');
    }
    function v6_expand_OKCaption() {
        return $this->parent->xml_value('hotpot-config-file,global,ok-caption');
    }
    function v6_expand_Restart() {
        return $this->int_value('hotpot-config-file,'.$this->parent->quiztype.',include-restart');
    }
    function v6_expand_RestartCaption() {
        return $this->parent->xml_value('hotpot-config-file,global,restart-caption');
    }
    function v6_expand_ShowAllQuestionsCaption() {
        return $this->js_value('hotpot-config-file,global,show-all-questions-caption');
    }
    function v6_expand_ShowOneByOneCaption() {
        return $this->js_value('hotpot-config-file,global,show-one-by-one-caption');
    }
    function v6_expand_TheseAnswersToo() {
        return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',also-correct');
    }
    function v6_expand_ThisMuch() {
        return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',this-much-correct');
    }
    function v6_expand_Undo() {
        return $this->int_value('hotpot-config-file,'.$this->parent->quiztype.',include-undo');
    }
    function v6_expand_UndoCaption() {
        return $this->parent->xml_value('hotpot-config-file,global,undo-caption');
    }
    function v6_expand_YourScoreIs() {
        return $this->js_value('hotpot-config-file,global,your-score-is');
    }

    // reading

    function v6_expand_Reading() {
        return $this->int_value('data,reading,include-reading');
    }
    function v6_expand_ReadingText() {
        $title = $this->v6_expand_ReadingTitle();
        $value = $this->parent->xml_value('data,reading,reading-text');
        $value = empty($value) ? '' : ('<div class="ReadingText">'.$value.'</div>');
        return $title.$value;
    }
    function v6_expand_ReadingTitle() {
        $value = $this->parent->xml_value('data,reading,reading-title');
        return empty($value) ? '' : ('<h3 class="ExerciseSubtitle">'.$value.'</h3>');
    }

    // timer 

    function v6_expand_Timer() {
        return $this->int_value('data,timer,include-timer');
    }
    function v6_expand_JSTimer() {
        return $this->read_template('hp6timer.js_');
    }
    function v6_expand_Seconds() {
        return $this->parent->xml_value('data,timer,seconds');
    }

    // send results 

    function v6_expand_SendResults() {
        return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',send-email');
    }
    function v6_expand_JSSendResults() {
        return $this->read_template('hp6sendresults.js_');
    }
    function v6_expand_FormMailURL() {
        return $this->parent->xml_value('hotpot-config-file,global,formmail-url');
    }
    function v6_expand_EMail() {
        return $this->parent->xml_value('hotpot-config-file,global,email');
    }
    function v6_expand_NamePlease() {
        return $this->js_value('hotpot-config-file,global,name-please');
    }

    // preload images

    function v6_expand_PreloadImages() {
        $value = $this->v6_expand_PreloadImageList();
        return empty($value) ? false : true;
    }
    function v6_expand_PreloadImageList() {

        // check it has not been set already
        if (!isset($this->PreloadImageList)) {

            // the list of image urls
            $list = array();

            // extract <img> tags
            $img_tag = htmlspecialchars('|&#x003C;img.*?src="(.*?)".*?&#x003E;|is');
            if (preg_match_all($img_tag, $this->parent->source, $matches)) {
                $list = $matches[1];

                // remove duplicates
                $list = array_unique($list);
            }

            // convert to comma delimited string
            $this->PreloadImageList = empty($list) ? '' : "'".implode(',', $list)."'";
        }
        return $this->PreloadImageList;
    }

    // html files (all quiz types)

    function v6_expand_PlainTitle() {
        return $this->parent->xml_value('data,title');
    }
    function v6_expand_ExerciseSubtitle() {
        return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',exercise-subtitle');
    }
    function v6_expand_Instructions() {
        return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',instructions');
    }
    function v6_expand_DublinCoreMetadata() {
        $dc = '<link rel="schema.DC" href="'.$this->parent->xml_value('', "['rdf:RDF'][0]['@']['xmlns:dc']").'" />'."\n";
        if (is_string($this->parent->xml_value('rdf:RDF,rdf:Description'))) {
            // do nothing (there is no more dc info)
        } else {
            $dc .= '<meta name="DC:Creator" content="'.$this->parent->xml_value('rdf:RDF,rdf:Description,dc:creator').'" />'."\n";
            $dc .= '<meta name="DC:Title" content="'.strip_tags($this->parent->xml_value('rdf:RDF,rdf:Description,dc:title')).'" />'."\n";
        }
        return $dc;
    }
    function v6_expand_FullVersionInfo() {
        global $CFG;
        require_once($CFG->hotpotroot.DIRECTORY_SEPARATOR.'version.php'); // set $module
        return $this->parent->xml_value('version').'.x (Moodle '.$CFG->release.', hotpot-module '.$this->parent->obj_value($module, 'release').')';
    }
    function v6_expand_HeaderCode() {
        return $this->parent->xml_value('hotpot-config-file,global,header-code');
    }
    function v6_expand_StyleSheet() {
        $this->read_template('hp6.cs_', 'css');
        $this->css = hotpot_convert_stylesheets_urls($this->parent->get_baseurl(), $this->parent->reference, $this->css);
        return $this->css;
    }

    // stylesheet (hp6.cs_)

    function v6_expand_PageBGColor() {
        return $this->parent->xml_value('hotpot-config-file,global,page-bg-color');
    }
    function v6_expand_GraphicURL() {
        return $this->parent->xml_value('hotpot-config-file,global,graphic-url');
    }
    function v6_expand_ExBGColor() {
        return $this->parent->xml_value('hotpot-config-file,global,ex-bg-color');
    }

    function v6_expand_FontFace() {
        return $this->parent->xml_value('hotpot-config-file,global,font-face');
    }
    function v6_expand_FontSize() {
        $value = $this->parent->xml_value('hotpot-config-file,global,font-size');
        return (empty($value) ? 'small' : $value);
    }
    function v6_expand_TextColor() {
        return $this->parent->xml_value('hotpot-config-file,global,text-color');
    }
    function v6_expand_TitleColor() {
        return $this->parent->xml_value('hotpot-config-file,global,title-color');
    }
    function v6_expand_LinkColor() {
        return $this->parent->xml_value('hotpot-config-file,global,link-color');
    }
    function v6_expand_VLinkColor() {
        return $this->parent->xml_value('hotpot-config-file,global,vlink-color');
    }

    function v6_expand_NavTextColor() {
        return $this->parent->xml_value('hotpot-config-file,global,page-bg-color');
    }
    function v6_expand_NavBarColor() {
        return $this->parent->xml_value('hotpot-config-file,global,nav-bar-color');
    }
    function v6_expand_NavLightColor() {
        $color = $this->parent->xml_value('hotpot-config-file,global,nav-bar-color');
        return $this->get_halfway_color($color, '#ffffff'); 
    }
    function v6_expand_NavShadeColor() {
        $color = $this->parent->xml_value('hotpot-config-file,global,nav-bar-color');
        return $this->get_halfway_color($color, '#000000');
    }

    function v6_expand_FuncLightColor() { // top-left of buttons
        $color = $this->parent->xml_value('hotpot-config-file,global,ex-bg-color');
        return $this->get_halfway_color($color, '#ffffff');
    }
    function v6_expand_FuncShadeColor() { // bottom right of buttons
        $color = $this->parent->xml_value('hotpot-config-file,global,ex-bg-color');
        return $this->get_halfway_color($color, '#000000');
    }

    // navigation buttons

    function v6_expand_NavButtons() {
        $back = $this->v6_expand_Back();
        $next_ex = $this->v6_expand_NextEx();
        $contents = $this->v6_expand_Contents();
        return (empty($back) && empty($next_ex) && empty($contents) ? false : true);
    }
    function v6_expand_NavBarJS() {
        return $this->v6_expand_NavButtons();
    }

    // switch off scorm
    function v6_expand_Scorm12() {
        return false;
    }

    // js files (all quiz types)

    function v6_expand_JSBrowserCheck() {
        return $this->read_template('hp6browsercheck.js_');
    }
    function v6_expand_JSButtons() {
        return $this->read_template('hp6buttons.js_');
    }
    function v6_expand_JSCard() {
        return $this->read_template('hp6card.js_');
    }
    function v6_expand_JSCheckShortAnswer() {
        return $this->read_template('hp6checkshortanswer.js_');
    }
    function v6_expand_JSHotPotNet() {
        return $this->read_template('hp6hotpotnet.js_');
    }
    function v6_expand_JSShowMessage() {
        return $this->read_template('hp6showmessage.js_');
    }
    function v6_expand_JSUtilities() {
        return $this->read_template('hp6utilities.js_');
    }

    // js files

    function v6_expand_JSJCloze6() {
        return $this->read_template('jcloze6.js_');
    }
    function v6_expand_JSJCross6() {
        return $this->read_template('jcross6.js_');
    }
    function v6_expand_JSJMatch6() {
        return $this->read_template('jmatch6.js_');
    }
    function v6_expand_JSJMix6() {
        return $this->read_template('jmix6.js_');
    }
    function v6_expand_JSJQuiz6() {
        return $this->read_template('jquiz6.js_');
    }

    // drag and drop

    function v6_expand_JSDJMatch6() {
        return $this->read_template('djmatch6.js_');
    }
    function v6_expand_JSDJMix6() {
        return $this->read_template('djmix6.js_');
    }

    // what are these for?

    function v6_expand_JSFJMatch6() {
        return $this->read_template('fjmatch6.js_');
    }
    function v6_expand_JSFJMix6() {
        return $this->read_template('fjmix6.js_');
    }

    // jmatch6.js_

    function v6_expand_ShuffleQs() {
        return $this->bool_value('hotpot-config-file,'.$this->parent->quiztype.',shuffle-questions');
    }
    function v6_expand_QsToShow() {
        $i = $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',show-limited-questions');
        if ($i) {
            $i = $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',questions-to-show');
        }
        if (empty($i)) {
            $i = 0;
            switch ($this->parent->quiztype) {
                case 'jmatch':
                    $values = $this->parent->xml_values('data,matching-exercise,pair');
                    $i = count($values);
                    break;
                case 'jquiz':
                    $tags = 'data,questions,question-record';
                    while (($question="[$i]['#']") && $this->parent->xml_value($tags, $question)) {
                        $i++;
                    }
                    break;
            } // end switch
        }
        return $i;
    }
    function v6_expand_MatchDivItems() {
        $l_items = array();
        $r_items = array();
        $this->get_jmatch_items($l_items, $r_items);

        $l_keys = $this->shuffle_jmatch_items($l_items);
        $r_keys = $this->shuffle_jmatch_items($r_items);

        $options = '<option value="x">'.$this->parent->xml_value('data,matching-exercise,default-right-item').'</option>';
        foreach ($r_keys as $key) {
            if (empty($r_items[$key]['fixed'][0]['#'])) {
                $options .= '<option value="'.$key.'">'.$r_items[$key]['text'][0]['#'].'</option>'."\n";
            }
        }

        $str = '';
        foreach ($l_keys as $key) {
            $str .= '<tr><td class="LeftItem">'.$l_items[$key]['text'][0]['#'].'</td>';
            $str .= '<td class="RightItem">';
            if (empty($r_items[$key]['fixed'][0]['#'])) {
                $str .= '<select id="s'.$key.'_'.$key.'">'.$options.'</select>';
            }  else {
                $str .= $r_items[$key]['text'][0]['#'];
            }
            $str .= '</td><td></td></tr>';
        }
        return $str;
    }

    // jmix6.js_

    function v6_expand_Punctuation() {
        $tags = 'data,jumbled-order-exercise';
        $chars = array_merge(
            $this->jmix_Punctuation("$tags,main-order,segment"),
            $this->jmix_Punctuation("$tags,alternate")
        );
        $chars = array_unique($chars);
        $chars = implode('', $chars);
        $chars = $this->js_safe($chars, true);
        return $chars;
    }
    function jmix_Punctuation($tags) {
        $chars = array();

        // all punctutation except '&#;' (because they are used in html entities)
        $ENTITIES = $this->jmix_encode_punctuation('!"$%'."'".'()*+,-./:<=>?@[\]^_`{|}~');
        $pattern = "/&#x([0-9A-F]+);/i";
        $i = 0;

        // get next segment (or alternate answer)
        while ($value = $this->parent->xml_value($tags, "[$i]['#']")) {

            // convert low-ascii punctuation to entities
            $value = strtr($value, $ENTITIES);

            // extract all hex HTML entities
            if (preg_match_all($pattern, $value, $matches)) {

                // loop through hex entities
                $m_max = count($matches[0]);
                for ($m=0; $m<$m_max; $m++) {

                    // convert to hex number
                    eval('$hex=0x'.$matches[1][$m].';');

                    // is this a punctuation character?
                    if (
                        ($hex>=0x0020 && $hex<=0x00BF) || // ascii punctuation
                        ($hex>=0x2000 && $hex<=0x206F) || // general punctuation
                        ($hex>=0x3000 && $hex<=0x303F) || // CJK punctuation
                        ($hex>=0xFE30 && $hex<=0xFE4F) || // CJK compatability
                        ($hex>=0xFE50 && $hex<=0xFE6F) || // small form variants
                        ($hex>=0xFF00 && $hex<=0xFF40) || // halfwidth and fullwidth forms (1)
                        ($hex>=0xFF5B && $hex<=0xFF65) || // halfwidth and fullwidth forms (2)
                        ($hex>=0xFFE0 && $hex<=0xFFEE)    // halfwidth and fullwidth forms (3)
                    ) {
                        // add this character
                        $chars[] = $matches[0][$m];
                    }
                }
            }
            $i++;
        }

        return $chars;
    }
    function v6_expand_OpenPunctuation() {
        $tags = 'data,jumbled-order-exercise';
        $chars = array_merge(
            $this->jmix_OpenPunctuation("$tags,main-order,segment"),
            $this->jmix_OpenPunctuation("$tags,alternate")
        );
        $chars = array_unique($chars);
        $chars = implode('', $chars);
        $chars = $this->js_safe($chars, true);
        return $chars;
    }
    function jmix_OpenPunctuation($tags) {
        $chars = array();

        // unicode punctuation designations (pi="initial quote", ps="open")
        //  http://www.sql-und-xml.de/unicode-database/pi.html
        //  http://www.sql-und-xml.de/unicode-database/ps.html
        $pi = '0022|0027|00AB|2018|201B|201C|201F|2039';
        $ps = '0028|005B|007B|0F3A|0F3C|169B|201A|201E|2045|207D|208D|2329|23B4|2768|276A|276C|276E|2770|2772|2774|27E6|27E8|27EA|2983|2985|2987|2989|298B|298D|298F|2991|2993|2995|2997|29D8|29DA|29FC|3008|300A|300C|300E|3010|3014|3016|3018|301A|301D|FD3E|FE35|FE37|FE39|FE3B|FE3D|FE3F|FE41|FE43|FE47|FE59|FE5B|FE5D|FF08|FF3B|FF5B|FF5F|FF62';
        $pattern = "/(&#x($pi|$ps);)/i";

        $ENTITIES = $this->jmix_encode_punctuation('"'."'".'(<[{');

        $i = 0;
        while ($value = $this->parent->xml_value($tags, "[$i]['#']")) {
            $value = strtr($value, $ENTITIES);
            if (preg_match_all($pattern, $value, $matches)) {
                $chars = array_merge($chars, $matches[0]);
            } 
            $i++;
        }

        return $chars;
    }
    function jmix_encode_punctuation($str) {
        $ENTITIES = array();
        $i_max = strlen($str);
        for ($i=0; $i<$i_max; $i++) {
            $ENTITIES[$str{$i}] = '&#x'.sprintf('%04X', ord($str{$i})).';';
        }
        return $ENTITIES;
    }
    function v6_expand_ExerciseTitle() {
        return $this->parent->xml_value('data,title');
    }

    // Jmix specials

    function v6_expand_SegmentArray() {

        $segments = array();
        $values = array();
        $VALUES = array();

        // XML tags to the start of a segment
        $tags = 'data,jumbled-order-exercise,main-order,segment';

        $i = 0;
        while ($value = $this->parent->xml_value($tags, "[$i]['#']")) {
            $VALUE = strtoupper($value);
            $key = array_search($VALUE, $VALUES);
            if (is_numeric($key)) {
                $segments[] = $key;
            } else {
                $segments[] = $i;
                $values[$i] = $value;
                $VALUES[$i] = $VALUE;
            }
            $i++;
        }

        $this->seed_random_number_generator();
        $keys = array_keys($segments);
        shuffle($keys);

        $str = '';
        for($i=0; $i<count($keys); $i++) {
            $key = $segments[$keys[$i]];
            $str .= "Segments[$i] = new Array();\n";
            $str .= "Segments[$i][0] = '".$this->js_safe($values[$key], true)."';\n";
            $str .= "Segments[$i][1] = ".($key+1).";\n";
            $str .= "Segments[$i][2] = 0;\n";
        }
        return $str;
    }
    function v6_expand_AnswerArray() {

        $segments = array();
        $values = array();
        $VALUES = array();
        $escapedvalues = array();

        // XML tags to the start of a segment
        $tags = 'data,jumbled-order-exercise,main-order,segment';

        $i = 0;
        while ($value = $this->parent->xml_value($tags, "[$i]['#']")) {
            $VALUE = strtoupper($value);
            $key = array_search($VALUE, $VALUES);
            if (is_numeric($key)) {
                $segments[] = $key+1;
            } else {
                $segments[] = $i+1;
                $values[$i] = $value;
                $VALUES[$i] = $VALUE;
                $escapedvalues[] = preg_quote($value, '/');
            }
            $i++;
        }

        // start the answers array
        $a = 0;
        $str = 'Answers['.($a++).'] = new Array('.implode(',', $segments).");\n";

        // pattern to match the next part of an alternate answer
        $pattern = '/^('.implode('|', $escapedvalues).')\\s*/i';

        // XML tags to the start of an alternate answer
        $tags = 'data,jumbled-order-exercise,alternate';

        $i = 0;
        while ($value = $this->parent->xml_value($tags, "[$i]['#']")) {
            $segments = array();
            while (strlen($value) && preg_match($pattern, $value, $matches)) {
                $key = array_search($matches[1], $values);
                if (is_numeric($key)) {
                    $segments[] = $key+1;
                    $value = substr($value, strlen($matches[0]));
                } else {
                    // invalid alternate sequence
                    $segments = array();
                    break;
                }
            }
            if (count($segments)) {
                $str .= 'Answers['.($a++).'] = new Array('.implode(',', $segments).");\n";
            }
            $i++;
        }
        return $str;
    }

    // ===============================================================

    // JMix (jmix6.js_)

    function v6_expand_RemainingWords() {
        return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',remaining-words');
    }
    function v6_expand_TimesUp() {
        return $this->parent->xml_value('hotpot-config-file,global,times-up');
    }

    // nav bar

    function v6_expand_NavBar($navbarid='') {
        $this->navbarid = $navbarid;

        $tag = 'navbar';
        $this->read_template('hp6navbar.ht_', $tag);

        unset($this->navbarid);

        return $this->$tag;
    }
    function v6_expand_TopNavBar() {
        return $this->v6_expand_NavBar('TopNavBar');
    }
    function v6_expand_BottomNavBar() {
        return $this->v6_expand_NavBar('BottomNavBar');
    }

    // hp6navbar.ht_

    function v6_expand_NavBarID() {
        // $this->navbarid is set in "$this->v6_expand_NavBar"
        return empty($this->navbarid) ? '' : $this->navbarid;
    }
    function v6_expand_ContentsURL() {
        $url = $this->parent->xml_value('hotpot-config-file,global,contents-url');
        if ($url) {
            $url = hotpot_convert_navbutton_url($this->parent->get_baseurl(), $this->parent->reference, $url, $this->parent->course);
        }
        return $url;
    }
    function v6_expand_NextExURL() {
        $url = $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',next-ex-url');
        if ($url) {
            $url = hotpot_convert_navbutton_url($this->parent->get_baseurl(), $this->parent->reference, $url, $this->parent->course);
        }
        return $url;
    }

    // conditional blocks

    function v6_expand_ShowAnswer() {
        return $this->int_value('hotpot-config-file,'.$this->parent->quiztype.',include-show-answer');
    }
    function v6_expand_Slide() {
        return true; // whats's this (JMatch drag and drop)
    }

    // specials (JMatch)

    function v6_expand_FixedArray() {
        $l_items = array();
        $r_items = array();
        $this->get_jmatch_items($l_items, $r_items);

        $str = '';
        foreach ($l_items as $i=>$item) {
            $str .= "F[$i] = new Array();\n";
            $str .= "F[$i][0] = '".$this->js_safe($item['text'][0]['#'], true)."';\n";
            $str .= "F[$i][1] = ".($i+1).";\n";
        }
        return $str;
    }
    function v6_expand_DragArray() {
        $l_items = array();
        $r_items = array();
        $this->get_jmatch_items($l_items, $r_items);

        $str = '';
        foreach ($r_items as $i=>$item) {
            $str .= "D[$i] = new Array();\n";
            $str .= "D[$i][0] = '".$this->js_safe($item['text'][0]['#'], true)."';\n";
            $str .= "D[$i][1] = ".($i+1).";\n";
            $str .= "D[$i][2] = '".(empty($item['fixed'][0]['#']) ? 0 : 1)."';\n";
        }
        return $str;
    }

    function get_jmatch_items(&$l_items, &$r_items) {
        $tags = 'data,matching-exercise,pair';
        $i = 0;
        while($item = $this->parent->xml_value($tags,"[$i]['#']['left-item'][0]['#']")) {
            if (!empty($item['text'][0]['#'])) {
                $l_items[] = $item;
            }
            $i++;
        }
        $i = 0;
        while($item = $this->parent->xml_value($tags,"[$i]['#']['right-item'][0]['#']")) {
            if (!empty($item['text'][0]['#'])) {
                $r_items[] = $item;
            }
            $i++;
        }
    }
    function shuffle_jmatch_items(&$items) {
        // get moveable items
        $moveable_keys = array();
        for($i=0; $i<count($items); $i++) {
            if(empty($items[$i]['fixed'][0]['#'])) {
                $moveable_keys[] = $i;
            }
        }
        // shuffle moveable items
        $this->seed_random_number_generator();
        shuffle($moveable_keys);

        $keys = array();
        for($i=0, $ii=0; $i<count($items); $i++) {
            if(empty($items[$i]['fixed'][0]['#'])) {
                //  moveable items are inserted in a shuffled order
                $keys[] = $moveable_keys[$ii++];
            } else {
                //  fixed items stay where they are
                $keys[] = $i;
            }
        }
        return $keys;
    }
    function seed_random_number_generator() {
        static $seeded_RNG = FALSE;
        if (!$seeded_RNG) {
            srand((double) microtime() * 1000000);
            $seeded_RNG = TRUE;
        }
    }

    // specials (JMix)


    // specials (JCloze)

    function v6_expand_ItemArray() {
        $q = 0;
        $str = '';
        switch ($this->parent->quiztype) {
            case 'jcloze':
                $tags = 'data,gap-fill,question-record';
                while (($question="[$q]['#']") && $this->parent->xml_value($tags, $question)) {
                    $a = 0;
                    $aa = 0;
                    while (($answer=$question."['answer'][$a]['#']") && $this->parent->xml_value($tags, $answer)) {
                        $text = $this->js_value($tags,  $answer."['text'][0]['#']", true);
                        if (strlen($text)) {
                            if ($aa==0) { // first time only
                                $str .= "\n";
                                $str .= "I[$q] = new Array();\n";
                                $str .= "I[$q][1] = new Array();\n";
                            }
                            $str .= "I[$q][1][$aa] = new Array();\n";
                            $str .= "I[$q][1][$aa][0] = '$text';\n";
                            $aa++;
                        }
                        $a++;
                    }
                    // add clue, if any answers were found
                    if ($aa) {
                        $clue = $this->js_value($tags, $question."['clue'][0]['#']", true);
                        $str .= "I[$q][2] = '$clue';\n";
                    }
                    $q++;
                }
                break;
            case 'jquiz':
                $str .= "I=new Array();\n";
                $tags = 'data,questions,question-record';
                while (($question="[$q]['#']") && $this->parent->xml_value($tags, $question)) {

                    $question_type = $this->int_value($tags, $question."['question-type'][0]['#']");
                    $weighting = $this->int_value($tags, $question."['weighting'][0]['#']");
                    $clue = $this->js_value($tags, $question."['clue'][0]['#']", true);

                    $answers = $question."['answers'][0]['#']";

                    $a = 0;
                    $aa = 0;
                    while (($answer = $answers."['answer'][$a]['#']") && $this->parent->xml_value($tags, $answer)) {
                        $text =     $this->js_value($tags,  $answer."['text'][0]['#']", true);
                        $feedback = $this->js_value($tags,  $answer."['feedback'][0]['#']", true);
                        $correct =  $this->int_value($tags, $answer."['correct'][0]['#']");
                        $percent =  $this->int_value($tags, $answer."['percent-correct'][0]['#']");
                        $include =  $this->int_value($tags, $answer."['include-in-mc-options'][0]['#']");
                        if (strlen($text)) {
                            if ($aa==0) { // first time only
                                $str .= "\n";
                                $str .= "I[$q] = new Array();\n";
                                $str .= "I[$q][0] = $weighting;\n";
                                $str .= "I[$q][1] = '$clue';\n";
                                $str .= "I[$q][2] = '".($question_type-1)."';\n";
                                $str .= "I[$q][3] = new Array();\n";
                            }
                            $str .= "I[$q][3][$aa] = new Array('$text','$feedback',$correct,$percent,$include);\n";
                            $aa++;
                        }
                        $a++;
                    }
                    $q++;
                }
                break;
        }
        return $str;
    }

    function v6_expand_ClozeBody() {
        $str = '';

        // get drop down list of words, if required
        $dropdownlist = '';
        if ($this->v6_use_DropDownList()) {
            $this->v6_set_WordList();
            foreach ($this->wordlist as $word) {
                $dropdownlist .= '<option value="'.$word.'">'.$word.'</option>';
            }
        }

        // cache clues flag and caption
        $includeclues = $this->v6_expand_Clues();
        $cluecaption = $this->v6_expand_ClueCaption();

        // detect if cloze starts with gap
        $strpos = strpos($this->parent->source, '<gap-fill><question-record>');
        if (is_numeric($strpos)) {
            $startwithgap = true;
        } else {
            $startwithgap = false;
        }

        // initialize loop values
        $q = 0;
        $tags = 'data,gap-fill';
        $question_record = "$tags,question-record";

        // loop through text and gaps
        do {
            $text = $this->parent->xml_value($tags, "[0]['#'][$q]");
            $gap = '';
            if (($question="[$q]['#']") && $this->parent->xml_value($question_record, $question)) {
                $gap .= '<span class="GapSpan" id="GapSpan'.$q.'">';
                if ($this->v6_use_DropDownList()) {
                    $gap .= '<select id="Gap'.$q.'"><option value=""></option>'.$dropdownlist.'</select>';
                } else {
                    // minimum gap size
                    $gapsize = 6;

                    // increase gap size to length of longest answer for this gap
                    $a = 0;
                    while (($answer=$question."['answer'][$a]['#']") && $this->parent->xml_value($question_record, $answer)) {
                        $answertext = $this->parent->xml_value($question_record,  $answer."['text'][0]['#']");
                        $answertext = preg_replace('|&[#a-zA-Z0-9]+;|', 'x', $answertext);
                        $gapsize = max($gapsize, strlen($answertext));
                        $a++;
                    }

                    $gap .= '<input type="text" id="Gap'.$q.'" onfocus="TrackFocus('.$q.')" onblur="LeaveGap()" class="GapBox" size="'.$gapsize.'" /></input>';
                }
                if ($includeclues) {
                    $clue = $this->parent->xml_value($question_record, $question."['clue'][0]['#']");
                    if (strlen($clue)) {
                        $gap .= '<button style="line-height: 1.0" class="FuncButton" onfocus="FuncBtnOver(this)" onmouseover="FuncBtnOver(this)" onblur="FuncBtnOut(this)" onmouseout="FuncBtnOut(this)" onmousedown="FuncBtnDown(this)" onmouseup="FuncBtnOut(this)" onclick="ShowClue('.$q.')">'.$cluecaption.'</button>';
                    }
                }
                $gap .= '</span>';
            }
            if ($startwithgap) {
                $str .= "$gap$text";
            } else {
                $str .= "$text$gap";
            }
            $q++;
        } while (strlen($text) || strlen($gap));

        return $str;
    }

    // JCloze quiztype

    function v6_expand_WordList() {
        $str = '';
        if ($this->v6_include_WordList()) {
            $this->v6_set_WordList();
            $str = implode(' &#160;&#160; ', $this->wordlist);
        }
        return $str;
    }
    function v6_include_WordList() {
        return $this->int_value('hotpot-config-file,'.$this->parent->quiztype.',include-word-list');
    }
    function v6_use_DropDownList() {
        return $this->int_value('hotpot-config-file,'.$this->parent->quiztype.',use-drop-down-list');
    }
    function v6_set_WordList() {

        if (isset($this->wordlist)) {
            // do nothing
        } else {
            $this->wordlist = array();

            // is the wordlist required
            if ($this->v6_include_WordList() || $this->v6_use_DropDownList()) {

                $q = 0;
                $tags = 'data,gap-fill,question-record';
                while (($question="[$q]['#']") && $this->parent->xml_value($tags, $question)) {
                    $a = 0;
                    $aa = 0;
                    while (($answer=$question."['answer'][$a]['#']") && $this->parent->xml_value($tags, $answer)) {
                        $text = $this->parent->xml_value($tags,  $answer."['text'][0]['#']");
                        $correct =  $this->int_value($tags, $answer."['correct'][0]['#']");
                        if ($text && $correct) { // $correct is always true
                            $this->wordlist[] = $text;
                            $aa++;
                        }
                        $a++;
                    }
                    $q++;
                }
                $this->wordlist = array_unique($this->wordlist);
                sort($this->wordlist);
            }
        }
    }
    function v6_expand_Keypad() {
        $str = '';
        if ($this->int_value('hotpot-config-file,'.$this->parent->quiztype.',include-keypad')) {

            // these characters must always be in the keypad
            $chars = array();
            $this->add_keypad_chars($chars, $this->parent->xml_value('hotpot-config-file,global,keypad-characters'));

            // append other characters used in the answers
            $tags = '';
            switch ($this->parent->quiztype) {
                case 'jcloze':
                    $tags = 'data,gap-fill,question-record';
                    break;
                case 'jquiz':
                    $tags = 'data,questions,question-record';
                    break;
            }
            if ($tags) {
                $q = 0;
                while (($question="[$q]['#']") && $this->parent->xml_value($tags, $question)) {

                    if ($this->parent->quiztype=='jquiz') {
                        $answers = $question."['answers'][0]['#']";
                    } else {
                        $answers = $question;
                    }

                    $a = 0;
                    while (($answer=$answers."['answer'][$a]['#']") && $this->parent->xml_value($tags, $answer)) {
                        $this->add_keypad_chars($chars, $this->parent->xml_value($tags,  $answer."['text'][0]['#']"));
                        $a++;
                    }
                    $q++;
                }
            }

            // remove duplicate characters and sort
            $chars = array_unique($chars);
            usort($chars, "hotpot_sort_keypad_chars");

            // create keypad buttons for each character
            foreach ($chars as $char) {
                $str .= "<button onclick=\"TypeChars('".$this->js_safe($char, true)."'); return false;\">$char</button>";
            }
        }
        return $str;
    }
    function add_keypad_chars(&$chars, $text) {
        if (preg_match_all('|&[^;]+;|i', $text, $more_chars)) {
            $chars = array_merge($chars, $more_chars[0]);
        }
    }
    function v6_expand_Correct() {
        return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',guesses-correct');
    }
    function v6_expand_Incorrect() {
        return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',guesses-incorrect');
    }
    function v6_expand_GiveHint() {
        return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',next-correct-letter');
    }
    function v6_expand_CaseSensitive() {
        return $this->bool_value('hotpot-config-file,'.$this->parent->quiztype.',case-sensitive');
    }

    // JCross quiztype

    function v6_expand_CluesAcrossLabel() {
        return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',clues-across');
    }
    function v6_expand_CluesDownLabel() {
        return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',clues-down');
    }
    function v6_expand_EnterCaption() {
        return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',enter-caption');
    }
    function v6_expand_ShowHideClueList() {
        $value = $this->int_value('hotpot-config-file,'.$this->parent->quiztype.',include-clue-list');
        return empty($value) ? ' style="display: none;"' : '';
    }

    // JCross specials

    function v6_expand_CluesDown() {
        return $this->v6_expand_jcross_clues('D');
    }
    function v6_expand_CluesAcross() {
        return $this->v6_expand_jcross_clues('A');
    }
    function v6_expand_jcross_clues($direction) {
        // $direction: A(cross) or D(own)
        $row = NULL;
        $r_max = 0;
        $c_max = 0;
        $this->v6_get_jcross_grid($row, $r_max, $c_max);

        $i = 0; // clue index;
        $str = '';
        for($r=0; $r<=$r_max; $r++) {
            for($c=0; $c<=$c_max; $c++) {
                $aword = $this->get_jcross_aword($row, $r, $r_max, $c, $c_max);
                $dword = $this->get_jcross_dword($row, $r, $r_max, $c, $c_max);
                if ($aword || $dword) {
                    $i++; // increment clue index

                    // get the definition for this word
                    $def = '';
                    $word = ($direction=='A') ? $aword : $dword;
                    $clues = $this->parent->xml_values('data,crossword,clues,item');
                    foreach ($clues as $clue) {
                        if ($clue['word'][0]['#']==$word) {
                            $def = $clue['def'][0]['#'];
                            $def = strtr($def, array('&#x003C;'=>'<', '&#x003E;'=>'>', "\n"=>'<br />'));
                            break;
                        }
                    }

                    if (!empty($def)) {
                        $str .= '<tr><td class="ClueNum">'.$i.'. </td><td id="Clue_'.$direction.'_'.$i.'" class="Clue">'.$def.'</td></tr>';
                    }
                }
            }
        }
        return $str;
    }

    // jcross6.js_

    function v6_expand_LetterArray() {
        $row = NULL;
        $r_max = 0;
        $c_max = 0;
        $this->v6_get_jcross_grid($row, $r_max, $c_max);

        $str = '';
        for($r=0; $r<=$r_max; $r++) {
            $str .= "L[$r] = new Array(";
            for($c=0; $c<=$c_max; $c++) {
                $str .= ($c>0 ? ',' : '')."'".$this->js_safe($row[$r]['cell'][$c]['#'], true)."'";
            }
            $str .= ");\n";
        }
        return $str;
    }
    function v6_expand_GuessArray() {
        $row = NULL;
        $r_max = 0;
        $c_max = 0;
        $this->v6_get_jcross_grid($row, $r_max, $c_max);

        $str = '';
        for($r=0; $r<=$r_max; $r++) {
            $str .= "G[$r] = new Array('".str_repeat("','", $c_max)."');\n";
        }
        return $str;
    }
    function v6_expand_ClueNumArray() {
        $row = NULL;
        $r_max = 0;
        $c_max = 0;
        $this->v6_get_jcross_grid($row, $r_max, $c_max);

        $i = 0; // clue index
        $str = '';
        for($r=0; $r<=$r_max; $r++) {
            $str .= "CL[$r] = new Array(";
            for($c=0; $c<=$c_max; $c++) {
                if ($c>0) {
                    $str .= ',';
                }
                $aword = $this->get_jcross_aword($row, $r, $r_max, $c, $c_max);
                $dword = $this->get_jcross_dword($row, $r, $r_max, $c, $c_max);
                if (empty($aword) && empty($dword)) {
                    $str .= 0;
                } else {
                    $i++; // increment the clue index
                    $str .= $i;
                }
            }
            $str .= ");\n";
        }
        return $str;
    }
    function v6_expand_GridBody() {
        $row = NULL;
        $r_max = 0;
        $c_max = 0;
        $this->v6_get_jcross_grid($row, $r_max, $c_max);

        $i = 0; // clue index;
        $str = '';
        for($r=0; $r<=$r_max; $r++) {
            $str .= '<tr id="Row_'.$r.'">';
            for($c=0; $c<=$c_max; $c++) {
                if (empty($row[$r]['cell'][$c]['#'])) {
                    $str .= '<td class="BlankCell">&nbsp;</td>';
                } else {
                    $aword = $this->get_jcross_aword($row, $r, $r_max, $c, $c_max);
                    $dword = $this->get_jcross_dword($row, $r, $r_max, $c, $c_max);
                    if (empty($aword) && empty($dword)) {
                        $str .= '<td class="LetterOnlyCell"><span id="L_'.$r.'_'.$c.'">&nbsp;</span></td>';
                    } else {
                        $i++; // increment clue index
                        $str .= '<td class="NumLetterCell"><a href="javascript:void(0);" class="GridNum" onclick="ShowClue('.$i.','.$r.','.$c.')">'.$i.'</a><span class="NumLetterCellText" id="L_'.$r.'_'.$c.'" onclick="ShowClue('.$i.','.$r.','.$c.')">&nbsp;&nbsp;&nbsp;</span></td>';
                    }
                }
            }
            $str .= '</tr>';
        }
        return $str;
    }
    function v6_get_jcross_grid(&$row, &$r_max, &$c_max) {
        $row = $this->parent->xml_values('data,crossword,grid,row');
        $r_max = 0;
        $c_max = 0;
        if (isset($row) && is_array($row)) {
            for($r=0; $r<count($row); $r++) {
                if (isset($row[$r]['cell']) && is_array($row[$r]['cell'])) {
                    for($c=0; $c<count($row[$r]['cell']); $c++) {
                        if (!empty($row[$r]['cell'][$c]['#'])) {
                            $r_max = max($r, $r_max);
                            $c_max = max($c, $c_max);
                        }
                    } // end for $c
                }
            } // end for $r
        }
    }
    function get_jcross_dword(&$row, $r, $r_max, $c, $c_max) {
        $str = '';
        if (($r==0 || empty($row[$r-1]['cell'][$c]['#'])) && $r<$r_max && !empty($row[$r+1]['cell'][$c]['#'])) {
            $str = $this->get_jcross_word($row, $r, $r_max, $c, $c_max, true);
        }
        return $str;
    }
    function get_jcross_aword(&$row, $r, $r_max, $c, $c_max) {
        $str = '';
        if (($c==0 || empty($row[$r]['cell'][$c-1]['#'])) && $c<$c_max && !empty($row[$r]['cell'][$c+1]['#'])) {
            $str = $this->get_jcross_word($row, $r, $r_max, $c, $c_max, false);
        }
        return $str;
    }
    function get_jcross_word(&$row, $r, $r_max, $c, $c_max, $go_down=false) {
        $str = '';
        while ($r<=$r_max && $c<=$c_max && !empty($row[$r]['cell'][$c]['#'])) {
            $str .= $row[$r]['cell'][$c]['#'];
            if ($go_down) {
                $r++;
            } else {
                $c++;
            }
        }
        return $str;
    }

    // specials (JQuiz)

    function v6_expand_QuestionOutput() {
        $str = '';
        $str .= '<ol class="QuizQuestions" id="Questions">'."\n";

        $q = 0;
        $tags = 'data,questions,question-record';
        while (($question="[$q]['#']") && $this->parent->xml_value($tags, $question)) {

            // get question
            $question_text = $this->parent->xml_value($tags, $question."['question'][0]['#']");
            $question_type = $this->parent->xml_value($tags, $question."['question-type'][0]['#']");

            $first_answer_text = $this->parent->xml_value($tags, $question."['answers'][0]['#']['answer'][0]['#']['text'][0]['#']");

            // check we have a question (or at least one answer)
            if (($question_text || $first_answer_text) && $question_type) {

                $str .= '<li class="QuizQuestion" id="Q_'.$q.'" style="display: none;">';
                $str .= '<p class="QuestionText">'.$question_text.'</p>';

                if (
                    $question_type==HOTPOT_JQUIZ_SHORTANSWER || 
                    $question_type==HOTPOT_JQUIZ_HYBRID
                ) {
                    $str .= '<div class="ShortAnswer" id="Q_'.$q.'_SA"><form method="post" action="" onsubmit="return false;"><div>';
                    $str .= '<input type="text" id="Q_'.$q.'_Guess" onfocus="TrackFocus('."'".'Q_'.$q.'_Guess'."'".')" onblur="LeaveGap()" class="ShortAnswerBox" size="9" /></input><br /><br />';

                    $caption = $this->v6_expand_CheckCaption();
                    $str .= $this->v6_expand_jquiz_button($caption, "CheckShortAnswer($q)");

                    if ($this->v6_expand_Hint()) {
                        $caption = $this->v6_expand_HintCaption();
                        $str .= $this->v6_expand_jquiz_button($caption, "ShowHint($q)");
                    }

                    if ($this->v6_expand_ShowAnswer()) {
                        $caption = $this->v6_expand_ShowAnswerCaption();
                        $str .= $this->v6_expand_jquiz_button($caption, "ShowAnswers($q)");
                    }

                    $str .= '</div></form></div>';
                }

                if (
                    $question_type==HOTPOT_JQUIZ_MULTICHOICE || 
                    $question_type==HOTPOT_JQUIZ_HYBRID ||
                    $question_type==HOTPOT_JQUIZ_MULTISELECT
                ) {

                    switch ($question_type) {
                        case HOTPOT_JQUIZ_MULTICHOICE: 
                            $str .= '<ol class="MCAnswers">'."\n";
                        break;
                        case HOTPOT_JQUIZ_HYBRID:
                            $str .= '<ol class="MCAnswers" id="Q_'.$q.'_Hybrid_MC" style="display: none;">'."\n";
                        break;
                        case HOTPOT_JQUIZ_MULTISELECT:
                            $str .= '<ol class="MSelAnswers">'."\n";
                        break;
                    }

                    $a = 0;
                    $aa = 0;
                    $answers = $question."['answers'][0]['#']";
                    while (($answer = $answers."['answer'][$a]['#']") && $this->parent->xml_value($tags, $answer)) {
                        $text = $this->parent->xml_value($tags, $answer."['text'][0]['#']");
                        if ($text) {
                            switch ($question_type) {
                                case HOTPOT_JQUIZ_MULTICHOICE:
                                case HOTPOT_JQUIZ_HYBRID:
                                    $include = $this->int_value($tags, $answer."['include-in-mc-options'][0]['#']");
                                    if ($include) {
                                        $str .= '<li id="Q_'.$q.'_'.$aa.'"><button class="FuncButton" onfocus="FuncBtnOver(this)" onblur="FuncBtnOut(this)" onmouseover="FuncBtnOver(this)" onmouseout="FuncBtnOut(this)" onmousedown="FuncBtnDown(this)" onmouseup="FuncBtnOut(this)" id="Q_'.$q.'_'.$aa.'_Btn" onclick="CheckMCAnswer('.$q.','.$aa.',this)">&nbsp;&nbsp;?&nbsp;&nbsp;</button>&nbsp;&nbsp;'.$text.'</li>'."\n";
                                    }
                                break;
                                case HOTPOT_JQUIZ_MULTISELECT:
                                    $str .= '<li id="Q_'.$q.'_'.$aa.'"><form method="post" action="" onsubmit="return false;"><div><input type="checkbox" id="Q_'.$q.'_'.$aa.'_Chk" class="MSelCheckbox" />'.$text.'</div></form></li>'."\n";
                                break;
                            }
                            $aa++;
                        }
                        $a++;
                    }

                    $str .= '</ol>';

                    if ($question_type==HOTPOT_JQUIZ_MULTISELECT) {
                        $caption = $this->v6_expand_CheckCaption();
                        $str .= $this->v6_expand_jquiz_button($caption, "CheckMultiSelAnswer($q)");
                    }
                }

                $str .= "</li>\n";
            }
            $q++;

        } // end while $question

        $str .= "</ol>\n";
        return $str;
    }

    function v6_expand_jquiz_button($caption, $onclick) {
        return '<button class="FuncButton" onfocus="FuncBtnOver(this)" onblur="FuncBtnOut(this)" onmouseover="FuncBtnOver(this)" onmouseout="FuncBtnOut(this)" onmousedown="FuncBtnDown(this)" onmouseup="FuncBtnOut(this)" onclick="'.$onclick.'">'.$caption.'</button>';
    }

    // jquiz.js_

    function v6_expand_MultiChoice() {
        return $this->v6_jquiz_question_type(HOTPOT_JQUIZ_MULTICHOICE);
    }
    function v6_expand_ShortAnswer() {
        return $this->v6_jquiz_question_type(HOTPOT_JQUIZ_SHORTANSWER);
    }
    function v6_expand_MultiSelect() {
        return $this->v6_jquiz_question_type(HOTPOT_JQUIZ_MULTISELECT);
    }
    function v6_jquiz_question_type($type) {
        // does this quiz have any questions of the given $type?
        $flag = false;

        $q = 0;
        $tags = 'data,questions,question-record';
        while (($question = "[$q]['#']") && $this->parent->xml_value($tags, $question)) {
            $question_type = $this->parent->xml_value($tags, $question."['question-type'][0]['#']");
            if ($question_type==$type || ($question_type==HOTPOT_JQUIZ_HYBRID && ($type==HOTPOT_JQUIZ_MULTICHOICE || $type==HOTPOT_JQUIZ_SHORTANSWER))) {
                $flag = true;
                break;
            }
            $q++;
        }
        return $flag;
    }
    function v6_expand_CorrectFirstTime() {
        return $this->js_value('hotpot-config-file,global,correct-first-time');
    }
    function v6_expand_ContinuousScoring() {
        return $this->bool_value('hotpot-config-file,'.$this->parent->quiztype.',continuous-scoring');
    }
    function v6_expand_ShowCorrectFirstTime() {
        return $this->bool_value('hotpot-config-file,'.$this->parent->quiztype.',show-correct-first-time');
    }
    function v6_expand_ShuffleAs() {
        return $this->bool_value('hotpot-config-file,'.$this->parent->quiztype.',shuffle-answers');
    }

    function v6_expand_DefaultRight() {
        return $this->v6_expand_GuessCorrect();
    }
    function v6_expand_DefaultWrong() {
        return $this->v6_expand_GuessIncorrect();
    }
    function v6_expand_ShowAllQuestionsCaptionJS() {
        return $this->v6_expand_ShowAllQuestionsCaption();
    }
    function v6_expand_ShowOneByOneCaptionJS() {
        return $this->v6_expand_ShowOneByOneCaption();
    }

    // hp6checkshortanswers.js_ (JQuiz)

    function v6_expand_CorrectList() {
        return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',correct-answers');
    }
    function v6_expand_HybridTries() {
        return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',short-answer-tries-on-hybrid-q');
    }
    function v6_expand_PleaseEnter() {
        return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',enter-a-guess');
    }
    function v6_expand_PartlyIncorrect() {
        return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',partly-incorrect');
    }
    function v6_expand_ShowAnswerCaption() {
        return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',show-answer-caption');
    }
    function v6_expand_ShowAlsoCorrect() {
        return $this->bool_value('hotpot-config-file,global,show-also-correct');
    }

} // end class
function hotpot_sort_keypad_chars($a, $b) {
    $a =  hotpot_keypad_sort_value($a);
    $b =  hotpot_keypad_sort_value($b);
    return ($a<$b) ? -1 : ($a==$b ? 0 : 1);
}
function hotpot_keypad_sort_value($char) {

    // hexadecimal
    if (preg_match('|&#x([0-9A-F]+);|ie', $char, $matches)) {
        $ord = hexdec($matches[1]);

    // decimal
    } else if (preg_match('|&#(\d+);|i', $char, $matches)) {
        $ord = intval($matches[1]);

    // other html entity
    } else if (preg_match('|&[^;]+;|', $char, $matches)) {
        $char = html_entity_decode($matches[0]);
        $ord = empty($char) ? 0 : ord($char);

    // not an html entity
    } else {
        $char = trim($char);
        $ord = empty($char) ? 0 : ord($char);
    }

    // lowercase letters (plain or accented)
    if (($ord>=97 && $ord<=122) || ($ord>=224 && $ord<=255)) {
        $sort_value = ($ord-31).'.'.sprintf('%04d', $ord);

    // all other characters
    } else {
        $sort_value = $ord;
    }

    return $sort_value;
} 

?>