From 70329f93a46c59d9364e02e52126b9957c6529e6 Mon Sep 17 00:00:00 2001 From: David Wei Date: Tue, 19 Aug 2025 07:19:03 +1200 Subject: [PATCH] Improve multi-monitor support and DPI awareness --- shotpath.cs | 70 ++++++++++++++++++++++++++++++++------------------- shotpath.exe | Bin 30720 -> 30720 bytes 2 files changed, 44 insertions(+), 26 deletions(-) diff --git a/shotpath.cs b/shotpath.cs index 7ca7acc..e9c4e40 100644 --- a/shotpath.cs +++ b/shotpath.cs @@ -36,9 +36,6 @@ public class ShotPath : Form [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern bool DestroyIcon(IntPtr handle); - [DllImport("user32.dll")] - private static extern bool SetProcessDPIAware(); - private const int HOTKEY_ID = 9000; private const int HOTKEY_ID_CTRL = 9001; private const int HOTKEY_ID_ALT = 9002; @@ -160,24 +157,27 @@ private void TakeScreenshot(bool copyAsImage = false, bool uploadToImgur = false { // Small delay to let menus settle System.Threading.Thread.Sleep(100); + + // Use virtual screen to capture entire desktop (handles multi-monitor automatically) + Rectangle virtualScreen = SystemInformation.VirtualScreen; + selectionForm = new SelectionForm(virtualScreen); - selectionForm = new SelectionForm(); if (selectionForm.ShowDialog() == DialogResult.OK) { Rectangle selection = selectionForm.Selection; - // Use the pre-captured screenshot from SelectionForm using (Bitmap bitmap = new Bitmap(selection.Width, selection.Height)) { using (Graphics g = Graphics.FromImage(bitmap)) { - // Account for virtual screen offset + // Selection coordinates are in virtual screen space Rectangle sourceRect = new Rectangle( - selection.X - SystemInformation.VirtualScreen.X, - selection.Y - SystemInformation.VirtualScreen.Y, + selection.X - virtualScreen.X, + selection.Y - virtualScreen.Y, selection.Width, selection.Height ); + g.DrawImage(selectionForm.Screenshot, 0, 0, sourceRect, GraphicsUnit.Pixel); } @@ -571,10 +571,16 @@ protected override void Dispose(bool disposing) base.Dispose(disposing); } + [DllImport("user32.dll")] + private static extern bool SetProcessDpiAwarenessContext(IntPtr value); + + private static readonly IntPtr DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = new IntPtr(-4); + [STAThread] static void Main() { - SetProcessDPIAware(); + // Use modern DPI awareness for proper multi-monitor support + SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new ShotPath()); @@ -597,29 +603,29 @@ public class SelectionForm : Form [DllImport("user32.dll")] private static extern int GetWindowLong(IntPtr hWnd, int nIndex); + private const int GWL_EXSTYLE = -20; private const int WS_EX_TRANSPARENT = 0x00000020; private const int WS_EX_LAYERED = 0x00080000; - public SelectionForm() + public SelectionForm(Rectangle virtualScreen) { - // Set DPI awareness this.AutoScaleMode = AutoScaleMode.None; - // Get virtual screen bounds (all monitors) - Rectangle bounds = SystemInformation.VirtualScreen; - - // Capture screenshot before showing form - screenshot = new Bitmap(bounds.Width, bounds.Height); + // Capture screenshot of entire virtual screen + screenshot = new Bitmap(virtualScreen.Width, virtualScreen.Height); using (Graphics g = Graphics.FromImage(screenshot)) { - g.CopyFromScreen(bounds.X, bounds.Y, 0, 0, bounds.Size); + g.CopyFromScreen(virtualScreen.X, virtualScreen.Y, 0, 0, virtualScreen.Size); } this.FormBorderStyle = FormBorderStyle.None; this.Cursor = Cursors.Cross; - this.Location = new Point(bounds.X, bounds.Y); - this.Size = new Size(bounds.Width, bounds.Height); + this.StartPosition = FormStartPosition.Manual; + + // Position form to cover entire virtual screen + this.Location = virtualScreen.Location; + this.Size = virtualScreen.Size; this.TopMost = true; this.DoubleBuffered = true; this.ShowInTaskbar = false; @@ -635,7 +641,8 @@ private void OnMouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { - startPoint = e.Location; + // Convert form-local coordinates to global screen coordinates + startPoint = new Point(e.X + this.Location.X, e.Y + this.Location.Y); isSelecting = true; } } @@ -644,10 +651,13 @@ private void OnMouseMove(object sender, MouseEventArgs e) { if (isSelecting) { - int x = Math.Min(startPoint.X, e.X); - int y = Math.Min(startPoint.Y, e.Y); - int width = Math.Abs(startPoint.X - e.X); - int height = Math.Abs(startPoint.Y - e.Y); + // Convert form-local coordinates to global screen coordinates + Point currentPoint = new Point(e.X + this.Location.X, e.Y + this.Location.Y); + + int x = Math.Min(startPoint.X, currentPoint.X); + int y = Math.Min(startPoint.Y, currentPoint.Y); + int width = Math.Abs(startPoint.X - currentPoint.X); + int height = Math.Abs(startPoint.Y - currentPoint.Y); selection = new Rectangle(x, y, width, height); this.Invalidate(); @@ -677,9 +687,17 @@ private void OnPaint(object sender, PaintEventArgs e) if (selection.Width > 0 && selection.Height > 0) { + // Convert global selection coordinates to local form coordinates for drawing + Rectangle localSelection = new Rectangle( + selection.X - this.Location.X, + selection.Y - this.Location.Y, + selection.Width, + selection.Height + ); + // Draw darkened overlay outside selection Region region = new Region(this.ClientRectangle); - region.Exclude(selection); + region.Exclude(localSelection); using (SolidBrush brush = new SolidBrush(Color.FromArgb(120, 0, 0, 0))) { @@ -690,7 +708,7 @@ private void OnPaint(object sender, PaintEventArgs e) using (Pen pen = new Pen(Color.Red, 2)) { pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash; - e.Graphics.DrawRectangle(pen, selection); + e.Graphics.DrawRectangle(pen, localSelection); } } else diff --git a/shotpath.exe b/shotpath.exe index e20e4ff78e5a221bed7238dfae48cf75de8ca9c0..79a1b0c7a09a721e3e18edae55a2916cb77043ab 100644 GIT binary patch delta 15394 zcmbVz33wFOmF}sftE(5a)ZHKn5U4SW8xR;F2w)qqkOZ_rXb0g0ibMHO(Z1>z-)y?R8(&&5A@jK=pum4g%xu0Ls6%>$G5^V-!wZr_k z6K8gZ9!e55F+EDOuKL9MXnwxbCH;GTOuAB9mp>!zj-AH{{%pgaOdfi4Ez!R(A(BAP zA=2{Ibt~;F|6 zYao1vd`W{)&5D3yMp=w}Y;wq6cLBy%R%Y$Pje zPjqG%U^Vte$;5oe8`f-$AAuvG0mCfVgC@cZx5X>am~#QL%Q0O<%CE)efq?)8yj41h z4nH}}pk7r5-GwkM4n=IutQ3-#MO}V8#v&aiU8pLe>?TO|ne)MpU%_Aj0Q6@eQwLut z2zJ7^5Tjg9nYl<1Fb=9Z&WSH()>4}!*h};+sk>aR0xEH84ub>7gh`2CiD9t_2$63$ zf)fWP7?I=1cYnYeV|6Y`MLuXMmzHwYYDCLcdt*yPM^p`~+*LNwHOm`Y>U4R+9=j@l zX=Uy-l9l*Up%)aGvr?nIykS_8%HH@g?ub_b`en_6C$tf)grG1qmxEu%E?-}TIWSys z5eSWSU4dRSSD~@6W4 zYvtw|u!$}dg*{bz*kgW-$v3h?oD?Vy{!g!mYvb#HMOE3^vtbqKVk5O+pz4#4aTCWd zzj-xJmVM?mXmi-v(ufCrbRpoY^7>rSYSbI{R$*_u6N??c*C?9e_iC-&3#j$5N zDl_31vCM`7+h#rr1{Ogo%X9-Zogr*l##`t~kA#g+v|=)}OMw?+$#@}lOXsXqF`G~g z5iYC)Z~P~fD*GLH27_!KwGrAZrV9%Kl>Hgl-pO3gdSn_btt^Rea)z*`PQpsG=3}&g z6Bf0OE@ELAGJRpcw*G6ZeKrgs*?R$ISFRM20^W*CQcz!iH~e4F)w&K#ATP{Xv{AJ* z>RA>Gt6|T{C=1ri&0r(Ip2YxQc*;7X$ltJfPiobx@(d9~`560r#wA6>hMmo{S;sRm zgbDC?-^MN~(Cce5*@M|1L9sHkUWkY6MN!m@B83LS`hVsJ4j0ib3U-qRbp$yt(ep3R zqQVw_0KF)YVGG+-^K0@5QdQNIk@>8I=4fFyi2TD=QVX0dP-6tU6O1@2uQn0`E?Zlf zja0yHV;K7(q?_A>U4o%q(hwQ9>?S7p=JkxDcNzC?2NB-^uo#1*D`lLY?0^2q@ka1P zF^MBXwZ$%ji^wzvmkyU9JXz}0w)jq72uY|AvWaw&3%B4D_h&c3m!)PiP-s$BqGdl1 zhS>rdk+PRbrGX1!t;(yp8*4FvL0)L+?1(6pFC!SuACYt#yStS)9v?wwD+I-HB=E7z zMN6fVXi)}{jFSqKxe6#a6Dla)hDl~SfE{%7(ajD}*rLVcFiOo`f`MH>MLD`qj|1T` z7%=5Pn7&CIwKxg6@)Jc0-bo;tP|#Q*R2Xr{I`<7+ zG0GfcCzgRh#qJ_yg%uo6X!I;(z;!rBtlg02r^;ABGdqELYeJg22j`#Pdr5-qWl~vG zLl_##>lGC`s5=GPOJVP96NSYOWUl#f2Pro{;UK8KUayH;3RFe$#ep04x`Cu+KIGhu z=n9f6!rMx*qYj6-Px&OPgI}g^sv6v&4p{Is;^KTbvkp_ z@!Xu1I{gloqEd&+>V{x{X<*$e;K1I>*feug3abTk)OZi?KeHDzaKQ1uxB(pd@w)4* z{lKCg3=eze&8sY_Eb&$@zabXFMmPI-!bi`Vc>naN8c)?Gr&iuDIZuO|oP4+G4Hl$= zp}Kx^eWf|hGE=;m>l*Twbq2iiE{VhE>e!$E{AVqyFC%skPB%U?nrLpi;Gw%{_9F#+ zKINZuaK2wW3D@9|30o_%|3!7eWUh_438H@T#R=D;i6VvC!yV|yB(ATxM$L99^Cs5M z=`jxo$DnlKMyQRT^0`+w?HJ?ErOGX4ED5u)z8X7^9a5-f%tyVdh5+YEoR}j2dd5*? zyc9tkpc5`8g$U!?he=4Tk3_f-;8IaEOGSjOG>_!q+F{S^*_Gv$<>mm(zAUI2aHr%0 zf{MF_$wL_#6bQmR>och9(xTGJKxK(_5Zp%uT~-;Yj837;D`!>)CuuXw`6m{g%!tbq zLKB-O;1!!Es28>lNkv{~<7m#t@kPDJ1yMOgE^MF~Ers}-wCno?JW4P8tdI+~Ok0r* zxV@lA;DKfxLMbBz2r`m@A8(j)13PiPBL3VpdAcI?l(@y-So#3ng4>Q7pUqo3o?~8V ze25zh2e}qMBu0I#@{iVGVD=~vUW(JmLl{e_eq8a6@SrJYQd#Boah%wif6B2m%jE@J z9-mBeTwYMC@_DN?-KlK29M5wti9L;anEfpZcy^gegXOk+@Gp(7l(>LkbyncmENJCl zM%n})Pc_WPV~4}%+c760PM+|@qho1&SSVgBi7P9bt3ZnaG{Q5T`65qo7NUC<^52iP z22E)xkfT7%V*tpCsRxf-8o!yja(skG+#>MOI8P@T^G1Qh#|jiniQg)yviNOIYu+x} z(l}y`Id~RP_rI%#BV~J;#viJimP>z3A$c5LC zK%B`2GP%@o8|Nu@KV)BlC_RXQPS%!|%JI)J6+a2+9{K;rRoDNMaKG#hTqOi>fTL=J zeT(|H$L-@i-~?avv9}6cE4a%skWCWLfO7ovK&^)WihR2HFj}fSQi@05FEHP&@Qwvx zkI(!f54fzp+o!-rfhYIC=K^15p60RcR82R(RG2!gN-tYSmDf&R&s&(}b+j}8rZ98b z#R!|jJ+6OZQ}kDbx{OOsg@p5ux6MYWe3yfB9?a(nP98i0iIsE2%K#*K`SgIYU>;wE zR^$zbajsjoCQCYp*f}!b|B1ql_hnz^X^s$uMj-^nnYU6UC#HbMf%2X4dik($`lbvwzlveb;a|C83V-(AvQFE26rD&hUP7ET*>kANnt0RVyyU@o?-BPq zY{xK>b%rNcFi{J55JmBC z0Q$_w0d2mFX8X}+J^^wbKUAvOqoDB;0j0wq)x5kx!&=z0$NVN3*;~+=y`5)_gB(G{ zbbaH!q%G$v_$1izrvUIwJ++3@g|!wkS>vZuc?1Phjp}yT8`eiqPx*GmJ_th!a(ucJ zQBEs3FLZkJ38$QLMtt{sv=&tskKi)>J;H?&z~N$*;?66EW9%Qtxj6XL!fkDWYm3Ln ziSu3XMQFbT{r$^|@lNLNfCaqf(`X3fx6v-YcmX|^N)hfk?yXgxvXYYpLe>?$DD2{B zOe`wm?9lcxoIgxZXx4n!PbsMJ=%4kpUD@^p1Vw{;S&T^in{RU!`~A8RpW0B z{*X1oBo5-Ne8=o1_9eVs=8r}ro~wcyJuG00ry^KPO{g*&%@drno(f%~;Ub3Xf&1xd z{jDG#iF^!S_rDbk(cdd4@e=(HUgmr@z?|8>lbS|BKac;Z!kh;6q!yyHeumNDNgLf~ zgwSsWdC;Yzx1hv;|D2>zhk&;gKLsVeKv&Bl+NATeUui7#L$yMWP$2X~kxA#VsY3LL z5HEis$jhGs3{e%9_tWFRHM-KvGM_0vC;90qq2jCRTS41TFF|)dJp(&5Iuu|f-VxpZ z1r}&@OlOOm)N@jZDvEevOXD$(#oT)l<8f@uo3M-l2_ZTs#{5QM{%ue(L=PA3LGNr> zAECaY3aqsTM*8VJ_)oLxMpy~wFhQHVo3OxXKtF8~3Y`&$msY@(84#N;85jeX^5J>?o0plVB z{{vQrs8eNeC%}o&Pkm1mMd(rA|CBXq)}9DyblAsMJ_{>3gPKGlNt}DwKta#B;4I({ zWgv%`lJQqUC0?RMz!j4C;<*6R7g0IQBLx$2)=>vlB5j$<32GsZQl@?{sKs~@%M`EI zL2+71i>b!<6;+}?>t_I07C#0!%X=2^o63`b)%w$bLH!xEW%PdOETArP@7jRP&253_ z01v4w;<&(npudPgw)7Ri#|3;%z%NKY1m}AKo)_?M1iT1XO)t?uK*H|OKLUQ*_X^-W z+Rp*+3cZF|cM1vb33w0?$r!v~qbV->72pTjSwLP`qkjxB{#{t0(U<8rfY%rQ8{icZ z!is%lPih(Mo z`wCPb;0aR@<(KCz3j}OWlqyiOnS3{}77q>2xzsB~0Z%E-K#AnO_x(qua=O{2?vn$a za=Oo@{^YNt+0@B(4kP~o={biUa;fE7#50F(#}USTe+-s;D(H!24)seUuU$cdxWjPg zxZaLeoloQL!1kU}>j+0ZKJ2z%hsZOR0xOt4L5K8x(mbkmsPZ=hOkF3aFR#e(G|)fiml}CF{<&`cox&B zOMT#}@x*Bd*L3v#75bLalP=X1y2evQ&A7yK-*$hUX9bN4$}wprJuN6F*wtjeD9GDr zAM~!KW;_59-9~rOc2CW;p{r?-4-oW)P)1jOq_6X1PT#7(&{x0K>AM~)uy~1PDtw3H zZ_^Z;+KO-p;@ght9TJtR%-Nuqlt}cjQc@z*pHSr`+6E}o9PR%H|KPG&_Ed4dhDH+o zQ4G3Wz<>5I=RT-dSklpb3l30)&WJIS9Emzm%Ko2Jv@g@hS$OJ_b8vf@RKiEE2PE7t zdC$)R^rKQTUJF=4?+d(Iz=VTKs&_V3OP^Nf(R%5wqJ@CpDqcdh()UAa$xhG@)oUq1 zdY}%^xh$wf`bBUXC8gH`J86$JB)8K+;F`eqQ3_+$0(N=p0H2i^j>&y^r6A@K3muj| zsb>HmDbCTDSh9sq=||{J=^EcHNXzp|j!sAq6wRa0*-~xsZJ7LX|DAxpQ|h2f8shGx z*R%%#&v_rB)6)0pLGZZ*ospjQKTT()I{mxg{6u>J+i{KeLBQ`6JxHH}5ys-Xxx-qy(`cS$EK}l2!_>8{iZ;)E(v#230^h_v62ZcWl zlI4|v@ACEm-j9mvli9Cf`8DqzsaBG0^&y%izf!bMnlC>bxJi1MI*T)aKky7mDH@lL zN=xK>i|+v3?#t23bl!6hdcWhjPhwlwVtKYcDXc$DP0Cs6G$oa%0S_zB0-jUOiIL|4 zD}4{)EA1lnpQK@7WDpXNe+hX>=ua3rJD|u3IWGI9<<7wgET4|C0JZAlO55r@?&$#@C(9h+wF22csLAJwq zfAfwUmN;1wLbOldVTlvRC*bpPRww0oIS|y8TIoqxpP)Y!1(XDx1U^eD4lV?r15qn+ z8rDk7)g{V&*tY`kZe@kSeqF7crnqk-@L`#~)vj(+PQ!k+2_2Q{Ze@v7t?X0Iz_GY8 zQ+Mb=z?Z!@DJLLkQ29{sKcuZicPMYlL-IY!m~?yaKJe$tCzZG5Ez*|&2en5rey;Wn z0mlK4YTpK2s64B@@7n!_@_i*pF9lvzW{|x;^c!VZrm2oY5 z1aJwUPS?@^;B}M*tf#}O58qqf47h{F0GsJkfbDcQU?&~Nm_fQ9Fb5y$bcDXBUWv!n zZ{j!#&<%i5>H(Z%)2*I5T7U_4cse|;_6WSk#h20Dp8qO1zZOuDc;o^B_bD~NPbthP zrK{*(`YPTpE|;35Ug;L;r1VAU4QaW&TJDxD`KWBmx6A(`e;|jI{mLQb$BG9PmFQNV z-HZxvhdS^DJFcIo@|F1J{sHgrq+j83>ZP7y43m76MXTXQ08t;)Yv|Yf1(Z}v&uiS) z(KuRl6cVR>s&J^`6r1?Gt5l}@v_1ARkTm-o>%A-(!9jI5>|DJ!?Hn(EpXUb}H! zS6ABXNv5r8YE1QH+fB>dpIfmzm8n@p5TD7Rt#3|r)$XosZP?k+*49>WxQ8>wyB${7PI z>a)qic+xJktLkZYTUSG8*N)mf4Xq9Jw5_Rqd&8bCJZ*2?y#pO>?R$1KP;GN_*Us9; z2HLf~>w0Qzsu$X}HtisLVnSD4d+QF-w>z=3uw0@^aN4#dwzN;m?yB9$kVo z?rdvjU$hJ5JE^r{Yoe{abx#-c5v)CU)OSp+Pv(-eC2J1UW&?fQG+_0Z*>tKqzkX@O z#@(6T=B(L6Y-nw^huZtIMzWWZy}eyK5L&A3?G@5m4To9RZ}c26dh7a=nLeX8e{o4{ z6FbjklQjiz$XG*Jqb--r=7t6vGRf{VWblA`a|rn6q5b=fEMzQP6}vvwOZ`xV>e8vf zZZnzfrB(x3+hfqSRIed4*lrBhnZQ{>?NH8aL%J9Um&0irFwI;)LX|IBJ;&xT&8Z_s zx@rG@;9^w6k)HGrMzbRl1Ia#vdd$J$TFb%PjGTjDo8;PhvWAhd`c0R|&T)F#)<*0B zo}S1YG7lJJ2+JtJ`^>c1N)qeuN?9o;c*?e9rWYtL?V|9X;H1*&R--2eZ@NR_0c^ZU z9Y~pPRXKcwP2Mj{|jrJ6fI&+{ql|h@v z?q+DAQ>YEyph-g-?gtN+p%C<98r2(VqmL0@6#KCkWgy2iFFBRwfnc+>yVd?w&dASS zGt(aEHhO!F-r5{qSalDfA1VyOhU``&V`L#`O4r1o4tDPZ1r@r7`uflE=h+|?K%A|0KKoXf=<4DtfVSIC@kLs|8at7B)M10-=v)p>(Y%fHH z8Ztd5hbaHYtIBPt<-F3PwxMoIyxgN+5f~ntvfAL>o*d)T>k{=I-f0}(VWI;foNx#V z=1rwgyz5ch@f!z@Poo7nCIY-UJ7o1!W75v`Q;N4lGi;>6OrK~WvE3LL6gbL%P9W2_ zhhP<)O0JI)Gh{Y26dre}W+Nj+?nPl=zEmce76dEX4pq4WF_?M; zlUs*2n@2=4PK(;XLBvAr z9YOEFfy^68C_X_r-b!Tl!%I$gEi%&;G2z2W|8d6Je3W9#x-O-is7hk@)tTu6Z)#Wu zrto(g-P>>?akwYOa{7pKrP;J_X~E(gv*{d^dt=a5%+7Uf9?In~u5~Cgxy|d%!_OjoMN%K)Tv)Ghoc35=sTv0GO1`9HQv8D|fySFYmi2F{);C4cL zCN`&X18CaPh5?8OZ^pJU%?yH$i;tVBVoDv--8hnKG%`aXeW@*H4pPEOWZWYb8H_3- zPFrUUNK0helhy&dJDEkfHvpRk4J3FP{&W~FZcUtc1%`o|mL*|P!y%kV&bgJPX5@5k z8V7!wM!RPZpEy~v_|9lsmP6GIWwVgQ`w{y%ji1=CGr+ZgPMF(f3}O?*vs}~~GDDCf zs1@vOTG1mKREp+Y*1h4lH&7aydLO0QZc8NcRy&&<>`(Pr6V)@7?8}%|ZVC&Dk%Pi3 z3g=TB%1{coUH9}s>E%m=#Ts!MSg7B8BH@tddcX%UhT^E^AX~V+BztSq>CMAA5RImd zN+w)Xo5hzllO7ag!F__bcH`=s~3vAw~T*fABamu{4f_H%B zo;-YWgT`D9EWQfZla!mkqDKVR*%(;Qxz(VW6ga$;v-K?6Z^8W3{uIguIpKmGxHn>w zP^k{OS~PJEw(9|v zH)V%HW- zY-gMuD-ce8ffQ=KAh3-Kt?T0Y!Bp*G*59yhvfMfVcTU`1xhA+YpU6{4@n9xsJ{|j2@5kr+`JBKRGQ8c$pQxF$esj_?ChDG>ZIg6iFrG)l z7WI>f=lnsuhRRX@_>JpUDEU*@ek*_P+Lt5I4)D|HPf{=56yp5Jzjw_O`BT@l;?4K) zFPd+d`{m=?9=`Qof86-Q3%B4mh?1n^g}LMb5)KPE7cb&uyqFDnNDhTUDoHX>DUu9% zy=q97Begs$r16Z=FEcLVC3|G_F;7gED#`;fB{KR{C{i66J&Q3q2p$?4wa?g(9^w>ohi#4GC2UD63FJ z#*&dnJK^!N@_` z;b=~SRl{S893hMF$_)fO$DRQe48&m0LH4C1H%gjUi7aHT3MxUPA&A}JX9dQV^GHWp zwGTof2j_-IKk4x*umoP=Okqba(!BW3C}4Rd1Q2U9GHA)aR$FB|vm4=9%oK#%j0wvl zV=c^#jCDB89t~dNH86f`Z;{u_1Z%-Ol7S$oj`rcb5wDKHiOA>)^a{O)I94qH;RHJ_ zoUrkR$8mx#3>aIE(T+|AyCrfkoY1))Th3FkXbRhf(>F@+y(}sCA-FFx5~-N$nd=GZ zdL$;YBr-N2qRKl7e24;^>w*6xV?&q?97&;v^2e_$TRS#_U---nkB%X9kqy2W2|P+( zmj`{Z+TR`h#I9MZe|e|=#HKDg{4@X6`JoMITjl>3rSgAYQ2B?U>h-7?cpnI$GLRYI z6&k7U;8)ZT1dQ-%3*QuLx}rsv;BUFCh0s*vZwCI>;BP(tHprS!*2+~4&Qmn(LQMv@ z5q~9KH=PvCj+BFe?W4-&y3dCYphXDeayDOqut$R1c6*$~oUnaEG*5oy#&(aRAk zM6Fz;U`1r~PWCz4&$#XVaFSG^#(Cq%F-Mo6JAdZ!H?Zw;X?}cj*$!~=B>+B)`3rFV zDydyA!ll7H+=yc>HHb(1cG;K6^c&d}o|6gV@f{a`UQ9YI!wZbZPRuWr&gXx-Igt<5 zhw!Zdjq=Yxj-xHlpRJ#{)rWP7?jRcFl}@3>mM8oaWt9DW9<2xMMYQ4tBj({9C6%LP z#qs0YQ6JiE`IqXiQlG}u{Q3GB>Z_O|5FLXA@*;l8Baq+Yt1*GB4!cO_Ob40ud*|y@ zh%0=c8mj&g2rpB&;ak`Isrnhxqk??HCG$V7FE3hm6=vK@^c34N{^7P~rJ^6+h7*8I z;?MX~*GJ{h#ZTft78F=Ces0GVa&b8<|Jw;3jlZ??G1>pqyNKqq8)*EmTb3$5{T}=% zhUxKdx7R4X`V+`{_Rjd*yXUC>{`=uib_%|I`NRX>5*Yw@l^b4#g@f6pJ|&E2|R!XF{IGT6$JE9j$lpwtd|{3}~FOVZW(x3~64oAZs^9uI7Loai@_7@YsO gRXcvt`i6x6oBI>rKJmXb=)LOk@S%656Dz&{8{1^gYybcN delta 14930 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 a2;%>8J{8zW@;7pc=Ht