xref: /haiku/src/preferences/keymap/KeymapWindow.cpp (revision 4f2fd49bdc6078128b1391191e4edac647044c3d)
1 /*
2  * Copyright 2004-2008 Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Sandor Vroemisse
7  *		Jérôme Duval
8  *		Alexandre Deckner, alex@zappotek.com
9  */
10 
11 #include <Alert.h>
12 #include <Application.h>
13 #include <Bitmap.h>
14 #include <Box.h>
15 #include <Button.h>
16 #include <Clipboard.h>
17 #include <Debug.h>
18 #include <Directory.h>
19 #include <FindDirectory.h>
20 #include <GraphicsDefs.h>
21 #include <ListView.h>
22 #include <MenuItem.h>
23 #include <Path.h>
24 #include <Region.h>
25 #include <ScrollView.h>
26 #include <StringView.h>
27 #include <TextView.h>
28 #include <View.h>
29 #include <string.h>
30 #include "KeymapWindow.h"
31 #include "KeymapListItem.h"
32 #include "KeymapApplication.h"
33 
34 static const uint32 kMsgMenuFileOpen = 'mMFO';
35 static const uint32 kMsgMenuFileSave = 'mMFS';
36 static const uint32 kMsgMenuFileSaveAs = 'mMFA';
37 static const uint32 kMsgMenuEditUndo = 'mMEU';
38 static const uint32 kMsgMenuEditCut = 'mMEX';
39 static const uint32 kMsgMenuEditCopy = 'mMEC';
40 static const uint32 kMsgMenuEditPaste = 'mMEV';
41 static const uint32 kMsgMenuEditClear = 'mMEL';
42 static const uint32 kMsgMenuEditSelectAll = 'mMEA';
43 static const uint32 kMsgMenuFontChanged = 'mMFC';
44 static const uint32 kMsgSystemMapSelected = 'SmST';
45 static const uint32 kMsgUserMapSelected = 'UmST';
46 static const uint32 kMsgUseKeymap = 'UkyM';
47 static const uint32 kMsgRevertKeymap = 'Rvrt';
48 
49 KeymapWindow::KeymapWindow()
50 	:	BWindow(BRect(80, 25, 750, 280), "Keymap", B_TITLED_WINDOW,
51 			B_NOT_ZOOMABLE | B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS )
52 {
53 	fFirstTime = true;
54 
55 	// Add the menu bar
56 	BMenuBar *menubar = AddMenuBar();
57 
58 	// The view to hold all but the menu bar
59 	BRect bounds = Bounds();
60 	bounds.top = menubar->Bounds().bottom + 1;
61 	BBox *placeholderView = new BBox(bounds, "placeholderView",
62 		B_FOLLOW_ALL);
63 	placeholderView->SetBorder(B_NO_BORDER);
64 	AddChild(placeholderView);
65 
66 	// Create the Maps box and contents
67 	AddMaps(placeholderView);
68 
69 	fMapView = new MapView(BRect(205, 15, 655, 189), "mapView", &fCurrentMap);
70 	placeholderView->AddChild(fMapView);
71 
72 	BMenuItem *item = fFontMenu->FindMarked();
73 	if (item) {
74 		fMapView->SetFontFamily(item->Label());
75 	}
76 
77 	// The 'Use' button
78 	fUseButton = new BButton(BRect(582, 200, 655, 220), "useButton", "Use",
79 		new BMessage(kMsgUseKeymap));
80 	placeholderView->AddChild(fUseButton);
81 
82 	// The 'Revert' button
83 	fRevertButton = new BButton(BRect(497, 200, 570, 220), "revertButton",
84 		 "Revert", new BMessage(kMsgRevertKeymap));
85 	placeholderView->AddChild(fRevertButton);
86 	UpdateButtons();
87 
88 	BPath path;
89 	find_directory(B_USER_SETTINGS_DIRECTORY, &path);
90 	path.Append("Keymap");
91 
92 	entry_ref ref;
93 	get_ref_for_path(path.Path(), &ref);
94 
95 	BDirectory userKeymapsDir(&ref);
96 	if (userKeymapsDir.InitCheck() != B_OK) {
97 		create_directory(path.Path(), S_IRWXU | S_IRWXG | S_IRWXO);
98 	}
99 
100 	BMessenger messenger(this);
101 	fOpenPanel = new BFilePanel(B_OPEN_PANEL, &messenger, &ref,
102 		B_FILE_NODE, false, NULL);
103 	fSavePanel = new BFilePanel(B_SAVE_PANEL, &messenger, &ref,
104 		B_FILE_NODE, false, NULL);
105 }
106 
107 
108 KeymapWindow::~KeymapWindow(void)
109 {
110 	delete fOpenPanel;
111 	delete fSavePanel;
112 }
113 
114 
115 BMenuBar *
116 KeymapWindow::AddMenuBar()
117 {
118 	BRect		bounds;
119 	BMenu		*menu;
120 	BMenuItem	*currentItem;
121 	BMenuBar	*menubar;
122 
123 	bounds = Bounds();
124 	menubar = new BMenuBar(bounds, "menubar");
125 	AddChild(menubar);
126 
127 	// Create the File menu
128 	menu = new BMenu("File");
129 	menu->AddItem(new BMenuItem("Open" B_UTF8_ELLIPSIS,
130 		new BMessage(kMsgMenuFileOpen), 'O'));
131 	menu->AddSeparatorItem();
132 	currentItem = new BMenuItem("Save",
133 		new BMessage(kMsgMenuFileSave), 'S');
134 	currentItem->SetEnabled(false);
135 	menu->AddItem(currentItem);
136 	menu->AddItem(new BMenuItem("Save As" B_UTF8_ELLIPSIS,
137 		new BMessage(kMsgMenuFileSaveAs)));
138 	menu->AddSeparatorItem();
139 	menu->AddItem(new BMenuItem("Quit",
140 		new BMessage(B_QUIT_REQUESTED), 'Q'));
141 	menubar->AddItem(menu);
142 
143 	// Create the Edit menu
144 	menu = new BMenu("Edit");
145 	currentItem = new BMenuItem("Undo",
146 		new BMessage(kMsgMenuEditUndo), 'Z');
147 	currentItem->SetEnabled(false);
148 	menu->AddItem(currentItem);
149 	menu->AddSeparatorItem();
150 	menu->AddItem(new BMenuItem( "Cut",
151 		new BMessage(kMsgMenuEditCut), 'X'));
152 	menu->AddItem(new BMenuItem( "Copy",
153 		new BMessage(kMsgMenuEditCopy), 'C'));
154 	menu->AddItem(new BMenuItem( "Paste",
155 		new BMessage(kMsgMenuEditPaste), 'V'));
156 	menu->AddItem(new BMenuItem( "Clear",
157 		new BMessage(kMsgMenuEditClear)));
158 	menu->AddSeparatorItem();
159 	menu->AddItem(new BMenuItem( "Select All",
160 		new BMessage(kMsgMenuEditSelectAll), 'A'));
161 	menubar->AddItem(menu);
162 
163 	// Create the Font menu
164 	fFontMenu = new BMenu("Font");
165 	fFontMenu->SetRadioMode(true);
166 	int32 numFamilies = count_font_families();
167 	font_family family, current_family;
168 	font_style current_style;
169 	uint32 flags;
170 
171 	be_plain_font->GetFamilyAndStyle(&current_family, &current_style);
172 
173 	for (int32 i = 0; i < numFamilies; i++ )
174 		if (get_font_family(i, &family, &flags) == B_OK) {
175 			BMenuItem *item =
176 				new BMenuItem(family, new BMessage(kMsgMenuFontChanged));
177 			fFontMenu->AddItem(item);
178 			if (strcmp(family, current_family) == 0)
179 				item->SetMarked(true);
180 		}
181 	menubar->AddItem(fFontMenu);
182 
183 	return menubar;
184 }
185 
186 
187 void
188 KeymapWindow::AddMaps(BView *placeholderView)
189 {
190 	// The System list
191 	BStringView *systemLabel = new BStringView(BRect(13, 5, 143, 28), "system", "System:");
192 	placeholderView->AddChild(systemLabel);
193 
194 	BRect bounds = BRect(13, 27, 173, 130);
195 	fSystemListView = new BListView(bounds, "systemList");
196 
197 	placeholderView->AddChild(new BScrollView("systemScrollList", fSystemListView,
198 		B_FOLLOW_LEFT | B_FOLLOW_TOP, 0, false, true));
199 	fSystemListView->SetSelectionMessage(new BMessage(kMsgSystemMapSelected));
200 
201 	// The User list
202 	BStringView *userLabel = new BStringView(BRect(13, 135, 143, 153), "user", "User:");
203 	placeholderView->AddChild(userLabel);
204 
205 	bounds = BRect(13, 155, 173, 225);
206 	fUserListView = new BListView(bounds, "userList");
207 	// '(Current)'
208 	KeymapListItem *currentKeymapItem = static_cast<KeymapListItem*>(fUserListView->FirstItem());
209 	if (currentKeymapItem != NULL)
210 		fUserListView->AddItem(currentKeymapItem);
211 	// Saved keymaps
212 	placeholderView->AddChild(new BScrollView("userScrollList", fUserListView,
213 		B_FOLLOW_LEFT | B_FOLLOW_TOP, 0, false, true));
214 	fUserListView->SetSelectionMessage(new BMessage(kMsgUserMapSelected));
215 
216 	FillSystemMaps();
217 	FillUserMaps();
218 
219 	// try and find the current map name in the two list views (if the name was read at all)
220 	if (!SelectCurrentMap(fSystemListView))
221 		if (!SelectCurrentMap(fUserListView))
222 			fUserListView->Select(0L);
223 }
224 
225 
226 bool
227 KeymapWindow::QuitRequested()
228 {
229 	be_app->PostMessage(B_QUIT_REQUESTED);
230 	return true;
231 }
232 
233 
234 void
235 KeymapWindow::MessageReceived(BMessage* message)
236 {
237 	switch(message->what) {
238 		case B_SIMPLE_DATA:
239 		case B_REFS_RECEIVED:
240 		{
241 			entry_ref ref;
242 			int32 i = 0;
243 			while (message->FindRef("refs", i++, &ref) == B_OK) {
244 				fCurrentMap.Load(ref);
245 			}
246 			fMapView->Invalidate();
247 			fSystemListView->DeselectAll();
248 			fUserListView->DeselectAll();
249 		}
250 			break;
251 		case B_SAVE_REQUESTED:
252 		{
253 			entry_ref ref;
254 			const char *name;
255 			if ((message->FindRef("directory", &ref) == B_OK)
256 				&& (message->FindString("name", &name) == B_OK)) {
257 
258 				BDirectory directory(&ref);
259 				BEntry entry(&directory, name);
260 				entry.GetRef(&ref);
261 				fCurrentMap.Save(ref);
262 
263 				FillUserMaps();
264 			}
265 		}
266 			break;
267 		case kMsgMenuFileOpen:
268 			fOpenPanel->Show();
269 			break;
270 		case kMsgMenuFileSave:
271 			break;
272 		case kMsgMenuFileSaveAs:
273 			fSavePanel->Show();
274 			break;
275 		case kMsgMenuEditUndo:
276 		case kMsgMenuEditCut:
277 		case kMsgMenuEditCopy:
278 		case kMsgMenuEditPaste:
279 		case kMsgMenuEditClear:
280 		case kMsgMenuEditSelectAll:
281 			fMapView->MessageReceived(message);
282 			break;
283 		case kMsgMenuFontChanged:
284 		{
285 			BMenuItem *item = fFontMenu->FindMarked();
286 			if (item) {
287 				fMapView->SetFontFamily(item->Label());
288 				fMapView->Invalidate();
289 			}
290 		}
291 			break;
292 		case kMsgSystemMapSelected:
293 		{
294 			KeymapListItem *keymapListItem =
295 				static_cast<KeymapListItem*>(fSystemListView->ItemAt(fSystemListView->CurrentSelection()));
296 			if (keymapListItem) {
297 				fCurrentMap.Load(keymapListItem->KeymapEntry());
298 
299 				if (fFirstTime) {
300 					fPreviousMap.Load(keymapListItem->KeymapEntry());
301 					fAppliedMap.Load(keymapListItem->KeymapEntry());
302 					fFirstTime = false;
303 				}
304 
305 				fMapView->Invalidate();
306 
307 				// Deselect item in other BListView
308 				fUserListView->DeselectAll();
309 				UpdateButtons();
310 			}
311 		}
312 			break;
313 		case kMsgUserMapSelected:
314 		{
315 			KeymapListItem *keymapListItem =
316 				static_cast<KeymapListItem*>(fUserListView->ItemAt(fUserListView->CurrentSelection()));
317 			if (keymapListItem) {
318 				fCurrentMap.Load(keymapListItem->KeymapEntry());
319 
320 				if (fFirstTime) {
321 					fPreviousMap.Load(keymapListItem->KeymapEntry());
322 					fAppliedMap.Load(keymapListItem->KeymapEntry());
323 					fFirstTime = false;
324 				}
325 
326 				fMapView->Invalidate();
327 
328 				// Deselect item in other BListView
329 				fSystemListView->DeselectAll();
330 				UpdateButtons();
331 			}
332 		}
333 			break;
334 		case kMsgUseKeymap:
335 			UseKeymap();
336 			UpdateButtons();
337 			break;
338 		case kMsgRevertKeymap:
339 			RevertKeymap();
340 			UpdateButtons();
341 			break;
342 		default:
343 			BWindow::MessageReceived(message);
344 			break;
345 	}
346 }
347 
348 
349  void
350 KeymapWindow::UpdateButtons()
351 {
352 	fUseButton->SetEnabled(!fCurrentMap.Equals(fAppliedMap));
353 	fRevertButton->SetEnabled(!fCurrentMap.Equals(fPreviousMap));
354 }
355 
356 
357 void
358 KeymapWindow::RevertKeymap()
359 {
360 	//saves previous map to the Key_map file
361 
362 	BPath path;
363 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path)!=B_OK)
364 		return;
365 
366 	path.Append("Key_map");
367 
368 	entry_ref ref;
369 	get_ref_for_path(path.Path(), &ref);
370 
371 	status_t err;
372 	if ((err = fPreviousMap.Save(ref)) != B_OK) {
373 		printf("error when saving : %s", strerror(err));
374 		return;
375 	}
376 	fPreviousMap.Use();
377 	fAppliedMap.Load(ref);
378 
379 	fCurrentMapName = GetActiveKeymapName();
380 
381 	if (!SelectCurrentMap(fSystemListView))
382 		if (!SelectCurrentMap(fUserListView))
383 			fUserListView->Select(0L);
384 }
385 
386 
387 void
388 KeymapWindow::UseKeymap()
389 {
390 	BPath path;
391 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
392 		return;
393 
394 	path.Append("Key_map");
395 
396 	entry_ref ref;
397 	get_ref_for_path(path.Path(), &ref);
398 
399 	status_t err;
400 	if ((err = fCurrentMap.Save(ref)) != B_OK) {
401 		printf("error when saving : %s", strerror(err));
402 		return;
403 	}
404 	fCurrentMap.Use();
405 	fAppliedMap.Load(ref);
406 
407 	fCurrentMapName = GetActiveKeymapName();
408 }
409 
410 
411 void
412 KeymapWindow::FillSystemMaps()
413 {
414 	BListItem *item;
415 	while ((item = fSystemListView->RemoveItem(static_cast<int32>(0))))
416 		delete item;
417 
418 	BPath path;
419 	if (find_directory(B_BEOS_ETC_DIRECTORY, &path) != B_OK)
420 		return;
421 
422 	path.Append("Keymap");
423 
424 	BDirectory directory;
425 	entry_ref ref;
426 
427 	if (directory.SetTo(path.Path()) == B_OK)
428 		while( directory.GetNextRef(&ref) == B_OK ) {
429 			fSystemListView->AddItem(new KeymapListItem(ref));
430 		}
431 }
432 
433 
434 void
435 KeymapWindow::FillUserMaps()
436 {
437 	BListItem *item;
438 	while ((item = fUserListView->RemoveItem(static_cast<int32>(0))))
439 		delete item;
440 
441 	BPath path;
442 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
443 		return;
444 
445 	path.Append("Key_map");
446 
447 	entry_ref ref;
448 	get_ref_for_path(path.Path(), &ref);
449 
450 	fUserListView->AddItem(new KeymapListItem(ref, "(Current)"));
451 
452 	fCurrentMapName = GetActiveKeymapName();
453 
454 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
455 		return;
456 
457 	path.Append("Keymap");
458 
459 	BDirectory directory;
460 
461 	if (directory.SetTo(path.Path()) == B_OK)
462 		while( directory.GetNextRef(&ref) == B_OK ) {
463 			fUserListView->AddItem(new KeymapListItem(ref));
464 		}
465 }
466 
467 
468 BString
469 KeymapWindow::GetActiveKeymapName()
470 {
471 	BString mapName = "(Current)";	//safe default
472 
473 	BPath path;
474 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
475 		return mapName;
476 
477 	path.Append("Key_map");
478 
479 	entry_ref ref;
480 	get_ref_for_path(path.Path(), &ref);
481 	BNode node(&ref);
482 
483 	if (node.InitCheck() == B_OK)
484 		node.ReadAttrString("keymap:name", &mapName);
485 
486 	return mapName;
487 }
488 
489 
490 bool
491 KeymapWindow::SelectCurrentMap(BListView *view)
492 {
493 	bool found = false;
494 	if (fCurrentMapName.Length() > 0) {
495 		for (int32 i = 0; i < view->CountItems(); i++) {
496 			BStringItem *current = dynamic_cast<BStringItem *>(view->ItemAt(i));
497 			if (current && (fCurrentMapName == current->Text())) {
498 				found = true;
499 				view->Select(i);
500 				view->ScrollToSelection();
501 				break;
502 			}
503 		}
504 	}
505 	return found;
506 }
507 
508 
509 MapView::MapView(BRect rect, const char *name, Keymap* keymap)
510 	: BControl(rect, name, NULL, NULL, B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW),
511 		fCurrentFont(*be_plain_font),
512 		fCurrentMap(keymap),
513 		fCurrentMouseKey(0)
514 {
515 	// TODO: Properly handle font sensitivity in drawing the keys.
516 	// This at least prevents the app from looking horrible until the font sensitivity for this app
517 	// can be done the Right Way.
518 	if (fCurrentFont.Size() > 14)
519 		fCurrentFont.SetSize(14);
520 
521 	BRect frameRect = BRect(14, 16, Bounds().right - 12, 30);
522 	BRect textRect = frameRect;
523 	textRect.OffsetTo(B_ORIGIN);
524 	textRect.InsetBy(1, 1);
525 	fTextView = new KeymapTextView(frameRect, "testzone", textRect,
526 		B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_FRAME_EVENTS);
527 	fTextView->MakeEditable(true);
528 	fTextView->MakeSelectable(true);
529 
530 	AddChild(fTextView);
531 
532 	fBitmap = new BBitmap(Bounds(), B_RGB32, true, false);
533 	fOffscreenView = new BView(Bounds(), "off_view", 0, 0);
534 
535 	fBitmap->Lock();
536 	fBitmap->AddChild(fOffscreenView);
537 	fBitmap->Unlock();
538 
539 	for (uint32 j = 0; j < 128; j++)
540 		fKeysToDraw[j] = false;
541 
542 	BRect keyRect = BRect(11, 50, 29, 68);
543 	uint32 i = 1;
544 	fKeysRect[i] = keyRect;
545 	fKeysToDraw[i] = true;
546 
547 	// Fx keys
548 	i++;
549 	keyRect.OffsetBySelf(36, 0);
550 	fKeysRect[i] = keyRect;
551 	fKeysToDraw[i] = true;
552 	i++;
553 	keyRect.OffsetBySelf(18, 0);
554 	fKeysRect[i] = keyRect;
555 	fKeysToDraw[i] = true;
556 	i++;
557 	keyRect.OffsetBySelf(18, 0);
558 	fKeysRect[i] = keyRect;
559 	fKeysToDraw[i] = true;
560 	i++;
561 	keyRect.OffsetBySelf(18, 0);
562 	fKeysRect[i] = keyRect;
563 	fKeysToDraw[i] = true;
564 
565 	i++;
566 	keyRect.OffsetBySelf(27, 0);
567 	fKeysRect[i] = keyRect;
568 	fKeysToDraw[i] = true;
569 	i++;
570 	keyRect.OffsetBySelf(18, 0);
571 	fKeysRect[i] = keyRect;
572 	fKeysToDraw[i] = true;
573 	i++;
574 	keyRect.OffsetBySelf(18, 0);
575 	fKeysRect[i] = keyRect;
576 	fKeysToDraw[i] = true;
577 	i++;
578 	keyRect.OffsetBySelf(18, 0);
579 	fKeysRect[i] = keyRect;
580 	fKeysToDraw[i] = true;
581 
582 	i++;
583 	keyRect.OffsetBySelf(27, 0);
584 	fKeysRect[i] = keyRect;
585 	fKeysToDraw[i] = true;
586 	i++;
587 	keyRect.OffsetBySelf(18, 0);
588 	fKeysRect[i] = keyRect;
589 	fKeysToDraw[i] = true;
590 	i++;
591 	keyRect.OffsetBySelf(18, 0);
592 	fKeysRect[i] = keyRect;
593 	fKeysToDraw[i] = true;
594 	i++;
595 	keyRect.OffsetBySelf(18, 0);
596 	fKeysRect[i] = keyRect;
597 	fKeysToDraw[i] = true;
598 
599 	// Pause, PrintScreen, ...
600 	i++;
601 	keyRect.OffsetBySelf(35, 0);
602 	fKeysRect[i] = keyRect;
603 	fKeysToDraw[i] = true;
604 	i++;
605 	keyRect.OffsetBySelf(18, 0);
606 	fKeysRect[i] = keyRect;
607 	fKeysToDraw[i] = true;
608 	i++;
609 	keyRect.OffsetBySelf(18, 0);
610 	fKeysRect[i] = keyRect;
611 	fKeysToDraw[i] = true;
612 
613 	// 1st line : numbers and backspace
614 	i++;
615 	keyRect = BRect(11, 78, 29, 96);
616 	fKeysRect[i] = keyRect;
617 	fKeysToDraw[i] = true;
618 	i++;
619 	keyRect.OffsetBySelf(18, 0);
620 	fKeysRect[i] = keyRect;
621 	fKeysToDraw[i] = true;
622 	i++;
623 	keyRect.OffsetBySelf(18, 0);
624 	fKeysRect[i] = keyRect;
625 	fKeysToDraw[i] = true;
626 	i++;
627 	keyRect.OffsetBySelf(18, 0);
628 	fKeysRect[i] = keyRect;
629 	fKeysToDraw[i] = true;
630 	i++;
631 	keyRect.OffsetBySelf(18, 0);
632 	fKeysRect[i] = keyRect;
633 	fKeysToDraw[i] = true;
634 	i++;
635 	keyRect.OffsetBySelf(18, 0);
636 	fKeysRect[i] = keyRect;
637 	fKeysToDraw[i] = true;
638 	i++;
639 	keyRect.OffsetBySelf(18, 0);
640 	fKeysRect[i] = keyRect;
641 	fKeysToDraw[i] = true;
642 	i++;
643 	keyRect.OffsetBySelf(18, 0);
644 	fKeysRect[i] = keyRect;
645 	fKeysToDraw[i] = true;
646 	i++;
647 	keyRect.OffsetBySelf(18, 0);
648 	fKeysRect[i] = keyRect;
649 	fKeysToDraw[i] = true;
650 	i++;
651 	keyRect.OffsetBySelf(18, 0);
652 	fKeysRect[i] = keyRect;
653 	fKeysToDraw[i] = true;
654 	i++;
655 	keyRect.OffsetBySelf(18, 0);
656 	fKeysRect[i] = keyRect;
657 	fKeysToDraw[i] = true;
658 	i++;
659 	keyRect.OffsetBySelf(18, 0);
660 	fKeysRect[i] = keyRect;
661 	fKeysToDraw[i] = true;
662 	i++;
663 	keyRect.OffsetBySelf(18, 0);
664 	fKeysRect[i] = keyRect;
665 	fKeysToDraw[i] = true;
666 	i++;
667 	keyRect.OffsetBySelf(18, 0);
668 	keyRect.right += 18;
669 	fKeysRect[i] = keyRect;
670 	fKeysToDraw[i] = true;
671 	keyRect.left += 18;
672 
673 	// Insert, pg up ...
674 	i++;
675 	keyRect.OffsetBySelf(35, 0);
676 	fKeysRect[i] = keyRect;
677 	fKeysToDraw[i] = true;
678 	i++;
679 	keyRect.OffsetBySelf(18, 0);
680 	fKeysRect[i] = keyRect;
681 	fKeysToDraw[i] = true;
682 	i++;
683 	keyRect.OffsetBySelf(18, 0);
684 	fKeysRect[i] = keyRect;
685 	fKeysToDraw[i] = true;
686 
687 	// 2nd line : tab and azerty ...
688 	i = 0x26;
689 	keyRect = BRect(11, 96, 38, 114);
690 	fKeysRect[i] = keyRect;
691 	fKeysToDraw[i] = true;
692 	i++;
693 	keyRect.OffsetBySelf(27, 0);
694 	keyRect.right -= 9;
695 	fKeysRect[i] = keyRect;
696 	fKeysToDraw[i] = true;
697 	i++;
698 	keyRect.OffsetBySelf(18, 0);
699 	fKeysRect[i] = keyRect;
700 	fKeysToDraw[i] = true;
701 	i++;
702 	keyRect.OffsetBySelf(18, 0);
703 	fKeysRect[i] = keyRect;
704 	fKeysToDraw[i] = true;
705 	i++;
706 	keyRect.OffsetBySelf(18, 0);
707 	fKeysRect[i] = keyRect;
708 	fKeysToDraw[i] = true;
709 	i++;
710 	keyRect.OffsetBySelf(18, 0);
711 	fKeysRect[i] = keyRect;
712 	fKeysToDraw[i] = true;
713 	i++;
714 	keyRect.OffsetBySelf(18, 0);
715 	fKeysRect[i] = keyRect;
716 	fKeysToDraw[i] = true;
717 	i++;
718 	keyRect.OffsetBySelf(18, 0);
719 	fKeysRect[i] = keyRect;
720 	fKeysToDraw[i] = true;
721 	i++;
722 	keyRect.OffsetBySelf(18, 0);
723 	fKeysRect[i] = keyRect;
724 	fKeysToDraw[i] = true;
725 	i++;
726 	keyRect.OffsetBySelf(18, 0);
727 	fKeysRect[i] = keyRect;
728 	fKeysToDraw[i] = true;
729 	i++;
730 	keyRect.OffsetBySelf(18, 0);
731 	fKeysRect[i] = keyRect;
732 	fKeysToDraw[i] = true;
733 	i++;
734 	keyRect.OffsetBySelf(18, 0);
735 	fKeysRect[i] = keyRect;
736 	fKeysToDraw[i] = true;
737 	i++;
738 	keyRect.OffsetBySelf(18, 0);
739 	fKeysRect[i] = keyRect;
740 	fKeysToDraw[i] = true;
741 	i++;
742 	keyRect.OffsetBySelf(18, 0);
743 	keyRect.right += 9;
744 	fKeysRect[i] = keyRect;
745 	fKeysToDraw[i] = true;
746 	keyRect.left += 9;
747 
748 	// Suppr, pg down ...
749 	i++;
750 	keyRect.OffsetBySelf(35, 0);
751 	fKeysRect[i] = keyRect;
752 	fKeysToDraw[i] = true;
753 	i++;
754 	keyRect.OffsetBySelf(18, 0);
755 	fKeysRect[i] = keyRect;
756 	fKeysToDraw[i] = true;
757 	i++;
758 	keyRect.OffsetBySelf(18, 0);
759 	fKeysRect[i] = keyRect;
760 	fKeysToDraw[i] = true;
761 
762 	// 3rd line : caps and qsdfg ...
763 	i = 0x3b;
764 	keyRect = BRect(11, 114, 47, 132);
765 	fKeysRect[i] = keyRect;
766 	fKeysToDraw[i] = true;
767 	i++;
768 	keyRect.OffsetBySelf(36, 0);
769 	keyRect.right -= 18;
770 	fKeysRect[i] = keyRect;
771 	fKeysToDraw[i] = true;
772 	i++;
773 	keyRect.OffsetBySelf(18, 0);
774 	fKeysRect[i] = keyRect;
775 	fKeysToDraw[i] = true;
776 	i++;
777 	keyRect.OffsetBySelf(18, 0);
778 	fKeysRect[i] = keyRect;
779 	fKeysToDraw[i] = true;
780 	i++;
781 	keyRect.OffsetBySelf(18, 0);
782 	fKeysRect[i] = keyRect;
783 	fKeysToDraw[i] = true;
784 	i++;
785 	keyRect.OffsetBySelf(18, 0);
786 	fKeysRect[i] = keyRect;
787 	fKeysToDraw[i] = true;
788 	i++;
789 	keyRect.OffsetBySelf(18, 0);
790 	fKeysRect[i] = keyRect;
791 	fKeysToDraw[i] = true;
792 	i++;
793 	keyRect.OffsetBySelf(18, 0);
794 	fKeysRect[i] = keyRect;
795 	fKeysToDraw[i] = true;
796 	i++;
797 	keyRect.OffsetBySelf(18, 0);
798 	fKeysRect[i] = keyRect;
799 	fKeysToDraw[i] = true;
800 	i++;
801 	keyRect.OffsetBySelf(18, 0);
802 	fKeysRect[i] = keyRect;
803 	fKeysToDraw[i] = true;
804 	i++;
805 	keyRect.OffsetBySelf(18, 0);
806 	fKeysRect[i] = keyRect;
807 	fKeysToDraw[i] = true;
808 	i++;
809 	keyRect.OffsetBySelf(18, 0);
810 	fKeysRect[i] = keyRect;
811 	fKeysToDraw[i] = true;
812 	i++;
813 	keyRect.OffsetBySelf(18, 0);
814 	keyRect.right += 18;
815 	fKeysRect[i] = keyRect;
816 	fKeysToDraw[i] = true;
817 	keyRect.left += 18;
818 
819 	// 4th line : shift and wxcv ...
820 	i = 0x4b;
821 	keyRect = BRect(11, 132, 56, 150);
822 	fKeysRect[i] = keyRect;
823 	fKeysToDraw[i] = true;
824 	i++;
825 	keyRect.OffsetBySelf(45, 0);
826 	keyRect.right -= 27;
827 	fKeysRect[i] = keyRect;
828 	fKeysToDraw[i] = true;
829 	i++;
830 	keyRect.OffsetBySelf(18, 0);
831 	fKeysRect[i] = keyRect;
832 	fKeysToDraw[i] = true;
833 	i++;
834 	keyRect.OffsetBySelf(18, 0);
835 	fKeysRect[i] = keyRect;
836 	fKeysToDraw[i] = true;
837 	i++;
838 	keyRect.OffsetBySelf(18, 0);
839 	fKeysRect[i] = keyRect;
840 	fKeysToDraw[i] = true;
841 	i++;
842 	keyRect.OffsetBySelf(18, 0);
843 	fKeysRect[i] = keyRect;
844 	fKeysToDraw[i] = true;
845 	i++;
846 	keyRect.OffsetBySelf(18, 0);
847 	fKeysRect[i] = keyRect;
848 	fKeysToDraw[i] = true;
849 	i++;
850 	keyRect.OffsetBySelf(18, 0);
851 	fKeysRect[i] = keyRect;
852 	fKeysToDraw[i] = true;
853 	i++;
854 	keyRect.OffsetBySelf(18, 0);
855 	fKeysRect[i] = keyRect;
856 	fKeysToDraw[i] = true;
857 	i++;
858 	keyRect.OffsetBySelf(18, 0);
859 	fKeysRect[i] = keyRect;
860 	fKeysToDraw[i] = true;
861 	i++;
862 	keyRect.OffsetBySelf(18, 0);
863 	fKeysRect[i] = keyRect;
864 	fKeysToDraw[i] = true;
865 	i++;
866 	keyRect.OffsetBySelf(18, 0);
867 	keyRect.right += 27;
868 	fKeysRect[i] = keyRect;
869 	fKeysToDraw[i] = true;
870 	keyRect.left += 27;
871 
872 	//5th line : Ctrl, Alt, Space ...
873 	i = 0x5c;
874 	keyRect = BRect(11, 150, 38, 168);
875 	fKeysRect[i] = keyRect;
876 	fKeysToDraw[i] = true;
877 	i++;
878 	keyRect.OffsetBySelf(27, 0);
879 	keyRect.OffsetBySelf(26, 0);
880 	fKeysRect[i] = keyRect;
881 	fKeysToDraw[i] = true;
882 	i++;
883 	keyRect.OffsetBySelf(27, 0);
884 	keyRect.right += 92;
885 	fKeysRect[i] = keyRect;
886 	fKeysToDraw[i] = true;
887 	i++;
888 	keyRect.right -= 92;
889 	keyRect.OffsetBySelf(92, 0);
890 	keyRect.OffsetBySelf(27, 0);
891 	fKeysRect[i] = keyRect;
892 	fKeysToDraw[i] = true;
893 	i++;
894 	keyRect.OffsetBySelf(26, 0);
895 	keyRect.OffsetBySelf(18, 0);
896 	fKeysRect[i] = keyRect;
897 	fKeysToDraw[i] = true;
898 
899 	// Arrows
900 	i++;
901 	keyRect = BRect(298, 150, 316, 168);
902 	fKeysRect[i] = keyRect;
903 	fKeysToDraw[i] = true;
904 	i++;
905 	keyRect.OffsetBySelf(18, 0);
906 	fKeysRect[i] = keyRect;
907 	fKeysToDraw[i] = true;
908 	i++;
909 	keyRect.OffsetBySelf(18, 0);
910 	fKeysRect[i] = keyRect;
911 	fKeysToDraw[i] = true;
912 	i = 0x57;
913 	keyRect.OffsetBySelf(-18, -18);
914 	fKeysRect[i] = keyRect;
915 	fKeysToDraw[i] = true;
916 
917 	// numkeys
918 	i = 0x22;
919 	keyRect = BRect(369, 78, 387, 96);
920 	fKeysRect[i] = keyRect;
921 	fKeysToDraw[i] = true;
922 	i++;
923 	keyRect.OffsetBySelf(18, 0);
924 	fKeysRect[i] = keyRect;
925 	fKeysToDraw[i] = true;
926 	i++;
927 	keyRect.OffsetBySelf(18, 0);
928 	fKeysRect[i] = keyRect;
929 	fKeysToDraw[i] = true;
930 	i++;
931 	keyRect.OffsetBySelf(18, 0);
932 	fKeysRect[i] = keyRect;
933 	fKeysToDraw[i] = true;
934 	i = 0x37;
935 	keyRect.OffsetBySelf(-54, 18);
936 	fKeysRect[i] = keyRect;
937 	fKeysToDraw[i] = true;
938 	i++;
939 	keyRect.OffsetBySelf(18, 0);
940 	fKeysRect[i] = keyRect;
941 	fKeysToDraw[i] = true;
942 	i++;
943 	keyRect.OffsetBySelf(18, 0);
944 	fKeysRect[i] = keyRect;
945 	fKeysToDraw[i] = true;
946 	i++;
947 	keyRect.OffsetBySelf(18, 0);
948 	keyRect.bottom += 18;
949 	fKeysRect[i] = keyRect;
950 	fKeysToDraw[i] = true;
951 	i = 0x48;
952 	keyRect.bottom -= 18;
953 	keyRect.OffsetBySelf(-54, 18);
954 	fKeysRect[i] = keyRect;
955 	fKeysToDraw[i] = true;
956 	i++;
957 	keyRect.OffsetBySelf(18, 0);
958 	fKeysRect[i] = keyRect;
959 	fKeysToDraw[i] = true;
960 	i++;
961 	keyRect.OffsetBySelf(18, 0);
962 	fKeysRect[i] = keyRect;
963 	fKeysToDraw[i] = true;
964 	i = 0x58;
965 	keyRect.OffsetBySelf(-36, 18);
966 	fKeysRect[i] = keyRect;
967 	fKeysToDraw[i] = true;
968 	i++;
969 	keyRect.OffsetBySelf(18, 0);
970 	fKeysRect[i] = keyRect;
971 	fKeysToDraw[i] = true;
972 	i++;
973 	keyRect.OffsetBySelf(18, 0);
974 	fKeysRect[i] = keyRect;
975 	fKeysToDraw[i] = true;
976 	i++;
977 	keyRect.OffsetBySelf(18, 0);
978 	keyRect.bottom += 18;
979 	fKeysRect[i] = keyRect;
980 	fKeysToDraw[i] = true;
981 	i = 0x64;
982 	keyRect.bottom -= 18;
983 	keyRect.OffsetBySelf(-54, 18);
984 	keyRect.right += 18;
985 	fKeysRect[i] = keyRect;
986 	fKeysToDraw[i] = true;
987 	i++;
988 	keyRect.right -= 18;
989 	keyRect.OffsetBySelf(36, 0);
990 	fKeysRect[i] = keyRect;
991 	fKeysToDraw[i] = true;
992 
993 	for (uint32 j = 0; j < 128; j++)
994 		fKeysVertical[j] = false;
995 
996 	fKeysVertical[0x5e] = true;
997 
998 	fActiveDeadKey = 0;
999 
1000 	for (int8 j = 0; j < 16; j++)
1001 		fOldKeyInfo.key_states[j] = 0;
1002 	fOldKeyInfo.modifiers = 0;
1003 }
1004 
1005 
1006 MapView::~MapView()
1007 {
1008 	delete fBitmap;
1009 }
1010 
1011 
1012 void
1013 MapView::_InitOffscreen()
1014 {
1015 	if (fBitmap->Lock()) {
1016 		_DrawBackground();
1017 		fOffscreenView->Sync();
1018 		fBitmap->Unlock();
1019 	}
1020 }
1021 
1022 
1023 void
1024 MapView::AttachedToWindow()
1025 {
1026 	BControl::AttachedToWindow();
1027 
1028 	SetEventMask(B_KEYBOARD_EVENTS, 0);
1029 	SetViewColor(B_TRANSPARENT_COLOR);
1030 	fTextView->SetViewColor(255, 255, 255);
1031 	_InitOffscreen();
1032 }
1033 
1034 
1035 void
1036 MapView::_DrawBackground(){
1037 	BRect r = fOffscreenView->Bounds();
1038 	fOffscreenView->SetHighColor(0, 0, 0);
1039 	fOffscreenView->StrokeRect(r);
1040 
1041 	r.InsetBySelf(1, 1);
1042 	fOffscreenView->SetHighColor(168, 168, 168);
1043 	fOffscreenView->StrokeRect(r);
1044 	fOffscreenView->SetHighColor(80, 80, 80);
1045 	fOffscreenView->StrokeLine(BPoint(r.left + 2, r.bottom), r.RightBottom());
1046 	fOffscreenView->StrokeLine(r.RightTop());
1047 
1048 	r.InsetBySelf(1, 1);
1049 	fOffscreenView->SetHighColor(255, 255, 255);
1050 	fOffscreenView->StrokeRect(r);
1051 	fOffscreenView->SetHighColor(112, 112, 112);
1052 	fOffscreenView->StrokeLine(BPoint(r.left + 1, r.bottom), r.RightBottom());
1053 	fOffscreenView->StrokeLine(r.RightTop());
1054 
1055 	r.InsetBySelf(1, 1);
1056 	fOffscreenView->SetHighColor(168, 168, 168);
1057 	fOffscreenView->FillRect(r);
1058 
1059 	fOffscreenView->SetHighColor(255, 255, 255);
1060 	fOffscreenView->FillRect(BRect(r.right - 1, r.bottom - 1, r.right, r.bottom));
1061 	fOffscreenView->SetHighColor(184, 184, 184);
1062 	fOffscreenView->StrokeLine(BPoint(r.right - 9, r.bottom), BPoint(r.right - 2, r.bottom));
1063 	fOffscreenView->StrokeLine(BPoint(r.right, r.bottom - 9), BPoint(r.right, r.bottom - 2));
1064 
1065 	// Esc key
1066 	_DrawBorder(fOffscreenView, BRect(10, 49, 30, 69));
1067 
1068 	// Fx keys
1069 	_DrawBorder(fOffscreenView, BRect(46, 49, 120, 69));
1070 
1071 	_DrawBorder(fOffscreenView, BRect(127, 49, 201, 69));
1072 
1073 	_DrawBorder(fOffscreenView, BRect(208, 49, 282, 69));
1074 
1075 	// Pause, PrintScreen, ...
1076 	_DrawBorder(fOffscreenView, BRect(297, 49, 353, 69));
1077 
1078 	// Insert, pg up ...
1079 	_DrawBorder(fOffscreenView, BRect(297, 77, 353, 115));
1080 
1081 	fOffscreenView->SetHighColor(80, 80, 80);
1082 	fOffscreenView->StrokeLine(BPoint(10, 169), BPoint(10, 77));
1083 	fOffscreenView->StrokeLine(BPoint(282, 77));
1084 	fOffscreenView->SetHighColor(255, 255, 255);
1085 	fOffscreenView->StrokeLine(BPoint(282, 169));
1086 	fOffscreenView->StrokeLine(BPoint(253, 169));
1087 	fOffscreenView->SetHighColor(80, 80, 80);
1088 	fOffscreenView->StrokeLine(BPoint(253, 151));
1089 	fOffscreenView->SetHighColor(255, 255, 255);
1090 	fOffscreenView->StrokeLine(BPoint(238, 151));
1091 	fOffscreenView->StrokeLine(BPoint(238, 169));
1092 	fOffscreenView->StrokeLine(BPoint(63, 169));
1093 	fOffscreenView->SetHighColor(80, 80, 80);
1094 	fOffscreenView->StrokeLine(BPoint(63, 151));
1095 	fOffscreenView->SetHighColor(255, 255, 255);
1096 	fOffscreenView->StrokeLine(BPoint(39, 151));
1097 	fOffscreenView->StrokeLine(BPoint(39, 169));
1098 	fOffscreenView->StrokeLine(BPoint(11, 169));
1099 
1100 	// Arrows
1101 	fOffscreenView->SetHighColor(80, 80, 80);
1102 	fOffscreenView->StrokeLine(BPoint(297, 169), BPoint(297, 149));
1103 	fOffscreenView->StrokeLine(BPoint(315, 149));
1104 	fOffscreenView->StrokeLine(BPoint(315, 131));
1105 	fOffscreenView->StrokeLine(BPoint(335, 131));
1106 	fOffscreenView->StrokeLine(BPoint(336, 149), BPoint(353, 149));
1107 	fOffscreenView->SetHighColor(255, 255, 255);
1108 	fOffscreenView->StrokeLine(BPoint(335, 132), BPoint(335, 149));
1109 	fOffscreenView->StrokeLine(BPoint(353, 150), BPoint(353, 169));
1110 	fOffscreenView->StrokeLine(BPoint(298, 169));
1111 
1112 	// numkeys
1113 	_DrawBorder(fOffscreenView, BRect(368, 77, 442, 169));
1114 
1115 	_DrawLocksBackground();
1116 
1117 	// the line separator
1118 	r = BRect(11, 40, 353, 43);
1119 	fOffscreenView->SetHighColor(255, 255, 255);
1120 	fOffscreenView->StrokeLine(r.LeftBottom(), r.LeftTop());
1121 	fOffscreenView->StrokeLine(r.RightTop());
1122 	fOffscreenView->SetHighColor(80, 80, 80);
1123 	fOffscreenView->StrokeLine(r.RightBottom());
1124 	fOffscreenView->StrokeLine(r.LeftBottom());
1125 	r.OffsetBySelf(2, 4);
1126 	r.bottom = r.top + 1;
1127 	fOffscreenView->SetHighColor(136, 136, 136);
1128 	fOffscreenView->FillRect(r);
1129 	fOffscreenView->FillRect(BRect(354, 41, 355, 43));
1130 
1131 	// around the textview
1132 	fOffscreenView->SetHighColor(0, 0, 0);
1133 	r = BRect(11, 13, Bounds().right - 11, 31);
1134 	fOffscreenView->StrokeLine(r.LeftBottom(), r.LeftTop());
1135 	fOffscreenView->StrokeLine(r.RightTop());
1136 	fOffscreenView->SetHighColor(80, 80, 80);
1137 	fOffscreenView->StrokeLine(r.LeftBottom() + BPoint(1, 0),
1138 		r.LeftTop() + BPoint(1, 1));
1139 	fOffscreenView->StrokeLine(r.RightTop() + BPoint(0,1));
1140 	fOffscreenView->SetHighColor(136, 136, 136);
1141 	fOffscreenView->StrokeLine(r.LeftBottom() + BPoint(2, -1),
1142 		r.LeftTop() + BPoint(2, 2));
1143 	fOffscreenView->StrokeLine(r.RightTop()+BPoint(0, 2));
1144 	fOffscreenView->StrokeLine(r.LeftBottom()+BPoint(1, 0),
1145 		r.LeftBottom() + BPoint(1, 0));
1146 	fOffscreenView->SetHighColor(255, 255, 255);
1147 	fOffscreenView->StrokeLine(r.RightTop() + BPoint(0, 1), r.RightBottom());
1148 	fOffscreenView->StrokeLine(r.LeftBottom() + BPoint(2, 0));
1149 
1150 	_DrawKeysBackground();
1151 
1152 }
1153 
1154 
1155 void
1156 MapView::Draw(BRect rect)
1157 {
1158 	// draw the background
1159 	if (!fBitmap->Lock())
1160 		return;
1161 
1162 	if (fOffscreenView->Bounds().Intersects(rect)) {
1163 		BRegion region(rect);
1164 		ConstrainClippingRegion(&region);
1165 		DrawBitmapAsync(fBitmap, B_ORIGIN);
1166 		ConstrainClippingRegion(NULL);
1167 	}
1168 
1169 	fBitmap->Unlock();
1170 
1171 	// draw symbols and lights
1172 	for (uint32 i = 1; i <= 128; i++)
1173 		if (fKeysToDraw[i] && rect.Intersects(fKeysRect[i]))
1174 			_DrawKey(i);
1175 
1176 	if (rect.Intersects(BRect(368, 49, 442, 69)))
1177 		_DrawLocksLights();
1178 }
1179 
1180 
1181 void
1182 MapView::_DrawLocksBackground()
1183 {
1184 	_DrawBorder(fOffscreenView, BRect(368, 49, 442, 69));
1185 
1186 	escapement_delta delta;
1187 	delta.nonspace = 0.0;
1188 	BFont font(be_plain_font);
1189 	font.SetSize(8.0);
1190 	font.SetFlags(B_DISABLE_ANTIALIASING);
1191 	font.SetSpacing(B_CHAR_SPACING);
1192 	fOffscreenView->SetFont(&font);
1193 	BRect lightRect = BRect(372, 53, 386, 56);
1194 
1195 	fOffscreenView->SetHighColor(80, 80, 80);
1196 	fOffscreenView->StrokeLine(lightRect.LeftBottom(), lightRect.RightBottom());
1197 	fOffscreenView->StrokeLine(lightRect.RightTop());
1198 	fOffscreenView->SetHighColor(255, 255, 255);
1199 	fOffscreenView->StrokeLine(BPoint(lightRect.right - 1, lightRect.top),
1200 		lightRect.LeftTop());
1201 	fOffscreenView->StrokeLine(BPoint(lightRect.left, lightRect.bottom - 1));
1202 	fOffscreenView->SetHighColor(0, 55, 0);
1203 	fOffscreenView->FillRect(lightRect.InsetByCopy(1, 1));
1204 	fOffscreenView->SetHighColor(64, 64, 64);
1205 	fOffscreenView->DrawString("num", BPoint(lightRect.left - 2, 65), &delta);
1206 
1207 	lightRect.OffsetBy(26, 0);
1208 	fOffscreenView->SetHighColor(80, 80, 80);
1209 	fOffscreenView->StrokeLine(lightRect.LeftBottom(), lightRect.RightBottom());
1210 	fOffscreenView->StrokeLine(lightRect.RightTop());
1211 	fOffscreenView->SetHighColor(255, 255, 255);
1212 	fOffscreenView->StrokeLine(BPoint(lightRect.right - 1, lightRect.top),
1213 		lightRect.LeftTop());
1214 	fOffscreenView->StrokeLine(BPoint(lightRect.left, lightRect.bottom - 1));
1215 	fOffscreenView->SetHighColor(0, 55, 0);
1216 	fOffscreenView->FillRect(lightRect.InsetByCopy(1, 1));
1217 	fOffscreenView->SetHighColor(64, 64, 64);
1218 	fOffscreenView->DrawString("caps", BPoint(lightRect.left - 2, 65), &delta);
1219 
1220 	lightRect.OffsetBy(26, 0);
1221 	fOffscreenView->SetHighColor(80, 80, 80);
1222 	fOffscreenView->StrokeLine(lightRect.LeftBottom(), lightRect.RightBottom());
1223 	fOffscreenView->StrokeLine(lightRect.RightTop());
1224 	fOffscreenView->SetHighColor(255, 255, 255);
1225 	fOffscreenView->StrokeLine(BPoint(lightRect.right - 1, lightRect.top),
1226 		lightRect.LeftTop());
1227 	fOffscreenView->StrokeLine(BPoint(lightRect.left, lightRect.bottom - 1));
1228 	fOffscreenView->SetHighColor(0, 55, 0);
1229 	fOffscreenView->FillRect(lightRect.InsetByCopy(1, 1));
1230 	fOffscreenView->SetHighColor(64, 64, 64);
1231 	fOffscreenView->DrawString("scroll", BPoint(lightRect.left - 4, 65), &delta);
1232 }
1233 
1234 
1235 void MapView::_DrawLocksLights()
1236 {
1237 	BRect lightRect = BRect(372, 53, 386, 56);
1238 	lightRect.InsetBy(1, 1);
1239 
1240 	SetHighColor(0, 55, 0);
1241 	if (fOldKeyInfo.modifiers & B_NUM_LOCK)
1242 		SetHighColor(0, 178, 0);
1243 	FillRect(lightRect);
1244 
1245 	lightRect.OffsetBy(26, 0);
1246 	SetHighColor(0, 55, 0);
1247 	if (fOldKeyInfo.modifiers & B_CAPS_LOCK)
1248 		SetHighColor(0, 178, 0);
1249 	FillRect(lightRect);
1250 
1251 	lightRect.OffsetBy(26, 0);
1252 	SetHighColor(0, 55, 0);
1253 	if (fOldKeyInfo.modifiers & B_SCROLL_LOCK)
1254 		SetHighColor(0, 178, 0);
1255 	FillRect(lightRect);
1256 }
1257 
1258 
1259 void
1260 MapView::_InvalidateKeys()
1261 {
1262 	Invalidate();
1263 }
1264 
1265 
1266 void
1267 MapView::_InvalidateKey(uint32 keyCode)
1268 {
1269 	Invalidate(fKeysRect[keyCode]);
1270 
1271 }
1272 
1273 
1274 void
1275 MapView::_DrawKeysBackground()
1276 {
1277 	for (uint32 keyCode = 1; keyCode <= 128; keyCode++){
1278 
1279 		BRect r = fKeysRect[keyCode];
1280 		if (!r.IsValid())
1281 			return;
1282 		fOffscreenView->SetHighColor(0, 0, 0);
1283 		fOffscreenView->StrokeRect(r);
1284 
1285 		bool vertical = fKeysVertical[keyCode];
1286 		int32 deadKey = fCurrentMap->IsDeadKey(keyCode, fOldKeyInfo.modifiers);
1287 		bool secondDeadKey = fCurrentMap->IsDeadSecondKey(keyCode,
1288 			 fOldKeyInfo.modifiers, fActiveDeadKey);
1289 
1290 		r.InsetBySelf(1, 1);
1291 		if (!secondDeadKey && deadKey == 0) {
1292 			fOffscreenView->SetHighColor(64, 64, 64);
1293 			fOffscreenView->StrokeRect(r);
1294 
1295 			fOffscreenView->BeginLineArray(14);
1296 			rgb_color color1 = {200, 200, 200};
1297 			fOffscreenView->AddLine(BPoint(r.left, r.bottom - 1), r.LeftTop(),
1298 				 color1);
1299 			fOffscreenView->AddLine(r.LeftTop(), BPoint(r.left+3, r.top),
1300 				 color1);
1301 			rgb_color color2 = {184, 184, 184};
1302 			fOffscreenView->AddLine(BPoint(r.left + 3, r.top),
1303 				 BPoint(r.left + 6, r.top), color2);
1304 			rgb_color color3 = {168, 168, 168};
1305 			fOffscreenView->AddLine(BPoint(r.left + 6, r.top),
1306 				 BPoint(r.left + 9, r.top), color3);
1307 			rgb_color color4 = {152, 152, 152};
1308 			fOffscreenView->AddLine(BPoint(r.left + 9, r.top),
1309 				 BPoint(r.right - 1, r.top), color4);
1310 
1311 			r.InsetBySelf(1,1);
1312 			fOffscreenView->SetHighColor(255, 255, 255);
1313 			fOffscreenView->StrokeRect(r);
1314 
1315 			rgb_color color6 = {96, 96, 96};
1316 			fOffscreenView->AddLine(r.LeftBottom(), r.RightBottom(), color6);
1317 			rgb_color color5 = {160, 160, 160};
1318 			fOffscreenView->AddLine(r.LeftBottom(), r.LeftBottom(), color5);
1319 			rgb_color color7 = {64, 64, 64};
1320 			fOffscreenView->AddLine(r.RightBottom(),
1321 				 BPoint(r.right, r.bottom - 1), color7);
1322 			fOffscreenView->AddLine(BPoint(r.right, r.bottom - 1),
1323 				 BPoint(r.right, r.top - 1), color6);
1324 			fOffscreenView->AddLine(BPoint(r.right, r.top - 1), r.RightTop(),
1325 				 color5);
1326 			rgb_color color8 = {255, 255, 255};
1327 			fOffscreenView->AddLine(BPoint(r.left + 1, r.bottom - 1),
1328 				 BPoint(r.left + 2, r.bottom - 1), color8);
1329 			fOffscreenView->AddLine(BPoint(r.left + 2, r.bottom - 1),
1330 				 BPoint(r.right - 1, r.bottom - 1), color1);
1331 			fOffscreenView->AddLine(BPoint(r.right - 1, r.bottom - 1),
1332 				 BPoint(r.right - 1, r.bottom - 2), color5);
1333 			fOffscreenView->AddLine(BPoint(r.right - 1, r.bottom - 2),
1334 				 BPoint(r.right - 1, r.top + 1), color1);
1335 			fOffscreenView->EndLineArray();
1336 		}
1337 
1338 		r.InsetBySelf(1, 1);
1339 		r.bottom -= 1;
1340 		BRect fillRect = r;
1341 
1342 		if (!vertical) {
1343 			int32 w1 = 4;
1344 			int32 w2 = 3;
1345 			if (fKeysRect[keyCode].Width() > 20) {
1346 				w1 = 6;
1347 				w2 = 6;
1348 			}
1349 
1350 			fillRect.right = fillRect.left + w1;
1351 			fOffscreenView->SetHighColor(152, 152, 152);
1352 			fOffscreenView->FillRect(fillRect);
1353 			fillRect.left += w1;
1354 			fillRect.right = fillRect.left + w2;
1355 			fOffscreenView->SetHighColor(168, 168, 168);
1356 			fOffscreenView->FillRect(fillRect);
1357 			fillRect.left += w2;
1358 			fillRect.right = r.right - 1;
1359 			fOffscreenView->SetHighColor(184, 184, 184);
1360 			fOffscreenView->FillRect(fillRect);
1361 		} else {
1362 			fOffscreenView->SetHighColor(200, 200, 200);
1363 			fillRect.right -= 1;
1364 			fillRect.bottom = fillRect.top + 2;
1365 			fOffscreenView->FillRect(fillRect);
1366 			fOffscreenView->SetHighColor(184, 184, 184);
1367 			fillRect.OffsetBySelf(0, 3);
1368 			fOffscreenView->FillRect(fillRect);
1369 			fOffscreenView->SetHighColor(168, 168, 168);
1370 			fillRect.OffsetBySelf(0, 3);
1371 			fOffscreenView->FillRect(fillRect);
1372 			fOffscreenView->SetHighColor(152, 152, 152);
1373 			fillRect.OffsetBySelf(0, 3);
1374 			fOffscreenView->FillRect(fillRect);
1375 		}
1376 	}
1377 
1378 }
1379 
1380 
1381 void
1382 MapView::_DrawKey(uint32 keyCode)
1383 {
1384 	BRect r = fKeysRect[keyCode];
1385 	if (!r.IsValid())
1386 		return;
1387 
1388 	bool pressed = (fOldKeyInfo.key_states[keyCode >> 3] & (1 << (7 - keyCode % 8))) || (keyCode == fCurrentMouseKey);
1389 	int32 deadKey = fCurrentMap->IsDeadKey(keyCode, fOldKeyInfo.modifiers);
1390 	bool secondDeadKey = fCurrentMap->IsDeadSecondKey(keyCode, fOldKeyInfo.modifiers, fActiveDeadKey);
1391 
1392 	if (!pressed) {
1393 		r.InsetBySelf(1, 1);
1394 		if (secondDeadKey) {
1395 			SetHighColor(255, 0, 0);
1396 			StrokeRect(r);
1397 			r.InsetBySelf(1, 1);
1398 			StrokeRect(r);
1399 		} else if (deadKey > 0) {
1400 			SetHighColor(255, 255, 0);
1401 			StrokeRect(r);
1402 			r.InsetBySelf(1, 1);
1403 			StrokeRect(r);
1404 		}
1405 	} else {
1406 		r.InsetBySelf(1, 1);
1407 
1408 		if (secondDeadKey) {
1409 			SetHighColor(255, 0, 0);
1410 			StrokeRect(r);
1411 			r.InsetBySelf(1, 1);
1412 			StrokeRect(r);
1413 		} else if (deadKey > 0) {
1414 			SetHighColor(255, 255, 0);
1415 			StrokeRect(r);
1416 			r.InsetBySelf(1, 1);
1417 			StrokeRect(r);
1418 		} else {
1419 			SetHighColor(48, 48, 48);
1420 			StrokeRect(r);
1421 
1422 			BeginLineArray(2);
1423 			rgb_color color1 = {136, 136, 136};
1424 			AddLine(BPoint(r.left + 1, r.bottom), r.RightBottom(), color1);
1425 			AddLine(r.RightBottom(), BPoint(r.right, r.top + 1), color1);
1426 			EndLineArray();
1427 
1428 			r.InsetBySelf(1, 1);
1429 			SetHighColor(72, 72, 72);
1430 			StrokeRect(r);
1431 
1432 			BeginLineArray(4);
1433 			rgb_color color2 = {48, 48, 48};
1434 			AddLine(r.LeftTop(), r.LeftTop(), color2);
1435 			rgb_color color3 = {152, 152, 152};
1436 			AddLine(BPoint(r.left + 1, r.bottom), r.RightBottom(), color3);
1437 			AddLine(r.RightBottom(), r.RightTop(), color3);
1438 			rgb_color color4 = {160, 160, 160};
1439 			AddLine(r.RightTop(), r.RightTop(), color4);
1440 			EndLineArray();
1441 		}
1442 
1443 		r.InsetBySelf(1, 1);
1444 		SetHighColor(112, 112, 112);
1445 		FillRect(r);
1446 		SetHighColor(136, 136, 136);
1447 		StrokeLine(r.LeftTop(), r.LeftTop());
1448 	}
1449 
1450 	char *str = NULL;
1451 	int32 numBytes;
1452 
1453 	fCurrentMap->GetChars(keyCode, fOldKeyInfo.modifiers, fActiveDeadKey, &str, &numBytes);
1454 	if (str) {
1455 		bool hasGlyphs;
1456 		if (deadKey > 0) {
1457 			delete[] str;
1458 			switch (deadKey) {
1459 				case 1: str = strdup("'"); break;
1460 				case 2: str = strdup("`"); break;
1461 				case 3: str = strdup("^"); break;
1462 				case 4: str = strdup("\""); break;
1463 				case 5: str = strdup("~"); break;
1464 			}
1465 		}
1466 		fCurrentFont.GetHasGlyphs(str, 1, &hasGlyphs);
1467 
1468 		if (hasGlyphs) {
1469 			SetFont(&fCurrentFont);
1470 			SetHighColor(0, 0, 0);
1471 			SetLowColor(160, 160, 160);
1472 			BPoint point = fKeysRect[keyCode].LeftBottom();
1473 			point.x += 5;
1474 			point.y -= 5;
1475 			if (pressed) {
1476 				point.y += 1;
1477 				SetLowColor(112, 112, 112);
1478 			}
1479 			DrawString(str, point);
1480 		}
1481 		delete[] str;
1482 	}
1483 }
1484 
1485 
1486 void
1487 MapView::_DrawBorder(BView *view, const BRect& rect)
1488 {
1489 	rgb_color gray = {80, 80, 80};
1490 	rgb_color white = {255, 255, 255};
1491 
1492 	view->BeginLineArray(4);
1493 	view->AddLine(rect.LeftTop(), rect.LeftBottom(), gray);
1494 	view->AddLine(rect.LeftTop(), rect.RightTop(), gray);
1495 	view->AddLine(BPoint(rect.left + 1, rect.bottom), rect.RightBottom(), white);
1496 	view->AddLine(rect.RightBottom(), BPoint(rect.right, rect.top + 1), white);
1497 	view->EndLineArray();
1498 }
1499 
1500 
1501 void
1502 MapView::MessageReceived(BMessage *msg)
1503 {
1504 	switch (msg->what) {
1505 		case kMsgMenuEditUndo:
1506 			fTextView->Undo(be_clipboard);
1507 			break;
1508 		case kMsgMenuEditCut:
1509 			fTextView->Cut(be_clipboard);
1510 			break;
1511 		case kMsgMenuEditCopy:
1512 			fTextView->Copy(be_clipboard);
1513 			break;
1514 		case kMsgMenuEditPaste:
1515 			fTextView->Paste(be_clipboard);
1516 			break;
1517 		case kMsgMenuEditClear:
1518 			fTextView->Clear();
1519 			break;
1520 		case kMsgMenuEditSelectAll:
1521 			fTextView->SelectAll();
1522 			break;
1523 		case B_KEY_DOWN:
1524 		case B_KEY_UP:
1525 		case B_UNMAPPED_KEY_DOWN:
1526 		case B_UNMAPPED_KEY_UP:
1527 		case B_MODIFIERS_CHANGED: {
1528 			key_info info;
1529 			const uint8 *states;
1530 			ssize_t size;
1531 
1532 			if ((msg->FindData("states", B_UINT8_TYPE, reinterpret_cast<const void **>(&states), &size) != B_OK)
1533 				|| (msg->FindInt32("modifiers", reinterpret_cast<int32 *>(&info.modifiers)) != B_OK))
1534 				break;
1535 
1536 			if (fOldKeyInfo.modifiers != info.modifiers) {
1537 				fOldKeyInfo.modifiers = info.modifiers;
1538 				for (int8 i = 0; i < 16; i++)
1539 					fOldKeyInfo.key_states[i] = states[i];
1540 				_InvalidateKeys();
1541 				_DrawLocksLights();
1542 			} else {
1543 
1544 				int32 keyCode = -1;
1545 				for (int8 i = 0; i < 16; i++)
1546 					if (fOldKeyInfo.key_states[i] != states[i]) {
1547 						uint8 stbits = fOldKeyInfo.key_states[i] ^ states[i];
1548 						fOldKeyInfo.key_states[i] = states[i];
1549 						for (int8 j = 7; stbits; j--, stbits >>= 1)
1550 							if (stbits & 1) {
1551 								keyCode = i * 8 + j;
1552 								_InvalidateKey(keyCode);
1553 							}
1554 					}
1555 
1556 				if (keyCode < 0)
1557 					for (int8 i = 0; i < 16; i++) {
1558 						uint8 stbits = states[i];
1559 						for (int8 j = 7; stbits; j--, stbits >>= 1)
1560 							if (stbits & 1) {
1561 								keyCode = i * 8 + j;
1562 								if (!fCurrentMap->IsModifierKey(keyCode)) {
1563 									i = 16;
1564 									break;
1565 								}
1566 							}
1567 					}
1568 
1569 				if (Window()->IsActive()
1570 					&& msg->what == B_KEY_DOWN) {
1571 					char *str = NULL;
1572 					int32 numBytes;
1573 					if (fActiveDeadKey) {
1574 						fCurrentMap->GetChars(keyCode, fOldKeyInfo.modifiers, fActiveDeadKey, &str, &numBytes);
1575 						if (numBytes > 0) {
1576 							fTextView->FakeKeyDown(str, numBytes);
1577 						}
1578 						fActiveDeadKey = 0;
1579 						_InvalidateKeys();
1580 					} else {
1581 						fCurrentMap->GetChars(keyCode, fOldKeyInfo.modifiers, fActiveDeadKey, &str, &numBytes);
1582 						fActiveDeadKey = fCurrentMap->IsDeadKey(keyCode, fOldKeyInfo.modifiers);
1583 						if (fActiveDeadKey)
1584 							_InvalidateKeys();
1585 						else if (numBytes > 0) {
1586 							fTextView->FakeKeyDown(str, numBytes);
1587 						}
1588 					}
1589 					delete[] str;
1590 				}
1591 			}
1592 			break;
1593 		}
1594 		default:
1595 			BControl::MessageReceived(msg);
1596 	}
1597 }
1598 
1599 
1600 void
1601 MapView::KeyDown(const char* bytes, int32 numBytes)
1602 {
1603 	MessageReceived(Window()->CurrentMessage());
1604 }
1605 
1606 
1607 void
1608 MapView::KeyUp(const char* bytes, int32 numBytes)
1609 {
1610 	MessageReceived(Window()->CurrentMessage());
1611 }
1612 
1613 
1614 void
1615 MapView::MouseDown(BPoint point)
1616 {
1617 	uint32 buttons;
1618 	GetMouse(&point, &buttons);
1619 	if (buttons & B_PRIMARY_MOUSE_BUTTON) {
1620 		fCurrentMouseKey = 0;
1621 		for (int32 i = 0; i < 128; i++) {
1622 			if (fKeysRect[i].IsValid() && fKeysRect[i].Contains(point)) {
1623 				fCurrentMouseKey = i;
1624 				_DrawKey(fCurrentMouseKey);
1625 				char *str = NULL;
1626 				int32 numBytes;
1627 				fCurrentMap->GetChars(fCurrentMouseKey, fOldKeyInfo.modifiers, fActiveDeadKey, &str, &numBytes);
1628 				if (numBytes > 0)
1629 					fTextView->FakeKeyDown(str, numBytes);
1630 
1631 				delete[] str;
1632 				SetTracking(true);
1633 				SetMouseEventMask(B_POINTER_EVENTS,
1634 					B_LOCK_WINDOW_FOCUS | B_NO_POINTER_HISTORY);
1635 				break;
1636 			}
1637 		}
1638 	}
1639 }
1640 
1641 
1642 void
1643 MapView::MouseUp(BPoint point)
1644 {
1645 	if (IsTracking())
1646 		SetTracking(false);
1647 	uint32 value = fCurrentMouseKey;
1648 	fCurrentMouseKey = 0;
1649 	_InvalidateKey(value);
1650 }
1651 
1652 
1653 void
1654 MapView::MouseMoved(BPoint point, uint32 transit, const BMessage *msg)
1655 {
1656 	if (IsTracking()) {
1657 		uint32 value = fCurrentMouseKey;
1658 		for (int32 i = 0; i < 128; i++) {
1659 			if (fKeysRect[i].Contains(point) && !fKeysRect[value].Contains(point)) {
1660 				fCurrentMouseKey = i;
1661 				_InvalidateKey(value);
1662 				_InvalidateKey(fCurrentMouseKey);
1663 				char *str = NULL;
1664 				int32 numBytes;
1665 				fCurrentMap->GetChars(fCurrentMouseKey, fOldKeyInfo.modifiers, fActiveDeadKey, &str, &numBytes);
1666 				if (numBytes > 0) {
1667 					fTextView->FakeKeyDown(str, numBytes);
1668 					delete[] str;
1669 				}
1670 				break;
1671 			}
1672 		}
1673 	}
1674 	BControl::MouseMoved(point, transit, msg);
1675 }
1676 
1677 
1678 void
1679 MapView::SetFontFamily(const font_family family)
1680 {
1681 	fCurrentFont.SetFamilyAndStyle(family, NULL);
1682 	fTextView->SetFontAndColor(&fCurrentFont);
1683 }
1684