From owner-p4-projects@FreeBSD.ORG Fri Jul 27 20:12:34 2012 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id CB94B1065678; Fri, 27 Jul 2012 20:12:33 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8DB131065675 for ; Fri, 27 Jul 2012 20:12:33 +0000 (UTC) (envelope-from brooks@freebsd.org) Received: from skunkworks.freebsd.org (skunkworks.freebsd.org [IPv6:2001:4f8:fff6::2d]) by mx1.freebsd.org (Postfix) with ESMTP id 756EC8FC1B for ; Fri, 27 Jul 2012 20:12:33 +0000 (UTC) Received: from skunkworks.freebsd.org (localhost [127.0.0.1]) by skunkworks.freebsd.org (8.14.4/8.14.4) with ESMTP id q6RKCX7D099170 for ; Fri, 27 Jul 2012 20:12:33 GMT (envelope-from brooks@freebsd.org) Received: (from perforce@localhost) by skunkworks.freebsd.org (8.14.4/8.14.4/Submit) id q6RKCXi7099167 for perforce@freebsd.org; Fri, 27 Jul 2012 20:12:33 GMT (envelope-from brooks@freebsd.org) Date: Fri, 27 Jul 2012 20:12:33 GMT Message-Id: <201207272012.q6RKCXi7099167@skunkworks.freebsd.org> X-Authentication-Warning: skunkworks.freebsd.org: perforce set sender to brooks@freebsd.org using -f From: Brooks Davis To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 215017 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 27 Jul 2012 20:12:34 -0000 http://p4web.freebsd.org/@@215017?ac=10 Change 215017 by brooks@brooks_ecr_current on 2012/07/27 20:12:24 Alter browser to be pinch-to-exit. In the process add additional debouncing of inputs since otherwise closing text or png files being read resulted in closing the application. Affected files ... .. //depot/projects/ctsrd/beribsd/src/ctsrd-lib/libde4tc/de4tc.c#12 edit .. //depot/projects/ctsrd/beribsd/src/ctsrd-lib/libde4tc/de4tc.h#10 edit .. //depot/projects/ctsrd/beribsd/src/ctsrd/browser/browser.c#16 edit .. //depot/projects/ctsrd/beribsd/src/ctsrd/browser/images/browser.png#4 edit .. //depot/projects/ctsrd/beribsd/src/ctsrd/pictview/img/browser-thumb.png#2 edit Differences ... ==== //depot/projects/ctsrd/beribsd/src/ctsrd-lib/libde4tc/de4tc.c#12 (text+ko) ==== @@ -1,5 +1,6 @@ /*- * Copyright (c) 2012 Simon W. Moore + * Copyright (c) 2012 SRI International * All rights reserved. * * This software was developed by SRI International and the University of @@ -56,6 +57,7 @@ volatile u_int32_t *pfbp; static volatile u_int16_t *tfbp; volatile u_int32_t *mtlctrl; +static struct tsstate *sp = NULL; // fade timing (for crude timing loop) static const int fb_cross_fade_time = 500; @@ -153,7 +155,6 @@ ts_poll(void) { struct timespec stime = {0, 1000000}; - static struct tsstate *sp = NULL; int init = 0, first_pass = 1; int check_release = 0; struct tsstate tmp_s, rel_s; @@ -217,6 +218,27 @@ } +void +ts_drain(void) +{ + struct timespec stime = {0, 1000000}; + int noprevtouch = 0; + + if (sp == NULL || sp->ts_count == 0) + noprevtouch = 1; + + for (;;) { + nanosleep(&stime, NULL); + if ((int32_t)le32toh(mtlctrl[7]) < 0) { + if (noprevtouch) + return; + else + noprevtouch++; + } + } +} + + /***************************************************************************** * frame buffer routines * TODO: put in seperate library @@ -612,6 +634,7 @@ char *textdup; u_int32_t *textbuf, *titlebuf; struct tsstate *ts; + struct timespec stime; titlewidth = strlen(title) * fb_get_font_width() * 2; if (titlewidth + FBD_BORDER_WIDTH * 2 > fb_width) @@ -708,13 +731,19 @@ free(textbuf); free(lines); + /* Ignore all input for a quarter second to let the display settle. */ + stime.tv_sec = 0; + stime.tv_nsec = 250 * 1000 * 1000; + nanosleep(&stime, NULL); + ts_drain(); + switch (type) { case FBDT_PINCH2CLOSE: for (;;) { ts = ts_poll(); if (ts->ts_gesture == TSG2_ZOOM_OUT) { - while (ts_poll()->ts_count != 0) - /* do nothing */; + if (ts_poll()->ts_count != 0) + ts_drain(); return(FBDA_OK); } } @@ -723,18 +752,18 @@ ts = ts_poll(); switch (ts->ts_gesture) { case TSG2_ZOOM_OUT: - while (ts_poll()->ts_count != 0) - /* do nothing */; + if (ts_poll()->ts_count != 0) + ts_drain(); return(FBDA_OK); case TSG_NORTH: case TSG2_NORTH: - while (ts_poll()->ts_count != 0) - /* do nothing */; + if (ts_poll()->ts_count != 0) + ts_drain(); return(FBDA_DOWN); case TSG_SOUTH: case TSG2_SOUTH: - while (ts_poll()->ts_count != 0) - /* do nothing */; + if (ts_poll()->ts_count != 0) + ts_drain(); return(FBDA_UP); } } ==== //depot/projects/ctsrd/beribsd/src/ctsrd-lib/libde4tc/de4tc.h#10 (text+ko) ==== @@ -102,6 +102,7 @@ void multitouch_filter(void); void multitouch_release_event(void); struct tsstate* ts_poll(void); +void ts_drain(void); void fb_init(void); void fb_fini(void); u_int32_t fb_colour(int r, int g, int b); ==== //depot/projects/ctsrd/beribsd/src/ctsrd/browser/browser.c#16 (text+ko) ==== @@ -562,12 +562,19 @@ static int get_action(void) { + struct timespec stime; struct tsstate *ts; int col, i, row; if (verbose) printf("entering get_action\n"); + /* Ignore all input for a quarter second to let the display settle. */ + stime.tv_sec = 0; + stime.tv_nsec = 250 * 1000 * 1000; + nanosleep(&stime, NULL); + ts_drain(); + for (;;) { ts = ts_poll(); if (verbose) @@ -599,11 +606,19 @@ return (ACT_REFRESH); } } - } - if (ts->ts_gesture == TSG_EAST) + } else if(ts->ts_gesture == TSG2_ZOOM_OUT) { + if (ts->ts_count != 0) + ts_drain(); + return (ACT_QUIT); + } else if (ts->ts_gesture == TSG_EAST) { + if (ts->ts_count != 0) + ts_drain(); return (ACT_PREV); - if (ts->ts_gesture == TSG_WEST) + } else if (ts->ts_gesture == TSG_WEST) { + if (ts->ts_count != 0) + ts_drain(); return (ACT_NEXT); + } } /* NOTREACHED */ return (ACT_QUIT); @@ -614,6 +629,7 @@ { int fd, ret = 0; u_int32_t *image, *previmage; + struct tsstate *ts; image = malloc(sizeof(u_int32_t) * fb_width * fb_height); previmage = malloc(sizeof(u_int32_t) * fb_width * fb_height); @@ -632,9 +648,14 @@ } /* read_png_fd() closes the descriptor */ fb_post(image); - for (;;) - if(ts_poll()->ts_gesture == TSG2_ZOOM_OUT) + for (;;) { + ts = ts_poll(); + if(ts->ts_gesture == TSG2_ZOOM_OUT) { + if (ts->ts_count != 0) + ts_drain(); break; + } + } end: fb_post(previmage); free(previmage); @@ -654,11 +675,8 @@ const size_t maxbuflen = 32 * 1024 - 1; u_int32_t *image; - printf("entering show_text_file\n"); - if ((fd = openat(dfd, name, O_RDONLY)) < 0) return (-1); - printf("fd = %d\n", fd); fbuf = malloc(maxbuflen + 1); if (fbuf == NULL) @@ -682,7 +700,6 @@ else fbuf[fbuflen] = '\0'; - printf("fbuf = '%s'\n", fbuf); nlines = 0; while (nlines <= 1024 && (lines[nlines] = strsep(&fbuf, "\n")) != NULL) { @@ -907,6 +924,7 @@ } fb_init(); + ts_drain(); busy_indicator(); fb_fade2on(); fb_load_syscons_font(NULL, "/usr/share/syscons/fonts/iso-8x16.fnt"); @@ -939,5 +957,7 @@ while (dfd != -1) dfd = browsedir(dfd); + ts_drain(); + fb_fini(); return (0); } ==== //depot/projects/ctsrd/beribsd/src/ctsrd/browser/images/browser.png#4 (text+ko) ==== @@ -1,10 +1,10 @@ PNG  --B>4J vXqy… [l;k֬|ݻwvzh\;ƌ7|sxͶ夓NCƠA 'C>ٸ>N;#}xG뮋C=;.~_#<7xcvi[l܎ޱV䶫ŭRkb :433njB\ַU{qg7裏Ι3g|(nʶm6i'gf~袋mGK}IW@^{8qbff~{k27=أz(3swψ6m\`Az&wyc5[W_}533Νڵk2nȐ!_=Pu9~a}8tЬk2 6 뮚|ڴi7[mRJi+ϩS6±+:X;@)Ժ;k/oUBGccc92mQ~s{,33_&'p@ffΟ?? [ou~3/Փ{キr*dܸqp|G;,#Z@:w˻;33ǎĿr>v|rذa~7?dG`̙9hРرco>8|3٧O̜7o^ݺuk>7Y~833/dGA˽;^{\wusРA9eʔ<#̣rѣs٩Su]+kRjMeƲe J)&֘1c23+\TرcM6MݻzBveDZk6ą^j_1f̘evOZ]>CqG"--kyr!ѡC(-?Gydͫ 19ɸJ0`@ 0 }&L&Lw=?&#"v3f̈W_}56eʔ8#3c֋_?">vXme]bkE6mi>I%zYI|ZSk7ɓ'Wg۷o6_=]=zk :(kVGydf.6w;5ּ>{葧vZΞ=;33y&m*@z^/KT光&LhSUeT^ xM75_I]}]̜4iRuX+~aNMwԩ,[Ҷ_)ĪKci헡տRjM#8"̙S#F]wU=\]65dw?9dȐ~v[uy.vEH梮v?^{rM6i2N?|׿s՗Ν;__]ǻ1>nf~E/skOSN9%oᆜ5kVy><3k38#/Ǎ;v\WJ5>7|,m:D)VBu5os9ٕJ&DD3|f{Ci6@>n /rg͚?kN3x7o^|A^~jRjM̏Bkǒ_| 2` wѳgϘ6mZ<31a„Ux}}}3! 묳N+C5m۶;;f͊ѣG/lbw:23ƏFS8MΝO>vŔ)S_җ? -3- %MkƌW^ye>df_^o}[- J)`Y֎#8ɴ-\k׮_w/꯫1ҥKi.袈0`@~:uW]uUt9Տ'qq5[s=7YgxW.i+kW.?g?Yti"?wmڴ>Iq}Ӛƪ|'L={'|2۬xM6OĕW^n/< P9Ah׮]Ou]w~[nea~zn1mڴZ̟??v_gx뭷Z|H9bʃ;S|?z-qd+ٯ -kVzTK{%묳R\ No newline at end of file ++2?#9&@|O*""+,R{'"V[P{@+駟(:g?Vlٲxn61hР8Sg?Y\{1k֬={vlV1cƌ뮻hkkkcԨQ%ëbvmF۶m?>F iK g]v|UW]U /ܠ j-(\Zf^{ꍞ47t|#3 _ԁX̞{N;JwqGJ)U~R}7|s֣pdܹH={LӧOO)+qD)oBkqGEl6fΜGɓ'odSOEDM4ȽWvaeZlY\veGeee 0 w7uXSRJ/5k{ưΗ`?8#saz+<gyfq;E]Tl׺uFt%LoF׿I&?.]{`^fNJ8nݺŔ)Sb裏Ɣ)SK.$z[L:5F555KV<087n\u濦Xp[l_~ylqg[ne]vѯ_{c…7ztE?СC\yqW>unO{l|qWrǀbРAFfbm۶??w;C̜93&L㥗^3-[%\-o1g8# +2<[̟??FvUc+~8ꨣ_!C稣#<2F>`qx{quEƍO o}[1cƌxGbذape]⬳Ί^zEeee{o7'ZD|qYo{ưVLVw V~ߦR1bDqع瞛RJN\sMҁaÆ3M48nſ?ty>S%\ưV[G}lٳg~w?,[|yO?4kn]u,ԧ~RZqŔ)SJhѢtGLwꩧ۴ifJ[-Z;/Ғ%KU%X9?un睊I)4vد4c=6-]?i.J%ĉS׮]Lװa /r9+?}`MHL)t]bV+S-J'NLַR6mR޽ӿRJӦM+y + ~%*@r6k#|Gֶ6m>쳔RJ]w]jREEEҥK/~Q.ݺu+NS iO}I[ou߿z7RJ)3tWR=ztիWjذajڴi߿9sfJ)N:ؾ>6XW /Nd8D)6v 7ܐSV>(٬wcCя~3gΌN:ū=z(io~3hԨQ+q뭷FĊˋ +P 4iiӦ\7Ka^xa~1{'OKFuuu|.{1}zoRX}p>{wmEEEO-Zr6e_eo 4-ZQޛnnnkoB/W{eĊGYG[o5n+_.yg&LHCc,XtEo[lYl߰a؇+ 8(ӥKq{麮cᑢ:u*M81ґGYgza}vu⺤W_>nl: N)ӧaÆG}4͘18|Ĉδ_}>`K4eʔ4gΜ㏧R?YoW~ '|>4dȐtW{8O`sMw^:th߆[nX}*M<9CMC IӧOO˗//ZSJԷo6m߄6VޟEp@q=z(Oz RJM!HD-Ze~{jԨQ4~zZdIڕiuƧ7tSzK׸qg3&}kr_뺎)$"%\Rlr\ No newline at end of file ==== //depot/projects/ctsrd/beribsd/src/ctsrd/pictview/img/browser-thumb.png#2 (text+ko) ==== @@ -1,32 +1,54 @@ PNG  --tUݲ-;aM7(V||RJm۶)trʩs)Zree%8+-.0੩s\rX Uv~x%"fg=RJ#G(H)oy)cY "QFY@QU+N#FX233R.ս{wRΝsz{ٙ)S,7\xQ.]kHVVJKKW׮] 999j٪jժO&Lp֭[?J)fΜ/B)ԛoYg>RJe=zPJ)x⼟mذA)U@@@=888ܳQ#G,t7 EQűQFRC5c-ݖ{WRRRĉRD K-\޽{rG1{lo*O[fͼ΂u35n,wbUȑ#Օ+WRJ_>:@2e=Yrxر3U7;wneyٻn~}~Y"קTJ3g,+y'7eEQű -ʕ|oa-߿ EQŹ~uռhϞ=bcc?!W/zw=ܓӦMjҤI꥗^Rb@>ue˖J*{G}4%Kǫ=0333 7g}?#yϟ_?R?cSO#FoFٳRןN'QF{/ᏇRʕsi)[\ f#PEyՂ Ta.]^{g*r˝-nm?EQTq*~~ae-ΟA-rRJ  .Ujjz-ɑCNYZre8m6ٵk:5jp{:_++9?&KHss 3s&"J+رcJ)T@@@e&MRJ)5}1^:alllڨT駟|ϟ?bbb +l)BPE[vW+/t8vBCCU֭պuRJ8qݻ+z4iWZ8p`e˖'/VD .\ *Vʕ+w:T $TJ)^N[nƱfR}U" 2vR۷W~~~*00P 4H%''++֭[ +'xZZZV?Ν;zmݺu(ͦN>](d<#J)>Rjʕ+ԕ+WRُ#G7/}?RJ?~\/_kMREQT+""Ex^SL?;p@ϪV*""ݺu͛ٳgeƌ9~\RDM|tyE)v{_޶m[1cF{@WD/_^6o,W.GʺuDDG""EHΝ7xCDDt钿{YrdddȵG_ +oKpp=:gyE>T/kX~+,''Gf͚ "n|>ܹs""ҼyBv)/_vy| +ՓvԩSeҰaCi߾}g_P 6K:w֭ҧOY\\9R:u.]HJJ|7HTTHFFt-uyfϞ-۷AɩSモ+VȊ+r…{˖-+z*4N&RlYiܸq-j+ F|||.˛vYntI$<<\D$ҳ˗˃>(]tm۶w-{Gh{ƌ駟JǎG#mڴ:H~o8[o&{Zv+/".iiirر$''s='J)PB y{~ܖ[RSSoi+OfΜiy)"(*u+W?*..NOr^ wuW׫I&_|Q=@;% J)[dUJ7ͲINNdIJJd9};vL+ +P򅄄Ȃ dԨQ +pSkѢKpp++͛7=zH}Rzu/\ [nx۷iwq\T)???u)g^ /yذa*s@BBB/N8a:$&&>@j}v6l?KOp8ҥKՈ#Tr<2Fo+57P/^ts9iӦj߾}N+..(M}qEDDJ)SsΙn˗ۗh<ի̜9-_4ݦm[K.5q.xҾ*ӧo*T]}5UjJQX:U\Ym߾]ܹi=*N+ T-ZP'OVG ~ov-[oey׻QmCuoyUJ˳\m޼Y=*,,̰M???u}~IXj￷|O r8*88Xn[s.߰ѣGhiVu*nfxx7nv^ZnѸ+(VMǟ\g8~:|}}]n3.]RzgHZ3l] 6̰b뙙Ĩ[>+ +2=p]eddHwUTQ'O4.u… }ȕOoR_oW_}մ/+잂lUvmӶ7nlիW]~fszɝRM6.>a]v5m㥗^2lwukРE\j.EY**%eƶ ȑ#lٲnwņ-_ܥ"""Lo~'u{\j~-[=H||[~Ua_֭sȵK)ԖٱG.l?OtK/{g9m… .>}{P{?ѓ]yb;]V<jAzf%tu:^gzXB/_^:c+nsΆ}:ur[*U2]Xg}ְGԞoi=΀(ԉ' /%>e}TZO?FEEӯ_?6֬YҸ{mժUK=NzH:u ce_ZʭiӦW^qZ7N^Tqܥ(JAhRSS>Ne%|nYf}fgg[n'0lСC}Օ+W P~}!TժU{p+<)))G-{s)a?U%M*##}zfs<*Q5k4+}G.jذr_ҙk ȷqFK0Js+2[ٔ}, Ja9 ~H6:бc"ovvdoٲD*TVZyLL-ZYӌɜ9sdС*-[q_^Q/M'qp X #G@\Էo_uo߮a$glz~wun+pp8\g)6֭[װ UfMl6'rssUZ,KQJyUPAm߾vW)S +*+ Qx8-KtyQuQ=t.0tiյk/}~S>ٳؗײeTٲe=]g϶4^{}kܾeʔQ7o.(nUdy}+*_~Y>}3gΨYf z|;n\ܼyS*v +vvv ADD"""ꊌ \v DYYY{W,Rh-Kν= ++߿6 ~P+gϞEuu5+ +B\\\{WHG:555}vj^[[vvv8p |}}닱cb8ydLDDY䥗^Ҝ*˗/W?U3(_􊦶߽{w1FGI;;;ٺu6yl;R]qIٲe IOO" K6\'33cdɒN_rHYfҭ[7i׮kNVjŋe'qqq`:qŝsSŧԙ3gL o|7֋/h:!CXj瀄W^yE4ibcc]ގ3WÆ ofBCCմiMʕ+Uv4u5~fΜ}K/nӏ?߭˗ըQ#W=wi_ٳ*[swT-*FcWLVBvFe-wȟ'uΊSNN:iy>}v[).]&OJ,qN:*!!tF~v- hw cۥM6m޼Yh7.s̱؊w臦VZI||T^cm:ce?Nj 5k֔˗KXX >tok{{=He˖-n5v2ĕP-7o&O=jy{=ov-[oey7VmCEGGR-*UdyY=*,,̰̀%JȺu{<6o Xg~1*.\0[ti)޶n6HŊM޽[zt'?8,_cmիEjfIpp/_^ʖ-kxM!CHTTS>\1Ɠm۶ ׭['IIIϙ~`o߾v1l'66OǎM?l-Kki<ҤI1ҥK/7駟?{]r y̾^V"^i[Q+̾s8r̙"cf݆˫U汾N>n7CdϞ='ȠA$,,Lbbb,ɻeΜ9nIqSf^d6CoXqr!۴i#tرП߿?3Wvz)WDDDet#))ɥKW\"_}[n-sΕ$ѣG=cxY'q\%XsuBBBx\K 40\&=z8 MiUFF\|#m)rrrd%C_*Vh޽{< ,|u 64 W_}{95h աCհaC*T5kz衆&OvV?GȭtDDTݺuUjj{>sUNK={NkϞ=ncy')nƌ{oPK,i޽{U޽U@@Go>K?>+߰ߨcǎnյkW2eGO8pǏ'xB~RСCզMLHHHp}e\~ɂ ߿x>^Ξ=+ΝXT^]U&2h r-\P ڴi#6mnzzHVV[}JJJ1&&Hg\n4p@7ouO8!qqqfټyorռ塡RfM뮻K.裏Zҥ[7s<QVk:mv$^~eWm} ^g-{oP 2335s= -7n7?׊+ߪU,uEg>PgϞU.]r &iw)i|-  7@nnnnnnnnnnnnnlE@DDDDD-***]zrdeeU""\Ĝܾ}[VZ%fpuuWWW1 l7ED믿nzuh}DDd^C&յk䷿mӜx@{e[Njj{F?OO]W^i|}}W_}%~~~۶m$''9a0 ' \Mݻ7|||ꊥK"""ᨯt3-۷ -R;..;c` /#$$HII={Y>} &&aaaGAA?xBK3f "##;wXf d㥗^O<www>}v닉'5}l̽6lxzzwP=#G|}}ܔL-???-V]fj]]jkk-e^/!mo\~]6l ,76S|wFrwwǢEPYYu!,, &MBLL ***>@^ؐ f͚g}Dii)._|Q٦@KP#Ƅ p9Ǜg„ ɓ'{nur]^:u*yܽ{{QQQ~a=z4lllp)|GV?my;g[օ ڹFDDzd\,%ȉ'is>HV\vؿZfĈ{wYY̝;W-{!n?"bԍk׮w^rEEE2~xGFF͛7ruuuߗmpG%߿/",rrrLYYY)&ƪecGi `ܹsEDJ=^ .XzK׋իW['JuuZOٳgKmm1̔!C-ץKvXhi qqq""󎈈l۶Mx票d/aaaFP\~];TG; ǏܥKy`0L@Kݻ76mR+ HFFw}'˗ /' + -L+**74ٖIUUI+**Qڀmljry̝;W^~e ÜΘO]ѣG1a0G# GӿpBpvv5tssChh(?~ݻ#;;/_nOKo}|yl,6G + ED@9R -!CPVV . 77ng Ayy9;ft Fׯ#77^^^P__vqPRRMk 41|p 8"6J9m \ No newline at end of file +/jؘ{mX{ӧza:nݺaÆ~~~R_tnLZZT+___v&o&M+@}X1qD(..Fvv6푟vx'MذaEZc;,\+'''|pvvnr6l@~͟?Æ CQQ>S+e^/!moƍe޼yi&ÆǏ7S6AFF$$$ X^^.[n ȺuƣwwwWwEN>aeZ]]mƶ5 )y233ED$&&hz{}rWEDncca͘2e:\H^^߿_+wU8qB|||]f:ݻeѢEcɑboDDjm8 ;wΝ;/K.}f̘a?j;زe̙3GΝ+ j1;;;$>>^򤮮N[|]lٲEDL QQQ:o/a{2C#GT1|p6ax g-`cԇ~(&̘1Cr omlldFE꿚{InL(?1OxZ7_% -R6L@>6\ ׿ߗ%K|Pˎ;_ $5  =$$DҌ/--7|d[666'&u,--?Fk涱ɩΝ;2{lyE& 91ݻǏc`0Fo߾G>}p\xo %%%Hzzz""" BAAN<{222pڵF4GƒkÚv튐/^DVVV΂8qx 9B~? NJ1cƠ\ No newline at end of file