aboutsummaryrefslogtreecommitdiff
path: root/src/guiChatConsole.cpp
blob: 5bb80bbbe1b8c44931d5d7f2725f310b5bbcf718 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
/*
Minetest
Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "guiChatConsole.h"
#include "chat.h"
#include "client.h"
#include "debug.h"
#include "gettime.h"
#include "keycode.h"
#include "settings.h"
#include "porting.h"
#include "client/tile.h"
#include "fontengine.h"
#include "log.h"
#include "gettext.h"
#include <string>

#if USE_FREETYPE
	#include "xCGUITTFont.h"
#endif

inline u32 clamp_u8(s32 value)
{
	return (u32) MYMIN(MYMAX(value, 0), 255);
}


GUIChatConsole::GUIChatConsole(
		gui::IGUIEnvironment* env,
		gui::IGUIElement* parent,
		s32 id,
		ChatBackend* backend,
		Client* client,
		IMenuManager* menumgr
):
	IGUIElement(gui::EGUIET_ELEMENT, env, parent, id,
			core::rect<s32>(0,0,100,100)),
	m_chat_backend(backend),
	m_client(client),
	m_menumgr(menumgr),
	m_screensize(v2u32(0,0)),
	m_animate_time_old(porting::getTimeMs()),
	m_open(false),
	m_close_on_enter(false),
	m_height(0),
	m_desired_height(0),
	m_desired_height_fraction(0.0),
	m_height_speed(5.0),
	m_open_inhibited(0),
	m_cursor_blink(0.0),
	m_cursor_blink_speed(0.0),
	m_cursor_height(0.0),
	m_background(NULL),
	m_background_color(255, 0, 0, 0),
	m_font(NULL),
	m_fontsize(0, 0)
{
	// load background settings
	s32 console_alpha = g_settings->getS32("console_alpha");
	m_background_color.setAlpha(clamp_u8(console_alpha));

	// load the background texture depending on settings
	ITextureSource *tsrc = client->getTextureSource();
	if (tsrc->isKnownSourceImage("background_chat.jpg")) {
		m_background = tsrc->getTexture("background_chat.jpg");
		m_background_color.setRed(255);
		m_background_color.setGreen(255);
		m_background_color.setBlue(255);
	} else {
		v3f console_color = g_settings->getV3F("console_color");
		m_background_color.setRed(clamp_u8(myround(console_color.X)));
		m_background_color.setGreen(clamp_u8(myround(console_color.Y)));
		m_background_color.setBlue(clamp_u8(myround(console_color.Z)));
	}

	m_font = g_fontengine->getFont(FONT_SIZE_UNSPECIFIED, FM_Mono);

	if (m_font == NULL)
	{
		errorstream << "GUIChatConsole: Unable to load mono font ";
	}
	else
	{
		core::dimension2d<u32> dim = m_font->getDimension(L"M");
		m_fontsize = v2u32(dim.Width, dim.Height);
		m_font->grab();
	}
	m_fontsize.X = MYMAX(m_fontsize.X, 1);
	m_fontsize.Y = MYMAX(m_fontsize.Y, 1);

	// set default cursor options
	setCursor(true, true, 2.0, 0.1);
}

GUIChatConsole::~GUIChatConsole()
{
	if (m_font)
		m_font->drop();
}

void GUIChatConsole::openConsole(f32 scale)
{
	assert(scale > 0.0f && scale <= 1.0f);

	m_open = true;
	m_desired_height_fraction = scale;
	m_desired_height = scale * m_screensize.Y;
	reformatConsole();
	m_animate_time_old = porting::getTimeMs();
	IGUIElement::setVisible(true);
	Environment->setFocus(this);
	m_menumgr->createdMenu(this);
}

bool GUIChatConsole::isOpen() const
{
	return m_open;
}

bool GUIChatConsole::isOpenInhibited() const
{
	return m_open_inhibited > 0;
}

void GUIChatConsole::closeConsole()
{
	m_open = false;
	Environment->removeFocus(this);
	m_menumgr->deletingMenu(this);
}

void GUIChatConsole::closeConsoleAtOnce()
{
	closeConsole();
	m_height = 0;
	recalculateConsolePosition();
}

f32 GUIChatConsole::getDesiredHeight() const
{
	return m_desired_height_fraction;
}

void GUIChatConsole::replaceAndAddToHistory(std::wstring line)
{
	ChatPrompt& prompt = m_chat_backend->getPrompt();
	prompt.addToHistory(prompt.getLine());
	prompt.replace(line);
}


void GUIChatConsole::setCursor(
	bool visible, bool blinking, f32 blink_speed, f32 relative_height)
{
	if (visible)
	{
		if (blinking)
		{
			// leave m_cursor_blink unchanged
			m_cursor_blink_speed = blink_speed;
		}
		else
		{
			m_cursor_blink = 0x8000;  // on
			m_cursor_blink_speed = 0.0;
		}
	}
	else
	{
		m_cursor_blink = 0;  // off
		m_cursor_blink_speed = 0.0;
	}
	m_cursor_height = relative_height;
}

void GUIChatConsole::draw()
{
	if(!IsVisible)
		return;

	video::IVideoDriver* driver = Environment->getVideoDriver();

	// Check screen size
	v2u32 screensize = driver->getScreenSize();
	if (screensize != m_screensize)
	{
		// screen size has changed
		// scale current console height to new window size
		if (m_screensize.Y != 0)
			m_height = m_height * screensize.Y / m_screensize.Y;
		m_desired_height = m_desired_height_fraction * m_screensize.Y;
		m_screensize = screensize;
		reformatConsole();
	}

	// Animation
	u64 now = porting::getTimeMs();
	animate(now - m_animate_time_old);
	m_animate_time_old = now;

	// Draw console elements if visible
	if (m_height > 0)
	{
		drawBackground();
		drawText();
		drawPrompt();
	}

	gui::IGUIElement::draw();
}

void GUIChatConsole::reformatConsole()
{
	s32 cols = m_screensize.X / m_fontsize.X - 2; // make room for a margin (looks better)
	s32 rows = m_desired_height / m_fontsize.Y - 1; // make room for the input prompt
	if (cols <= 0 || rows <= 0)
		cols = rows = 0;
	m_chat_backend->reformat(cols, rows);
}

void GUIChatConsole::recalculateConsolePosition()
{
	core::rect<s32> rect(0, 0, m_screensize.X, m_height);
	DesiredRect = rect;
	recalculateAbsolutePosition(false);
}

void GUIChatConsole::animate(u32 msec)
{
	// animate the console height
	s32 goal = m_open ? m_desired_height : 0;

	// Set invisible if close animation finished (reset by openConsole)
	// This function (animate()) is never called once its visibility becomes false so do not
	//		actually set visible to false before the inhibited period is over
	if (!m_open && m_height == 0 && m_open_inhibited == 0)
		IGUIElement::setVisible(false);

	if (m_height != goal)
	{
		s32 max_change = msec * m_screensize.Y * (m_height_speed / 1000.0);
		if (max_change == 0)
			max_change = 1;

		if (m_height < goal)
		{
			// increase height
			if (m_height + max_change < goal)
				m_height += max_change;
			else
				m_height = goal;
		}
		else
		{
			// decrease height
			if (m_height > goal + max_change)
				m_height -= max_change;
			else
				m_height = goal;
		}

		recalculateConsolePosition();
	}

	// blink the cursor
	if (m_cursor_blink_speed != 0.0)
	{
		u32 blink_increase = 0x10000 * msec * (m_cursor_blink_speed / 1000.0);
		if (blink_increase == 0)
			blink_increase = 1;
		m_cursor_blink = ((m_cursor_blink + blink_increase) & 0xffff);
	}

	// decrease open inhibit counter
	if (m_open_inhibited > msec)
		m_open_inhibited -= msec;
	else
		m_open_inhibited = 0;
}

void GUIChatConsole::drawBackground()
{
	video::IVideoDriver* driver = Environment->getVideoDriver();
	if (m_background != NULL)
	{
		core::rect<s32> sourcerect(0, -m_height, m_screensize.X, 0);
		driver->draw2DImage(
			m_background,
			v2s32(0, 0),
			sourcerect,
			&AbsoluteClippingRect,
			m_background_color,
			false);
	}
	else
	{
		driver->draw2DRectangle(
			m_background_color,
			core::rect<s32>(0, 0, m_screensize.X, m_height),
			&AbsoluteClippingRect);
	}
}

void GUIChatConsole::drawText()
{
	if (m_font == NULL)
		return;

	ChatBuffer& buf = m_chat_backend->getConsoleBuffer();
	for (u32 row = 0; row < buf.getRows(); ++row)
	{
		const ChatFormattedLine& line = buf.getFormattedLine(row);
		if (line.fragments.empty())
			continue;

		s32 line_height = m_fontsize.Y;
		s32 y = row * line_height + m_height - m_desired_height;
		if (y + line_height < 0)
			continue;

		for (u32 i = 0; i < line.fragments.size(); ++i)
		{
			const ChatFormattedFragment& fragment = line.fragments[i];
			s32 x = (fragment.column + 1) * m_fontsize.X;
			core::rect<s32> destrect(
				x, y, x + m_fontsize.X * fragment.text.size(), y + m_fontsize.Y);


			#if USE_FREETYPE
			// Draw colored text if FreeType is enabled
				irr::gui::CGUITTFont *tmp = static_cast<irr::gui::CGUITTFont*>(m_font);
				tmp->draw(
					fragment.text,
					destrect,
					video::SColor(255, 255, 255, 255),
					false,
					false,
					&AbsoluteClippingRect);
			#else
			// Otherwise use standard text
				m_font->draw(
					fragment.text.c_str(),
					destrect,
					video::SColor(255, 255, 255, 255),
					false,
					false,
					&AbsoluteClippingRect);
			#endif
		}
	}
}

void GUIChatConsole::drawPrompt()
{
	if (m_font == NULL)
		return;

	u32 row = m_chat_backend->getConsoleBuffer().getRows();
	s32 line_height = m_fontsize.Y;
	s32 y = row * line_height + m_height - m_desired_height;

	ChatPrompt& prompt = m_chat_backend->getPrompt();
	std::wstring prompt_text = prompt.getVisiblePortion();

	// FIXME Draw string at once, not character by character
	// That will only work with the cursor once we have a monospace font
	for (u32 i = 0; i < prompt_text.size(); ++i)
	{
		wchar_t ws[2] = {prompt_text[i], 0};
		s32 x = (1 + i) * m_fontsize.X;
		core::rect<s32> destrect(
			x, y, x + m_fontsize.X, y + m_fontsize.Y);
		m_font->draw(
			ws,
			destrect,
			video::SColor(255, 255, 255, 255),
			false,
			false,
			&AbsoluteClippingRect);
	}

	// Draw the cursor during on periods
	if ((m_cursor_blink & 0x8000) != 0)
	{
		s32 cursor_pos = prompt.getVisibleCursorPosition();
		if (cursor_pos >= 0)
		{
			s32 cursor_len = prompt.getCursorLength();
			video::IVideoDriver* driver = Environment->getVideoDriver();
			s32 x = (1 + cursor_pos) * m_fontsize.X;
			core::rect<s32> destrect(
				x,
				y + m_fontsize.Y * (1.0 - m_cursor_height),
				x + m_fontsize.X * MYMAX(cursor_len, 1),
				y + m_fontsize.Y * (cursor_len ? m_cursor_height+1 : 1)
			);
			video::SColor cursor_color(255,255,255,255);
			driver->draw2DRectangle(
				cursor_color,
				destrect,
				&AbsoluteClippingRect);
		}
	}

}

bool GUIChatConsole::OnEvent(const SEvent& event)
{

	ChatPrompt &prompt = m_chat_backend->getPrompt();

	if(event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown)
	{
		// Key input
		if(KeyPress(event.KeyInput) == getKeySetting("keymap_console"))
		{
			closeConsole();

			// inhibit open so the_game doesn't reopen immediately
			m_open_inhibited = 50;
			m_close_on_enter = false;
			return true;
		}
		else if(event.KeyInput.Key == KEY_ESCAPE)
		{
			closeConsoleAtOnce();
			m_close_on_enter = false;
			// inhibit open so the_game doesn't reopen immediately
			m_open_inhibited = 1; // so the ESCAPE button doesn't open the "pause menu"
			return true;
		}
		else if(event.KeyInput.Key == KEY_PRIOR)
		{
			m_chat_backend->scrollPageUp();
			return true;
		}
		else if(event.KeyInput.Key == KEY_NEXT)
		{
			m_chat_backend->scrollPageDown();
			return true;
		}
		else if(event.KeyInput.Key == KEY_RETURN)
		{
			prompt.addToHistory(prompt.getLine());
			std::wstring text = prompt.replace(L"");
			m_client->typeChatMessage(text);
			if (m_close_on_enter) {
				closeConsoleAtOnce();
				m_close_on_enter = false;
			}
			return true;
		}
		else if(event.KeyInput.Key == KEY_UP)
		{
			// Up pressed
			// Move back in history
			prompt.historyPrev();
			return true;
		}
		else if(event.KeyInput.Key == KEY_DOWN)
		{
			// Down pressed
			// Move forward in history
			prompt.historyNext();
			return true;
		}
		else if(event.KeyInput.Key == KEY_LEFT || event.KeyInput.Key == KEY_RIGHT)
		{
			// Left/right pressed
			// Move/select character/word to the left depending on control and shift keys
			ChatPrompt::CursorOp op = event.KeyInput.Shift ?
				ChatPrompt::CURSOROP_SELECT :
				ChatPrompt::CURSOROP_MOVE;
			ChatPrompt::CursorOpDir dir = event.KeyInput.Key == KEY_LEFT ?
				ChatPrompt::CURSOROP_DIR_LEFT :
				ChatPrompt::CURSOROP_DIR_RIGHT;
			ChatPrompt::CursorOpScope scope = event.KeyInput.Control ?
				ChatPrompt::CURSOROP_SCOPE_WORD :
				ChatPrompt::CURSOROP_SCOPE_CHARACTER;
			prompt.cursorOperation(op, dir, scope);
			return true;
		}
		else if(event.KeyInput.Key == KEY_HOME)
		{
			// Home pressed
			// move to beginning of line
			prompt.cursorOperation(
				ChatPrompt::CURSOROP_MOVE,
				ChatPrompt::CURSOROP_DIR_LEFT,
				ChatPrompt::CURSOROP_SCOPE_LINE);
			return true;
		}
		else if(event.KeyInput.Key == KEY_END)
		{
			// End pressed
			// move to end of line
			prompt.cursorOperation(
				ChatPrompt::CURSOROP_MOVE,
				ChatPrompt::CURSOROP_DIR_RIGHT,
				ChatPrompt::CURSOROP_SCOPE_LINE);
			return true;
		}
		else if(event.KeyInput.Key == KEY_BACK)
		{
			// Backspace or Ctrl-Backspace pressed
			// delete character / word to the left
			ChatPrompt::CursorOpScope scope =
				event.KeyInput.Control ?
				ChatPrompt::CURSOROP_SCOPE_WORD :
				ChatPrompt::CURSOROP_SCOPE_CHARACTER;
			prompt.cursorOperation(
				ChatPrompt::CURSOROP_DELETE,
				ChatPrompt::CURSOROP_DIR_LEFT,
				scope);
			return true;
		}
		else if(event.KeyInput.Key == KEY_DELETE)
		{
			// Delete or Ctrl-Delete pressed
			// delete character / word to the right
			ChatPrompt::CursorOpScope scope =
				event.KeyInput.Control ?
				ChatPrompt::CURSOROP_SCOPE_WORD :
				ChatPrompt::CURSOROP_SCOPE_CHARACTER;
			prompt.cursorOperation(
				ChatPrompt::CURSOROP_DELETE,
				ChatPrompt::CURSOROP_DIR_RIGHT,
				scope);
			return true;
		}
		else if(event.KeyInput.Key == KEY_KEY_A && event.KeyInput.Control)
		{
			// Ctrl-A pressed
			// Select all text
			prompt.cursorOperation(
				ChatPrompt::CURSOROP_SELECT,
				ChatPrompt::CURSOROP_DIR_LEFT, // Ignored
				ChatPrompt::CURSOROP_SCOPE_LINE);
			return true;
		}
		else if(event.KeyInput.Key == KEY_KEY_C && event.KeyInput.Control)
		{
			// Ctrl-C pressed
			// Copy text to clipboard
			if (prompt.getCursorLength() <= 0)
				return true;
			std::wstring wselected = prompt.getSelection();
			std::string selected(wselected.begin(), wselected.end());
			Environment->getOSOperator()->copyToClipboard(selected.c_str());
			return true;
		}
		else if(event.KeyInput.Key == KEY_KEY_V && event.KeyInput.Control)
		{
			// Ctrl-V pressed
			// paste text from clipboard
			if (prompt.getCursorLength() > 0) {
				// Delete selected section of text
				prompt.cursorOperation(
					ChatPrompt::CURSOROP_DELETE,
					ChatPrompt::CURSOROP_DIR_LEFT, // Ignored
					ChatPrompt::CURSOROP_SCOPE_SELECTION);
			}
			IOSOperator *os_operator = Environment->getOSOperator();
			const c8 *text = os_operator->getTextFromClipboard();
			if (!text)
				return true;
			std::basic_string<unsigned char> str((const unsigned char*)text);
			prompt.input(std::wstring(str.begin(), str.end()));
			return true;
		}
		else if(event.KeyInput.Key == KEY_KEY_X && event.KeyInput.Control)
		{
			// Ctrl-X pressed
			// Cut text to clipboard
			if (prompt.getCursorLength() <= 0)
				return true;
			std::wstring wselected = prompt.getSelection();
			std::string selected(wselected.begin(), wselected.end());
			Environment->getOSOperator()->copyToClipboard(selected.c_str());
			prompt.cursorOperation(
				ChatPrompt::CURSOROP_DELETE,
				ChatPrompt::CURSOROP_DIR_LEFT, // Ignored
				ChatPrompt::CURSOROP_SCOPE_SELECTION);
			return true;
		}
		else if(event.KeyInput.Key == KEY_KEY_U && event.KeyInput.Control)
		{
			// Ctrl-U pressed
			// kill line to left end
			prompt.cursorOperation(
				ChatPrompt::CURSOROP_DELETE,
				ChatPrompt::CURSOROP_DIR_LEFT,
				ChatPrompt::CURSOROP_SCOPE_LINE);
			return true;
		}
		else if(event.KeyInput.Key == KEY_KEY_K && event.KeyInput.Control)
		{
			// Ctrl-K pressed
			// kill line to right end
			prompt.cursorOperation(
				ChatPrompt::CURSOROP_DELETE,
				ChatPrompt::CURSOROP_DIR_RIGHT,
				ChatPrompt::CURSOROP_SCOPE_LINE);
			return true;
		}
		else if(event.KeyInput.Key == KEY_TAB)
		{
			// Tab or Shift-Tab pressed
			// Nick completion
			std::list<std::string> names = m_client->getConnectedPlayerNames();
			bool backwards = event.KeyInput.Shift;
			prompt.nickCompletion(names, backwards);
			return true;
		} else if (!iswcntrl(event.KeyInput.Char) && !event.KeyInput.Control) {
			#if defined(__linux__) && (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 9)
				wchar_t wc = L'_';
				mbtowc( &wc, (char *) &event.KeyInput.Char, sizeof(event.KeyInput.Char) );
				prompt.input(wc);
			#else
				prompt.input(event.KeyInput.Char);
			#endif
			return true;
		}
	}
	else if(event.EventType == EET_MOUSE_INPUT_EVENT)
	{
		if(event.MouseInput.Event == EMIE_MOUSE_WHEEL)
		{
			s32 rows = myround(-3.0 * event.MouseInput.Wheel);
			m_chat_backend->scroll(rows);
		}
	}

	return Parent ? Parent->OnEvent(event) : false;
}

void GUIChatConsole::setVisible(bool visible)
{
	m_open = visible;
	IGUIElement::setVisible(visible);
	if (!visible) {
		m_height = 0;
		recalculateConsolePosition();
	}
}

BpN!JqFc)Z;Rj#˲Mw6Ic탃ݖm 6\ݽދǙ\䮤]Ml>)ģu𪪪Rh3ncŤUV bCUUU^1PΛ(PbBFNRy)N63sYXK9w1N!=_"|"E'eC'V)v+iq ,g YCJb>Y~,E(YE7 8/%s!]E׈,mm֤A_o^yW;QPH 328lRXh&q(G0R9J}fڲ1Եk@ &"Ƭȥ#3C,piÐ&5Ze f';XppIL `RxkM[lt 3X2C:Gyx `oV-E sQϥC[ևb V!gF7Đ;?(/F]Z] B%a"ڮj]_N+BRBs=hEvvL:ln&3c&;xݑЛ/XcE`Z$T6gtقF#Ӷ3 |I R%R) f1cBeUbxBnfH P'a!RfPGK}slMsxcIv1os۳ہX0HY/hB$i)kԆh j ']ѥ\lkuB؋-R3/cd2{›LCi"r>,+>ƓA=zƢ eEm6g}*4>?#S yI` 6CPAˡ,6 =_(OxMZnJğW<S=TskŢ2|3 'C" gt㖙N0ɨXaXabG6t x|:E&u)OraMzpg2(+p[Ʃ5S>{<Ԉ7ȃπ55 's^iGG}g34I5A>t|^B}H}?%;NjCX5S};.*GyU+Xw[>S "L}aW6D\)kv홀lu;P@!:K2hgSGMnKB$Sal% EI\WcʺxKK&$ ?E~Zb>Uő,b2,JgU`ur;T$Z02S=ˋSwc`]$ auؾ nPZ( b2D10xm矕QA$w,ϝ wǒN ѿHUOVCb(_/[˗dPp@+邙H4 iRUgrAOcE(Е6I_F8QAm-U MWm'5~DpZ`BSk1LBI@2]P$6fUYb0oy\tgHAĤ !uulj⻚pCNo6+^sa N.ȴ[YV.u3;|㓾OݛQCt~H:p;~2Ye\*Qfaro9A9Y3oּd)fmffo-QY>o%k!be7s̉C)HE6Mfa)i{`勴VZ6`D6灄 ŲϏPri2DCCzٛOӖ`L@cBfMDR%k:H]@!v8.KbP,Kͬ9xd9s_C<Ǜe2e55s7n{ bRu8Dx3kO!1&pcQA+ol5,1qdEyxez= yX|:qH1w(Hhk)k)0̣ 55^&{߄Pc,tmLk];a}/*}Z}u]_EiUy/Cdљ(Yށìwy$L D ߙ",l5+%(FKV2I$_kF0}#ߚjDFdg4"M!q &rl &E4iv9ӟܢA3Ja@$DY,',(b)kkHhʃ=r NIpȱg y3Kb%LL'miv"R}nR$]i&BXUD$-OتHȥMw{D;Kh zrpǹQO'e&eR Jն<-+L%ۛѵɣsx2qyHWA'H  ZǽJȑK9h 8$fv$!_tٍPa]%1#dLN.v酶Ԣx L JJϑ řfظX L̓6K/:"iHazrB vHA_ Zƪ+lAkK$mxJhikf,mNe\5~3 Y[*Ԧʲ3TtWXE*K#m&PPDbKVaT v"kCQ: 0Jʹrl9t67/V45q7VKzWo{&Qj"BHEG*^$X A1A=b>P*[Z?b1=4d[2_bUlZS4,!E !P,尒VHF"2@d,H=i%@ 0|(>3lonrZL ^jT7c^$3/=Їs*Jֹ!2D5Z \b99 8z_/g7SHV9|\7/zʜ[ɠhaN$lIn[ 9lkh m& ,ᲺdRQ)&S6Ē@ɨ̄RA3$5eWe7imh)(ޘ g߂t4 &K*]6NQ[l-h&QٌsP5ژRFE)# 4aF4wK茶b"|qbϓGrEӞS`F$fq[L={eWRƛ)1(R澤.H!'KOpe`"c-ubxF{P}$ސȽL&酪xyxc9`=Pǒ0wc$awqы9: #J879I9xYjE< v,GVB5P#9&s4^, %6]6ۆD=b8D6C tV*KXRR"&SI3Y;!hMm!pX 1 jpq;F _Ƹ UtlZș!m8vxpJKZ(vlߚf+2cYŨUĊ[i$a|Vضb_ZSU}jQ2J#9';gm_N&,`CA~2 Y(hkbfyz8{/TJ(( xIvߎ9|C1ĝ%B(ͮ:Ԓ*@@kmr5٤^5J@YPH`0,?Hv79<3i7>GjlDl*>3[?ҰT3l Oi3Np6fAoDh|ug="$]lt$`dJ;QxM܍m]aͰJT+eR0& !*i1(_8  Ě/1Lj*I(baT B*CF$8M-&"I*%3J U C|jʮ z|^i¡Q-.ғX4.U'} 1dJ/ ͹' F AyHcWzz>OR5R)sF&*n񻩋h!&,Vu r՚boDD ˸i߶$TeiK1naf$C0RlMܖs$߁ W3Xs BB#=/ֵVbZK@ h8ޖ2@W)6TC!8` O?~>6Ś,L*LZU=lꢔ<<VVP(EY6I"fʢ%JRR"&f Cڷo\#|_ke<&HP<E)J⊉`l>ᒇm z׆1Kd͜h0OYK?zpf=fb́$6L0VAСDF @:Zewe43%T~0 '03Wce2Kmfyd#񣏏pÄ9ςܓt?z%/`EUUGCPBܞ\H?-9QO:MӛC#IWډZGߏ2o;\K92TRjAN1iwwyxeX\JMs0 ],K~zFɔ/*wY{"W5$Rk7wIIEPWy^d٤u.h%j0EsO?Tc"ͤhrRF^[fLJ&bZeE9j tK?OƥE&G":vDYɃQ Ӌyg<.r挘8.l<r Oio/PG<1 з[/fɢӳ,\a,Y$ FcM-fyƃ 9<6V#8g&zhRiDg{+&9)N;"[?UbՅy571alX{Md$ kGR`ĩs<ѬXڌ*-l[HǴ׍X4Q!Cu qzmnhh;M8 )쀫<; -(aA1qiDq|Y*k2q, ێ/3e\>Yvt:x>aYFv bCB-ILY[}ͅ Pکo&jF C E&qp WT(I}< 6!,$<.S NͤN4 luK{|-G6rRjXoAP קdgk㞡,x[HɜTT++om2'fj3KSz %H`>#Ώݛ4%M.Xn{J7dLVsi4 9<((X{$=RA ѸS0\mF&jY#JVNZce Ѕ$!U1]j-$.zCNF1uRӦWdHŧXuրL&ޕM摹Is,~IHmgkRIi bҬ; kdQJ*}RB;CYbȚjIѼ)z{l]%JXFHWr>Sū {939--gC]6R]$ayDt~\8MGC8Tp,(@i0;ޑLHIUz1 1e2!43ͼn)riĘ:fES Ʋ&y2gdV3&5<d*k,GoBm 878$|m4#97"yI5{M4(*:x%tW"O}lu9(fMt;23`8"^GѸX`7nSM59iuuee5V^Vrmh-e6N$j* qh))vʲZڃ3O-K+ck(P]^]>媾Yeq`+64 !>,q{CCB{,;{TɤD挃:bHIi:^nK{sL!m2;;5c;rM.F̈́u]wv4Bъ-eeRLaŸM&Ei,r^\DTwܙ;rL[GBg~9_!ښM&]gėnJ%׻GX|y|Ռ8O,qٹ9%텲{5RF='):l.S{wi'~M};a >ԍ:0eX?m iKV:u Z$كtVw"XbA!rDY)Q;뫁uU&IU&BmB&rJw:Y; $ywLCSY0ocX)︞y%%^eZ"qo2(L/U.xw2'C'Il6]ATd@.Lѹ@蜓e g+)`~)_m$&'R$?A9pszt,y6[;C$@$'2b! Jj+9$ P P`jK̛ P!|.dmYuozI*Nl0yyQJoԲ 8dhS5 n-H40iyyC Z2.oNǰM(3 4"vtH $>.iUYAQaޥB최&OXn==Qg:Ք93[r-ѷ=@^Y,(/,S'DҔ XDP5oa&Ӳ)+L ,x-xZS2pld ׸SZq1-1]EJÝ*wI@$&'W45ۯkO cxK}3L0MЙ >1vPTͰIOUAT_X. uiE !tvyr`{>?\q̏,w;Sj'`ჽؖEWjIТ'CAUd& .jJ" m(.ˎ) e)D. ð`ZF%U )ř*\[,ffr,5|, >Ǘm_f[SKl&%N6=!YX-(ZK^ьyq31Z\L[TS4HD:ILPB_V _]xF[-l<~\݋iY$>W;읭y v)ythAN[B7[nxk;fa ?O~v`BىS7u"b`+m*7/áv7d"]_u9SVr8g. PYP{W2_3e8Ȝ8Hm !ǜ9|!s?Y7.=m9<2ڎIF03})9$= iѓ֙0e3 9l" ̳@ЪJbD h{잰6Q'X,,` 3&2}1D2eYg,;3K !Z1I(zhƕ =>x%* R 1aD!|\*jJE*3WGj.9 IMY;dȋPci u5ڠGBw/@v)1P;4cV7LB-2 [-(ߴi7cBXHstsTF ,2L,Dl<i['S2cМ fm8C$I 8A.Ȟ<ѕmIl{ d֜7,Ns`$H "3͋t8xc"eG ej 2\3 A3" BR'8+&r% lT+!DX05U{Ysg<30N4үFC=5ijXNٝf6&&bF CQ5nЙo:) fYR'4=$0ay *!^orzvn1L6 ʸ:4ђ+1FX- v Va, %`HBîC]T DX2`X*ԊO}$<> MkZIri{q\8 anoXYÁݍȮkjI#k"* 'i}caB,D>U4iXM6 XM $_$I%vҾq"[%nbYHEV`b3i&Ϋ`W[bZ65lldtKl:qy6ײu_'1eҖ+eQZ,iJR|Bڝ1A98=."4Sͺ=&U/oyCzLĠH%3R>ՠcdKgMlJL¡qS؈퍱?T2T"0@@g k#-&j R|qʢ| D=82$.gBqѸa`TK _͹X y-,;0[BOJ'H,翽!b'D/۾l 1oq GHb0v[%vme xF([p:K*Ym&YVu3'2s$~@s2ڥ#\X1 Jeb4QE?[_"KmyNJw#$gŒ7ڵiUaBkK4NZbynBbl 쥟I4|b(R40mpFPxGCol"{e 81%A VlJTVVqWah>HdzG|j!i+7e1^ xvhY䈰5P1#'qdw86C@պ)]x$JT%$ʢyOT=^1q8]C؍(JV%e4'[~3GLpD KZmԸbgl"S2?d"?JtəJ+1NdxSFs9On)Fl"{Dן84?Crw>{;GrNto20cm6urm)%&PPý[;JmoP憯?wW1{hPFqsQe4i9NoY4ɺu{p-3j 1W]!4NfwC3`W@?(59RՅ_V8""XAxhPB1,bcӥgjYfN_J6s)ϓ>nQRY`wU!Z\ˌH [-[?86M7ɸG^9Mr[nEq]4Qd 9o`&'4z3f,-A$\}3И'hmq2U3+vY JfNLGt:>lS ZqԏO %=)O>}ph=zvPOz"FLŦ7D2*#eT5vo&s>ke!#dhj<rFHԝɵ;Y>vFH3dufz|7 -XfO oNZ0wim.iÜ,ۓ`'l, Y1 8s86q 0p)68S'N g,KLp,,HȰHF :*M1%f[ i(1md²b9G#~G]X][UYO(i*jM{#Z7C9cMK2,$󦟮n2q@^UmēFOD%$H|4Ќ/ET [075BrIH) `?ma~J32VKyuS;Ppt\d r=y8Dtl`ApXLRUw1 \Rj[K-FU(KVdV14]xG,D1V1GqzNl mc-I *)kqb'4v3#_Lm@~@~I"G"2CxS?oBaI46]bvW+8\>;#<) %{4XRVi8Oom0:(`9&ygK>lBjFxL5IxE,TJ1-d'?ɳ:5fٷUkn..S!#(޷:oQعS\ ?F6l-,TUKm%$$JɿOI?(O0m3O?Xj7nP)D?&<4h&j=QD1S$2I(Lə$I)Tq97Mny8#Ռ9 6J)("5ǒK.\X/] O_IݑS r:ѳ/o;'{G{Sȟ?0JOby4-:m[ū 51P5 `1DWJDR dOR 3A1RcJuXȈdyeV>{ȻC쎭9M[7qe8g4FSǡbbjKV+nAf ,b$D檄| :F0104ߞt4djz () * # &4%*l$KrZ0L OM3`%)77Ɇf (S|LLfJI,Sh4݌qg2&D)F)EKKkBZrWoh13*NSPjiK YR~DGΟyǏP=eĞ,|w< CyQa;8֍?F~(A绚=zn`N}~ܜDgtcH*@w ljM>>1荠qClj >Z)*=Hjq9ӮC?ԺSp܄?Il|{׿S)Oaێs$Œ&ܩ _:wI›WH&ˆ1mjq s,8#ÛZ{cN8\Y:s4,ʌᇗ՘Z5e*cFI0QO,c9f 1XA,<03`0Oɞ{9v(5 *PxYA,hYB}(>)'ѶP'MԶlHڞ|#4ʉbLPc+&.C!˘rK9RMpCy ŋhIGG M桵1ܓ#F&"(QQEJ111Mݥ]YeM2]7nfinɩe6դaC̿8g1&8hCQT8j T|߈?z~zvyA&Mɽ4~)B ,Ӓ+ZZ$de0lJ`TATjZHNu`Y!3^]ٷNE)]DAJSf0EjK5),Ͳl241YUVŋT${p $))m1\(*c$Sjn)k. +椙FycGé' H&>ђGyN9187^kQw|RJlI$g,ICJoɪ"1;$55=˥<# 1|YÑA10! H#YG76o䛳IMmyGOX؉ȍ&ܦR|4&Glͬ4i[6n-[fF Q j+*"A@wtr|Ffb93I3[cSjv@`&)VkQ~ajRnZG.;#mc~3>p nN88F:LO7(rS9nQ>0X`s|ݹ<1I9rOn'~nGSr¼S)̶eWF?_Зc$u;6>JJR[-&Y,K%11e6j)VYIV~CrQ(r Z}wdKu}8ekm T?,qk:ch@@hmzSlqÛZ lc@N&qLo4nEʋU*J"ɤi)O*H:$NF5gVXƵrH34ɑ?b=J<,sg\3gee,c\l`ӻ$N*s9}@G2g2>=)IJKeԲK%dX1c%V,[7mFU fUnH{ͪr%[-JrbC? x)`;~#96~:>03rMa?J% gNR^e)Qooiq]m R?T)MdZ pcc-#xTpCL?f8? !#А}ތ "I.b~@ޓ1ôG#2Է:S_Eoϻ*ߧjVzz)$<ȩɎ2{O`+!چRIXIO5Gf$`SXRFt#=AR^?RFsP~<˔I$, B|d|ާoJ,:P};Aچd\h&K<;h7vޞ|ޝ*Jg3~kᾄy"0SFS)E)  Ag_U-_z&Wk 4 Ca%-3uF1Aq8BgG1CĎ#՟=遁O\N)oO6;#M`9)`RRR)$qӘ#ކ91Ij@jS$ԜȔM*UUUć m ' #}$~C<ن &S*a7CujtCN= ]ҪϚ}#`x=@ӷ 'ZO~2Qhdpc8Hn ([y>*ZЭs$܈,( a? @go6w1+&L4C($=1e?i'k4B40a'':n?/byw,{S$e / pEa))HIȱ#dfL6Sݜc4F~9,9֓ x(*r3y<L`yA04Prӝ|gqw^-l:͢x3؟PS"qGY14x$瓟93 96Do<Lz|WVОl\A }6DDf[׻z$^]ٙútwc1&(XSi0o >}?n[m+15bAYȑ1hd",ziU# +@Z jb-{-i[nkII%HY1&)#mmO{N:d~›$.i%,&p*RSȘ?`0JUEEWDaf3SI32`ά3' JDD10DLL0ުIL S#@aц *faZS3$Rrdg*TƉ!jԞVw-)|x:kH?g=?c-Z;yj2Z3$c \cɁηRh)dյw],_F^GҏR7C8;p'Lh3q~;ꦴ4cOFih0űS'xd9Ac:5Lw}I;ػi&ȍRef=*X0 =d&C&ݙn۶5L 6amI̥R23C#@d13dsBkL)hݲ%5<V'X7#N7IH{G}*ѭm+`Y1înͮw&vs]wasն֔iJ~P?gΉO!C"?t?|?凮DI&}:(ԱÜ ,s+M#/^-YV0&,0&Lx&H)ϟ8JJ!H0ю d#&?(rm[V=X~RSUѪZ0UYFGf?x}3hٌ8eSqc~RT%%J,$2>*|O &'?(Li*pO}YNFaMP~#;Nފ F(q,fiM N}8c 9"(yD>W_t=yarP}"ѡP4!y9Ko"yljb"}؃ↁ8cnpr%y}̔UM3Dd}rvI~Y-Rʱw^0F!nztwÌS9ߙI! '<ƬԩGXiGz"C< B{TB#; .1gxߠ|RfjM?\h扉?9Ժ:Tqc l:qӦij>(>ԑ+U1vG`Q9Ǟ0OOI3l#k6ē Yk٧ 5"Hs4[m={ XO*fItM^^рvc5`xٶʫmC;% IJxlf17''8lo{?/z"\EՠD)#œVdw9⎘<ڕO) sa՜R{S@=ć >" |©O.2GpA0W?ɨXNgpfs;A&ygYW#دd-,-Z՗mR̉bY>8뿲ۭFbh3K6uGe2ܺkv}cS!8Ì>$̢j&$Z,АGS*46Dz֕F-^u$)0FQ 1,|;.hSOa 5;C }07j$'\q=è# e9N6#! wn{|]T)rYkUBzkEi)yTb5/VQ%a"UD]EMXj=L| XzFa3cS<)M$i8G6)#|8O~8FS՜ڛd`5vf7n+vM_+"KxIVe*%gguV)7醄yzZ}ϼmFNVbj?8{i*ڶݥkRe B`k"'* Q 7)Ȏ)ʕ3 3nj]3)|__d)~׏edEf:fMiie1*bf5Sgwv0~@H:/<8 H2: doY. ƛK,&N]"gsJt@O1󆹦y3߸GU WkKVF UcH؃>Q8B%`>O%%'lקhd0^7CHb8dӋ} (Bq"9N9!F74'((vO>j;׺>k!ӟ&$$'=Ygmg(Yvyt4sWDs/MV-Ǘ]8hM11>be9*za3%9`aFpC)d%Ff3#*C6a?yѼmW$DI.)YA-6b&SY$!?8sėȬel%Ra)FDY*I1i4-7퇻ŶTNOሓ&LY`<'[;Tm'߹VFneS(g7oeYx/m9M..N*G 8bU G3 ČM6 &km@Q sI` fso'ZN;^x[<6x_Jgp62ZNs߱J=jMdbI$(e2;hv>w?Q2$'T*}Cɓ~d0FcVN=7DZAť;C;{x[+F71= _pb iUbŖ,dGJqLyȏUه&iG,,,N5l4%,g#8s$r%cӟ! AhS14Y\NN?"v@RR>͛N4pR{q+&Nde V16` TAh z%xuK Sgʊ*JdhTXFkJ?(f3er%>)# zm۠:׉c:>ii?^~TYSٍc׎' %L 2J?Um 'bHQ"Iԏ,cfGMYNI>Jr`!k"ڋ[2D4z G5ӈde9NǜdY3(~0zš#R0d?fbpS8g3˳mշۚ I\=13}4=IV\Ɣ Ƭ{Qe6C&yʝs ɹP~pG*2L* 666B@ő43$9do+}T<1(kCYJTEBEϧ?$?y13"H46L$NUfm,Slr m`gL+*Z/Pn&sbB~z<4jMa J./p88^^F͍.1L $)labwɩ\cRSowO!C0&H,kEbSoroTbbwXk8'2nvG8'Dȣv7 RV~8FYLN '!TB4#B_pGGzlw;9eN7q1T0S9nD>{<xI:͏ROppnSznc,w?pwsG68ŮLqɝ6G(h#܏dG*qϠ;xN ̏ 8鍁G{񪫻ܳ|RE9 S 3|7rj[XO8Rm<1V2&IU VZg=G:ز|&yVrMIbK7Omyi>Ql}ӟ9*3Es& ,O&'@}ۻː[o@5~˹ݲdɓ3&L2~`jf~T8P4L櫓<)IJJc3S5%dY,1K%d5f_S}nf5- svaL9I9Z[^mmԯ_3Ḯ#&FM{Uy'$g$ Ep`ݙΔ4$̙)LҎYlTJ.2Abĥ7Y{{~On;?t:vgt㌍ٻ?@ ?(P᝼┢L8TS*EJT %"=w?0aF VL,ʲ;!o?P'BM $y̜cMgo4d0ն['??,H5 0eYb\[~̇!!R} 4=U= lI1$=I;PYY=qz<,z'5'hMYIǚ3ЖilL%4=D֚'JrrSz9bݔ52!EC$SFHhI ^tm\VwG~ҳY l* <`μIN=>~ޏ~x~yRO'BpdCJ^S QLS1sM()eaM SE^qJYýwŠp1)RNqt;-iPGE;ត``1~甴yciޝň `L7!it '_W_Ӿ|1*3D H$_*Y?B*J'.FNf$Fsƞm#ӌ0-5Xp&,,Z֖lI2S F4Uzj& TߍDoӂK4f.ޗ[OU,S l\5110`W45Svz=zvC@{D~^ԫ}#hmg?3 k7G&k/x_X;ַQ \c&JT%eRֲݯMsoffY`)EQYlM2&64M,oS޻y4,ujScJi3I2boTf޾5+DusFSSI7hQ/m.iYIeYO,}d8JRIMue*S"$TQJLa0Ȫ̝_84hib:4bdhكke𧑴:ZXhtZLM-[[4[M0ŋbly:tţ4`цIHilXb1Xahe١l6`hѴhli4$*g)MY ƢS?mYm#`fM:-g8c7ȩIQ+ 3L° 4;jնU>XF=;mSJŖ,U8"o)i|TߏZ?lգ:?6$NQCO%1JS'x5bYb $$bD0,5ZR(I7C'*vߎ5ǵ=jN0?qLhtȎ#yMNPIB<9\'}, HqeFt>˒:cxnFsTCQ,n1VXTQn͉eY$˺%U]4㹝̢VHfl2U[M#4J$,CiRSX͕W 5/,݋t۪Ͱ30C׻*7|?tvMX#zMFHڟ$mG-g9hӞ=PE;)5gƯwku%]7KOǜcܷvbIC6#PG2c @JW|l?_i^ھZd]ԑ1\FDgpcnn`s 544H⡦^ P{#C#Yd_308frNħѢX/ԍiXy٧\<]Jgzy3>XG`Ȍ`QSjml&fS z(ޙI34 &s2E0L93C#@hqShf8M5 3ɧVd1Tg rj33~O15?DoI2qRѸַX0%JܛoEF[C~P^Rg 9bgMҸqsbYvXg.HaƂh22 NIgeM Ȧ5c'# i#_opbcgc_&XQcj87s>xD'W~ן^o.Y4HRtxA8!@X}5!&>nhKq29Ս:Rzz?|9UjMF(o+߁C"F>y]_p+qGΎk II),$o)_4 0?)G6?x<ХnfT?de+>vm?'6 RwÛ6vxY:,̘NTW_#i9j:rk!@$CkuVݯȿҏ5=2`kHxk]FO%CiMS*5RZ:$t}#ah|ԖehS+KڵuvYV\eXh$%;_McdYb6V+~V{qqnE%LåM0NȬ:~᱌Km=,'.JNC?9Ur/~\}r`h~!!RY㸐 E[fksp?/]G[-me#)XR1bK,e10NϮXōhLr,V##XHx`BħEʊF(Ŭ-v4Z3:yTG `>Y>0Z~>j2Uۛsn,2DOnkƺx_! 4y8"DRInb}pG^Z)_sϦҥ_V̻7A9p}IXVr##xI=} ؟d9<۾᏶%2kl?])ƜN$r#`#p/fOMݵ Ѕjj5n="!u$Ǩۖ:dڌ_h'2&ry30|yZz.Z}دAh &(wQàNN8hh..1l#1Mtm Vfe3 5FcЎm~Q&8(d9CTwud mșqO +JVWZ-Zh4rIY%3hSKufϟMb229A)ύ?}3降RTc ~gj26fK73 GhTzSǿ?vtKd5&qcbT{Ț$|Oqqf=O5yϻ1ty>ɍ"YR07:M3w ϸf[{Jڵbe:fSH}|p ≘ɮr'J{>;>}a+*xSd fLΌ22YR,^(}3Ja2F}1 # V&F'˟4iGEyB ?4^fz"kْj!fdl<Rm> I"D42$1HdUI^Hd)Z(Ԛф:3r}%4=l *M%MѺ0S*fdz<5 g=C0dneM7jۄL&2'5i58kIITN;ux!,J:L w}w"z1R;e?~'1V7u%IQ00S$jYx%gK8=) #)R<5^bTb46EI FSPΛOLsS|slrNJ6P(kYIM7CxKVZ/Rr'z|Q̏^4-qg/pvW ɷuwqƸ$lbcxrxKmvndR;ի]uOvbL/(4Yˎ4&tڧenMA=s̰s\>#JDip18)ox6;Ȝ?i9Ӹ|LlVvVm~vI獖Y,lI:.gN]Y':Iǟ:ӌsG:S<#6Dvcb)駣0uӏ{v~t1zɤjYgG~`d۲V[A Wf_jBvnSCB. /."  ǒ!Q,ܟ')Zfm0oZk7RŖ}$m$ri:,Q:ï>ާ2s.r9'=;=a;ݜ wu=y?N@O~͞ z,=AO=gv;) ~Nwi=)vG7gYN͝dxc8t# y6cf6fý:2o3ޜyAkdzgxhCӉ=I${ǓyiK*W{:phrn\?cwOpri՟L> zⓀ;hI=O@~x9OSN E<`wCᎅ'q=p#}'➞uv<ɌO=rx̤%aEXUOaǒk& :#ۘv2\ 4`@}s5pj V>9YbJi ~)`-\0Va *kDԅb80?c))4 ȏ %/ B-YVRT)HUUeeUA/ *K* eaB/W]U&Ě\T CxLpwaUl24 @JTXCd a,J_e@q Q0C!0XUSpjfIC%.^j[پM<[+ 7jjQS`(UMB B U}PRO\luJ*66+*, Tºۓ$|~\0ɔߕ',y }(rn(SO=NIM:`w|R D~AяNOyU|$Jk8 ;rv{#:n'\4uvG=<ŶO?~ g5~TRDe]b,Ř>fc\̾mz;%^|۽Yˌ@g8~=1S0q~qt?x` ӾQI?YS θ7C;3>;ê`蒱2dX:[hbkyg`dpn I7u\6q Ik50n 4ԓƟ~P0<#NTB;!*>ht|;c?tG|:H|<>}#S> ۍ|i>Qډ\|;?j;$:cwAU8LsIkiiӌ=QϤ14J>~O&OLYlxg9RCM @{<lir[Lp7΃L1?Gg/cӭY*}h{q9Βv-r}hvz${Ǝxg(z@|ܧb9xK w:JN<{RwAGNJu[g칪/(}LP͝/QnMw70?,T:bGe;^ ?׾Kqfh??b3$>U. A,>ާ[|B|vUO;BwD9TM\i 4x珼>Dt`c#sByS;`õG w}d>8^xosQ|61fЎ;P|S蒦$;;z{RRa5چ Nx#79iĞO4w1>9\ݘ 'tv1_°ڏBMDplqp2[g>§3 $:r:c?$Zy1yf~'=՞G:~qOvf?|G'qOǟ#9sd|IO>9tǴ? y#Oݞ#y N rzs?|{W|=h} ߋ6LFR?wG=x *W2yaСw#<+InTANiFJONfIǝbn ?6$io|T8Es>e`w_|0VV{,eT7 eGߝ!ݣ|4k zz[lLf[xNTk"w0{:2S<@<ڪ͑]`$CAGrz'o_U5Xxf;)dL~ ?MC&>oM~*έ8_vkC/%ܲ~cO9M{}>rq>v1qjgHS+ysFdG\>r~ q0?ţ30tg3#&t2*CӚyDݏ'|?\8Xalp4h JOQ?K~Ʉ>3|¤ά0c#R|e> *Ixn[gS|3N\+F|&Xણ28;;'l2z4N3I>IǨʪ;۠~ 'H/'޶hO4s#[|_=g2!܏?=Q)Ye є\XV/~gPDI{ՀS^A .k j[9Im Px0.yJK^jWub/!y5d ;)k-$y[pk%5w s~ J)ej<>pP>/~K퍡ݒ#͎_%`g1o" w3T#0[( ;ZzZyϙHdibO]jNLvG9kϚ6 #= uGrj|.+w \52 K]NpxqўUSrCjrG~[Y5FG፱Ɲ>,q'2arlIMcӏ~%9 xeW)zڶSz[pl nzA#tGGѪN Ѥh79Ɓ]!0X{Wf޶a=;S5NP hpÍ. $Q?~(O 60 `~#OZġgNBb4(bYetS |o ǴN ȏQif5S6</4)hMtWU67Nhp#j:lGsRqǴУwj|T#8*rv'k%%'h9v##'oL:nd2$ۻmxpm=7$$GxɃ9=Xsdέ^\*# 랈{SdUdd22SMsĜNMsOB9ھmQ)ptt^18NQ7T#< BǴu9N3-e3ٓb30h*ugJx;ےUs=\7Ru̝w'09tcfGNrJm2M3fbwA8!waq=PǞh:@3qߜ\vY"9&PAI6Vr"!3`9PQme,.]e[#%Es1jkcwyƍxGG}\EIJ:| kI4OFߣhəL0j97R/~=er3ef{TU5USILķMp3rm~=#$3&F~OwhtbǜC8|7:Toh{s.x1O8<DSc^OhsL%ڂg9ÎEs9Û99srt#ؑE`|!A? K[Wp q8C֍ ' v)SɞjFN\]ƴk/T$Д5\iN8د~!0HKXVLdJ mpDDN:K`ZYICt8c#;j갭t@+L2eXf`9qdՏ.į, CD|!o?Tmm6K$@x eU{qLr^Rcc_w+rRD\FۂNLg†n8hN\v]G*i[6=?~[m7!pNzяFj[}{>|eTO^UMc ,\yt\ݧOè7ɾ,LY}δ9F#▫~Mtgx֬G*y#t1x,d[J80j;B_XjjM3γMDi\ha2zǜdUSZ"fdL5n*5 hNx=xK,p^=`z*^@s\U]` 2%:BʀNdrƥ6wzR1X.NwxNl ^IA 7*LzeV|Db/'NrN;m]m] z@؎Qj5,<@_ :۹w|L{#cs -?u12dYF4{< % # jwcǎ<8С-N0s¶&:zw-hb[U&=<ښu K"TTuged[\VDvz`.'oM;$PqtTsMA52[ fᆸnx H6]@ V6ץNI?JfBB E%$,hjmx@nL.c&a0x1MroHwٜswqFY dƙ{dV55UVLVu~UerOaۋm9vr2dɆd&q"wq ;5jbŌpCZ9HݛQЍMS;q+Mspoƨ񦓚0n ƫeUJht y6JܟGWD؀q:pKLsC2,|wdsfYɞi\huu}'єk롿$7iZLj BPx2?<("Jҧ*uG,39p;;cIg*2rDϽ B,-C>lվD(bsa~pኯ8|t)mY0%ZZRduI:؆iRĤFe)0 t)S:Yӎ&s n02mG&Cxt#dž?k1O)MTG> c8>ē 1RaTRʫ b@dBj-3&͙$K$l99ople[o>A4 &%U5s"L\ aɝW:{0q.28Rs1!7fecl2S&W4zI_?p|z:aO!?%,MRN|nOZrG,\*d 3*alg&D'杴~)g3M%F11ՆteJLloh' 'PcT{!0x}Q?8÷y-ʲ=FSpуA*-,5$ \:$1*R:t!ywdQ&ALbA8fTk)+͓55IMBRe JY)d4.J_8'rg%)JJ{ݏ0#}HMQ$&}ГVwQcȦ@l 6OLoz$IWb"I(E1,s-3dis.i)f笟>$U8OuBڣʍN;mIܳ22!O$ e+(d2U$[2J6%O 9ѹj6=sݒx-|}5TUkibZ#<&,Tz$XT᧓8iS|sQ8[Wk7 \\Kq1]w17cП= gr3b i_~6p+S恣% FH)()(()f(ȥ)(ɑpehe`٣F훺8n8,4hjV0a6aa  fbS4č^S*S)JٷRIR()FE6 L24P 1D!0` e2^F;Bd %BB ihae0eգV #ߟoQ djMQ$&umյm\$ Ac@2C)/ϯUhPuHz'"'0R`N]"?Q;P= MOF}FyAcrB7ߨ[mo8ONC);Q=H%$=AOS=a[Q ʵ+\JHYYf S!8c|ddpR N@!=Iޭ6qb@ A((8pdaJΑL*#~H&)~RūL²i1dfRH&ĔlXjB dś'D~@<˧~%LxrŶgp<(>>3X25YJ"pCxOh7 z:rz!6SX惘 51yNWtՋUV6#ד߅d":؇2>$qu:n~zz$&x\6A`Ԉ憬Um&*фD"RZYJ Jk@CIJRH fgc ?Lp%(`,wų|Ҩe *mE?>k7iNG8?-:Orf?<8}&?7| Iȥ8q#Rp'hajY2̡^K}uov?@C3mON! 8qenySy7וOI9S L@ /kτ㨫(UMHUCZVM6SEQQpf(-Bk̝%|3P:Q!Ο~϶?oE(srR˜)9ܛAq2>Fhb]mq~x " 2FZCڂVxb^M/j< ""D!RT݁6CE7+jڪǞyx\c~7)?Y휤񳾷S'Vj$Syi&n ؄(g7a61T0xGM\Uh?)T+WP5D0yd[Ǩ軀8{1tf.,*sSu#Q\kW&$IR?[)ۏsdaSX7bm ˓`Xv3"$i& Jt"T#b( Œ!F6MoCٙEG8oLN!Jg{+‡-\a,"o36f;'wZUT W=pq8LiZх Kj*?gќ(#:I=;|@Lg'M#;!MNTrG<:!c28#D~vV^r]ʱ+ BFhPRն58MA,II4),A`Jx"THxJ"BȈvb&)iN1'bFc1N' a@ڏO><`I?M;lwzyOJ#>!%(w~Ob|v {uǚvxm풵> چ쎐mxQ2%w}a#q9%7߉XYf;> ތ~=3ehg<(k1*bkmޕ Œ ߺɡ<$ԑ5Qk62fbApqIGqr&ϮXd̬.dg4$#! ?mgf#;v?pwvzӟ$>G(xɺ!_,~c5#Vٜ":,6k8`|uOklUǝ93T?hhqu,eW5IZis/dL3*& 7C}2QT2mdRE)*Y[T xmͩRT8>SYE"ӦșhL0y[v/+EіX@Fw< p)\eeDQQ D!H@Ie,$YofI]f&J2XѨ-Z1qijuٛ9t;.2-9lFLS$i%8EX:ZZ21-hBQ$@2[v20ˑK2ŌLF_1YVX勏%e-VF̎&b٥ܴՌe--ڱjFij4v8[VYyMI[jYfYEj qmdn2Y%r]o,T+V]2ŵ1ibŖG][ZY6k  [5V[]6ËV՗efj݋#.-U,nb1e.]-VXUƘ2Ђz=1WD=0~pC' `OzspfMd{tx^'-W!L}o=YYፂ[939+4"PF,ioieݶ3~7Y}uir嫖[ZXr˗.Frt#9,,v2,H4e1c)Yv#,ND#1%,M4ґYbDbD'%1g#,4ӄ35,̲uufeeefeݖ11, RY5 08' ⓣkc[Bqů0We_N;Tqi"2*#q+u۞cix1N܍$UO<7V.PeVrylj&l5O:O85dL'2y:rɑÃ10p1g1khmB.pr.\rnb=y/,s1:mu*5F@ |1Y›o#L'N=MA ?8liu 7ʌ & &r7G>ѐLI65 a ?m?ܦ}#$g5K_5ѐu㸞tY+M8n]:s\ϞJam*JeRcjnG6M$5M-=Hh3E9BIi6_"(EZ%Uŋ-{RMktD靴:HHڏqOxsǏ:sCD;xnSp4V3&3O:3 d>yNoNQξӦs->P=Ӓ9#;\n9ATjH J'NaX)iiV*Gʊ~"l䐇>Q#m ƅ*6|k&4 gψʮ^e (8 ,ZѲ#"|dybnISyllY&RY%5]MD))"ZNVIU)3j a ;?vOYWH(=86xCOݐÊtD:: $lI*O!WZ# &@20Gx99 l0$?.d`e6 # :F#Y'#6#ʊs9Lar0Şufh^uïxo of|z_5W{;4fHDbI$`x-ELj" S>AJqKWZ8I<C77$;"oF՗k $Ju2dK)NI%L9ЍWvlJ1j"oC5 Cw7skQ˾Uuy"%[zVZm--+F-LTQQj*II)Z䛹yQ 岶q<6.&$t퓸x6wk#a)<9E>ܛ$ $SYa5l4v-Ieq0Qh0 TNAP\Ϟ_bd ؛7Ld5[E-mmZjRKkmL6f[4?`=?[OI&V1I1o#L! d]Us-r:DJJO2&B0Gx~ =\>Pfsl,0c;!7ɟ?KW6$!6(hD%tSf2:\v5oL|~IK!D!.Bf61p41?{Yq]ftrh5ZHA_H<&mۨ#scA8j"p4<8͵(4 PN<%9Iӧ mEF U4x-:j(7WpjQiÖK!1ăFeV*EUiE71nLBYIda s^p(Z( hĺq-QKh06{ݑ^8N1*(br ^rsɑQ5sa{sR0jvJsbxR*(!/%Js1ÑL)i78s֫ Rw,klR2,F"#19qx k uy'9pAbOf鶦1E*R0.]uLݦ]a7He1e6ҔҔVRΏ0f0fk.S`QJRLJRף(dJHɶfF VIfH$J &R4£EQ4"(KL:18S D2# ~ֺeTޒ9Ab4hK=a?scz?Go@zS';I921U,d1GCaahF T`ƃjJd*a=I>x3 AMY > tC<me)0)G t~݈0`F*Xl Lٔhohğ襒'?zO?Xi40QP$9TݙΧj jVtLXBN *ڷ{ﺺI75b*-BʉK!aRm ?7;T?F,kؾX><ѠOR%#GnFLRqYNs:SȯoGNjpKv](vL8Fi e S^Lc8\pJ1å1QC1ޔLpN3ѥJ3]$  eEladx9(jtzty5zጜf'?Rllz3ɓgȏjRIh4jSt;22%.긹MC0>O021^Q,"D8x?8Z AlD(. 5I,g!5'qR׎"d'TNmꪹgw'])LV1qpeJ[E F[mQ-[DjjUsۥwuwiݝ9cvw7[+-Z[mYUUe6;}[hQ>{AÔK$57O"{%~w'?-Oc|ksf͌c[ 'p34{S'0Sٟ3#7>LSLb $i3k#eRg.q(gZ!IQL#&bxGN5M+G 11L1w,F`j-N`|w#vp?σ$$S]m..IRH`¥UONɤlG,`g3fTkG`Mp|'>oXZVևho<[CşЈɊqo@JPUA5̀%r'vR@KK!SZvץs M`v!ٝq06ٹJiP:~ ؏P,oo08ŵhkDfk~ w-b+(dԇ&L)SG iǓ]Z7X(n/]hn9[f/O0qt,z!D6;0ݞp34U2ܳaL^\wcJ0 &:.Jc$\٪gS ؟7|aS|7w JYu2IUR7cTe&tn#40gAr8=[Q 1n p%?6a8-JUcI⡞5+GNNG y;xv|cbUQmQj[e"0mIH+EΥ%eVUamZcmDkc"BceQZ e Y.j;Kr{gOԙ6t{uu0dkfd\1"A,~V1fjfY,K%fcWҶEa1,>߫֒9ϞTX͚-_VI ^W$(I% eו<&LTS LS =& 8pC $H R:TΙ&s {pU88rdx?X6me_޵353RYUJU)IJJRi8$|tpPIS4>u^sSxy9; >J:!S>9 9zZ?L0EevK)*jb<ٷ17]ԗHl=jkߝ<8k7PzLFr\eJB6T4 !njMk-2Y b$kWnkMB֪MS:0񢷨H' 0B)5-d^aYXDB`,0=Yc,1x2IDQS5Nm<0 ~B[2gq`}yJnVq'b~GO<8kcE5fjƠb$"/jReD|6â %) *-RSpsQap8*b5G8^-y0`C@|:GM,XqBxRiTS|7bLbمe*I?4'916 hC[,;igpM.jjJQ? >ERb2elY8Coh>CPmGa82լ;ѣo@OzB}'(MnYfjdMM'/8pQD&:m=43'~{[08T#Vd=;`ENĥ9#a7%QJS~m[EX`Af҂=#8#|G ?UޕٙH|3abcJ9M.)hRE.[uѪngN{;(fc0#ͶJβ;$ $P ʝ{L!YӽEYx;^p&+',+SzǷ*`IġΜD0e)Q`TɭO$A=p@ƍF,X`iKɘCKAYYC9A%%:`Rx=ba Rc hkN<fʹbvv1vfbG#h՟`a<ý 7mQݟ>4iKߦ4Ph'#䭷i3G'\}g'LA˙TڶkYYz 3~Q3k~X 5u:CD6#NԒ~>JSȣ#T (Ǚ7:L7O%')Պ7F씪a-%'5F)ʩ)JEMY;=k+(ho}p5\L#чf&  0T3Ȍg)(Z%Z[ME.? pV Ww--EK)mjk`ҔLaZl%DEۣLI1?p'_1RQ+ ǹLƂM&Q`Œٝ)? G,~}!ѹQ;Yth32U\!bj9q'hx3#0L1p][4VBpO 7FqmwHҙ6eI)~&imUōǧCzJ~