aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--anttasks/src/com/android/ant/LintExecTask.java22
-rw-r--r--assetstudio/src/images/clipart/big/1-navigation-accept.pngbin0 -> 1458 bytes
-rw-r--r--assetstudio/src/images/clipart/big/1-navigation-back.pngbin0 -> 897 bytes
-rw-r--r--assetstudio/src/images/clipart/big/1-navigation-cancel.pngbin0 -> 1758 bytes
-rw-r--r--assetstudio/src/images/clipart/big/1-navigation-collapse.pngbin0 -> 1797 bytes
-rw-r--r--assetstudio/src/images/clipart/big/1-navigation-expand.pngbin0 -> 1760 bytes
-rw-r--r--assetstudio/src/images/clipart/big/1-navigation-forward.pngbin0 -> 895 bytes
-rw-r--r--assetstudio/src/images/clipart/big/1-navigation-next-item.pngbin0 -> 1716 bytes
-rw-r--r--assetstudio/src/images/clipart/big/1-navigation-previous-item.pngbin0 -> 1702 bytes
-rw-r--r--assetstudio/src/images/clipart/big/1-navigation-refresh.pngbin0 -> 3502 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-accounts.pngbin0 -> 2563 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-add-alarm.pngbin0 -> 3828 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-alarms.pngbin0 -> 5045 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-battery.pngbin0 -> 653 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-bightness-low.pngbin0 -> 4363 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-bluetooth-connected.pngbin0 -> 3566 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-bluetooth-searching.pngbin0 -> 4461 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-bluetooth.pngbin0 -> 2748 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-brightness-auto.pngbin0 -> 4356 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-brightness-high.pngbin0 -> 5120 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-brightness-medium.pngbin0 -> 4226 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-call.pngbin0 -> 2783 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-camera.pngbin0 -> 2982 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-data-usage.pngbin0 -> 3887 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-dial-pad.pngbin0 -> 739 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-end-call.pngbin0 -> 2135 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-flash-automatic.pngbin0 -> 2714 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-flash-off.pngbin0 -> 2429 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-flash-on.pngbin0 -> 1477 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-location-found.pngbin0 -> 3992 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-location-off.pngbin0 -> 3968 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-location-searching.pngbin0 -> 3314 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-mic-muted.pngbin0 -> 2947 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-mic.pngbin0 -> 2608 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-network-cell.pngbin0 -> 697 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-network-wifi.pngbin0 -> 3739 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-new-account.pngbin0 -> 2232 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-not-secure.pngbin0 -> 1815 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-ring-volume.pngbin0 -> 3769 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-screen-locked-to-landscape.pngbin0 -> 1569 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-screen-locked-to-portrait.pngbin0 -> 1649 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-screen-rotation.pngbin0 -> 3589 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-sd-storage.pngbin0 -> 1377 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-secure.pngbin0 -> 1785 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-storage.pngbin0 -> 601 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-switch-camera.pngbin0 -> 4209 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-switch-video.pngbin0 -> 3166 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-time.pngbin0 -> 4432 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-usb.pngbin0 -> 2589 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-video.pngbin0 -> 1337 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-volume-muted.pngbin0 -> 4406 bytes
-rw-r--r--assetstudio/src/images/clipart/big/10-device-access-volume-on.pngbin0 -> 4983 bytes
-rw-r--r--assetstudio/src/images/clipart/big/11-alerts-and-states-airplane-mode-off.pngbin0 -> 3330 bytes
-rw-r--r--assetstudio/src/images/clipart/big/11-alerts-and-states-airplane-mode-on.pngbin0 -> 3121 bytes
-rw-r--r--assetstudio/src/images/clipart/big/11-alerts-and-states-error.pngbin0 -> 1425 bytes
-rw-r--r--assetstudio/src/images/clipart/big/11-alerts-and-states-warning.pngbin0 -> 2627 bytes
-rw-r--r--assetstudio/src/images/clipart/big/12-hardware-computer.pngbin0 -> 1009 bytes
-rw-r--r--assetstudio/src/images/clipart/big/12-hardware-dock.pngbin0 -> 1130 bytes
-rw-r--r--assetstudio/src/images/clipart/big/12-hardware-gamepad.pngbin0 -> 2682 bytes
-rw-r--r--assetstudio/src/images/clipart/big/12-hardware-headphones.pngbin0 -> 3389 bytes
-rw-r--r--assetstudio/src/images/clipart/big/12-hardware-headset.pngbin0 -> 3544 bytes
-rw-r--r--assetstudio/src/images/clipart/big/12-hardware-keyboard.pngbin0 -> 689 bytes
-rw-r--r--assetstudio/src/images/clipart/big/12-hardware-mouse.pngbin0 -> 2551 bytes
-rw-r--r--assetstudio/src/images/clipart/big/12-hardware-phone.pngbin0 -> 1726 bytes
-rw-r--r--assetstudio/src/images/clipart/big/2-action-about.pngbin0 -> 4047 bytes
-rw-r--r--assetstudio/src/images/clipart/big/2-action-help.pngbin0 -> 2193 bytes
-rw-r--r--assetstudio/src/images/clipart/big/2-action-search.pngbin0 -> 3302 bytes
-rw-r--r--assetstudio/src/images/clipart/big/2-action-settings.pngbin0 -> 1977 bytes
-rw-r--r--assetstudio/src/images/clipart/big/3-rating-bad.pngbin0 -> 1999 bytes
-rw-r--r--assetstudio/src/images/clipart/big/3-rating-favorite.pngbin0 -> 2282 bytes
-rw-r--r--assetstudio/src/images/clipart/big/3-rating-good.pngbin0 -> 2099 bytes
-rw-r--r--assetstudio/src/images/clipart/big/3-rating-half-important.pngbin0 -> 3748 bytes
-rw-r--r--assetstudio/src/images/clipart/big/3-rating-important.pngbin0 -> 3066 bytes
-rw-r--r--assetstudio/src/images/clipart/big/3-rating-not-important.pngbin0 -> 3746 bytes
-rw-r--r--assetstudio/src/images/clipart/big/4-collections-cloud.pngbin0 -> 1716 bytes
-rw-r--r--assetstudio/src/images/clipart/big/4-collections-collection.pngbin0 -> 2064 bytes
-rw-r--r--assetstudio/src/images/clipart/big/4-collections-go-to-today.pngbin0 -> 1243 bytes
-rw-r--r--assetstudio/src/images/clipart/big/4-collections-labels.pngbin0 -> 2525 bytes
-rw-r--r--assetstudio/src/images/clipart/big/4-collections-new-label.pngbin0 -> 2338 bytes
-rw-r--r--assetstudio/src/images/clipart/big/4-collections-sort-by-size.pngbin0 -> 485 bytes
-rw-r--r--assetstudio/src/images/clipart/big/4-collections-view-as-grid.pngbin0 -> 338 bytes
-rw-r--r--assetstudio/src/images/clipart/big/4-collections-view-as-list.pngbin0 -> 714 bytes
-rw-r--r--assetstudio/src/images/clipart/big/5-content-attachment.pngbin0 -> 2235 bytes
-rw-r--r--assetstudio/src/images/clipart/big/5-content-backspace.pngbin0 -> 2149 bytes
-rw-r--r--assetstudio/src/images/clipart/big/5-content-copy.pngbin0 -> 773 bytes
-rw-r--r--assetstudio/src/images/clipart/big/5-content-cut.pngbin0 -> 3947 bytes
-rw-r--r--assetstudio/src/images/clipart/big/5-content-discard.pngbin0 -> 2301 bytes
-rw-r--r--assetstudio/src/images/clipart/big/5-content-edit.pngbin0 -> 3893 bytes
-rw-r--r--assetstudio/src/images/clipart/big/5-content-email.pngbin0 -> 1337 bytes
-rw-r--r--assetstudio/src/images/clipart/big/5-content-event.pngbin0 -> 948 bytes
-rw-r--r--assetstudio/src/images/clipart/big/5-content-import-export.pngbin0 -> 2017 bytes
-rw-r--r--assetstudio/src/images/clipart/big/5-content-merge.pngbin0 -> 2574 bytes
-rw-r--r--assetstudio/src/images/clipart/big/5-content-new-attachment.pngbin0 -> 2867 bytes
-rw-r--r--assetstudio/src/images/clipart/big/5-content-new-email.pngbin0 -> 1501 bytes
-rw-r--r--assetstudio/src/images/clipart/big/5-content-new-event.pngbin0 -> 802 bytes
-rw-r--r--assetstudio/src/images/clipart/big/5-content-new-picture.pngbin0 -> 1759 bytes
-rw-r--r--assetstudio/src/images/clipart/big/5-content-new.pngbin0 -> 412 bytes
-rw-r--r--assetstudio/src/images/clipart/big/5-content-paste.pngbin0 -> 1982 bytes
-rw-r--r--assetstudio/src/images/clipart/big/5-content-picture.pngbin0 -> 1725 bytes
-rw-r--r--assetstudio/src/images/clipart/big/5-content-read.pngbin0 -> 2481 bytes
-rw-r--r--assetstudio/src/images/clipart/big/5-content-remove.pngbin0 -> 1758 bytes
-rw-r--r--assetstudio/src/images/clipart/big/5-content-save.pngbin0 -> 1072 bytes
-rw-r--r--assetstudio/src/images/clipart/big/5-content-select-all.pngbin0 -> 872 bytes
-rw-r--r--assetstudio/src/images/clipart/big/5-content-split.pngbin0 -> 2441 bytes
-rw-r--r--assetstudio/src/images/clipart/big/5-content-undo.pngbin0 -> 2358 bytes
-rw-r--r--assetstudio/src/images/clipart/big/5-content-unread.pngbin0 -> 2365 bytes
-rw-r--r--assetstudio/src/images/clipart/big/6-social-add-group.pngbin0 -> 4911 bytes
-rw-r--r--assetstudio/src/images/clipart/big/6-social-add-person.pngbin0 -> 2979 bytes
-rw-r--r--assetstudio/src/images/clipart/big/6-social-cc-bcc.pngbin0 -> 3714 bytes
-rw-r--r--assetstudio/src/images/clipart/big/6-social-chat.pngbin0 -> 848 bytes
-rw-r--r--assetstudio/src/images/clipart/big/6-social-forward.pngbin0 -> 2046 bytes
-rw-r--r--assetstudio/src/images/clipart/big/6-social-group.pngbin0 -> 4533 bytes
-rw-r--r--assetstudio/src/images/clipart/big/6-social-person.pngbin0 -> 2569 bytes
-rw-r--r--assetstudio/src/images/clipart/big/6-social-reply-all.pngbin0 -> 2995 bytes
-rw-r--r--assetstudio/src/images/clipart/big/6-social-reply.pngbin0 -> 2043 bytes
-rw-r--r--assetstudio/src/images/clipart/big/6-social-send-now.pngbin0 -> 1691 bytes
-rw-r--r--assetstudio/src/images/clipart/big/6-social-share.pngbin0 -> 2890 bytes
-rw-r--r--assetstudio/src/images/clipart/big/7-location-directions.pngbin0 -> 2130 bytes
-rw-r--r--assetstudio/src/images/clipart/big/7-location-map.pngbin0 -> 4653 bytes
-rw-r--r--assetstudio/src/images/clipart/big/7-location-place.pngbin0 -> 2684 bytes
-rw-r--r--assetstudio/src/images/clipart/big/7-location-web-site.pngbin0 -> 7855 bytes
-rw-r--r--assetstudio/src/images/clipart/big/8-images-crop.pngbin0 -> 1481 bytes
-rw-r--r--assetstudio/src/images/clipart/big/8-images-rotate-left.pngbin0 -> 3802 bytes
-rw-r--r--assetstudio/src/images/clipart/big/8-images-rotate-right.pngbin0 -> 3803 bytes
-rw-r--r--assetstudio/src/images/clipart/big/8-images-slideshow.pngbin0 -> 1949 bytes
-rw-r--r--assetstudio/src/images/clipart/big/9-av-add-to-queue.pngbin0 -> 719 bytes
-rw-r--r--assetstudio/src/images/clipart/big/9-av-download.pngbin0 -> 1375 bytes
-rw-r--r--assetstudio/src/images/clipart/big/9-av-fast-forward.pngbin0 -> 1835 bytes
-rw-r--r--assetstudio/src/images/clipart/big/9-av-full-screen.pngbin0 -> 3549 bytes
-rw-r--r--assetstudio/src/images/clipart/big/9-av-make-available-offline.pngbin0 -> 2489 bytes
-rw-r--r--assetstudio/src/images/clipart/big/9-av-next.pngbin0 -> 1827 bytes
-rw-r--r--assetstudio/src/images/clipart/big/9-av-pause-over-video.pngbin0 -> 4451 bytes
-rw-r--r--assetstudio/src/images/clipart/big/9-av-pause.pngbin0 -> 372 bytes
-rw-r--r--assetstudio/src/images/clipart/big/9-av-play-over-video.pngbin0 -> 4941 bytes
-rw-r--r--assetstudio/src/images/clipart/big/9-av-play.pngbin0 -> 1817 bytes
-rw-r--r--assetstudio/src/images/clipart/big/9-av-previous.pngbin0 -> 1821 bytes
-rw-r--r--assetstudio/src/images/clipart/big/9-av-repeat.pngbin0 -> 3099 bytes
-rw-r--r--assetstudio/src/images/clipart/big/9-av-replay.pngbin0 -> 3848 bytes
-rw-r--r--assetstudio/src/images/clipart/big/9-av-return-from-full-screen.pngbin0 -> 3364 bytes
-rw-r--r--assetstudio/src/images/clipart/big/9-av-rewind.pngbin0 -> 1974 bytes
-rw-r--r--assetstudio/src/images/clipart/big/9-av-shuffle.pngbin0 -> 3832 bytes
-rw-r--r--assetstudio/src/images/clipart/big/9-av-stop.pngbin0 -> 352 bytes
-rw-r--r--assetstudio/src/images/clipart/big/9-av-upload.pngbin0 -> 1500 bytes
-rw-r--r--assetstudio/src/images/clipart/big/attach.pngbin7872 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/big/call.pngbin6761 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/big/copy.pngbin4172 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/big/cut.pngbin7095 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/big/delete.pngbin5890 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/big/done.pngbin5481 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/big/edit.pngbin7978 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/big/locate.pngbin7961 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/big/mail.pngbin4954 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/big/microphone.pngbin6387 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/big/overflow.pngbin3725 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/big/paste.pngbin5722 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/big/photo.pngbin6299 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/big/refresh.pngbin7303 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/big/search.pngbin7309 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/big/select_all.pngbin5497 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/big/send.pngbin6016 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/big/share.pngbin6806 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/big/star.pngbin6927 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/big/user.pngbin6509 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/big/video.pngbin4713 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/small/1-navigation-accept.pngbin0 -> 530 bytes
-rw-r--r--assetstudio/src/images/clipart/small/1-navigation-back.pngbin0 -> 461 bytes
-rw-r--r--assetstudio/src/images/clipart/small/1-navigation-cancel.pngbin0 -> 438 bytes
-rw-r--r--assetstudio/src/images/clipart/small/1-navigation-collapse.pngbin0 -> 511 bytes
-rw-r--r--assetstudio/src/images/clipart/small/1-navigation-expand.pngbin0 -> 531 bytes
-rw-r--r--assetstudio/src/images/clipart/small/1-navigation-forward.pngbin0 -> 461 bytes
-rw-r--r--assetstudio/src/images/clipart/small/1-navigation-next-item.pngbin0 -> 486 bytes
-rw-r--r--assetstudio/src/images/clipart/small/1-navigation-previous-item.pngbin0 -> 507 bytes
-rw-r--r--assetstudio/src/images/clipart/small/1-navigation-refresh.pngbin0 -> 796 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-accounts.pngbin0 -> 694 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-add-alarm.pngbin0 -> 745 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-alarms.pngbin0 -> 820 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-battery.pngbin0 -> 486 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-bightness-low.pngbin0 -> 752 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-bluetooth-connected.pngbin0 -> 664 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-bluetooth-searching.pngbin0 -> 772 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-bluetooth.pngbin0 -> 609 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-brightness-auto.pngbin0 -> 765 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-brightness-high.pngbin0 -> 731 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-brightness-medium.pngbin0 -> 700 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-call.pngbin0 -> 659 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-camera.pngbin0 -> 709 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-data-usage.pngbin0 -> 716 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-dial-pad.pngbin0 -> 667 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-end-call.pngbin0 -> 613 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-flash-automatic.pngbin0 -> 645 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-flash-off.pngbin0 -> 645 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-flash-on.pngbin0 -> 555 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-location-found.pngbin0 -> 725 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-location-off.pngbin0 -> 732 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-location-searching.pngbin0 -> 668 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-mic-muted.pngbin0 -> 711 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-mic.pngbin0 -> 650 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-network-cell.pngbin0 -> 528 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-network-wifi.pngbin0 -> 753 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-new-account.pngbin0 -> 697 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-not-secure.pngbin0 -> 562 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-ring-volume.pngbin0 -> 710 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-screen-locked-to-landscape.pngbin0 -> 619 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-screen-locked-to-portrait.pngbin0 -> 630 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-screen-rotation.pngbin0 -> 686 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-sd-storage.pngbin0 -> 564 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-secure.pngbin0 -> 555 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-storage.pngbin0 -> 575 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-switch-camera.pngbin0 -> 819 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-switch-video.pngbin0 -> 721 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-time.pngbin0 -> 701 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-usb.pngbin0 -> 670 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-video.pngbin0 -> 486 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-volume-muted.pngbin0 -> 801 bytes
-rw-r--r--assetstudio/src/images/clipart/small/10-device-access-volume-on.pngbin0 -> 827 bytes
-rw-r--r--assetstudio/src/images/clipart/small/11-alerts-and-states-airplane-mode-off.pngbin0 -> 732 bytes
-rw-r--r--assetstudio/src/images/clipart/small/11-alerts-and-states-airplane-mode-on.pngbin0 -> 729 bytes
-rw-r--r--assetstudio/src/images/clipart/small/11-alerts-and-states-error.pngbin0 -> 507 bytes
-rw-r--r--assetstudio/src/images/clipart/small/11-alerts-and-states-warning.pngbin0 -> 617 bytes
-rw-r--r--assetstudio/src/images/clipart/small/12-hardware-computer.pngbin0 -> 464 bytes
-rw-r--r--assetstudio/src/images/clipart/small/12-hardware-dock.pngbin0 -> 499 bytes
-rw-r--r--assetstudio/src/images/clipart/small/12-hardware-gamepad.pngbin0 -> 655 bytes
-rw-r--r--assetstudio/src/images/clipart/small/12-hardware-headphones.pngbin0 -> 766 bytes
-rw-r--r--assetstudio/src/images/clipart/small/12-hardware-headset.pngbin0 -> 854 bytes
-rw-r--r--assetstudio/src/images/clipart/small/12-hardware-keyboard.pngbin0 -> 829 bytes
-rw-r--r--assetstudio/src/images/clipart/small/12-hardware-mouse.pngbin0 -> 654 bytes
-rw-r--r--assetstudio/src/images/clipart/small/12-hardware-phone.pngbin0 -> 525 bytes
-rw-r--r--assetstudio/src/images/clipart/small/2-action-about.pngbin0 -> 630 bytes
-rw-r--r--assetstudio/src/images/clipart/small/2-action-help.pngbin0 -> 626 bytes
-rw-r--r--assetstudio/src/images/clipart/small/2-action-search.pngbin0 -> 706 bytes
-rw-r--r--assetstudio/src/images/clipart/small/2-action-settings.pngbin0 -> 566 bytes
-rw-r--r--assetstudio/src/images/clipart/small/3-rating-bad.pngbin0 -> 596 bytes
-rw-r--r--assetstudio/src/images/clipart/small/3-rating-favorite.pngbin0 -> 591 bytes
-rw-r--r--assetstudio/src/images/clipart/small/3-rating-good.pngbin0 -> 606 bytes
-rw-r--r--assetstudio/src/images/clipart/small/3-rating-half-important.pngbin0 -> 729 bytes
-rw-r--r--assetstudio/src/images/clipart/small/3-rating-important.pngbin0 -> 673 bytes
-rw-r--r--assetstudio/src/images/clipart/small/3-rating-not-important.pngbin0 -> 748 bytes
-rw-r--r--assetstudio/src/images/clipart/small/4-collections-cloud.pngbin0 -> 541 bytes
-rw-r--r--assetstudio/src/images/clipart/small/4-collections-collection.pngbin0 -> 588 bytes
-rw-r--r--assetstudio/src/images/clipart/small/4-collections-go-to-today.pngbin0 -> 740 bytes
-rw-r--r--assetstudio/src/images/clipart/small/4-collections-labels.pngbin0 -> 684 bytes
-rw-r--r--assetstudio/src/images/clipart/small/4-collections-new-label.pngbin0 -> 706 bytes
-rw-r--r--assetstudio/src/images/clipart/small/4-collections-sort-by-size.pngbin0 -> 475 bytes
-rw-r--r--assetstudio/src/images/clipart/small/4-collections-view-as-grid.pngbin0 -> 484 bytes
-rw-r--r--assetstudio/src/images/clipart/small/4-collections-view-as-list.pngbin0 -> 571 bytes
-rw-r--r--assetstudio/src/images/clipart/small/5-content-attachment.pngbin0 -> 644 bytes
-rw-r--r--assetstudio/src/images/clipart/small/5-content-backspace.pngbin0 -> 603 bytes
-rw-r--r--assetstudio/src/images/clipart/small/5-content-copy.pngbin0 -> 615 bytes
-rw-r--r--assetstudio/src/images/clipart/small/5-content-cut.pngbin0 -> 800 bytes
-rw-r--r--assetstudio/src/images/clipart/small/5-content-discard.pngbin0 -> 646 bytes
-rw-r--r--assetstudio/src/images/clipart/small/5-content-edit.pngbin0 -> 710 bytes
-rw-r--r--assetstudio/src/images/clipart/small/5-content-email.pngbin0 -> 559 bytes
-rw-r--r--assetstudio/src/images/clipart/small/5-content-event.pngbin0 -> 557 bytes
-rw-r--r--assetstudio/src/images/clipart/small/5-content-import-export.pngbin0 -> 589 bytes
-rw-r--r--assetstudio/src/images/clipart/small/5-content-merge.pngbin0 -> 599 bytes
-rw-r--r--assetstudio/src/images/clipart/small/5-content-new-attachment.pngbin0 -> 715 bytes
-rw-r--r--assetstudio/src/images/clipart/small/5-content-new-email.pngbin0 -> 691 bytes
-rw-r--r--assetstudio/src/images/clipart/small/5-content-new-event.pngbin0 -> 657 bytes
-rw-r--r--assetstudio/src/images/clipart/small/5-content-new-picture.pngbin0 -> 676 bytes
-rw-r--r--assetstudio/src/images/clipart/small/5-content-new.pngbin0 -> 427 bytes
-rw-r--r--assetstudio/src/images/clipart/small/5-content-paste.pngbin0 -> 677 bytes
-rw-r--r--assetstudio/src/images/clipart/small/5-content-picture.pngbin0 -> 576 bytes
-rw-r--r--assetstudio/src/images/clipart/small/5-content-read.pngbin0 -> 706 bytes
-rw-r--r--assetstudio/src/images/clipart/small/5-content-remove.pngbin0 -> 438 bytes
-rw-r--r--assetstudio/src/images/clipart/small/5-content-save.pngbin0 -> 650 bytes
-rw-r--r--assetstudio/src/images/clipart/small/5-content-select-all.pngbin0 -> 697 bytes
-rw-r--r--assetstudio/src/images/clipart/small/5-content-split.pngbin0 -> 621 bytes
-rw-r--r--assetstudio/src/images/clipart/small/5-content-undo.pngbin0 -> 657 bytes
-rw-r--r--assetstudio/src/images/clipart/small/5-content-unread.pngbin0 -> 624 bytes
-rw-r--r--assetstudio/src/images/clipart/small/6-social-add-group.pngbin0 -> 938 bytes
-rw-r--r--assetstudio/src/images/clipart/small/6-social-add-person.pngbin0 -> 745 bytes
-rw-r--r--assetstudio/src/images/clipart/small/6-social-cc-bcc.pngbin0 -> 755 bytes
-rw-r--r--assetstudio/src/images/clipart/small/6-social-chat.pngbin0 -> 508 bytes
-rw-r--r--assetstudio/src/images/clipart/small/6-social-forward.pngbin0 -> 582 bytes
-rw-r--r--assetstudio/src/images/clipart/small/6-social-group.pngbin0 -> 816 bytes
-rw-r--r--assetstudio/src/images/clipart/small/6-social-person.pngbin0 -> 637 bytes
-rw-r--r--assetstudio/src/images/clipart/small/6-social-reply-all.pngbin0 -> 712 bytes
-rw-r--r--assetstudio/src/images/clipart/small/6-social-reply.pngbin0 -> 616 bytes
-rw-r--r--assetstudio/src/images/clipart/small/6-social-send-now.pngbin0 -> 545 bytes
-rw-r--r--assetstudio/src/images/clipart/small/6-social-share.pngbin0 -> 623 bytes
-rw-r--r--assetstudio/src/images/clipart/small/7-location-directions.pngbin0 -> 528 bytes
-rw-r--r--assetstudio/src/images/clipart/small/7-location-map.pngbin0 -> 895 bytes
-rw-r--r--assetstudio/src/images/clipart/small/7-location-place.pngbin0 -> 604 bytes
-rw-r--r--assetstudio/src/images/clipart/small/7-location-web-site.pngbin0 -> 1030 bytes
-rw-r--r--assetstudio/src/images/clipart/small/8-images-crop.pngbin0 -> 616 bytes
-rw-r--r--assetstudio/src/images/clipart/small/8-images-rotate-left.pngbin0 -> 783 bytes
-rw-r--r--assetstudio/src/images/clipart/small/8-images-rotate-right.pngbin0 -> 776 bytes
-rw-r--r--assetstudio/src/images/clipart/small/8-images-slideshow.pngbin0 -> 590 bytes
-rw-r--r--assetstudio/src/images/clipart/small/9-av-add-to-queue.pngbin0 -> 649 bytes
-rw-r--r--assetstudio/src/images/clipart/small/9-av-download.pngbin0 -> 555 bytes
-rw-r--r--assetstudio/src/images/clipart/small/9-av-fast-forward.pngbin0 -> 532 bytes
-rw-r--r--assetstudio/src/images/clipart/small/9-av-full-screen.pngbin0 -> 702 bytes
-rw-r--r--assetstudio/src/images/clipart/small/9-av-make-available-offline.pngbin0 -> 594 bytes
-rw-r--r--assetstudio/src/images/clipart/small/9-av-next.pngbin0 -> 589 bytes
-rw-r--r--assetstudio/src/images/clipart/small/9-av-pause-over-video.pngbin0 -> 699 bytes
-rw-r--r--assetstudio/src/images/clipart/small/9-av-pause.pngbin0 -> 402 bytes
-rw-r--r--assetstudio/src/images/clipart/small/9-av-play-over-video.pngbin0 -> 748 bytes
-rw-r--r--assetstudio/src/images/clipart/small/9-av-play.pngbin0 -> 557 bytes
-rw-r--r--assetstudio/src/images/clipart/small/9-av-previous.pngbin0 -> 613 bytes
-rw-r--r--assetstudio/src/images/clipart/small/9-av-repeat.pngbin0 -> 703 bytes
-rw-r--r--assetstudio/src/images/clipart/small/9-av-replay.pngbin0 -> 791 bytes
-rw-r--r--assetstudio/src/images/clipart/small/9-av-return-from-full-screen.pngbin0 -> 726 bytes
-rw-r--r--assetstudio/src/images/clipart/small/9-av-rewind.pngbin0 -> 530 bytes
-rw-r--r--assetstudio/src/images/clipart/small/9-av-shuffle.pngbin0 -> 694 bytes
-rw-r--r--assetstudio/src/images/clipart/small/9-av-stop.pngbin0 -> 397 bytes
-rw-r--r--assetstudio/src/images/clipart/small/9-av-upload.pngbin0 -> 546 bytes
-rw-r--r--assetstudio/src/images/clipart/small/attach.pngbin3379 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/small/call.pngbin3161 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/small/copy.pngbin3185 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/small/cut.pngbin3338 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/small/delete.pngbin3184 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/small/done.pngbin3024 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/small/edit.pngbin3275 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/small/locate.pngbin3315 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/small/mail.pngbin3076 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/small/microphone.pngbin3167 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/small/overflow.pngbin2999 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/small/paste.pngbin3250 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/small/photo.pngbin3235 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/small/refresh.pngbin3309 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/small/search.pngbin3228 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/small/select_all.pngbin3434 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/small/send.pngbin3114 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/small/share.pngbin3218 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/small/star.pngbin3187 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/small/user.pngbin3175 -> 0 bytes
-rw-r--r--assetstudio/src/images/clipart/small/video.pngbin3000 -> 0 bytes
-rw-r--r--build/tools.atree5
-rw-r--r--chimpchat/src/com/android/chimpchat/adb/AdbChimpDevice.java12
-rw-r--r--ddms/libs/ddmlib/src/com/android/ddmlib/CollectingOutputReceiver.java14
-rw-r--r--device_validator/app/src/com/android/validator/DeviceValidator.java4
-rw-r--r--device_validator/dvlib/src/com/android/dvlib/DeviceSchema.java2
-rw-r--r--device_validator/dvlib/src/com/android/dvlib/devices.xsd8
-rw-r--r--device_validator/dvlib/tests/src/com/android/dvlib/devices.xml2
-rw-r--r--device_validator/dvlib/tests/src/com/android/dvlib/devices_minimal.xml1
-rw-r--r--device_validator/dvlib/tests/src/com/android/dvlib/devices_no_default.xml1
-rw-r--r--device_validator/dvlib/tests/src/com/android/dvlib/devices_no_hardware.xml1
-rw-r--r--device_validator/dvlib/tests/src/com/android/dvlib/devices_no_states.xml1
-rw-r--r--device_validator/dvlib/tests/src/com/android/dvlib/devices_too_many_defaults.xml1
-rw-r--r--eclipse/dictionary.txt3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/resources/platform/AttrsXmlParser.java16
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtUtils.java39
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java19
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintFix.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintFixGenerator.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/SetAttributeFix.java38
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/SetPropertyFix.java23
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/TypoFix.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplatePage.java12
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizardState.java12
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/Parameter.java6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java21
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.monitor/.classpath1
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.monitor/META-INF/MANIFEST.MF3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.monitor/build.properties3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.monitor/src/com/android/ide/eclipse/monitor/MonitorApplication.java12
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.monitor/src/com/android/ide/eclipse/monitor/SdkToolsLocator.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ndk/src/com/android/ide/eclipse/ndk/internal/launch/NdkGdbLaunchDelegate.java36
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion11-expected-completion73.txt2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues1-expected-completion32.txt4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues2-expected-completion71.txt1
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion18.txt2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion69.txt1
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/AdtUtilsTest.java28
-rwxr-xr-xeclipse/scripts/create_all_symlinks.sh7
-rw-r--r--files/ant/build.xml4
-rw-r--r--files/typos/typos-de.txt2219
-rw-r--r--files/typos/typos-en.txt (renamed from files/typos-en.txt)7
-rw-r--r--files/typos/typos-es.txt733
-rw-r--r--files/typos/typos-hu.txt431
-rw-r--r--files/typos/typos-it.txt665
-rw-r--r--files/typos/typos-nb.txt (renamed from files/typos-nb.txt)3
-rw-r--r--files/typos/typos-pt.txt1647
-rw-r--r--files/typos/typos-tr.txt604
-rw-r--r--lint/cli/src/com/android/tools/lint/HtmlReporter.java5
-rw-r--r--lint/cli/src/com/android/tools/lint/Main.java105
-rw-r--r--lint/cli/src/com/android/tools/lint/XmlReporter.java49
-rw-r--r--lint/libs/lint_api/src/com/android/tools/lint/client/api/LintClient.java45
-rw-r--r--lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintConstants.java5
-rw-r--r--lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintUtils.java74
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/AccessibilityDetector.java7
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/TranslationDetector.java32
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/TypoDetector.java139
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/TypoLookup.java304
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/XmlReporterTest.java140
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AbstractCheckTest.java1
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/TranslationDetectorTest.java27
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/TypoDetectorTest.java12
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/TypoLookupTest.java472
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/accessibility.xml3
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/values-de/typos.xml12
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/values-nb/typos.xml2
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/values/nontranslatable.xml5
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/values/nontranslatable2.xml5
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/values/typos.xml4
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/detector/api/LintUtilsTest.java39
-rwxr-xr-xmanifmerger/src/com/android/manifmerger/ManifestMerger.java44
-rw-r--r--monitor/Android.mk2
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java17
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/devices/DeviceManager.java77
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/devices/DeviceParser.java2
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Software.java14
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/devices/devices.xml15
-rw-r--r--sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java15
-rwxr-xr-xsdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/sources/SdkSources.java16
-rwxr-xr-xsdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/AdtUpdateDialog.java47
-rwxr-xr-xsdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/AvdManagerWindowImpl1.java4
-rw-r--r--sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java1604
-rw-r--r--sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java20
-rw-r--r--sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/LegacyAvdEditDialog.java1425
-rw-r--r--templates/activities/BlankActivity/root/AndroidManifest.xml.ftl2
-rw-r--r--templates/activities/BlankActivity/root/res/layout/activity_simple.xml.ftl4
-rw-r--r--templates/activities/FullscreenActivity/globals.xml.ftl5
-rw-r--r--templates/activities/FullscreenActivity/recipe.xml.ftl24
-rw-r--r--templates/activities/FullscreenActivity/root/AndroidManifest.xml.ftl22
-rwxr-xr-xtemplates/activities/FullscreenActivity/root/res/layout/activity_fullscreen.xml.ftl49
-rw-r--r--templates/activities/FullscreenActivity/root/res/values-v11/styles.xml13
-rw-r--r--templates/activities/FullscreenActivity/root/res/values/colors.xml5
-rw-r--r--templates/activities/FullscreenActivity/root/res/values/strings.xml.ftl8
-rw-r--r--templates/activities/FullscreenActivity/root/res/values/styles.xml8
-rwxr-xr-xtemplates/activities/FullscreenActivity/root/src/app_package/FullscreenActivity.java.ftl197
-rw-r--r--templates/activities/FullscreenActivity/root/src/app_package/util/SystemUiHider.java.ftl172
-rw-r--r--templates/activities/FullscreenActivity/root/src/app_package/util/SystemUiHiderBase.java.ftl63
-rw-r--r--templates/activities/FullscreenActivity/root/src/app_package/util/SystemUiHiderHoneycomb.java.ftl133
-rw-r--r--templates/activities/FullscreenActivity/template.xml68
-rw-r--r--templates/activities/FullscreenActivity/template_fullscreen_activity.pngbin0 -> 16885 bytes
-rw-r--r--templates/activities/LoginActivity/globals.xml.ftl6
-rw-r--r--templates/activities/LoginActivity/recipe.xml.ftl19
-rw-r--r--templates/activities/LoginActivity/root/AndroidManifest.xml.ftl15
-rw-r--r--templates/activities/LoginActivity/root/res/layout/activity_login.xml.ftl69
-rw-r--r--templates/activities/LoginActivity/root/res/menu/activity_login.xml5
-rw-r--r--templates/activities/LoginActivity/root/res/values-large/styles.xml10
-rw-r--r--templates/activities/LoginActivity/root/res/values/strings.xml.ftl19
-rw-r--r--templates/activities/LoginActivity/root/res/values/styles.xml9
-rw-r--r--templates/activities/LoginActivity/root/src/app_package/LoginActivity.java.ftl278
-rw-r--r--templates/activities/LoginActivity/template.xml60
-rw-r--r--templates/activities/LoginActivity/template_login_activity.pngbin0 -> 5939 bytes
-rw-r--r--templates/activities/MasterDetailFlow/root/AndroidManifest.xml.ftl2
-rw-r--r--uiautomatorviewer/.classpath12
-rw-r--r--uiautomatorviewer/.gitignore1
-rw-r--r--uiautomatorviewer/.project17
-rw-r--r--uiautomatorviewer/Android.mk2
-rw-r--r--uiautomatorviewer/MODULE_LICENSE_APACHE20
-rw-r--r--uiautomatorviewer/src/com/android/uiautomator/DebugBridge.java76
-rw-r--r--uiautomatorviewer/src/com/android/uiautomator/UiAutomatorViewer.java5
-rw-r--r--uiautomatorviewer/src/com/android/uiautomator/actions/ScreenshotAction.java299
448 files changed, 11515 insertions, 1642 deletions
diff --git a/anttasks/src/com/android/ant/LintExecTask.java b/anttasks/src/com/android/ant/LintExecTask.java
index 64a6c00..3d687cb 100644
--- a/anttasks/src/com/android/ant/LintExecTask.java
+++ b/anttasks/src/com/android/ant/LintExecTask.java
@@ -28,6 +28,8 @@ public class LintExecTask extends ExecTask {
private String mExecutable;
private String mHtml;
private String mXml;
+ private Path mSourcePath;
+ private Path mClassPath;
/**
* Sets the value of the "executable" attribute.
@@ -37,6 +39,16 @@ public class LintExecTask extends ExecTask {
mExecutable = TaskHelper.checkSinglePath("executable", executable);
}
+ /** Sets the path where Java source code should be found */
+ public void setSrc(Path path) {
+ mSourcePath = path;
+ }
+
+ /** Sets the path where class files should be found */
+ public void setClasspath(Path path) {
+ mClassPath = path;
+ }
+
/**
* Sets the value of the "html" attribute: a path to a file or directory name
* where the HTML report should be written.
@@ -80,6 +92,16 @@ public class LintExecTask extends ExecTask {
task.createArg().setValue(mXml);
}
+ if (mSourcePath != null) {
+ task.createArg().setValue("--sources");
+ task.createArg().setValue(mSourcePath.toString());
+ }
+
+ if (mClassPath != null) {
+ task.createArg().setValue("--classpath");
+ task.createArg().setValue(mClassPath.toString());
+ }
+
task.createArg().setValue(getProject().getBaseDir().getAbsolutePath());
task.execute();
}
diff --git a/assetstudio/src/images/clipart/big/1-navigation-accept.png b/assetstudio/src/images/clipart/big/1-navigation-accept.png
new file mode 100644
index 0000000..121b347
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/1-navigation-accept.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/1-navigation-back.png b/assetstudio/src/images/clipart/big/1-navigation-back.png
new file mode 100644
index 0000000..863074c
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/1-navigation-back.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/1-navigation-cancel.png b/assetstudio/src/images/clipart/big/1-navigation-cancel.png
new file mode 100644
index 0000000..d968d34
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/1-navigation-cancel.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/1-navigation-collapse.png b/assetstudio/src/images/clipart/big/1-navigation-collapse.png
new file mode 100644
index 0000000..e525983
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/1-navigation-collapse.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/1-navigation-expand.png b/assetstudio/src/images/clipart/big/1-navigation-expand.png
new file mode 100644
index 0000000..f5b0728
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/1-navigation-expand.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/1-navigation-forward.png b/assetstudio/src/images/clipart/big/1-navigation-forward.png
new file mode 100644
index 0000000..4cae802
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/1-navigation-forward.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/1-navigation-next-item.png b/assetstudio/src/images/clipart/big/1-navigation-next-item.png
new file mode 100644
index 0000000..a1b8b83
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/1-navigation-next-item.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/1-navigation-previous-item.png b/assetstudio/src/images/clipart/big/1-navigation-previous-item.png
new file mode 100644
index 0000000..9312bf6
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/1-navigation-previous-item.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/1-navigation-refresh.png b/assetstudio/src/images/clipart/big/1-navigation-refresh.png
new file mode 100644
index 0000000..b5202f9
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/1-navigation-refresh.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-accounts.png b/assetstudio/src/images/clipart/big/10-device-access-accounts.png
new file mode 100644
index 0000000..64544c5
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-accounts.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-add-alarm.png b/assetstudio/src/images/clipart/big/10-device-access-add-alarm.png
new file mode 100644
index 0000000..bd4bcc3
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-add-alarm.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-alarms.png b/assetstudio/src/images/clipart/big/10-device-access-alarms.png
new file mode 100644
index 0000000..a5b1ead
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-alarms.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-battery.png b/assetstudio/src/images/clipart/big/10-device-access-battery.png
new file mode 100644
index 0000000..d86b2c1
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-battery.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-bightness-low.png b/assetstudio/src/images/clipart/big/10-device-access-bightness-low.png
new file mode 100644
index 0000000..738f203
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-bightness-low.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-bluetooth-connected.png b/assetstudio/src/images/clipart/big/10-device-access-bluetooth-connected.png
new file mode 100644
index 0000000..403a0b5
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-bluetooth-connected.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-bluetooth-searching.png b/assetstudio/src/images/clipart/big/10-device-access-bluetooth-searching.png
new file mode 100644
index 0000000..a99f65a
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-bluetooth-searching.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-bluetooth.png b/assetstudio/src/images/clipart/big/10-device-access-bluetooth.png
new file mode 100644
index 0000000..556499d
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-bluetooth.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-brightness-auto.png b/assetstudio/src/images/clipart/big/10-device-access-brightness-auto.png
new file mode 100644
index 0000000..46d2b8a
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-brightness-auto.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-brightness-high.png b/assetstudio/src/images/clipart/big/10-device-access-brightness-high.png
new file mode 100644
index 0000000..97e3f19
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-brightness-high.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-brightness-medium.png b/assetstudio/src/images/clipart/big/10-device-access-brightness-medium.png
new file mode 100644
index 0000000..5e361cb
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-brightness-medium.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-call.png b/assetstudio/src/images/clipart/big/10-device-access-call.png
new file mode 100644
index 0000000..940bcb6
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-call.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-camera.png b/assetstudio/src/images/clipart/big/10-device-access-camera.png
new file mode 100644
index 0000000..ad8857a
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-camera.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-data-usage.png b/assetstudio/src/images/clipart/big/10-device-access-data-usage.png
new file mode 100644
index 0000000..9fa73a5
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-data-usage.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-dial-pad.png b/assetstudio/src/images/clipart/big/10-device-access-dial-pad.png
new file mode 100644
index 0000000..81da080
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-dial-pad.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-end-call.png b/assetstudio/src/images/clipart/big/10-device-access-end-call.png
new file mode 100644
index 0000000..c28f284
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-end-call.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-flash-automatic.png b/assetstudio/src/images/clipart/big/10-device-access-flash-automatic.png
new file mode 100644
index 0000000..e5c2c03
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-flash-automatic.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-flash-off.png b/assetstudio/src/images/clipart/big/10-device-access-flash-off.png
new file mode 100644
index 0000000..dfcb747
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-flash-off.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-flash-on.png b/assetstudio/src/images/clipart/big/10-device-access-flash-on.png
new file mode 100644
index 0000000..1109aa0
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-flash-on.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-location-found.png b/assetstudio/src/images/clipart/big/10-device-access-location-found.png
new file mode 100644
index 0000000..d829a3c
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-location-found.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-location-off.png b/assetstudio/src/images/clipart/big/10-device-access-location-off.png
new file mode 100644
index 0000000..e58c258
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-location-off.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-location-searching.png b/assetstudio/src/images/clipart/big/10-device-access-location-searching.png
new file mode 100644
index 0000000..3de2f26
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-location-searching.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-mic-muted.png b/assetstudio/src/images/clipart/big/10-device-access-mic-muted.png
new file mode 100644
index 0000000..65b4ae6
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-mic-muted.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-mic.png b/assetstudio/src/images/clipart/big/10-device-access-mic.png
new file mode 100644
index 0000000..02c1ee8
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-mic.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-network-cell.png b/assetstudio/src/images/clipart/big/10-device-access-network-cell.png
new file mode 100644
index 0000000..9d60dbd
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-network-cell.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-network-wifi.png b/assetstudio/src/images/clipart/big/10-device-access-network-wifi.png
new file mode 100644
index 0000000..577abdb
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-network-wifi.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-new-account.png b/assetstudio/src/images/clipart/big/10-device-access-new-account.png
new file mode 100644
index 0000000..d9707d8
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-new-account.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-not-secure.png b/assetstudio/src/images/clipart/big/10-device-access-not-secure.png
new file mode 100644
index 0000000..2ea293a
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-not-secure.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-ring-volume.png b/assetstudio/src/images/clipart/big/10-device-access-ring-volume.png
new file mode 100644
index 0000000..9d19f89
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-ring-volume.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-screen-locked-to-landscape.png b/assetstudio/src/images/clipart/big/10-device-access-screen-locked-to-landscape.png
new file mode 100644
index 0000000..c702480
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-screen-locked-to-landscape.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-screen-locked-to-portrait.png b/assetstudio/src/images/clipart/big/10-device-access-screen-locked-to-portrait.png
new file mode 100644
index 0000000..f66923c
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-screen-locked-to-portrait.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-screen-rotation.png b/assetstudio/src/images/clipart/big/10-device-access-screen-rotation.png
new file mode 100644
index 0000000..22e0fcb
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-screen-rotation.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-sd-storage.png b/assetstudio/src/images/clipart/big/10-device-access-sd-storage.png
new file mode 100644
index 0000000..cbde363
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-sd-storage.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-secure.png b/assetstudio/src/images/clipart/big/10-device-access-secure.png
new file mode 100644
index 0000000..83f4f7d
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-secure.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-storage.png b/assetstudio/src/images/clipart/big/10-device-access-storage.png
new file mode 100644
index 0000000..5addbad
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-storage.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-switch-camera.png b/assetstudio/src/images/clipart/big/10-device-access-switch-camera.png
new file mode 100644
index 0000000..8b2a2e3
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-switch-camera.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-switch-video.png b/assetstudio/src/images/clipart/big/10-device-access-switch-video.png
new file mode 100644
index 0000000..a2919f1
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-switch-video.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-time.png b/assetstudio/src/images/clipart/big/10-device-access-time.png
new file mode 100644
index 0000000..aa21482
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-time.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-usb.png b/assetstudio/src/images/clipart/big/10-device-access-usb.png
new file mode 100644
index 0000000..ba01983
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-usb.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-video.png b/assetstudio/src/images/clipart/big/10-device-access-video.png
new file mode 100644
index 0000000..e18c6bd
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-video.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-volume-muted.png b/assetstudio/src/images/clipart/big/10-device-access-volume-muted.png
new file mode 100644
index 0000000..10433a7
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-volume-muted.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/10-device-access-volume-on.png b/assetstudio/src/images/clipart/big/10-device-access-volume-on.png
new file mode 100644
index 0000000..bc86a7b
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/10-device-access-volume-on.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/11-alerts-and-states-airplane-mode-off.png b/assetstudio/src/images/clipart/big/11-alerts-and-states-airplane-mode-off.png
new file mode 100644
index 0000000..f7db5e8
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/11-alerts-and-states-airplane-mode-off.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/11-alerts-and-states-airplane-mode-on.png b/assetstudio/src/images/clipart/big/11-alerts-and-states-airplane-mode-on.png
new file mode 100644
index 0000000..7e8bf73
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/11-alerts-and-states-airplane-mode-on.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/11-alerts-and-states-error.png b/assetstudio/src/images/clipart/big/11-alerts-and-states-error.png
new file mode 100644
index 0000000..24335f9
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/11-alerts-and-states-error.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/11-alerts-and-states-warning.png b/assetstudio/src/images/clipart/big/11-alerts-and-states-warning.png
new file mode 100644
index 0000000..be321f4
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/11-alerts-and-states-warning.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/12-hardware-computer.png b/assetstudio/src/images/clipart/big/12-hardware-computer.png
new file mode 100644
index 0000000..6170018
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/12-hardware-computer.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/12-hardware-dock.png b/assetstudio/src/images/clipart/big/12-hardware-dock.png
new file mode 100644
index 0000000..c2fc8c8
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/12-hardware-dock.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/12-hardware-gamepad.png b/assetstudio/src/images/clipart/big/12-hardware-gamepad.png
new file mode 100644
index 0000000..3ddc322
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/12-hardware-gamepad.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/12-hardware-headphones.png b/assetstudio/src/images/clipart/big/12-hardware-headphones.png
new file mode 100644
index 0000000..e7bce69
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/12-hardware-headphones.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/12-hardware-headset.png b/assetstudio/src/images/clipart/big/12-hardware-headset.png
new file mode 100644
index 0000000..29f659b
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/12-hardware-headset.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/12-hardware-keyboard.png b/assetstudio/src/images/clipart/big/12-hardware-keyboard.png
new file mode 100644
index 0000000..4a2bf70
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/12-hardware-keyboard.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/12-hardware-mouse.png b/assetstudio/src/images/clipart/big/12-hardware-mouse.png
new file mode 100644
index 0000000..2bf8c05
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/12-hardware-mouse.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/12-hardware-phone.png b/assetstudio/src/images/clipart/big/12-hardware-phone.png
new file mode 100644
index 0000000..423fe65
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/12-hardware-phone.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/2-action-about.png b/assetstudio/src/images/clipart/big/2-action-about.png
new file mode 100644
index 0000000..6d43316
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/2-action-about.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/2-action-help.png b/assetstudio/src/images/clipart/big/2-action-help.png
new file mode 100644
index 0000000..16eb8ef
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/2-action-help.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/2-action-search.png b/assetstudio/src/images/clipart/big/2-action-search.png
new file mode 100644
index 0000000..9345a06
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/2-action-search.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/2-action-settings.png b/assetstudio/src/images/clipart/big/2-action-settings.png
new file mode 100644
index 0000000..a049ca0
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/2-action-settings.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/3-rating-bad.png b/assetstudio/src/images/clipart/big/3-rating-bad.png
new file mode 100644
index 0000000..1ab8c5b
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/3-rating-bad.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/3-rating-favorite.png b/assetstudio/src/images/clipart/big/3-rating-favorite.png
new file mode 100644
index 0000000..9b68720
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/3-rating-favorite.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/3-rating-good.png b/assetstudio/src/images/clipart/big/3-rating-good.png
new file mode 100644
index 0000000..c72826b
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/3-rating-good.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/3-rating-half-important.png b/assetstudio/src/images/clipart/big/3-rating-half-important.png
new file mode 100644
index 0000000..2110a0f
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/3-rating-half-important.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/3-rating-important.png b/assetstudio/src/images/clipart/big/3-rating-important.png
new file mode 100644
index 0000000..dbad544
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/3-rating-important.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/3-rating-not-important.png b/assetstudio/src/images/clipart/big/3-rating-not-important.png
new file mode 100644
index 0000000..f7cf26f
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/3-rating-not-important.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/4-collections-cloud.png b/assetstudio/src/images/clipart/big/4-collections-cloud.png
new file mode 100644
index 0000000..a2cedbf
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/4-collections-cloud.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/4-collections-collection.png b/assetstudio/src/images/clipart/big/4-collections-collection.png
new file mode 100644
index 0000000..dfb2508
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/4-collections-collection.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/4-collections-go-to-today.png b/assetstudio/src/images/clipart/big/4-collections-go-to-today.png
new file mode 100644
index 0000000..b4971ca
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/4-collections-go-to-today.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/4-collections-labels.png b/assetstudio/src/images/clipart/big/4-collections-labels.png
new file mode 100644
index 0000000..16f35a8
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/4-collections-labels.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/4-collections-new-label.png b/assetstudio/src/images/clipart/big/4-collections-new-label.png
new file mode 100644
index 0000000..cbf02af
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/4-collections-new-label.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/4-collections-sort-by-size.png b/assetstudio/src/images/clipart/big/4-collections-sort-by-size.png
new file mode 100644
index 0000000..10aec0d
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/4-collections-sort-by-size.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/4-collections-view-as-grid.png b/assetstudio/src/images/clipart/big/4-collections-view-as-grid.png
new file mode 100644
index 0000000..10a8fe3
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/4-collections-view-as-grid.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/4-collections-view-as-list.png b/assetstudio/src/images/clipart/big/4-collections-view-as-list.png
new file mode 100644
index 0000000..5cf08e4
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/4-collections-view-as-list.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/5-content-attachment.png b/assetstudio/src/images/clipart/big/5-content-attachment.png
new file mode 100644
index 0000000..92e6726
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/5-content-attachment.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/5-content-backspace.png b/assetstudio/src/images/clipart/big/5-content-backspace.png
new file mode 100644
index 0000000..9a7e456
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/5-content-backspace.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/5-content-copy.png b/assetstudio/src/images/clipart/big/5-content-copy.png
new file mode 100644
index 0000000..284a5ce
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/5-content-copy.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/5-content-cut.png b/assetstudio/src/images/clipart/big/5-content-cut.png
new file mode 100644
index 0000000..18d1763
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/5-content-cut.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/5-content-discard.png b/assetstudio/src/images/clipart/big/5-content-discard.png
new file mode 100644
index 0000000..e40e1fe
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/5-content-discard.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/5-content-edit.png b/assetstudio/src/images/clipart/big/5-content-edit.png
new file mode 100644
index 0000000..f75157c
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/5-content-edit.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/5-content-email.png b/assetstudio/src/images/clipart/big/5-content-email.png
new file mode 100644
index 0000000..6bec626
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/5-content-email.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/5-content-event.png b/assetstudio/src/images/clipart/big/5-content-event.png
new file mode 100644
index 0000000..dc4ed94
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/5-content-event.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/5-content-import-export.png b/assetstudio/src/images/clipart/big/5-content-import-export.png
new file mode 100644
index 0000000..7dcd6b0
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/5-content-import-export.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/5-content-merge.png b/assetstudio/src/images/clipart/big/5-content-merge.png
new file mode 100644
index 0000000..45ca498
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/5-content-merge.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/5-content-new-attachment.png b/assetstudio/src/images/clipart/big/5-content-new-attachment.png
new file mode 100644
index 0000000..3e441d8
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/5-content-new-attachment.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/5-content-new-email.png b/assetstudio/src/images/clipart/big/5-content-new-email.png
new file mode 100644
index 0000000..fdcd64b
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/5-content-new-email.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/5-content-new-event.png b/assetstudio/src/images/clipart/big/5-content-new-event.png
new file mode 100644
index 0000000..29ef513
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/5-content-new-event.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/5-content-new-picture.png b/assetstudio/src/images/clipart/big/5-content-new-picture.png
new file mode 100644
index 0000000..1975219
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/5-content-new-picture.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/5-content-new.png b/assetstudio/src/images/clipart/big/5-content-new.png
new file mode 100644
index 0000000..9bb4337
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/5-content-new.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/5-content-paste.png b/assetstudio/src/images/clipart/big/5-content-paste.png
new file mode 100644
index 0000000..f9393c0
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/5-content-paste.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/5-content-picture.png b/assetstudio/src/images/clipart/big/5-content-picture.png
new file mode 100644
index 0000000..dc3251b
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/5-content-picture.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/5-content-read.png b/assetstudio/src/images/clipart/big/5-content-read.png
new file mode 100644
index 0000000..0a48d75
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/5-content-read.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/5-content-remove.png b/assetstudio/src/images/clipart/big/5-content-remove.png
new file mode 100644
index 0000000..d968d34
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/5-content-remove.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/5-content-save.png b/assetstudio/src/images/clipart/big/5-content-save.png
new file mode 100644
index 0000000..befe49a
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/5-content-save.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/5-content-select-all.png b/assetstudio/src/images/clipart/big/5-content-select-all.png
new file mode 100644
index 0000000..572b2b5
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/5-content-select-all.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/5-content-split.png b/assetstudio/src/images/clipart/big/5-content-split.png
new file mode 100644
index 0000000..7e5d059
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/5-content-split.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/5-content-undo.png b/assetstudio/src/images/clipart/big/5-content-undo.png
new file mode 100644
index 0000000..07fc7d8
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/5-content-undo.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/5-content-unread.png b/assetstudio/src/images/clipart/big/5-content-unread.png
new file mode 100644
index 0000000..41ba9e2
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/5-content-unread.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/6-social-add-group.png b/assetstudio/src/images/clipart/big/6-social-add-group.png
new file mode 100644
index 0000000..7822f4f
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/6-social-add-group.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/6-social-add-person.png b/assetstudio/src/images/clipart/big/6-social-add-person.png
new file mode 100644
index 0000000..b335788
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/6-social-add-person.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/6-social-cc-bcc.png b/assetstudio/src/images/clipart/big/6-social-cc-bcc.png
new file mode 100644
index 0000000..4db30a7
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/6-social-cc-bcc.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/6-social-chat.png b/assetstudio/src/images/clipart/big/6-social-chat.png
new file mode 100644
index 0000000..b0cccb3
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/6-social-chat.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/6-social-forward.png b/assetstudio/src/images/clipart/big/6-social-forward.png
new file mode 100644
index 0000000..a5abbfc
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/6-social-forward.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/6-social-group.png b/assetstudio/src/images/clipart/big/6-social-group.png
new file mode 100644
index 0000000..1b18678
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/6-social-group.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/6-social-person.png b/assetstudio/src/images/clipart/big/6-social-person.png
new file mode 100644
index 0000000..27ade22
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/6-social-person.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/6-social-reply-all.png b/assetstudio/src/images/clipart/big/6-social-reply-all.png
new file mode 100644
index 0000000..c2a87c6
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/6-social-reply-all.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/6-social-reply.png b/assetstudio/src/images/clipart/big/6-social-reply.png
new file mode 100644
index 0000000..550aa80
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/6-social-reply.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/6-social-send-now.png b/assetstudio/src/images/clipart/big/6-social-send-now.png
new file mode 100644
index 0000000..c3dad3c
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/6-social-send-now.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/6-social-share.png b/assetstudio/src/images/clipart/big/6-social-share.png
new file mode 100644
index 0000000..b664970
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/6-social-share.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/7-location-directions.png b/assetstudio/src/images/clipart/big/7-location-directions.png
new file mode 100644
index 0000000..c0e67e4
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/7-location-directions.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/7-location-map.png b/assetstudio/src/images/clipart/big/7-location-map.png
new file mode 100644
index 0000000..e32dc26
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/7-location-map.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/7-location-place.png b/assetstudio/src/images/clipart/big/7-location-place.png
new file mode 100644
index 0000000..fec173c
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/7-location-place.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/7-location-web-site.png b/assetstudio/src/images/clipart/big/7-location-web-site.png
new file mode 100644
index 0000000..4ef24a3
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/7-location-web-site.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/8-images-crop.png b/assetstudio/src/images/clipart/big/8-images-crop.png
new file mode 100644
index 0000000..bd44bf9
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/8-images-crop.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/8-images-rotate-left.png b/assetstudio/src/images/clipart/big/8-images-rotate-left.png
new file mode 100644
index 0000000..0410adb
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/8-images-rotate-left.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/8-images-rotate-right.png b/assetstudio/src/images/clipart/big/8-images-rotate-right.png
new file mode 100644
index 0000000..abcff9c
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/8-images-rotate-right.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/8-images-slideshow.png b/assetstudio/src/images/clipart/big/8-images-slideshow.png
new file mode 100644
index 0000000..94e47b4
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/8-images-slideshow.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/9-av-add-to-queue.png b/assetstudio/src/images/clipart/big/9-av-add-to-queue.png
new file mode 100644
index 0000000..57b2e61
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/9-av-add-to-queue.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/9-av-download.png b/assetstudio/src/images/clipart/big/9-av-download.png
new file mode 100644
index 0000000..46a1919
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/9-av-download.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/9-av-fast-forward.png b/assetstudio/src/images/clipart/big/9-av-fast-forward.png
new file mode 100644
index 0000000..f820f5a
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/9-av-fast-forward.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/9-av-full-screen.png b/assetstudio/src/images/clipart/big/9-av-full-screen.png
new file mode 100644
index 0000000..1dfd01a
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/9-av-full-screen.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/9-av-make-available-offline.png b/assetstudio/src/images/clipart/big/9-av-make-available-offline.png
new file mode 100644
index 0000000..2efcb11
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/9-av-make-available-offline.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/9-av-next.png b/assetstudio/src/images/clipart/big/9-av-next.png
new file mode 100644
index 0000000..871587c
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/9-av-next.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/9-av-pause-over-video.png b/assetstudio/src/images/clipart/big/9-av-pause-over-video.png
new file mode 100644
index 0000000..a2665f2
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/9-av-pause-over-video.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/9-av-pause.png b/assetstudio/src/images/clipart/big/9-av-pause.png
new file mode 100644
index 0000000..506b1d4
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/9-av-pause.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/9-av-play-over-video.png b/assetstudio/src/images/clipart/big/9-av-play-over-video.png
new file mode 100644
index 0000000..3db3a1a
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/9-av-play-over-video.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/9-av-play.png b/assetstudio/src/images/clipart/big/9-av-play.png
new file mode 100644
index 0000000..0c12f86
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/9-av-play.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/9-av-previous.png b/assetstudio/src/images/clipart/big/9-av-previous.png
new file mode 100644
index 0000000..28f2596
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/9-av-previous.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/9-av-repeat.png b/assetstudio/src/images/clipart/big/9-av-repeat.png
new file mode 100644
index 0000000..9a7a79a
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/9-av-repeat.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/9-av-replay.png b/assetstudio/src/images/clipart/big/9-av-replay.png
new file mode 100644
index 0000000..ce9df7f
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/9-av-replay.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/9-av-return-from-full-screen.png b/assetstudio/src/images/clipart/big/9-av-return-from-full-screen.png
new file mode 100644
index 0000000..24725c0
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/9-av-return-from-full-screen.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/9-av-rewind.png b/assetstudio/src/images/clipart/big/9-av-rewind.png
new file mode 100644
index 0000000..b09f61a
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/9-av-rewind.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/9-av-shuffle.png b/assetstudio/src/images/clipart/big/9-av-shuffle.png
new file mode 100644
index 0000000..6e90f7c
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/9-av-shuffle.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/9-av-stop.png b/assetstudio/src/images/clipart/big/9-av-stop.png
new file mode 100644
index 0000000..9ba88ee
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/9-av-stop.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/9-av-upload.png b/assetstudio/src/images/clipart/big/9-av-upload.png
new file mode 100644
index 0000000..41da601
--- /dev/null
+++ b/assetstudio/src/images/clipart/big/9-av-upload.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/attach.png b/assetstudio/src/images/clipart/big/attach.png
deleted file mode 100644
index cfadc2b..0000000
--- a/assetstudio/src/images/clipart/big/attach.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/call.png b/assetstudio/src/images/clipart/big/call.png
deleted file mode 100644
index b642c81..0000000
--- a/assetstudio/src/images/clipart/big/call.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/copy.png b/assetstudio/src/images/clipart/big/copy.png
deleted file mode 100644
index a018ff3..0000000
--- a/assetstudio/src/images/clipart/big/copy.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/cut.png b/assetstudio/src/images/clipart/big/cut.png
deleted file mode 100644
index 29034d1..0000000
--- a/assetstudio/src/images/clipart/big/cut.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/delete.png b/assetstudio/src/images/clipart/big/delete.png
deleted file mode 100644
index ea82cc7..0000000
--- a/assetstudio/src/images/clipart/big/delete.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/done.png b/assetstudio/src/images/clipart/big/done.png
deleted file mode 100644
index 56e57b9..0000000
--- a/assetstudio/src/images/clipart/big/done.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/edit.png b/assetstudio/src/images/clipart/big/edit.png
deleted file mode 100644
index 5a98da6..0000000
--- a/assetstudio/src/images/clipart/big/edit.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/locate.png b/assetstudio/src/images/clipart/big/locate.png
deleted file mode 100644
index 222f25c..0000000
--- a/assetstudio/src/images/clipart/big/locate.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/mail.png b/assetstudio/src/images/clipart/big/mail.png
deleted file mode 100644
index 5f66d14..0000000
--- a/assetstudio/src/images/clipart/big/mail.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/microphone.png b/assetstudio/src/images/clipart/big/microphone.png
deleted file mode 100644
index 0ede452..0000000
--- a/assetstudio/src/images/clipart/big/microphone.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/overflow.png b/assetstudio/src/images/clipart/big/overflow.png
deleted file mode 100644
index e88a95a..0000000
--- a/assetstudio/src/images/clipart/big/overflow.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/paste.png b/assetstudio/src/images/clipart/big/paste.png
deleted file mode 100644
index 5a9a59d..0000000
--- a/assetstudio/src/images/clipart/big/paste.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/photo.png b/assetstudio/src/images/clipart/big/photo.png
deleted file mode 100644
index 9e52bfb..0000000
--- a/assetstudio/src/images/clipart/big/photo.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/refresh.png b/assetstudio/src/images/clipart/big/refresh.png
deleted file mode 100644
index 4c4e7cf..0000000
--- a/assetstudio/src/images/clipart/big/refresh.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/search.png b/assetstudio/src/images/clipart/big/search.png
deleted file mode 100644
index b5a3572..0000000
--- a/assetstudio/src/images/clipart/big/search.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/select_all.png b/assetstudio/src/images/clipart/big/select_all.png
deleted file mode 100644
index b962a04..0000000
--- a/assetstudio/src/images/clipart/big/select_all.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/send.png b/assetstudio/src/images/clipart/big/send.png
deleted file mode 100644
index e7644cf..0000000
--- a/assetstudio/src/images/clipart/big/send.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/share.png b/assetstudio/src/images/clipart/big/share.png
deleted file mode 100644
index 95185d5..0000000
--- a/assetstudio/src/images/clipart/big/share.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/star.png b/assetstudio/src/images/clipart/big/star.png
deleted file mode 100644
index 0a245ce..0000000
--- a/assetstudio/src/images/clipart/big/star.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/user.png b/assetstudio/src/images/clipart/big/user.png
deleted file mode 100644
index bc1d946..0000000
--- a/assetstudio/src/images/clipart/big/user.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/big/video.png b/assetstudio/src/images/clipart/big/video.png
deleted file mode 100644
index 473076f..0000000
--- a/assetstudio/src/images/clipart/big/video.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/1-navigation-accept.png b/assetstudio/src/images/clipart/small/1-navigation-accept.png
new file mode 100644
index 0000000..f5069d9
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/1-navigation-accept.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/1-navigation-back.png b/assetstudio/src/images/clipart/small/1-navigation-back.png
new file mode 100644
index 0000000..f35aec5
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/1-navigation-back.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/1-navigation-cancel.png b/assetstudio/src/images/clipart/small/1-navigation-cancel.png
new file mode 100644
index 0000000..4302320
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/1-navigation-cancel.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/1-navigation-collapse.png b/assetstudio/src/images/clipart/small/1-navigation-collapse.png
new file mode 100644
index 0000000..9c40e2c
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/1-navigation-collapse.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/1-navigation-expand.png b/assetstudio/src/images/clipart/small/1-navigation-expand.png
new file mode 100644
index 0000000..684fc5a
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/1-navigation-expand.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/1-navigation-forward.png b/assetstudio/src/images/clipart/small/1-navigation-forward.png
new file mode 100644
index 0000000..beb6cf7
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/1-navigation-forward.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/1-navigation-next-item.png b/assetstudio/src/images/clipart/small/1-navigation-next-item.png
new file mode 100644
index 0000000..932d787
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/1-navigation-next-item.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/1-navigation-previous-item.png b/assetstudio/src/images/clipart/small/1-navigation-previous-item.png
new file mode 100644
index 0000000..679b586
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/1-navigation-previous-item.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/1-navigation-refresh.png b/assetstudio/src/images/clipart/small/1-navigation-refresh.png
new file mode 100644
index 0000000..b946402
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/1-navigation-refresh.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-accounts.png b/assetstudio/src/images/clipart/small/10-device-access-accounts.png
new file mode 100644
index 0000000..34b4d6a
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-accounts.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-add-alarm.png b/assetstudio/src/images/clipart/small/10-device-access-add-alarm.png
new file mode 100644
index 0000000..27c528a
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-add-alarm.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-alarms.png b/assetstudio/src/images/clipart/small/10-device-access-alarms.png
new file mode 100644
index 0000000..545a8fa
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-alarms.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-battery.png b/assetstudio/src/images/clipart/small/10-device-access-battery.png
new file mode 100644
index 0000000..52e08bf
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-battery.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-bightness-low.png b/assetstudio/src/images/clipart/small/10-device-access-bightness-low.png
new file mode 100644
index 0000000..a34cdea
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-bightness-low.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-bluetooth-connected.png b/assetstudio/src/images/clipart/small/10-device-access-bluetooth-connected.png
new file mode 100644
index 0000000..d04e9f4
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-bluetooth-connected.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-bluetooth-searching.png b/assetstudio/src/images/clipart/small/10-device-access-bluetooth-searching.png
new file mode 100644
index 0000000..06d69ae
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-bluetooth-searching.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-bluetooth.png b/assetstudio/src/images/clipart/small/10-device-access-bluetooth.png
new file mode 100644
index 0000000..11ad6b3
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-bluetooth.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-brightness-auto.png b/assetstudio/src/images/clipart/small/10-device-access-brightness-auto.png
new file mode 100644
index 0000000..cd50b9d
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-brightness-auto.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-brightness-high.png b/assetstudio/src/images/clipart/small/10-device-access-brightness-high.png
new file mode 100644
index 0000000..b9d8501
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-brightness-high.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-brightness-medium.png b/assetstudio/src/images/clipart/small/10-device-access-brightness-medium.png
new file mode 100644
index 0000000..7145eee
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-brightness-medium.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-call.png b/assetstudio/src/images/clipart/small/10-device-access-call.png
new file mode 100644
index 0000000..732e551
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-call.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-camera.png b/assetstudio/src/images/clipart/small/10-device-access-camera.png
new file mode 100644
index 0000000..f61ab27
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-camera.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-data-usage.png b/assetstudio/src/images/clipart/small/10-device-access-data-usage.png
new file mode 100644
index 0000000..a78127f
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-data-usage.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-dial-pad.png b/assetstudio/src/images/clipart/small/10-device-access-dial-pad.png
new file mode 100644
index 0000000..cfbee88
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-dial-pad.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-end-call.png b/assetstudio/src/images/clipart/small/10-device-access-end-call.png
new file mode 100644
index 0000000..2562d0d
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-end-call.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-flash-automatic.png b/assetstudio/src/images/clipart/small/10-device-access-flash-automatic.png
new file mode 100644
index 0000000..574219c
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-flash-automatic.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-flash-off.png b/assetstudio/src/images/clipart/small/10-device-access-flash-off.png
new file mode 100644
index 0000000..80e3d06
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-flash-off.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-flash-on.png b/assetstudio/src/images/clipart/small/10-device-access-flash-on.png
new file mode 100644
index 0000000..c9c2fff
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-flash-on.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-location-found.png b/assetstudio/src/images/clipart/small/10-device-access-location-found.png
new file mode 100644
index 0000000..4221d83
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-location-found.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-location-off.png b/assetstudio/src/images/clipart/small/10-device-access-location-off.png
new file mode 100644
index 0000000..ea0511d
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-location-off.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-location-searching.png b/assetstudio/src/images/clipart/small/10-device-access-location-searching.png
new file mode 100644
index 0000000..ef9dc2e
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-location-searching.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-mic-muted.png b/assetstudio/src/images/clipart/small/10-device-access-mic-muted.png
new file mode 100644
index 0000000..87bc6b3
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-mic-muted.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-mic.png b/assetstudio/src/images/clipart/small/10-device-access-mic.png
new file mode 100644
index 0000000..7569d6a
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-mic.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-network-cell.png b/assetstudio/src/images/clipart/small/10-device-access-network-cell.png
new file mode 100644
index 0000000..7a2c443
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-network-cell.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-network-wifi.png b/assetstudio/src/images/clipart/small/10-device-access-network-wifi.png
new file mode 100644
index 0000000..e25cc64
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-network-wifi.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-new-account.png b/assetstudio/src/images/clipart/small/10-device-access-new-account.png
new file mode 100644
index 0000000..c537899
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-new-account.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-not-secure.png b/assetstudio/src/images/clipart/small/10-device-access-not-secure.png
new file mode 100644
index 0000000..89c732e
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-not-secure.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-ring-volume.png b/assetstudio/src/images/clipart/small/10-device-access-ring-volume.png
new file mode 100644
index 0000000..5bfe27a
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-ring-volume.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-screen-locked-to-landscape.png b/assetstudio/src/images/clipart/small/10-device-access-screen-locked-to-landscape.png
new file mode 100644
index 0000000..a3b2bbb
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-screen-locked-to-landscape.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-screen-locked-to-portrait.png b/assetstudio/src/images/clipart/small/10-device-access-screen-locked-to-portrait.png
new file mode 100644
index 0000000..270c069
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-screen-locked-to-portrait.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-screen-rotation.png b/assetstudio/src/images/clipart/small/10-device-access-screen-rotation.png
new file mode 100644
index 0000000..a5337e9
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-screen-rotation.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-sd-storage.png b/assetstudio/src/images/clipart/small/10-device-access-sd-storage.png
new file mode 100644
index 0000000..fe09aca
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-sd-storage.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-secure.png b/assetstudio/src/images/clipart/small/10-device-access-secure.png
new file mode 100644
index 0000000..9bf3627
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-secure.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-storage.png b/assetstudio/src/images/clipart/small/10-device-access-storage.png
new file mode 100644
index 0000000..1d38109
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-storage.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-switch-camera.png b/assetstudio/src/images/clipart/small/10-device-access-switch-camera.png
new file mode 100644
index 0000000..972e3b3
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-switch-camera.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-switch-video.png b/assetstudio/src/images/clipart/small/10-device-access-switch-video.png
new file mode 100644
index 0000000..2ae54f4
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-switch-video.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-time.png b/assetstudio/src/images/clipart/small/10-device-access-time.png
new file mode 100644
index 0000000..f3d932e
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-time.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-usb.png b/assetstudio/src/images/clipart/small/10-device-access-usb.png
new file mode 100644
index 0000000..490d286
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-usb.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-video.png b/assetstudio/src/images/clipart/small/10-device-access-video.png
new file mode 100644
index 0000000..d069de4
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-video.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-volume-muted.png b/assetstudio/src/images/clipart/small/10-device-access-volume-muted.png
new file mode 100644
index 0000000..283d621
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-volume-muted.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/10-device-access-volume-on.png b/assetstudio/src/images/clipart/small/10-device-access-volume-on.png
new file mode 100644
index 0000000..a1d6670
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/10-device-access-volume-on.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/11-alerts-and-states-airplane-mode-off.png b/assetstudio/src/images/clipart/small/11-alerts-and-states-airplane-mode-off.png
new file mode 100644
index 0000000..bfce2ee
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/11-alerts-and-states-airplane-mode-off.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/11-alerts-and-states-airplane-mode-on.png b/assetstudio/src/images/clipart/small/11-alerts-and-states-airplane-mode-on.png
new file mode 100644
index 0000000..fba67ae
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/11-alerts-and-states-airplane-mode-on.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/11-alerts-and-states-error.png b/assetstudio/src/images/clipart/small/11-alerts-and-states-error.png
new file mode 100644
index 0000000..a32766b
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/11-alerts-and-states-error.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/11-alerts-and-states-warning.png b/assetstudio/src/images/clipart/small/11-alerts-and-states-warning.png
new file mode 100644
index 0000000..37af134
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/11-alerts-and-states-warning.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/12-hardware-computer.png b/assetstudio/src/images/clipart/small/12-hardware-computer.png
new file mode 100644
index 0000000..91c7cdf
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/12-hardware-computer.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/12-hardware-dock.png b/assetstudio/src/images/clipart/small/12-hardware-dock.png
new file mode 100644
index 0000000..c4a20ae
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/12-hardware-dock.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/12-hardware-gamepad.png b/assetstudio/src/images/clipart/small/12-hardware-gamepad.png
new file mode 100644
index 0000000..db62572
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/12-hardware-gamepad.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/12-hardware-headphones.png b/assetstudio/src/images/clipart/small/12-hardware-headphones.png
new file mode 100644
index 0000000..9d3b020
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/12-hardware-headphones.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/12-hardware-headset.png b/assetstudio/src/images/clipart/small/12-hardware-headset.png
new file mode 100644
index 0000000..d4efdf3
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/12-hardware-headset.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/12-hardware-keyboard.png b/assetstudio/src/images/clipart/small/12-hardware-keyboard.png
new file mode 100644
index 0000000..7b143d2
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/12-hardware-keyboard.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/12-hardware-mouse.png b/assetstudio/src/images/clipart/small/12-hardware-mouse.png
new file mode 100644
index 0000000..4f8d2df
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/12-hardware-mouse.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/12-hardware-phone.png b/assetstudio/src/images/clipart/small/12-hardware-phone.png
new file mode 100644
index 0000000..b5f78e1
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/12-hardware-phone.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/2-action-about.png b/assetstudio/src/images/clipart/small/2-action-about.png
new file mode 100644
index 0000000..56a3a55
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/2-action-about.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/2-action-help.png b/assetstudio/src/images/clipart/small/2-action-help.png
new file mode 100644
index 0000000..9104862
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/2-action-help.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/2-action-search.png b/assetstudio/src/images/clipart/small/2-action-search.png
new file mode 100644
index 0000000..1d3f206
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/2-action-search.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/2-action-settings.png b/assetstudio/src/images/clipart/small/2-action-settings.png
new file mode 100644
index 0000000..1dd6bbb
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/2-action-settings.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/3-rating-bad.png b/assetstudio/src/images/clipart/small/3-rating-bad.png
new file mode 100644
index 0000000..76060f7
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/3-rating-bad.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/3-rating-favorite.png b/assetstudio/src/images/clipart/small/3-rating-favorite.png
new file mode 100644
index 0000000..b6ab63f
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/3-rating-favorite.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/3-rating-good.png b/assetstudio/src/images/clipart/small/3-rating-good.png
new file mode 100644
index 0000000..0e6f861
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/3-rating-good.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/3-rating-half-important.png b/assetstudio/src/images/clipart/small/3-rating-half-important.png
new file mode 100644
index 0000000..d9aa154
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/3-rating-half-important.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/3-rating-important.png b/assetstudio/src/images/clipart/small/3-rating-important.png
new file mode 100644
index 0000000..0bc5c54
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/3-rating-important.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/3-rating-not-important.png b/assetstudio/src/images/clipart/small/3-rating-not-important.png
new file mode 100644
index 0000000..6ea5892
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/3-rating-not-important.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/4-collections-cloud.png b/assetstudio/src/images/clipart/small/4-collections-cloud.png
new file mode 100644
index 0000000..5d80291
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/4-collections-cloud.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/4-collections-collection.png b/assetstudio/src/images/clipart/small/4-collections-collection.png
new file mode 100644
index 0000000..d4a7dcb
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/4-collections-collection.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/4-collections-go-to-today.png b/assetstudio/src/images/clipart/small/4-collections-go-to-today.png
new file mode 100644
index 0000000..3326ead
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/4-collections-go-to-today.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/4-collections-labels.png b/assetstudio/src/images/clipart/small/4-collections-labels.png
new file mode 100644
index 0000000..e647488
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/4-collections-labels.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/4-collections-new-label.png b/assetstudio/src/images/clipart/small/4-collections-new-label.png
new file mode 100644
index 0000000..f822806
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/4-collections-new-label.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/4-collections-sort-by-size.png b/assetstudio/src/images/clipart/small/4-collections-sort-by-size.png
new file mode 100644
index 0000000..b097f67
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/4-collections-sort-by-size.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/4-collections-view-as-grid.png b/assetstudio/src/images/clipart/small/4-collections-view-as-grid.png
new file mode 100644
index 0000000..9f9e0c1
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/4-collections-view-as-grid.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/4-collections-view-as-list.png b/assetstudio/src/images/clipart/small/4-collections-view-as-list.png
new file mode 100644
index 0000000..39a2f1f
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/4-collections-view-as-list.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/5-content-attachment.png b/assetstudio/src/images/clipart/small/5-content-attachment.png
new file mode 100644
index 0000000..ae5dac4
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/5-content-attachment.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/5-content-backspace.png b/assetstudio/src/images/clipart/small/5-content-backspace.png
new file mode 100644
index 0000000..f2743fe
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/5-content-backspace.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/5-content-copy.png b/assetstudio/src/images/clipart/small/5-content-copy.png
new file mode 100644
index 0000000..7efa0ec
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/5-content-copy.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/5-content-cut.png b/assetstudio/src/images/clipart/small/5-content-cut.png
new file mode 100644
index 0000000..4f113d6
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/5-content-cut.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/5-content-discard.png b/assetstudio/src/images/clipart/small/5-content-discard.png
new file mode 100644
index 0000000..9bbe70c
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/5-content-discard.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/5-content-edit.png b/assetstudio/src/images/clipart/small/5-content-edit.png
new file mode 100644
index 0000000..dfef46d
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/5-content-edit.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/5-content-email.png b/assetstudio/src/images/clipart/small/5-content-email.png
new file mode 100644
index 0000000..0698571
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/5-content-email.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/5-content-event.png b/assetstudio/src/images/clipart/small/5-content-event.png
new file mode 100644
index 0000000..4fea671
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/5-content-event.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/5-content-import-export.png b/assetstudio/src/images/clipart/small/5-content-import-export.png
new file mode 100644
index 0000000..1b4ed11
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/5-content-import-export.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/5-content-merge.png b/assetstudio/src/images/clipart/small/5-content-merge.png
new file mode 100644
index 0000000..4f7451e
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/5-content-merge.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/5-content-new-attachment.png b/assetstudio/src/images/clipart/small/5-content-new-attachment.png
new file mode 100644
index 0000000..8028ea7
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/5-content-new-attachment.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/5-content-new-email.png b/assetstudio/src/images/clipart/small/5-content-new-email.png
new file mode 100644
index 0000000..699dca9
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/5-content-new-email.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/5-content-new-event.png b/assetstudio/src/images/clipart/small/5-content-new-event.png
new file mode 100644
index 0000000..4c4f674
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/5-content-new-event.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/5-content-new-picture.png b/assetstudio/src/images/clipart/small/5-content-new-picture.png
new file mode 100644
index 0000000..6b7b7ea
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/5-content-new-picture.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/5-content-new.png b/assetstudio/src/images/clipart/small/5-content-new.png
new file mode 100644
index 0000000..7ccce5b
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/5-content-new.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/5-content-paste.png b/assetstudio/src/images/clipart/small/5-content-paste.png
new file mode 100644
index 0000000..9c3d906
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/5-content-paste.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/5-content-picture.png b/assetstudio/src/images/clipart/small/5-content-picture.png
new file mode 100644
index 0000000..0676181
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/5-content-picture.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/5-content-read.png b/assetstudio/src/images/clipart/small/5-content-read.png
new file mode 100644
index 0000000..7c7186f
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/5-content-read.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/5-content-remove.png b/assetstudio/src/images/clipart/small/5-content-remove.png
new file mode 100644
index 0000000..97f11f7
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/5-content-remove.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/5-content-save.png b/assetstudio/src/images/clipart/small/5-content-save.png
new file mode 100644
index 0000000..4b38e6c
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/5-content-save.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/5-content-select-all.png b/assetstudio/src/images/clipart/small/5-content-select-all.png
new file mode 100644
index 0000000..cfb2282
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/5-content-select-all.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/5-content-split.png b/assetstudio/src/images/clipart/small/5-content-split.png
new file mode 100644
index 0000000..779f650
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/5-content-split.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/5-content-undo.png b/assetstudio/src/images/clipart/small/5-content-undo.png
new file mode 100644
index 0000000..87b0129
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/5-content-undo.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/5-content-unread.png b/assetstudio/src/images/clipart/small/5-content-unread.png
new file mode 100644
index 0000000..69cb276
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/5-content-unread.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/6-social-add-group.png b/assetstudio/src/images/clipart/small/6-social-add-group.png
new file mode 100644
index 0000000..cae89bb
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/6-social-add-group.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/6-social-add-person.png b/assetstudio/src/images/clipart/small/6-social-add-person.png
new file mode 100644
index 0000000..ec95691
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/6-social-add-person.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/6-social-cc-bcc.png b/assetstudio/src/images/clipart/small/6-social-cc-bcc.png
new file mode 100644
index 0000000..92772f7
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/6-social-cc-bcc.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/6-social-chat.png b/assetstudio/src/images/clipart/small/6-social-chat.png
new file mode 100644
index 0000000..675c7e3
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/6-social-chat.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/6-social-forward.png b/assetstudio/src/images/clipart/small/6-social-forward.png
new file mode 100644
index 0000000..f533b34
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/6-social-forward.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/6-social-group.png b/assetstudio/src/images/clipart/small/6-social-group.png
new file mode 100644
index 0000000..ee027a7
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/6-social-group.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/6-social-person.png b/assetstudio/src/images/clipart/small/6-social-person.png
new file mode 100644
index 0000000..bb685c7
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/6-social-person.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/6-social-reply-all.png b/assetstudio/src/images/clipart/small/6-social-reply-all.png
new file mode 100644
index 0000000..fc94679
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/6-social-reply-all.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/6-social-reply.png b/assetstudio/src/images/clipart/small/6-social-reply.png
new file mode 100644
index 0000000..e413c9a
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/6-social-reply.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/6-social-send-now.png b/assetstudio/src/images/clipart/small/6-social-send-now.png
new file mode 100644
index 0000000..6fa79f0
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/6-social-send-now.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/6-social-share.png b/assetstudio/src/images/clipart/small/6-social-share.png
new file mode 100644
index 0000000..fb74121
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/6-social-share.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/7-location-directions.png b/assetstudio/src/images/clipart/small/7-location-directions.png
new file mode 100644
index 0000000..c3e821d
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/7-location-directions.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/7-location-map.png b/assetstudio/src/images/clipart/small/7-location-map.png
new file mode 100644
index 0000000..4893657
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/7-location-map.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/7-location-place.png b/assetstudio/src/images/clipart/small/7-location-place.png
new file mode 100644
index 0000000..2d41b57
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/7-location-place.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/7-location-web-site.png b/assetstudio/src/images/clipart/small/7-location-web-site.png
new file mode 100644
index 0000000..fe15c10
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/7-location-web-site.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/8-images-crop.png b/assetstudio/src/images/clipart/small/8-images-crop.png
new file mode 100644
index 0000000..ddca47f
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/8-images-crop.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/8-images-rotate-left.png b/assetstudio/src/images/clipart/small/8-images-rotate-left.png
new file mode 100644
index 0000000..0450f2b
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/8-images-rotate-left.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/8-images-rotate-right.png b/assetstudio/src/images/clipart/small/8-images-rotate-right.png
new file mode 100644
index 0000000..a34d957
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/8-images-rotate-right.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/8-images-slideshow.png b/assetstudio/src/images/clipart/small/8-images-slideshow.png
new file mode 100644
index 0000000..5317cf7
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/8-images-slideshow.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/9-av-add-to-queue.png b/assetstudio/src/images/clipart/small/9-av-add-to-queue.png
new file mode 100644
index 0000000..544b8fc
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/9-av-add-to-queue.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/9-av-download.png b/assetstudio/src/images/clipart/small/9-av-download.png
new file mode 100644
index 0000000..bbf910c
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/9-av-download.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/9-av-fast-forward.png b/assetstudio/src/images/clipart/small/9-av-fast-forward.png
new file mode 100644
index 0000000..dc7e11f
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/9-av-fast-forward.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/9-av-full-screen.png b/assetstudio/src/images/clipart/small/9-av-full-screen.png
new file mode 100644
index 0000000..c1dd576
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/9-av-full-screen.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/9-av-make-available-offline.png b/assetstudio/src/images/clipart/small/9-av-make-available-offline.png
new file mode 100644
index 0000000..8e9459c
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/9-av-make-available-offline.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/9-av-next.png b/assetstudio/src/images/clipart/small/9-av-next.png
new file mode 100644
index 0000000..01e6543
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/9-av-next.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/9-av-pause-over-video.png b/assetstudio/src/images/clipart/small/9-av-pause-over-video.png
new file mode 100644
index 0000000..bac9ce4
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/9-av-pause-over-video.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/9-av-pause.png b/assetstudio/src/images/clipart/small/9-av-pause.png
new file mode 100644
index 0000000..6a17d65
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/9-av-pause.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/9-av-play-over-video.png b/assetstudio/src/images/clipart/small/9-av-play-over-video.png
new file mode 100644
index 0000000..a3a68fc
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/9-av-play-over-video.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/9-av-play.png b/assetstudio/src/images/clipart/small/9-av-play.png
new file mode 100644
index 0000000..2092eca
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/9-av-play.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/9-av-previous.png b/assetstudio/src/images/clipart/small/9-av-previous.png
new file mode 100644
index 0000000..cf10fbf
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/9-av-previous.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/9-av-repeat.png b/assetstudio/src/images/clipart/small/9-av-repeat.png
new file mode 100644
index 0000000..7638bea
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/9-av-repeat.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/9-av-replay.png b/assetstudio/src/images/clipart/small/9-av-replay.png
new file mode 100644
index 0000000..8f1dae0
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/9-av-replay.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/9-av-return-from-full-screen.png b/assetstudio/src/images/clipart/small/9-av-return-from-full-screen.png
new file mode 100644
index 0000000..96949cb
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/9-av-return-from-full-screen.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/9-av-rewind.png b/assetstudio/src/images/clipart/small/9-av-rewind.png
new file mode 100644
index 0000000..1811cd9
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/9-av-rewind.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/9-av-shuffle.png b/assetstudio/src/images/clipart/small/9-av-shuffle.png
new file mode 100644
index 0000000..6075afb
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/9-av-shuffle.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/9-av-stop.png b/assetstudio/src/images/clipart/small/9-av-stop.png
new file mode 100644
index 0000000..3c95c99
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/9-av-stop.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/9-av-upload.png b/assetstudio/src/images/clipart/small/9-av-upload.png
new file mode 100644
index 0000000..af9b895
--- /dev/null
+++ b/assetstudio/src/images/clipart/small/9-av-upload.png
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/attach.png b/assetstudio/src/images/clipart/small/attach.png
deleted file mode 100644
index 6bfc535..0000000
--- a/assetstudio/src/images/clipart/small/attach.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/call.png b/assetstudio/src/images/clipart/small/call.png
deleted file mode 100644
index 9ea8e0f..0000000
--- a/assetstudio/src/images/clipart/small/call.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/copy.png b/assetstudio/src/images/clipart/small/copy.png
deleted file mode 100644
index 68d31d8..0000000
--- a/assetstudio/src/images/clipart/small/copy.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/cut.png b/assetstudio/src/images/clipart/small/cut.png
deleted file mode 100644
index b94e50b..0000000
--- a/assetstudio/src/images/clipart/small/cut.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/delete.png b/assetstudio/src/images/clipart/small/delete.png
deleted file mode 100644
index 638c9c8..0000000
--- a/assetstudio/src/images/clipart/small/delete.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/done.png b/assetstudio/src/images/clipart/small/done.png
deleted file mode 100644
index aed3f0c..0000000
--- a/assetstudio/src/images/clipart/small/done.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/edit.png b/assetstudio/src/images/clipart/small/edit.png
deleted file mode 100644
index b677a6a..0000000
--- a/assetstudio/src/images/clipart/small/edit.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/locate.png b/assetstudio/src/images/clipart/small/locate.png
deleted file mode 100644
index cd16ada..0000000
--- a/assetstudio/src/images/clipart/small/locate.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/mail.png b/assetstudio/src/images/clipart/small/mail.png
deleted file mode 100644
index 8ae1cde..0000000
--- a/assetstudio/src/images/clipart/small/mail.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/microphone.png b/assetstudio/src/images/clipart/small/microphone.png
deleted file mode 100644
index bd58fb3..0000000
--- a/assetstudio/src/images/clipart/small/microphone.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/overflow.png b/assetstudio/src/images/clipart/small/overflow.png
deleted file mode 100644
index d3cd16c..0000000
--- a/assetstudio/src/images/clipart/small/overflow.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/paste.png b/assetstudio/src/images/clipart/small/paste.png
deleted file mode 100644
index b022176..0000000
--- a/assetstudio/src/images/clipart/small/paste.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/photo.png b/assetstudio/src/images/clipart/small/photo.png
deleted file mode 100644
index 906db99..0000000
--- a/assetstudio/src/images/clipart/small/photo.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/refresh.png b/assetstudio/src/images/clipart/small/refresh.png
deleted file mode 100644
index 6482017..0000000
--- a/assetstudio/src/images/clipart/small/refresh.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/search.png b/assetstudio/src/images/clipart/small/search.png
deleted file mode 100644
index fef5270..0000000
--- a/assetstudio/src/images/clipart/small/search.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/select_all.png b/assetstudio/src/images/clipart/small/select_all.png
deleted file mode 100644
index b32de7d..0000000
--- a/assetstudio/src/images/clipart/small/select_all.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/send.png b/assetstudio/src/images/clipart/small/send.png
deleted file mode 100644
index b2c768b..0000000
--- a/assetstudio/src/images/clipart/small/send.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/share.png b/assetstudio/src/images/clipart/small/share.png
deleted file mode 100644
index 11da57d..0000000
--- a/assetstudio/src/images/clipart/small/share.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/star.png b/assetstudio/src/images/clipart/small/star.png
deleted file mode 100644
index 847937e..0000000
--- a/assetstudio/src/images/clipart/small/star.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/user.png b/assetstudio/src/images/clipart/small/user.png
deleted file mode 100644
index 9c7a585..0000000
--- a/assetstudio/src/images/clipart/small/user.png
+++ /dev/null
Binary files differ
diff --git a/assetstudio/src/images/clipart/small/video.png b/assetstudio/src/images/clipart/small/video.png
deleted file mode 100644
index 9766009..0000000
--- a/assetstudio/src/images/clipart/small/video.png
+++ /dev/null
Binary files differ
diff --git a/build/tools.atree b/build/tools.atree
index 4777bee..893bd2a 100644
--- a/build/tools.atree
+++ b/build/tools.atree
@@ -176,9 +176,8 @@ external/chromium-trace/style.css tools/systrace/style.css
external/chromium-trace/LICENSE tools/systrace/LICENSE
external/chromium-trace/AUTHORS tools/systrace/AUTHORS
-# Misspelling databases for tools such as lint
-sdk/files/typos-en.txt tools/support/typos-en.txt
-sdk/files/typos-nb.txt tools/support/typos-nb.txt
+# Misspelling databases for lint
+sdk/files/typos tools/support
##############################################################################
# Tests Component
diff --git a/chimpchat/src/com/android/chimpchat/adb/AdbChimpDevice.java b/chimpchat/src/com/android/chimpchat/adb/AdbChimpDevice.java
index d4513d1..7c4b62a 100644
--- a/chimpchat/src/com/android/chimpchat/adb/AdbChimpDevice.java
+++ b/chimpchat/src/com/android/chimpchat/adb/AdbChimpDevice.java
@@ -481,7 +481,17 @@ public class AdbChimpDevice implements IChimpDevice {
@Override
public Map<String, Object> instrument(String packageName, Map<String, Object> args) {
- List<String> shellCmd = Lists.newArrayList("am", "instrument", "-w", "-r", packageName);
+ List<String> shellCmd = Lists.newArrayList("am", "instrument", "-w", "-r");
+ for (Entry<String, Object> entry: args.entrySet()) {
+ final String key = entry.getKey();
+ final Object value = entry.getValue();
+ if (key != null && value != null) {
+ shellCmd.add("-e");
+ shellCmd.add(key);
+ shellCmd.add(value.toString());
+ }
+ }
+ shellCmd.add(packageName);
String result = shell(shellCmd.toArray(ZERO_LENGTH_STRING_ARRAY));
return convertInstrumentResult(result);
}
diff --git a/ddms/libs/ddmlib/src/com/android/ddmlib/CollectingOutputReceiver.java b/ddms/libs/ddmlib/src/com/android/ddmlib/CollectingOutputReceiver.java
index cb4612f..80aa8e1 100644
--- a/ddms/libs/ddmlib/src/com/android/ddmlib/CollectingOutputReceiver.java
+++ b/ddms/libs/ddmlib/src/com/android/ddmlib/CollectingOutputReceiver.java
@@ -17,16 +17,24 @@ package com.android.ddmlib;
import java.io.UnsupportedEncodingException;
+import java.util.concurrent.CountDownLatch;
/**
* A {@link IShellOutputReceiver} which collects the whole shell output into one
* {@link String}.
*/
public class CollectingOutputReceiver implements IShellOutputReceiver {
-
+ private CountDownLatch mCompletionLatch;
private StringBuffer mOutputBuffer = new StringBuffer();
private boolean mIsCanceled = false;
+ public CollectingOutputReceiver() {
+ }
+
+ public CollectingOutputReceiver(CountDownLatch commandCompleteLatch) {
+ mCompletionLatch = commandCompleteLatch;
+ }
+
public String getOutput() {
return mOutputBuffer.toString();
}
@@ -68,6 +76,8 @@ public class CollectingOutputReceiver implements IShellOutputReceiver {
*/
@Override
public void flush() {
- // ignore
+ if (mCompletionLatch != null) {
+ mCompletionLatch.countDown();
+ }
}
}
diff --git a/device_validator/app/src/com/android/validator/DeviceValidator.java b/device_validator/app/src/com/android/validator/DeviceValidator.java
index e4038bc..8ca6afe 100644
--- a/device_validator/app/src/com/android/validator/DeviceValidator.java
+++ b/device_validator/app/src/com/android/validator/DeviceValidator.java
@@ -16,12 +16,12 @@
package com.android.validator;
+import com.android.dvlib.DeviceSchema;
+
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
-import com.android.dvlib.DeviceSchema;
-
public class DeviceValidator {
public static void main(String[] args) {
diff --git a/device_validator/dvlib/src/com/android/dvlib/DeviceSchema.java b/device_validator/dvlib/src/com/android/dvlib/DeviceSchema.java
index 6c45401..b02471b 100644
--- a/device_validator/dvlib/src/com/android/dvlib/DeviceSchema.java
+++ b/device_validator/dvlib/src/com/android/dvlib/DeviceSchema.java
@@ -90,6 +90,8 @@ public class DeviceSchema {
public static final String NODE_LIVE_WALLPAPER_SUPPORT = "live-wallpaper-support";
+ public static final String NODE_STATUS_BAR = "status-bar";
+
public static final String NODE_BUTTONS = "buttons";
public static final String NODE_CAMERA = "camera";
diff --git a/device_validator/dvlib/src/com/android/dvlib/devices.xsd b/device_validator/dvlib/src/com/android/dvlib/devices.xsd
index 0cc9411..d4678da 100644
--- a/device_validator/dvlib/src/com/android/dvlib/devices.xsd
+++ b/device_validator/dvlib/src/com/android/dvlib/devices.xsd
@@ -206,6 +206,14 @@
<xsd:list itemType="xsd:NMTOKEN" />
</xsd:simpleType>
</xsd:element>
+ <xsd:element name="status-bar" type="xsd:boolean">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies whether the device has a status bar in this
+ software configuration.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
</xsd:sequence>
</xsd:complexType>
diff --git a/device_validator/dvlib/tests/src/com/android/dvlib/devices.xml b/device_validator/dvlib/tests/src/com/android/dvlib/devices.xml
index b626012..6662099 100644
--- a/device_validator/dvlib/tests/src/com/android/dvlib/devices.xml
+++ b/device_validator/dvlib/tests/src/com/android/dvlib/devices.xml
@@ -123,6 +123,7 @@
GL_OES_vertex_array_object
GL_OES_vertex_half_float
</d:gl-extensions>
+ <d:status-bar>true</d:status-bar>
</d:software>
<d:state name="Portrait" default="true">
<d:description>The phone in portrait view</d:description>
@@ -248,6 +249,7 @@
GL_IMG_texture_stream
GL_IMG_vertex_program
</d:gl-extensions>
+ <d:status-bar>true</d:status-bar>
</d:software>
<d:state name="Portrait" default="true">
<d:description>The phone in portrait view</d:description>
diff --git a/device_validator/dvlib/tests/src/com/android/dvlib/devices_minimal.xml b/device_validator/dvlib/tests/src/com/android/dvlib/devices_minimal.xml
index 20d501f..e063fd1 100644
--- a/device_validator/dvlib/tests/src/com/android/dvlib/devices_minimal.xml
+++ b/device_validator/dvlib/tests/src/com/android/dvlib/devices_minimal.xml
@@ -117,6 +117,7 @@
GL_OES_vertex_array_object
GL_OES_vertex_half_float
</d:gl-extensions>
+ <d:status-bar>true</d:status-bar>
</d:software>
<d:state name="Portrait" default="true">
<d:description>The phone in portrait view</d:description>
diff --git a/device_validator/dvlib/tests/src/com/android/dvlib/devices_no_default.xml b/device_validator/dvlib/tests/src/com/android/dvlib/devices_no_default.xml
index 1247a45..605a6c1 100644
--- a/device_validator/dvlib/tests/src/com/android/dvlib/devices_no_default.xml
+++ b/device_validator/dvlib/tests/src/com/android/dvlib/devices_no_default.xml
@@ -122,6 +122,7 @@
GL_OES_vertex_array_object
GL_OES_vertex_half_float
</d:gl-extensions>
+ <d:status-bar>true</d:status-bar>
</d:software>
<d:state name="Portrait">
<d:description>The phone in portrait view</d:description>
diff --git a/device_validator/dvlib/tests/src/com/android/dvlib/devices_no_hardware.xml b/device_validator/dvlib/tests/src/com/android/dvlib/devices_no_hardware.xml
index 8f189a4..fb133ad 100644
--- a/device_validator/dvlib/tests/src/com/android/dvlib/devices_no_hardware.xml
+++ b/device_validator/dvlib/tests/src/com/android/dvlib/devices_no_hardware.xml
@@ -63,6 +63,7 @@
GL_OES_vertex_array_object
GL_OES_vertex_half_float
</d:gl-extensions>
+ <d:status-bar>true</d:status-bar>
</d:software>
<d:state name="Portrait" default="true">
<d:description>The phone in portrait view</d:description>
diff --git a/device_validator/dvlib/tests/src/com/android/dvlib/devices_no_states.xml b/device_validator/dvlib/tests/src/com/android/dvlib/devices_no_states.xml
index 89519cf..8685e3b 100644
--- a/device_validator/dvlib/tests/src/com/android/dvlib/devices_no_states.xml
+++ b/device_validator/dvlib/tests/src/com/android/dvlib/devices_no_states.xml
@@ -123,6 +123,7 @@
GL_OES_vertex_array_object
GL_OES_vertex_half_float
</d:gl-extensions>
+ <d:status-bar>true</d:status-bar>
</d:software>
</d:device>
</d:devices>
diff --git a/device_validator/dvlib/tests/src/com/android/dvlib/devices_too_many_defaults.xml b/device_validator/dvlib/tests/src/com/android/dvlib/devices_too_many_defaults.xml
index 5409d32..c720a7a 100644
--- a/device_validator/dvlib/tests/src/com/android/dvlib/devices_too_many_defaults.xml
+++ b/device_validator/dvlib/tests/src/com/android/dvlib/devices_too_many_defaults.xml
@@ -123,6 +123,7 @@
GL_OES_vertex_array_object
GL_OES_vertex_half_float
</d:gl-extensions>
+ <d:status-bar>true</d:status-bar>
</d:software>
<d:state name="Portrait" default="true">
<d:description>The phone in portrait view</d:description>
diff --git a/eclipse/dictionary.txt b/eclipse/dictionary.txt
index f29994a..ae582d3 100644
--- a/eclipse/dictionary.txt
+++ b/eclipse/dictionary.txt
@@ -107,6 +107,8 @@ froyo
gen
gif
git
+glob
+globbing
groovy
guava
guillemets
@@ -166,6 +168,7 @@ macs
malformed
markup
marquee
+maven
mdpi
memento
metadata
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/resources/platform/AttrsXmlParser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/resources/platform/AttrsXmlParser.java
index a0a5ad8..a7bc53b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/resources/platform/AttrsXmlParser.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/resources/platform/AttrsXmlParser.java
@@ -17,6 +17,7 @@
package com.android.ide.common.resources.platform;
import static com.android.ide.common.layout.LayoutConstants.DOT_LAYOUT_PARAMS;
+import static com.android.ide.eclipse.adt.AdtConstants.DOC_HIDE;
import com.android.ide.common.api.IAttributeInfo.Format;
import com.android.ide.common.log.ILogger;
@@ -291,7 +292,12 @@ public final class AttrsXmlParser {
mStyleMap.put(name, style);
unknownParents.remove(name);
if (lastComment != null) {
- style.setJavaDoc(parseJavadoc(lastComment.getNodeValue()));
+ String nodeValue = lastComment.getNodeValue();
+ if (nodeValue.contains(DOC_HIDE)) {
+ mStyleMap.remove(name);
+ } else {
+ style.setJavaDoc(parseJavadoc(nodeValue));
+ }
}
}
}
@@ -416,8 +422,12 @@ public final class AttrsXmlParser {
}
if (info != null) {
if (lastComment != null) {
- info.setJavaDoc(parseJavadoc(lastComment.getNodeValue()));
- info.setDeprecatedDoc(parseDeprecatedDoc(lastComment.getNodeValue()));
+ String nodeValue = lastComment.getNodeValue();
+ if (nodeValue.contains(DOC_HIDE)) {
+ return null;
+ }
+ info.setJavaDoc(parseJavadoc(nodeValue));
+ info.setDeprecatedDoc(parseDeprecatedDoc(nodeValue));
}
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java
index 8ac1012..670dd20 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java
@@ -289,4 +289,7 @@ public class AdtConstants {
public static final String CODESITE_BASE_URL = "http://code.google.com/android"; //$NON-NLS-1$
public static final String LIBRARY_TEST_RUNNER = "android.test.runner"; //$NON-NLS-1$
+
+ /** Documentation marker for elements, attributes etc that should be hidden */
+ public static final String DOC_HIDE = "@hide"; //$NON-NLS-1$
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtUtils.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtUtils.java
index 4cf4a00..d6ca12a 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtUtils.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtUtils.java
@@ -30,8 +30,6 @@ import com.android.sdklib.AndroidVersion;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.repository.PkgProps;
import com.android.util.XmlUtils;
-import com.google.common.base.Splitter;
-import com.google.common.collect.Iterables;
import com.google.common.io.ByteStreams;
import com.google.common.io.Closeables;
@@ -860,7 +858,7 @@ public class AdtUtils {
* @return the highest known API number
*/
public static int getHighestKnownApiLevel() {
- return 15;
+ return 16;
}
/**
@@ -981,41 +979,6 @@ public class AdtUtils {
}
/**
- * Splits the given path into its individual parts, attempting to be
- * tolerant about path separators (: or ;). It can handle possibly ambiguous
- * paths, such as {@code c:\foo\bar:\other}, though of course these are to
- * be avoided if possible.
- *
- * @param path the path variable to split, which can use both : and ; as
- * path separators.
- * @return the individual path components as an iterable of strings
- */
- public static Iterable<String> splitPath(String path) {
- if (path.indexOf(';') != -1) {
- return Splitter.on(';').omitEmptyStrings().trimResults().split(path);
- }
-
- List<String> combined = new ArrayList<String>();
- Iterables.addAll(combined, Splitter.on(':').omitEmptyStrings().trimResults().split(path));
- for (int i = 0, n = combined.size(); i < n; i++) {
- String p = combined.get(i);
- if (p.length() == 1 && i < n - 1 && Character.isLetter(p.charAt(0))
- // Technically, Windows paths do not have to have a \ after the :,
- // which means it would be using the current directory on that drive,
- // but that's unlikely to be the case in a path since it would have
- // unpredictable results
- && !combined.get(i+1).isEmpty() && combined.get(i+1).charAt(0) == '\\') {
- combined.set(i, p + ':' + combined.get(i+1));
- combined.remove(i+1);
- n--;
- continue;
- }
- }
-
- return combined;
- }
-
- /**
* Reads the contents of an {@link IFile} and return it as a byte array
*
* @param file the file to be read
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java
index 0237769..172b7a4 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java
@@ -67,6 +67,7 @@ import com.android.resources.UiMode;
import com.android.sdklib.AndroidVersion;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.devices.Device;
+import com.android.sdklib.devices.DeviceManager;
import com.android.sdklib.devices.State;
import com.android.sdklib.internal.avd.AvdInfo;
import com.android.sdklib.internal.avd.AvdManager;
@@ -204,6 +205,9 @@ public class ConfigurationComposite extends Composite implements SelectionListen
/** The config listener given to the constructor. Never null. */
private final IConfigListener mListener;
+ /** The device menu listener, so we can remove it when the device lists are updated */
+ private Listener mDeviceListener;
+
/** The {@link FolderConfiguration} representing the state of the UI controls */
private final FolderConfiguration mCurrentConfig = new FolderConfiguration();
@@ -1906,6 +1910,11 @@ public class ConfigurationComposite extends Composite implements SelectionListen
menu.setVisible(true);
}
};
+
+ if (mDeviceListener != null) {
+ combo.removeListener(SWT.Selection, mDeviceListener);
+ }
+ mDeviceListener = menuListener;
combo.addListener(SWT.Selection, menuListener);
}
@@ -2656,9 +2665,17 @@ public class ConfigurationComposite extends Composite implements SelectionListen
* Loads the list of {@link Device}s and inits the UI with it.
*/
private void initDevices() {
- Sdk sdk = Sdk.getCurrent();
+ final Sdk sdk = Sdk.getCurrent();
if (sdk != null) {
mDeviceList = sdk.getDevices();
+ DeviceManager manager = sdk.getDeviceManager();
+ manager.registerListener(new DeviceManager.DevicesChangeListener() {
+ @Override
+ public void onDevicesChange() {
+ mDeviceList = sdk.getDevices();
+ addDeviceMenuListener(mDeviceCombo);
+ }
+ });
} else {
mDeviceList = new ArrayList<Device>();
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintFix.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintFix.java
index 9fa5018..1ab02c3 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintFix.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintFix.java
@@ -28,6 +28,7 @@ import com.android.tools.lint.checks.PxUsageDetector;
import com.android.tools.lint.checks.ScrollViewChildDetector;
import com.android.tools.lint.checks.SecurityDetector;
import com.android.tools.lint.checks.TextFieldDetector;
+import com.android.tools.lint.checks.TranslationDetector;
import com.android.tools.lint.checks.TypoDetector;
import com.android.tools.lint.checks.TypographyDetector;
import com.android.tools.lint.checks.UseCompoundDrawableDetector;
@@ -153,6 +154,7 @@ abstract class LintFix implements ICompletionProposal {
sFixes.put(PxUsageDetector.PX_ISSUE.getId(), ConvertToDpFix.class);
sFixes.put(TextFieldDetector.ISSUE.getId(), SetAttributeFix.class);
sFixes.put(SecurityDetector.EXPORTED_SERVICE.getId(), SetAttributeFix.class);
+ sFixes.put(TranslationDetector.MISSING.getId(), SetAttributeFix.class);
sFixes.put(DetectMissingPrefix.MISSING_NAMESPACE.getId(), AddPrefixFix.class);
sFixes.put(ScrollViewChildDetector.ISSUE.getId(), SetScrollViewSizeFix.class);
sFixes.put(ObsoleteLayoutParamsDetector.ISSUE.getId(), ObsoleteLayoutParamsFix.class);
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintFixGenerator.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintFixGenerator.java
index a07101f..5d38df2 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintFixGenerator.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintFixGenerator.java
@@ -98,6 +98,7 @@ import java.util.List;
* in the Problems view; perhaps we should use a custom view for these. That would also
* make marker management more obvious.
*/
+@SuppressWarnings("restriction") // DOM model
public class LintFixGenerator implements IMarkerResolutionGenerator2, IQuickAssistProcessor {
/** Constructs a new {@link LintFixGenerator} */
public LintFixGenerator() {
@@ -248,7 +249,6 @@ public class LintFixGenerator implements IMarkerResolutionGenerator2, IQuickAssi
*
* @param marker the marker pointing to the error to be suppressed
*/
- @SuppressWarnings("restriction") // XML model
public static void addSuppressAnnotation(IMarker marker) {
String id = EclipseLintClient.getId(marker);
if (id != null) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/SetAttributeFix.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/SetAttributeFix.java
index 896966e..a860c69 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/SetAttributeFix.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/SetAttributeFix.java
@@ -18,17 +18,18 @@ package com.android.ide.eclipse.adt.internal.lint;
import static com.android.ide.common.layout.LayoutConstants.ATTR_CONTENT_DESCRIPTION;
import static com.android.ide.common.layout.LayoutConstants.ATTR_INPUT_TYPE;
import static com.android.ide.common.layout.LayoutConstants.VALUE_FALSE;
+import static com.android.tools.lint.detector.api.LintConstants.ATTR_TRANSLATABLE;
import com.android.tools.lint.checks.AccessibilityDetector;
import com.android.tools.lint.checks.InefficientWeightDetector;
import com.android.tools.lint.checks.SecurityDetector;
import com.android.tools.lint.checks.TextFieldDetector;
+import com.android.tools.lint.checks.TranslationDetector;
import com.android.tools.lint.detector.api.LintConstants;
import org.eclipse.core.resources.IMarker;
/** Shared fix class for various builtin attributes */
-@SuppressWarnings("restriction") // DOM model
final class SetAttributeFix extends SetPropertyFix {
private SetAttributeFix(String id, IMarker marker) {
super(id, marker);
@@ -44,6 +45,8 @@ final class SetAttributeFix extends SetPropertyFix {
return LintConstants.ATTR_PERMISSION;
} else if (mId.equals(TextFieldDetector.ISSUE.getId())) {
return ATTR_INPUT_TYPE;
+ } else if (mId.equals(TranslationDetector.MISSING.getId())) {
+ return ATTR_TRANSLATABLE;
} else {
assert false : mId;
return "";
@@ -51,6 +54,15 @@ final class SetAttributeFix extends SetPropertyFix {
}
@Override
+ protected boolean isAndroidAttribute() {
+ if (mId.equals(TranslationDetector.MISSING.getId())) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
public String getDisplayString() {
if (mId.equals(AccessibilityDetector.ISSUE.getId())) {
return "Add content description attribute";
@@ -60,6 +72,8 @@ final class SetAttributeFix extends SetPropertyFix {
return "Set input type";
} else if (mId.equals(SecurityDetector.EXPORTED_SERVICE.getId())) {
return "Add permission attribute";
+ } else if (mId.equals(TranslationDetector.MISSING.getId())) {
+ return "Mark this as a non-translatable resource";
} else {
assert false : mId;
return "";
@@ -67,15 +81,37 @@ final class SetAttributeFix extends SetPropertyFix {
}
@Override
+ public String getAdditionalProposalInfo() {
+ String help = super.getAdditionalProposalInfo();
+
+ if (mId.equals(TranslationDetector.MISSING.getId())) {
+ help = "<b>Adds translatable=\"false\" to this &lt;string&gt;.</b><br><br>" + help;
+ }
+
+ return help;
+ }
+
+ @Override
protected boolean invokeCodeCompletion() {
return mId.equals(SecurityDetector.EXPORTED_SERVICE.getId())
|| mId.equals(TextFieldDetector.ISSUE.getId());
}
@Override
+ public boolean selectValue() {
+ if (mId.equals(TranslationDetector.MISSING.getId())) {
+ return false;
+ } else {
+ return super.selectValue();
+ }
+ }
+
+ @Override
protected String getProposal() {
if (mId.equals(InefficientWeightDetector.BASELINE_WEIGHTS.getId())) {
return VALUE_FALSE;
+ } else if (mId.equals(TranslationDetector.MISSING.getId())) {
+ return VALUE_FALSE;
}
return super.getProposal();
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/SetPropertyFix.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/SetPropertyFix.java
index 2bfe5e8..8b32734 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/SetPropertyFix.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/SetPropertyFix.java
@@ -48,6 +48,9 @@ abstract class SetPropertyFix extends DocumentFix {
/** Attribute to be added */
protected abstract String getAttribute();
+ /** Whether it's in the android: namespace */
+ protected abstract boolean isAndroidAttribute();
+
protected String getProposal() {
return invokeCodeCompletion() ? "" : "TODO"; //$NON-NLS-1$
}
@@ -70,7 +73,10 @@ abstract class SetPropertyFix extends DocumentFix {
Element element = (Element) node;
String proposal = getProposal();
String localAttribute = getAttribute();
- String prefix = XmlUtils.lookupNamespacePrefix(node, ANDROID_URI);
+ String prefix = null;
+ if (isAndroidAttribute()) {
+ prefix = XmlUtils.lookupNamespacePrefix(node, ANDROID_URI);
+ }
String attribute = prefix != null ? prefix + ':' + localAttribute : localAttribute;
// This does not work even though it should: it does not include the prefix
@@ -78,18 +84,29 @@ abstract class SetPropertyFix extends DocumentFix {
// So workaround instead:
element.setAttribute(attribute, proposal);
- Attr attr = element.getAttributeNodeNS(ANDROID_URI, localAttribute);
+ Attr attr = null;
+ if (isAndroidAttribute()) {
+ attr = element.getAttributeNodeNS(ANDROID_URI, localAttribute);
+ } else {
+ attr = element.getAttributeNode(localAttribute);
+ }
if (attr instanceof IndexedRegion) {
IndexedRegion region = (IndexedRegion) attr;
int offset = region.getStartOffset();
// We only want to select the value part inside the quotes,
// so skip the attribute and =" parts added by WST:
offset += attribute.length() + 2;
- mSelect = new Region(offset, proposal.length());
+ if (selectValue()) {
+ mSelect = new Region(offset, proposal.length());
+ }
}
}
}
+ protected boolean selectValue() {
+ return true;
+ }
+
@Override
public void apply(IDocument document) {
try {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/TypoFix.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/TypoFix.java
index 7c34e3e..4358410 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/TypoFix.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/TypoFix.java
@@ -63,7 +63,7 @@ final class TypoFix extends DocumentFix {
return;
}
List<String> replacements = TypoDetector.getSuggestions(message);
- if (replacements.size() == 0) {
+ if (replacements == null || replacements.isEmpty()) {
return;
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java
index 467602f..022857e 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java
@@ -20,7 +20,6 @@ import static com.android.sdklib.internal.project.ProjectProperties.PROPERTY_SDK
import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.AdtUtils;
import com.android.ide.eclipse.adt.AndroidPrintStream;
import com.android.ide.eclipse.adt.internal.build.BuildHelper;
import com.android.ide.eclipse.adt.internal.build.DexException;
@@ -36,6 +35,7 @@ import com.android.sdklib.build.ApkCreationException;
import com.android.sdklib.build.DuplicateFileException;
import com.android.sdklib.internal.project.ProjectProperties;
import com.android.sdklib.xml.AndroidManifest;
+import com.android.tools.lint.detector.api.LintUtils;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
@@ -177,7 +177,7 @@ public final class ExportHelper {
proguardConfig = proguardConfig.replace('/', File.separatorChar);
}
- Iterable<String> paths = AdtUtils.splitPath(proguardConfig);
+ Iterable<String> paths = LintUtils.splitPath(proguardConfig);
for (String path : paths) {
if (path.startsWith(SDK_PROPERTY_REF)) {
path = AdtPrefs.getPrefs().getOsSdkFolder() +
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplatePage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplatePage.java
index 0a62c8b..5f10ce0 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplatePage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplatePage.java
@@ -239,9 +239,9 @@ public class NewTemplatePage extends WizardPage
String id = parameter.id;
assert id != null && !id.isEmpty() : ATTR_ID;
- String value = defaults.get(id);
+ Object value = defaults.get(id);
if (value == null) {
- value = parameter.initial;
+ value = parameter.value;
}
String name = parameter.name;
@@ -289,8 +289,8 @@ public class NewTemplatePage extends WizardPage
2, 1));
}
- if (value != null && !value.isEmpty()){
- text.setText(value);
+ if (value instanceof String) {
+ text.setText((String) value);
mValues.parameters.put(id, value);
}
@@ -319,8 +319,8 @@ public class NewTemplatePage extends WizardPage
checkBox.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false,
2, 1));
- if (value != null && !value.isEmpty()){
- Boolean selected = Boolean.valueOf(value);
+ if (value instanceof Boolean) {
+ Boolean selected = (Boolean) value;
checkBox.setSelection(selected);
mValues.parameters.put(id, value);
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizardState.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizardState.java
index 00183d2..6101161 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizardState.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizardState.java
@@ -29,6 +29,8 @@ import com.android.annotations.Nullable;
import com.android.ide.eclipse.adt.internal.assetstudio.ConfigureAssetSetPage;
import com.android.ide.eclipse.adt.internal.assetstudio.CreateAssetSetWizardState;
import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestInfo;
+import com.android.ide.eclipse.adt.internal.sdk.Sdk;
+import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
@@ -124,13 +126,17 @@ public class NewTemplateWizardState {
return manifest.getMinSdkVersion();
}
- /** Returns the min SDK version to use */
+ /** Returns the build API version to use */
int getBuildApi() {
if (project == null) {
return -1;
}
- ManifestInfo manifest = ManifestInfo.get(project);
- return manifest.getMinSdkVersion();
+ IAndroidTarget target = Sdk.getCurrent().getTarget(project);
+ if (target != null) {
+ return target.getVersion().getApiLevel();
+ }
+
+ return getMinSdk();
}
/** Computes the changes this wizard will make */
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/Parameter.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/Parameter.java
index 9c31033..a9a3f33 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/Parameter.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/Parameter.java
@@ -237,7 +237,11 @@ class Parameter {
constraints = EnumSet.noneOf(Constraint.class);
}
- value = initial;
+ if (initial != null && !initial.isEmpty() && type == Type.BOOLEAN) {
+ value = Boolean.valueOf(initial);
+ } else {
+ value = initial;
+ }
}
Parameter(@NonNull Type type, @NonNull String id, @NonNull String initialValue) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java
index 1c3b862..e214788 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java
@@ -98,8 +98,16 @@ import javax.xml.parsers.SAXParserFactory;
* and merging into existing files
*/
class TemplateHandler {
- /** Highest supported format; templates with a higher number will be skipped */
- static final int CURRENT_FORMAT = 1;
+ /** Highest supported format; templates with a higher number will be skipped
+ * <p>
+ * <ul>
+ * <li> 1: Initial format, supported by ADT 20 and up.
+ * <li> 2: ADT 21 and up. Boolean variables that have a default value and are not
+ * edited by the user would end up as strings in ADT 20; now they are always
+ * proper Booleans. Templates which rely on this should specify format >= 2.
+ * </ul>
+ */
+ static final int CURRENT_FORMAT = 2;
/**
* Special marker indicating that this path refers to the special shared
@@ -396,7 +404,14 @@ class TemplateHandler {
String id = attributes.getValue(ATTR_ID);
if (!paramMap.containsKey(id)) {
String value = attributes.getValue(ATTR_DEFAULT);
- paramMap.put(id, value);
+ Object mapValue = value;
+ if (value != null && !value.isEmpty()) {
+ String type = attributes.getValue(ATTR_TYPE);
+ if ("boolean".equals(type)) { //$NON-NLS-1$
+ mapValue = Boolean.valueOf(value);
+ }
+ }
+ paramMap.put(id, mapValue);
}
} else if (TAG_GLOBAL.equals(name)) {
String id = attributes.getValue(ATTR_ID);
diff --git a/eclipse/plugins/com.android.ide.eclipse.monitor/.classpath b/eclipse/plugins/com.android.ide.eclipse.monitor/.classpath
index 9642053..1be4b68 100644
--- a/eclipse/plugins/com.android.ide.eclipse.monitor/.classpath
+++ b/eclipse/plugins/com.android.ide.eclipse.monitor/.classpath
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
+ <classpathentry exported="true" kind="lib" path="libs/sdkuilib.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
diff --git a/eclipse/plugins/com.android.ide.eclipse.monitor/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.monitor/META-INF/MANIFEST.MF
index 2a2a405..047072b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.monitor/META-INF/MANIFEST.MF
+++ b/eclipse/plugins/com.android.ide.eclipse.monitor/META-INF/MANIFEST.MF
@@ -11,6 +11,7 @@ Require-Bundle: org.eclipse.ui,
com.android.ide.eclipse.base
Bundle-ActivationPolicy: lazy
Bundle-Vendor: %Bundle-Vendor
-Bundle-ClassPath: .
+Bundle-ClassPath: .,
+ libs/sdkuilib.jar
Bundle-Localization: plugin
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
diff --git a/eclipse/plugins/com.android.ide.eclipse.monitor/build.properties b/eclipse/plugins/com.android.ide.eclipse.monitor/build.properties
index 44471de..a2a2a99 100644
--- a/eclipse/plugins/com.android.ide.eclipse.monitor/build.properties
+++ b/eclipse/plugins/com.android.ide.eclipse.monitor/build.properties
@@ -7,4 +7,5 @@ bin.includes = META-INF/,\
plugin_customization.ini,\
plugin.properties,\
images/,\
- splash.bmp
+ splash.bmp,\
+ libs/sdkuilib.jar
diff --git a/eclipse/plugins/com.android.ide.eclipse.monitor/src/com/android/ide/eclipse/monitor/MonitorApplication.java b/eclipse/plugins/com.android.ide.eclipse.monitor/src/com/android/ide/eclipse/monitor/MonitorApplication.java
index 27fcdd9..5f87813 100644
--- a/eclipse/plugins/com.android.ide.eclipse.monitor/src/com/android/ide/eclipse/monitor/MonitorApplication.java
+++ b/eclipse/plugins/com.android.ide.eclipse.monitor/src/com/android/ide/eclipse/monitor/MonitorApplication.java
@@ -18,7 +18,11 @@ package com.android.ide.eclipse.monitor;
import com.android.ide.eclipse.monitor.SdkToolsLocator.SdkInstallStatus;
import com.android.prefs.AndroidLocation;
+import com.android.sdklib.ISdkLog;
+import com.android.sdklib.NullSdkLog;
+import com.android.sdklib.SdkManager;
import com.android.sdkstats.SdkStatsService;
+import com.android.sdkuilib.internal.repository.sdkman2.AdtUpdateDialog;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
@@ -55,6 +59,14 @@ public class MonitorApplication implements IApplication {
}
MonitorPlugin.getDefault().setSdkPath(sdkPath);
+ // install platform tools if necessary
+ ISdkLog sdkLog = new NullSdkLog();
+ SdkManager manager = SdkManager.createManager(sdkPath, sdkLog);
+ if (manager.getPlatformToolsVersion() == null) {
+ AdtUpdateDialog window = new AdtUpdateDialog(new Shell(display), sdkLog, sdkPath);
+ window.installPlatformTools();
+ }
+
// If this is the first time using ddms or adt, open up the stats service
// opt out dialog, and request user for permissions.
// Note that the actual ping is performed in MonitorStartup
diff --git a/eclipse/plugins/com.android.ide.eclipse.monitor/src/com/android/ide/eclipse/monitor/SdkToolsLocator.java b/eclipse/plugins/com.android.ide.eclipse.monitor/src/com/android/ide/eclipse/monitor/SdkToolsLocator.java
index ba87c7b..19e1a43 100644
--- a/eclipse/plugins/com.android.ide.eclipse.monitor/src/com/android/ide/eclipse/monitor/SdkToolsLocator.java
+++ b/eclipse/plugins/com.android.ide.eclipse.monitor/src/com/android/ide/eclipse/monitor/SdkToolsLocator.java
@@ -73,7 +73,7 @@ public class SdkToolsLocator {
}
public SdkInstallStatus isValidInstallation() {
- List<String> executables = Arrays.asList(getAdbLocation(),
+ List<String> executables = Arrays.asList(
getTraceViewLocation(),
getHprofConvLocation());
diff --git a/eclipse/plugins/com.android.ide.eclipse.ndk/src/com/android/ide/eclipse/ndk/internal/launch/NdkGdbLaunchDelegate.java b/eclipse/plugins/com.android.ide.eclipse.ndk/src/com/android/ide/eclipse/ndk/internal/launch/NdkGdbLaunchDelegate.java
index 57d96d7..818a5c1 100644
--- a/eclipse/plugins/com.android.ide.eclipse.ndk/src/com/android/ide/eclipse/ndk/internal/launch/NdkGdbLaunchDelegate.java
+++ b/eclipse/plugins/com.android.ide.eclipse.ndk/src/com/android/ide/eclipse/ndk/internal/launch/NdkGdbLaunchDelegate.java
@@ -19,9 +19,9 @@ package com.android.ide.eclipse.ndk.internal.launch;
import com.android.ddmlib.AdbCommandRejectedException;
import com.android.ddmlib.AndroidDebugBridge;
import com.android.ddmlib.Client;
+import com.android.ddmlib.CollectingOutputReceiver;
import com.android.ddmlib.IDevice;
import com.android.ddmlib.IDevice.DeviceUnixSocketNamespace;
-import com.android.ddmlib.IShellOutputReceiver;
import com.android.ddmlib.InstallException;
import com.android.ddmlib.ShellCommandUnresponsiveException;
import com.android.ddmlib.SyncException;
@@ -233,7 +233,7 @@ public class NdkGdbLaunchDelegate extends GdbLaunchDelegate {
activityName);
try {
CountDownLatch launchedLatch = new CountDownLatch(1);
- ShellOutputReceiver receiver = new ShellOutputReceiver(launchedLatch);
+ CollectingOutputReceiver receiver = new CollectingOutputReceiver(launchedLatch);
device.executeShellCommand(command, receiver);
launchedLatch.await(5, TimeUnit.SECONDS);
String shellOutput = receiver.getOutput();
@@ -479,39 +479,9 @@ public class NdkGdbLaunchDelegate extends GdbLaunchDelegate {
String command = String.format("run-as %s /system/bin/sh -c pwd", app); //$NON-NLS-1$
CountDownLatch commandCompleteLatch = new CountDownLatch(1);
- ShellOutputReceiver receiver = new ShellOutputReceiver(commandCompleteLatch);
+ CollectingOutputReceiver receiver = new CollectingOutputReceiver(commandCompleteLatch);
device.executeShellCommand(command, receiver);
commandCompleteLatch.await(timeout, timeoutUnit);
return receiver.getOutput().trim();
}
-
- private static class ShellOutputReceiver implements IShellOutputReceiver {
- private StringBuffer sb = new StringBuffer();
- private CountDownLatch mCompleteLatch;
-
- public ShellOutputReceiver(CountDownLatch commandCompleteLatch) {
- mCompleteLatch = commandCompleteLatch;
- }
-
- @Override
- public void addOutput(byte[] data, int offset, int length) {
- sb.append(new String(data, offset, length));
- }
-
- @Override
- public void flush() {
- if (mCompleteLatch != null) {
- mCompleteLatch.countDown();
- }
- }
-
- @Override
- public boolean isCancelled() {
- return false;
- }
-
- public String getOutput() {
- return sb.toString();
- }
- }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion11-expected-completion73.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion11-expected-completion73.txt
index 21baad8..a2feb13 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion11-expected-completion73.txt
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion11-expected-completion73.txt
@@ -1,5 +1,5 @@
Code completion in completion11.xml for ?android:attr/Textapp^:
-?android:attr/textAppearance
+?android:attr/textAppearance : Base text color, typeface, size, and style.
?android:attr/textAppearanceButton
?android:attr/textAppearanceInverse
?android:attr/textAppearanceLarge
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues1-expected-completion32.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues1-expected-completion32.txt
index 7e27fa6..30e6c31 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues1-expected-completion32.txt
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues1-expected-completion32.txt
@@ -88,7 +88,6 @@ android:fillViewport : Defines whether the scrollview should stretch its content
android:filterTouchesWhenObscured : Specifies whether to filter touches when the view's window is obscured by another visible window. [boolean]
android:firstDayOfWeek : The first day of week according to java.util.Calendar. [integer]
android:fitsSystemWindows : Boolean internal attribute to adjust view layout based on system windows such as the status bar. [boolean]
-android:flingable : @hide Whether the number picker supports fligning. [boolean]
android:flipInterval : [integer]
android:focusable : Boolean that controls whether a view can take focus. [boolean]
android:focusableInTouchMode : Boolean that controls whether a view can take focus while in touch mode. [boolean]
@@ -221,8 +220,6 @@ android:secondaryProgress : Defines the secondary progress value, between 0 and
android:selectAllOnFocus : If the text is selectable, select it all when the view takes focus instead of moving the cursor to the start or end. [boolean]
android:selectedDateVerticalBar : Drawable for the vertical bar shown at the beggining and at the end of a selected date. [reference]
android:selectedWeekBackgroundColor : The background color for the selected week. [color, reference]
-android:selectionDivider : @hide The divider for making the selection area. [reference]
-android:selectionDividerHeight : @hide The height of the selection divider. [dimension]
android:shadowColor : Place a shadow of the specified color behind the text. [color]
android:shadowDx : Horizontal offset of the shadow. [float]
android:shadowDy : Vertical offset of the shadow. [float]
@@ -233,7 +230,6 @@ android:shownWeekCount : The number of weeks to be shown. [integer]
android:shrinkColumns : The zero-based index of the columns to shrink. [string]
android:singleLine : Constrains the text to a single horizontally scrolling line instead of letting it wrap onto multiple lines, and advances focus instead of inserting a newline when you press the enter key. * Deprecated: This attribute is deprecated and is replaced by the textMultiLine flag in the inputType attribute. Use caution when altering existing layouts, as the default value of singeLine is false (multi-line mode), but if you specify any value for inputType, the default is single-line mode. (If both singleLine and inputType attributes are found, the inputType flags will override the value of singleLine.). [boolean]
android:smoothScrollbar : When set to true, the list will use a more refined calculation method based on the pixels height of the items visible on screen. [boolean]
-android:solidColor : @hide Color for the solid color background if such for optimized rendering. [color, reference]
android:soundEffectsEnabled : Boolean that controls whether a view should have sound effects enabled for events such as clicking and touching. [boolean]
android:spacing : [dimension]
android:spinnerMode : Display mode for spinner options. [enum]
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues2-expected-completion71.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues2-expected-completion71.txt
index 641cddb..c491fea 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues2-expected-completion71.txt
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues2-expected-completion71.txt
@@ -1,3 +1,2 @@
Code completion in completionvalues2.xml for <item name="main_layout5" type="string">@string/^app_name</item>:
@string/app_name
-@string/hello
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion18.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion18.txt
index 21bb2fa..853d9a5 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion18.txt
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion18.txt
@@ -1,5 +1,5 @@
Code completion in manifest.xml for <activity android:^name=".TestActivity":
-android:name : Required name of the class implementing the activity, deriving from android.app.Activity. [string]
+android:name : Required name of the class implementing the activity, deriving from android.app.Activity. [string]. * Required.
android:theme : The overall theme to use for an activity. [reference]
android:label : A user-legible name for the given item. [string, reference]
android:description : Descriptive text for the associated data. [reference]
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion69.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion69.txt
index 627ff01..c60a305 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion69.txt
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion69.txt
@@ -1,4 +1,5 @@
Code completion in manifest.xml for <uses-sdk android:minSdkVersion="^11" />:
+16 : API 16: Android 4.1 (JellyBean)
15 : API 15: Android 4.0.3 (IceCreamSandwich)
14 : API 14: Android 4.0 (IceCreamSandwich)
13 : API 13: Android 3.2 (Honeycomb)
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/AdtUtilsTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/AdtUtilsTest.java
index b2b6787..e0ebdbc 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/AdtUtilsTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/AdtUtilsTest.java
@@ -15,9 +15,6 @@
*/
package com.android.ide.eclipse.adt;
-import com.google.common.collect.Iterables;
-
-import java.util.Arrays;
import java.util.Locale;
import junit.framework.TestCase;
@@ -148,31 +145,6 @@ public class AdtUtilsTest extends TestCase {
assertEquals("Foo", AdtUtils.stripSuffix("Foo", "Bar"));
}
- public void testSplitPath() throws Exception {
- assertTrue(Arrays.equals(new String[] { "/foo", "/bar", "/baz" },
- Iterables.toArray(AdtUtils.splitPath("/foo:/bar:/baz"), String.class)));
-
- assertTrue(Arrays.equals(new String[] { "/foo", "/bar" },
- Iterables.toArray(AdtUtils.splitPath("/foo;/bar"), String.class)));
-
- assertTrue(Arrays.equals(new String[] { "/foo", "/bar:baz" },
- Iterables.toArray(AdtUtils.splitPath("/foo;/bar:baz"), String.class)));
-
- assertTrue(Arrays.equals(new String[] { "\\foo\\bar", "\\bar\\foo" },
- Iterables.toArray(AdtUtils.splitPath("\\foo\\bar;\\bar\\foo"), String.class)));
-
- assertTrue(Arrays.equals(new String[] { "${sdk.dir}\\foo\\bar", "\\bar\\foo" },
- Iterables.toArray(AdtUtils.splitPath("${sdk.dir}\\foo\\bar;\\bar\\foo"),
- String.class)));
-
- assertTrue(Arrays.equals(new String[] { "${sdk.dir}/foo/bar", "/bar/foo" },
- Iterables.toArray(AdtUtils.splitPath("${sdk.dir}/foo/bar:/bar/foo"),
- String.class)));
-
- assertTrue(Arrays.equals(new String[] { "C:\\foo", "/bar" },
- Iterables.toArray(AdtUtils.splitPath("C:\\foo:/bar"), String.class)));
- }
-
public void testFormatFloatValue() throws Exception {
assertEquals("1", AdtUtils.formatFloatAttribute(1.0f));
assertEquals("2", AdtUtils.formatFloatAttribute(2.0f));
diff --git a/eclipse/scripts/create_all_symlinks.sh b/eclipse/scripts/create_all_symlinks.sh
index 1bfa946..134a1b8 100755
--- a/eclipse/scripts/create_all_symlinks.sh
+++ b/eclipse/scripts/create_all_symlinks.sh
@@ -188,6 +188,13 @@ TV_LIBS="traceview"
LIBS="$LIBS $TV_LIBS"
CP_FILES="$CP_FILES @:$TV_DEST $TV_LIBS"
+### MONITOR ###
+
+MONITOR_DEST="sdk/eclipse/plugins/com.android.ide.eclipse.monitor/libs"
+MONITOR_LIBS="sdkuilib"
+
+LIBS="$LIBS $MONITOR_LIBS"
+CP_FILES="$CP_FILES @:$MONITOR_DEST $MONITOR_LIBS"
### SDKMANAGER ###
diff --git a/files/ant/build.xml b/files/ant/build.xml
index 769889c..0c486e6 100644
--- a/files/ant/build.xml
+++ b/files/ant/build.xml
@@ -1295,7 +1295,9 @@
description="Runs lint on the project to look for potential bugs" >
<lint executable="${lint}"
html="${lint.out.html}"
- xml="${lint.out.xml}" />
+ xml="${lint.out.xml}"
+ src="${source.absolute.dir}:${gen.absolute.dir}"
+ classpath="${out.classes.absolute.dir}" />
</target>
<!-- ******************************************************* -->
diff --git a/files/typos/typos-de.txt b/files/typos/typos-de.txt
new file mode 100644
index 0000000..5bcdffc
--- /dev/null
+++ b/files/typos/typos-de.txt
@@ -0,0 +1,2219 @@
+# This file contains a number of common German typos:
+andriod->android
+
+# The remainder of this file contains misspellings from
+# http://de.m.wikipedia.org/wiki/Wikipedia:Liste_von_Tippfehlern/F%C3%BCr_Maschinen
+# plus some post-processing to fix invalid entries, remove duplicates, etc.
+#
+# The content is available under the
+# "Creative Commons Attribution-ShareAlike License"
+# http://creativecommons.org/licenses/by-sa/3.0/
+#
+# THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
+# COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
+# COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
+# AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
+#
+# BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE
+# TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY
+# BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS
+# CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
+# CONDITIONS.
+#
+# *1. Definitions*
+#
+# 1. *"Adaptation"* means a work based upon the Work, or upon the Work
+# and other pre-existing works, such as a translation, adaptation,
+# derivative work, arrangement of music or other alterations of a
+# literary or artistic work, or phonogram or performance and includes
+# cinematographic adaptations or any other form in which the Work may
+# be recast, transformed, or adapted including in any form
+# recognizably derived from the original, except that a work that
+# constitutes a Collection will not be considered an Adaptation for
+# the purpose of this License. For the avoidance of doubt, where the
+# Work is a musical work, performance or phonogram, the
+# synchronization of the Work in timed-relation with a moving image
+# ("synching") will be considered an Adaptation for the purpose of
+# this License.
+# 2. *"Collection"* means a collection of literary or artistic works,
+# such as encyclopedias and anthologies, or performances, phonograms
+# or broadcasts, or other works or subject matter other than works
+# listed in Section 1(f) below, which, by reason of the selection and
+# arrangement of their contents, constitute intellectual creations, in
+# which the Work is included in its entirety in unmodified form along
+# with one or more other contributions, each constituting separate and
+# independent works in themselves, which together are assembled into a
+# collective whole. A work that constitutes a Collection will not be
+# considered an Adaptation (as defined below) for the purposes of this
+# License.
+# 3. *"Creative Commons Compatible License"* means a license that is
+# listed at http://creativecommons.org/compatiblelicenses that has
+# been approved by Creative Commons as being essentially equivalent to
+# this License, including, at a minimum, because that license: (i)
+# contains terms that have the same purpose, meaning and effect as the
+# License Elements of this License; and, (ii) explicitly permits the
+# relicensing of adaptations of works made available under that
+# license under this License or a Creative Commons jurisdiction
+# license with the same License Elements as this License.
+# 4. *"Distribute"* means to make available to the public the original
+# and copies of the Work or Adaptation, as appropriate, through sale
+# or other transfer of ownership.
+# 5. *"License Elements"* means the following high-level license
+# attributes as selected by Licensor and indicated in the title of
+# this License: Attribution, ShareAlike.
+# 6. *"Licensor"* means the individual, individuals, entity or entities
+# that offer(s) the Work under the terms of this License.
+# 7. *"Original Author"* means, in the case of a literary or artistic
+# work, the individual, individuals, entity or entities who created
+# the Work or if no individual or entity can be identified, the
+# publisher; and in addition (i) in the case of a performance the
+# actors, singers, musicians, dancers, and other persons who act,
+# sing, deliver, declaim, play in, interpret or otherwise perform
+# literary or artistic works or expressions of folklore; (ii) in the
+# case of a phonogram the producer being the person or legal entity
+# who first fixes the sounds of a performance or other sounds; and,
+# (iii) in the case of broadcasts, the organization that transmits the
+# broadcast.
+# 8. *"Work"* means the literary and/or artistic work offered under the
+# terms of this License including without limitation any production in
+# the literary, scientific and artistic domain, whatever may be the
+# mode or form of its expression including digital form, such as a
+# book, pamphlet and other writing; a lecture, address, sermon or
+# other work of the same nature; a dramatic or dramatico-musical work;
+# a choreographic work or entertainment in dumb show; a musical
+# composition with or without words; a cinematographic work to which
+# are assimilated works expressed by a process analogous to
+# cinematography; a work of drawing, painting, architecture,
+# sculpture, engraving or lithography; a photographic work to which
+# are assimilated works expressed by a process analogous to
+# photography; a work of applied art; an illustration, map, plan,
+# sketch or three-dimensional work relative to geography, topography,
+# architecture or science; a performance; a broadcast; a phonogram; a
+# compilation of data to the extent it is protected as a copyrightable
+# work; or a work performed by a variety or circus performer to the
+# extent it is not otherwise considered a literary or artistic work.
+# 9. *"You"* means an individual or entity exercising rights under this
+# License who has not previously violated the terms of this License
+# with respect to the Work, or who has received express permission
+# from the Licensor to exercise rights under this License despite a
+# previous violation.
+# 10. *"Publicly Perform"* means to perform public recitations of the Work
+# and to communicate to the public those public recitations, by any
+# means or process, including by wire or wireless means or public
+# digital performances; to make available to the public Works in such
+# a way that members of the public may access these Works from a place
+# and at a place individually chosen by them; to perform the Work to
+# the public by any means or process and the communication to the
+# public of the performances of the Work, including by public digital
+# performance; to broadcast and rebroadcast the Work by any means
+# including signs, sounds or images.
+# 11. *"Reproduce"* means to make copies of the Work by any means
+# including without limitation by sound or visual recordings and the
+# right of fixation and reproducing fixations of the Work, including
+# storage of a protected performance or phonogram in digital form or
+# other electronic medium.
+#
+# *2. Fair Dealing Rights.* Nothing in this License is intended to reduce,
+# limit, or restrict any uses free from copyright or rights arising from
+# limitations or exceptions that are provided for in connection with the
+# copyright protection under copyright law or other applicable laws.
+#
+# *3. License Grant.* Subject to the terms and conditions of this License,
+# Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
+# perpetual (for the duration of the applicable copyright) license to
+# exercise the rights in the Work as stated below:
+#
+# 1. to Reproduce the Work, to incorporate the Work into one or more
+# Collections, and to Reproduce the Work as incorporated in the
+# Collections;
+# 2. to create and Reproduce Adaptations provided that any such
+# Adaptation, including any translation in any medium, takes
+# reasonable steps to clearly label, demarcate or otherwise identify
+# that changes were made to the original Work. For example, a
+# translation could be marked "The original work was translated from
+# English to Spanish," or a modification could indicate "The original
+# work has been modified.";
+# 3. to Distribute and Publicly Perform the Work including as
+# incorporated in Collections; and,
+# 4. to Distribute and Publicly Perform Adaptations.
+# 5.
+#
+# For the avoidance of doubt:
+#
+# 1. *Non-waivable Compulsory License Schemes*. In those
+# jurisdictions in which the right to collect royalties through
+# any statutory or compulsory licensing scheme cannot be waived,
+# the Licensor reserves the exclusive right to collect such
+# royalties for any exercise by You of the rights granted under
+# this License;
+# 2. *Waivable Compulsory License Schemes*. In those jurisdictions in
+# which the right to collect royalties through any statutory or
+# compulsory licensing scheme can be waived, the Licensor waives
+# the exclusive right to collect such royalties for any exercise
+# by You of the rights granted under this License; and,
+# 3. *Voluntary License Schemes*. The Licensor waives the right to
+# collect royalties, whether individually or, in the event that
+# the Licensor is a member of a collecting society that
+# administers voluntary licensing schemes, via that society, from
+# any exercise by You of the rights granted under this License.
+#
+# The above rights may be exercised in all media and formats whether now
+# known or hereafter devised. The above rights include the right to make
+# such modifications as are technically necessary to exercise the rights
+# in other media and formats. Subject to Section 8(f), all rights not
+# expressly granted by Licensor are hereby reserved.
+#
+# *4. Restrictions.* The license granted in Section 3 above is expressly
+# made subject to and limited by the following restrictions:
+#
+# 1. You may Distribute or Publicly Perform the Work only under the terms
+# of this License. You must include a copy of, or the Uniform Resource
+# Identifier (URI) for, this License with every copy of the Work You
+# Distribute or Publicly Perform. You may not offer or impose any
+# terms on the Work that restrict the terms of this License or the
+# ability of the recipient of the Work to exercise the rights granted
+# to that recipient under the terms of the License. You may not
+# sublicense the Work. You must keep intact all notices that refer to
+# this License and to the disclaimer of warranties with every copy of
+# the Work You Distribute or Publicly Perform. When You Distribute or
+# Publicly Perform the Work, You may not impose any effective
+# technological measures on the Work that restrict the ability of a
+# recipient of the Work from You to exercise the rights granted to
+# that recipient under the terms of the License. This Section 4(a)
+# applies to the Work as incorporated in a Collection, but this does
+# not require the Collection apart from the Work itself to be made
+# subject to the terms of this License. If You create a Collection,
+# upon notice from any Licensor You must, to the extent practicable,
+# remove from the Collection any credit as required by Section 4(c),
+# as requested. If You create an Adaptation, upon notice from any
+# Licensor You must, to the extent practicable, remove from the
+# Adaptation any credit as required by Section 4(c), as requested.
+# 2. You may Distribute or Publicly Perform an Adaptation only under the
+# terms of: (i) this License; (ii) a later version of this License
+# with the same License Elements as this License; (iii) a Creative
+# Commons jurisdiction license (either this or a later license
+# version) that contains the same License Elements as this License
+# (e.g., Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons
+# Compatible License. If you license the Adaptation under one of the
+# licenses mentioned in (iv), you must comply with the terms of that
+# license. If you license the Adaptation under the terms of any of the
+# licenses mentioned in (i), (ii) or (iii) (the "Applicable License"),
+# you must comply with the terms of the Applicable License generally
+# and the following provisions: (I) You must include a copy of, or the
+# URI for, the Applicable License with every copy of each Adaptation
+# You Distribute or Publicly Perform; (II) You may not offer or impose
+# any terms on the Adaptation that restrict the terms of the
+# Applicable License or the ability of the recipient of the Adaptation
+# to exercise the rights granted to that recipient under the terms of
+# the Applicable License; (III) You must keep intact all notices that
+# refer to the Applicable License and to the disclaimer of warranties
+# with every copy of the Work as included in the Adaptation You
+# Distribute or Publicly Perform; (IV) when You Distribute or Publicly
+# Perform the Adaptation, You may not impose any effective
+# technological measures on the Adaptation that restrict the ability
+# of a recipient of the Adaptation from You to exercise the rights
+# granted to that recipient under the terms of the Applicable License.
+# This Section 4(b) applies to the Adaptation as incorporated in a
+# Collection, but this does not require the Collection apart from the
+# Adaptation itself to be made subject to the terms of the Applicable
+# License.
+# 3. If You Distribute, or Publicly Perform the Work or any Adaptations
+# or Collections, You must, unless a request has been made pursuant to
+# Section 4(a), keep intact all copyright notices for the Work and
+# provide, reasonable to the medium or means You are utilizing: (i)
+# the name of the Original Author (or pseudonym, if applicable) if
+# supplied, and/or if the Original Author and/or Licensor designate
+# another party or parties (e.g., a sponsor institute, publishing
+# entity, journal) for attribution ("Attribution Parties") in
+# Licensor's copyright notice, terms of service or by other reasonable
+# means, the name of such party or parties; (ii) the title of the Work
+# if supplied; (iii) to the extent reasonably practicable, the URI, if
+# any, that Licensor specifies to be associated with the Work, unless
+# such URI does not refer to the copyright notice or licensing
+# information for the Work; and (iv) , consistent with Ssection 3(b),
+# in the case of an Adaptation, a credit identifying the use of the
+# Work in the Adaptation (e.g., "French translation of the Work by
+# Original Author," or "Screenplay based on original Work by Original
+# Author"). The credit required by this Section 4(c) may be
+# implemented in any reasonable manner; provided, however, that in the
+# case of a Adaptation or Collection, at a minimum such credit will
+# appear, if a credit for all contributing authors of the Adaptation
+# or Collection appears, then as part of these credits and in a manner
+# at least as prominent as the credits for the other contributing
+# authors. For the avoidance of doubt, You may only use the credit
+# required by this Section for the purpose of attribution in the
+# manner set out above and, by exercising Your rights under this
+# License, You may not implicitly or explicitly assert or imply any
+# connection with, sponsorship or endorsement by the Original Author,
+# Licensor and/or Attribution Parties, as appropriate, of You or Your
+# use of the Work, without the separate, express prior written
+# permission of the Original Author, Licensor and/or Attribution Parties.
+# 4. Except as otherwise agreed in writing by the Licensor or as may be
+# otherwise permitted by applicable law, if You Reproduce, Distribute
+# or Publicly Perform the Work either by itself or as part of any
+# Adaptations or Collections, You must not distort, mutilate, modify
+# or take other derogatory action in relation to the Work which would
+# be prejudicial to the Original Author's honor or reputation.
+# Licensor agrees that in those jurisdictions (e.g. Japan), in which
+# any exercise of the right granted in Section 3(b) of this License
+# (the right to make Adaptations) would be deemed to be a distortion,
+# mutilation, modification or other derogatory action prejudicial to
+# the Original Author's honor and reputation, the Licensor will waive
+# or not assert, as appropriate, this Section, to the fullest extent
+# permitted by the applicable national law, to enable You to
+# reasonably exercise Your right under Section 3(b) of this License
+# (right to make Adaptations) but not otherwise.
+#
+# *5. Representations, Warranties and Disclaimer*
+#
+# UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR
+# OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY
+# KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,
+# INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF
+# LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS,
+# WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE
+# EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
+#
+# *6. Limitation on Liability.* EXCEPT TO THE EXTENT REQUIRED BY
+# APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL
+# THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY
+# DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF
+# LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+#
+# *7. Termination*
+#
+# 1. This License and the rights granted hereunder will terminate
+# automatically upon any breach by You of the terms of this License.
+# Individuals or entities who have received Adaptations or Collections
+# from You under this License, however, will not have their licenses
+# terminated provided such individuals or entities remain in full
+# compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
+# survive any termination of this License.
+# 2. Subject to the above terms and conditions, the license granted here
+# is perpetual (for the duration of the applicable copyright in the
+# Work). Notwithstanding the above, Licensor reserves the right to
+# release the Work under different license terms or to stop
+# distributing the Work at any time; provided, however that any such
+# election will not serve to withdraw this License (or any other
+# license that has been, or is required to be, granted under the terms
+# of this License), and this License will continue in full force and
+# effect unless terminated as stated above.
+#
+# *8. Miscellaneous*
+#
+# 1. Each time You Distribute or Publicly Perform the Work or a
+# Collection, the Licensor offers to the recipient a license to the
+# Work on the same terms and conditions as the license granted to You
+# under this License.
+# 2. Each time You Distribute or Publicly Perform an Adaptation, Licensor
+# offers to the recipient a license to the original Work on the same
+# terms and conditions as the license granted to You under this License.
+# 3. If any provision of this License is invalid or unenforceable under
+# applicable law, it shall not affect the validity or enforceability
+# of the remainder of the terms of this License, and without further
+# action by the parties to this agreement, such provision shall be
+# reformed to the minimum extent necessary to make such provision
+# valid and enforceable.
+# 4. No term or provision of this License shall be deemed waived and no
+# breach consented to unless such waiver or consent shall be in
+# writing and signed by the party to be charged with such waiver or
+# consent.
+# 5. This License constitutes the entire agreement between the parties
+# with respect to the Work licensed here. There are no understandings,
+# agreements or representations with respect to the Work not specified
+# here. Licensor shall not be bound by any additional provisions that
+# may appear in any communication from You. This License may not be
+# modified without the mutual written agreement of the Licensor and You.
+# 6. The rights granted under, and the subject matter referenced, in this
+# License were drafted utilizing the terminology of the Berne
+# Convention for the Protection of Literary and Artistic Works (as
+# amended on September 28, 1979), the Rome Convention of 1961, the
+# WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms
+# Treaty of 1996 and the Universal Copyright Convention (as revised on
+# July 24, 1971). These rights and subject matter take effect in the
+# relevant jurisdiction in which the License terms are sought to be
+# enforced according to the corresponding provisions of the
+# implementation of those treaty provisions in the applicable national
+# law. If the standard suite of rights granted under applicable
+# copyright law includes additional rights not granted under this
+# License, such additional rights are deemed to be included in the
+# License; this License is not intended to restrict the license of any
+# rights under applicable law.
+Aaachen->Aachen
+aberufen->abgerufen
+abgekürtzt->abgekürzt
+abgeschloßen->abgeschlossen
+Abhängikeit->Abhängigkeit
+Abhängkeit->Abhängigkeit
+abolvieren->absolvieren
+abolviert->absolviert
+abschliessen->abschließen
+abschliessend->abschließend
+abschliessende->abschließende
+abschliessenden->abschließenden
+abschliessender->abschließender
+abschliesst->abschließt
+Absorbtion->Absorption
+abzuschliessen->abzuschließen
+achsial*->axial*
+achzig->achtzig
+Addresse->Adresse
+addressiert->adressiert
+Adjudant->Adjutant
+Aeropag->Areopag
+Aeropagos->Areopag
+afrz->afrz.
+agberufen->abgerufen
+Agendas->Agenden
+agerufen->abgerufen
+agraisch->agrarisch
+agressiv->aggressiv
+akkomodieren->akkommodieren
+Akkustik->Akustik
+akreditiert->akkreditiert
+Aktivitiäten->Aktivitäten
+Aktzeptanz->Akzeptanz
+alamiert->alarmiert
+aler->aller
+alerdings->allerdings
+Algorhitmus->Algorithmus
+Algoritmus->Algorithmus
+aliiert->alliiert
+allerding->allerdings
+allgmein->allgemein
+alliert->alliiert
+allredings->allerdings
+all zu->allzu
+Alstadt->Altstadt
+am einem->an einem,am einen
+amerikanich->amerikanisch
+amerikansch->amerikanisch
+amerkanisch->amerikanisch
+am seinem->an seinem
+Amtsitz->Amtssitz
+Amtsprache->Amtssprache
+Amtsprachen->Amtssprachen
+Anaesthesie->Anästhesie
+Analen->Annalen
+anderere->andere
+andereren->anderen
+andererer->anderer
+andereseits->andererseits
+anders herum->andersherum
+andersrum->besser: andersherum
+angelsächisch->angelsächsisch
+angelsächsiche->angelsächsische
+angelsächsichen->angelsächsischen
+angesehendsten->angesehensten
+anlaesslich->anlässlich
+anlaeßlich->anlässlich
+änlich->ähnlich
+annährend->annähernd
+Annährung->Annäherung
+Annektion->Annexion
+annerkannt->anerkannt
+annerkannte->anerkannte
+Annerkennung->Anerkennung
+annuliert->annulliert
+Annulierung->Annullierung
+Anordung->Anordnung
+Anschaung->Anschauung
+anschliessen->anschließen
+anschliessend->anschließend
+anschliessende->anschließende
+anschliessenden->anschließenden
+anschliessender->anschließender
+anschliessendes->anschließendes
+anschliesst->anschließt
+Anstoss->Anstoß
+anvisiert->angekündigt,avisiert
+Anwendund->Anwendung
+Anwort->Antwort
+Appartment*->Apartment*,Appartement*
+aquirieren->akquirieren
+Aquisition->Akquisition
+archälogische->archäologische
+archälogischen->archäologischen
+Archeologe->Archäologe
+Argentur*->Agentur*
+Arikel->Artikel
+arithmetrisch->arithmetisch
+Artzt->Arzt
+assozial->asozial
+asymetrisch*->asymmetrisch*
+Atacke->Attacke
+atackieren->attackieren
+atakieren->attackieren
+Athleth*->Athlet*
+Athmosphäre*->Atmosphäre*
+athmosphärisch*->atmosphärisch*
+Atrappe->Attrappe
+attakieren->attackieren
+Aufällig->Auffällig
+Aufassung->Auffassung
+Aufassungen->Auffassungen
+auf dem ersten Blick->auf den ersten Blick
+auf eigenem Wunsch->auf eigenen Wunsch,aus eigenem Wunsch
+Aufenhalt->Aufenthalt
+Aufname->Aufnahme
+Auforderung->Aufforderung
+aufrecht erhält->aufrechterhält
+aufrecht erhalten->aufrechterhalten
+aufrecht erhielt->aufrechterhielt
+aufrecht zu erhalten->aufrechtzuerhalten
+Aufsteig->Aufstieg
+Auftieg->Aufstieg
+auftretenen->auftretenden
+auftretten->auftreten
+Augenlied->Augenlid
+augenommen->aufgenommen,ausgenommen
+auml->Ä,ä
+Ausage->Aussage
+Ausagen->Aussagen
+auschliesslich->ausschließlich
+auschließlich->ausschließlich
+auschliessliche->ausschließliche
+auschliesslichen->ausschließlichen
+Auseinadersetzung->Auseinandersetzung
+Auseindersetzung->Auseinandersetzung
+auserdem->außerdem
+auserhalb->außerhalb
+Ausgangpunkt->Ausgangspunkt
+ausgeschalten->ausgeschaltet
+Ausicht->Aussicht
+Ausmass->Ausmaß
+Ausprache->Aussprache
+Auspruch->Ausspruch
+ausschliessen->ausschließen
+ausschliesslich->ausschließlich
+ausschliesst->ausschließt
+Ausschwitz->Auschwitz
+aussen->außen
+Aussenminister->Außenminister
+ausser->außer
+ausserdem->außerdem
+äussere->äußere
+äusseren->äußeren
+äusserer->äußerer
+äusseres->äußeres
+aussergewöhnlich->außergewöhnlich
+aussergewöhnlichen->außergewöhnlichen
+ausserhalb->außerhalb
+ausserirdisch->außerirdisch
+ausserirdische->außerirdische
+ausserirdischen->außerirdischen
+äussern->äußern
+ausserordentlich->außerordentlich
+ausserordentliche->außerordentliche
+ausserordentlichem->außerordentlichem
+ausserordentlichen->außerordentlichen
+ausserordentlicher->außerordentlicher
+ausserordentliches->außerordentliches
+äusserst->äußerst
+äusserste->äußerste
+äussersten->äußersten
+äusserte->äußerte
+äusserten->äußerten
+Äusserung->Äußerung
+Äusserungen->Äußerungen
+aussschliesslich->ausschließlich
+aussschließlich->ausschließlich
+außschließlich->ausschließlich
+Austattung->Ausstattung
+Austellung->Ausstellung
+Austellungen->Ausstellungen
+Austerben->Aussterben
+Auszeichung->Auszeichnung
+Auszeichungen->Auszeichnungen
+auszuschliessen->auszuschließen
+Author des->Autor des
+authorisieren->autorisieren
+authorisiert->autorisiert
+Authorisierung*->Autorisierung*
+Authorität->Autorität
+dem Autoren->dem Autor
+des Autoren->des Autors
+vom Autoren->vom Autor
+Babies->Babys
+bafand->befand
+Balett->Ballett
+bassierend->basierend
+Batallion->Bataillon
+Battaillon->Bataillon
+Battallion->Bataillon
+Bauerhof->Bauernhof
+Bauerhöfe->Bauernhöfe
+bedeudend->bedeutend
+bedeudende->bedeutende
+bedeudenden->bedeutenden
+bedeudender->bedeutender
+bedeudendes->bedeutendes
+bedeudet->bedeutet
+bedeudete->bedeutete
+bedeutendeste->bedeutendste
+bedeutenste->bedeutendste
+bedeutensten->bedeutendsten
+bedeutenster->bedeutendster
+bedeutenstes->bedeutendstes
+bedeutesten->bedeutendsten
+Bedinung->Bedingung/Bedienung
+Bedürfniss->Bedürfnis
+beeinflußen->beeinflussen
+Beeinflußung->Beeinflussung
+beeinhalten->beinhalten
+beeinhaltet->beinhaltet
+befindet auf->befindet sich auf
+befindet ein*->befindet sich ein*
+befindet in->befindet sich in
+begang->beging,begann
+beherrbergt->beherbergt
+beherschen->beherrschen
+beherscht->beherrscht
+beherschte->beherrschte
+beidemale->beide Male
+beim dem->bei dem,beim
+beim der->bei der,beim,bei dem
+beindrucken->beeindrucken
+beinflussen->beeinflussen
+beinflusst*->beeinflusst*
+Beipiel*->Beispiel*
+Beispeil*->Beispiel*
+beispielswiese->beispielsweise
+beispielweise->beispielsweise
+Beitag->Beitrag
+bekammen->bekamen
+Bekenntniss->Bekenntnis
+Benefitz->Benefiz
+bennant->benannt
+Bennenung->Benennung
+Berechung->Berechnung
+bereit gehalten->bereitgehalten
+bereit gestellt->bereitgestellt
+bereit hält->bereithält
+bereit stand->bereitstand
+bereit stehen->bereitstehen
+bereit steht->bereitsteht
+bereit stellt->bereitstellt
+bereit zu halten->bereitzuhalten
+bereit zu stellen->bereitzustellen
+Berfung->Berufung
+Berreich->Bereich
+berücksichtig->berücksichtigt
+berümt->berühmt
+berümte->berühmte
+besass->besaß
+besassen->besaßen
+besitzten->besitzen
+Bespiel->Beispiel
+Bestandsteil->Bestandteil
+Bestandtteil->Bestandteil
+bestbezahltest*->bestbezahlt*
+bestimmmt->bestimmt
+bestreitete->bestritt
+Betreung->Betreuung
+Betriebsystem*->Betriebssystem*
+Bevökerung->Bevölkerung
+Beweiß->Beweis
+bezeichent->bezeichnet
+bezeichet->bezeichnet
+Bezeichung*->Bezeichnung*
+Biograpfie->Biografie
+bischen->bisschen
+Bischofsitz->Bischofssitz
+Bisquit->Biskuit
+bloss->bloß
+blosse->bloße
+blossen->bloßen
+blosser->bloßer
+blosses->bloßes
+an Board->an Bord
+on Bord->an Bord
+bombadieren->bombardieren
+bombadiert->bombardiert
+Bombadierung->Bombardierung
+boolsch->boolesch
+brilliant->brillant
+britsch->britisch
+britsche->britische
+britschen->britischen
+britscher->britischer
+britsches->britisches
+Bronzemedaillie*->Bronzemedaille*
+Bronzemedallie*->Bronzemedaille*
+Bügermeister->Bürgermeister
+Bundesaussenminister->Bundesaußenminister
+Bundesstrasse->Bundesstraße
+Bundestaat*->Bundesstaat*
+Bundestraße->Bundesstraße
+Bundsandstein*->Buntsandstein*
+byzantisch*->byzantinisch*
+chinesiche->chinesische
+chinesichen->chinesischen
+chinesicher->chinesischer
+Chirugie->Chirurgie
+Chonik->Chronik
+Chonist->Chronist
+chonologisch->chronologisch
+cirka->zirka,circa
+dadruch->dadurch
+daduch->dadurch
+danaben->daneben
+danch->danach
+dannach->danach
+deuten daraufhin->deuten darauf hin
+deutet daraufhin->deutet darauf hin
+weisen daraufhin->weisen darauf hin
+weist daraufhin->weist darauf hin
+darüberhinaus->darüber hinaus
+daruf->darauf
+darufhin->daraufhin
+das es sich bei->dass es sich bei
+das es sich um->dass es sich um
+so das der->so dass der
+so das die->so dass die
+so das er->so dass er
+so das sie->so dass sie
+dass heißt->das heißt
+dastellt->darstellt
+dazu gehörige*->dazugehörige*
+Debutalbum->Debütalbum
+Definiton->Definition
+definitv->definitiv
+Defintion->Definition
+deligiert->delegiert
+dem selben->demselben
+denoch->dennoch
+den selben->denselben
+derem->deren
+der Niederlanden->der Niederlande,den Niederlanden
+der selbe->derselbe
+der selben->derselben
+in der USA->in den USA
+des des->des
+des eines->eines,des,der eines,dem eines
+des selben->desselben
+dessem->dessen
+desshalb->deshalb
+desweiteren->des Weiteren
+desweitern->des Weiteren
+des Weitern->des Weiteren
+detailiert*->detailliert*
+detalliert->detailliert
+dezeit->derzeit
+Dezmber->Dezember
+die selbe->dieselbe
+die selben->dieselben
+Differentation->Differentiation
+Dikator->Diktator
+Dikatur->Diktatur
+Diphterie->Diphtherie
+Diphtong->Diphthong
+Dirgent->Dirigent
+Discografie->Diskografie
+Discographie->Diskographie
+diskreminieren->diskriminieren
+diskrimierend*->diskriminierend*
+Diskrimierung*->Diskriminierung*
+Diskusion->Diskussion
+Disseration->Dissertation
+Divison*->Division*
+Divsion*->Division*
+Diziplin*->Disziplin*
+Dollmetscher->Dolmetscher
+dort hin->dorthin
+draufhin->daraufhin
+draussen->draußen
+Dreick->Dreieck
+dreissig->dreißig
+dreissiger->dreißiger
+druch->durch
+druchgeführt->durchgeführt
+duch->durch
+duchführen->durchführen
+Duchführung->Durchführung
+duchgeführt->durchgeführt
+Duchschnitt->Durchschnitt
+durch geführt->durchgeführt
+Durchschlagkraft->Durchschlagskraft
+Durchsetztung->Durchsetzung
+durchstossen->durchstoßen
+Durschnitt->Durchschnitt
+durschnittlich->durchschnittlich
+durschnittliche->durchschnittliche
+durschnittlichen->durchschnittlichen
+ebefalls->ebenfalls
+eben dies->ebendies
+eben diese->ebendiese
+eben diesem->ebendiesem
+eben diesen->ebendiesen
+eben dieser->ebendieser
+eben dieses->ebendieses
+ebendso->ebenso
+ebenfall->ebenfalls
+ebenfals->ebenfalls
+Editon->Edition
+Edtion->Edition
+einem eigenem->einem eigenen
+ihrem eigenem->ihrem eigenen
+seinem eigenem->seinem eigenen
+eigenen sich->eignen sich
+mit einen->mit einem
+eines des->eines der
+Einflüße->Einflüsse
+Einfuss->Einfluss
+einge->einige
+eingen->einigen
+eingentlich->eigentlich
+einger->einiger
+einges->einiges
+eingesetz->eingesetzt
+eingesetzen->eingesetzten
+einigemal->einige Mal
+einklich->eigentlich
+Einordung->Einordnung
+einschliessen->einschließen
+einschliesslich->einschließlich
+einschliesst->einschließt
+einzelen->einzelne
+einzigste->einzige
+einzigster->einziger
+einzigstes->einziges
+ekklektizistisch->eklektizistisch
+ekstasisch->ekstatisch
+elekrisch->elektrisch
+elekronisch->elektronisch
+eleminieren->eliminieren
+eleminiert->eliminiert
+emigiert->emigriert
+emigiriert->emigriert
+Emmigrant->Emigrant
+Emmigration->Emigration
+emmigriert->emigriert
+emprisch->empirisch
+Emsemble->Ensemble
+endeckt->entdeckt
+endeckte->entdeckte
+Endeckung*->Entdeckung*
+enfernt->entfernt
+enfernte->entfernte
+Enfernung->Entfernung
+Enfernungen->Entfernungen
+Engeneering->Engineering
+englsich->englisch
+engültig->endgültig
+enhält->enthält
+enhalten->enthalten
+Enscheidung->Entscheidung
+enstand->entstand
+enstanden->entstanden
+enstehen->entstehen
+ensteht->entsteht
+Enstehung->Entstehung
+entgegen gebracht*->entgegengebracht*
+entgegen gesetzt*->entgegengesetzt*
+entgegen kam->entgegenkam
+entgegen nahm->entgegennahm
+entgegen zu gehen->entgegenzugehen
+entgegen zu kommen->entgegenzukommen
+entgegen zu nehmen->entgegenzunehmen
+entgegen zu schleudern->entgegenzuschleudern
+entgegen zu setzen->entgegenzusetzen
+entgegen zu stellen->entgegenzustellen
+entgegen zu treten->entgegenzutreten
+entgegen zu wirken->entgegenzuwirken
+Entgeld->Entgelt
+entgültig*->endgültig*
+entlang führt*->entlangführt*
+entlang geführt*->entlanggeführt*
+entprechend->entsprechend
+entprechende->entsprechende
+entprechender->entsprechender
+entsant->entsandt
+entscheidene*->entscheidende*
+entscheident->entscheidend
+entschloß->entschloss
+entspechen*->entsprechen*
+entsprechene->entsprechende
+entsprechenen->entsprechenden
+entstandt->entstand
+enwickelt->entwickelt
+enwickelte->entwickelte
+enwickelten->entwickelten
+enwickelter->entwickelter
+enwickeltes->entwickeltes
+Enwicklung->Entwicklung
+Enwicklungen->Entwicklungen
+ereichen->erreichen
+ereicht->erreicht
+ereichte->erreichte
+Ereignise->Ereignisse
+Ereignisen->Ereignissen
+Ereigniss->Ereignis
+Erfog->Erfolg
+erfogreich->erfolgreich
+erfolgslos->erfolglos
+erfolgsversprechend->erfolgversprechend
+Erfurcht->Ehrfurcht
+Ergebniss->Ergebnis
+Erkentnis->Erkenntnis
+Erkentnisse->Erkenntnisse
+erklährt->erklärt
+ermöglich->ermöglicht,ermöglichen
+erorbert->erobert
+errinnern->erinnern
+errinnert->erinnert
+errreichen->erreichen
+errreicht->erreicht
+errreichte->erreichte
+errrichtet->errichtet
+ersmals->erstmals
+dem erstem->dem ersten
+im erstem->im ersten
+erzeilt->erzielt
+erzeilte->erzielte
+erziehlen->erzielen
+erziehlt->erzielt
+estisch->estnisch
+Ettikett*->Etikett*
+dem europäischem->dem europäischen
+im europäischem->im europäischen
+Examplar->Exemplar
+examplarisch->exemplarisch
+exellent->exzellent
+exisitiert->existiert
+Existens->Existenz
+Expediton->Expedition
+experimentiell->experimentell
+Extase->Ekstase
+Fahradtour->Fahrradtour
+fälschlicher Weise->fälschlicherweise
+familär*->familiär*
+Famile->Familie
+Familen*->Familien*
+Famlie*->Familie*
+Februrar->Februar
+Feburar->Februar
+fern geblieben->ferngeblieben
+fern gehalten->ferngehalten
+fern zu halten->fernzuhalten
+Fersehen->Fernsehen
+Ferseh*->Fernseh*
+fertigestellt->fertiggestellt
+festellen->feststellen
+Festellung->Feststellung
+fidet->findet
+Fiedrich->Friedrich
+Flagschiff->Flaggschiff
+Flektion->Flexion
+fliessen->fließen
+fliesst->fließt
+des Flughafen->des Flughafens
+Fluß->Fluss
+Flüße->Flüsse
+fokusieren->fokussieren
+fokusiert->fokussiert
+Fokusierung->Fokussierung
+Foschung->Forschung
+Fotographie->Fotografie,Photographie
+Fotographien->Fotografien,Photographien
+fotographiert->fotografiert
+franösisch*->französisch*
+frantösisch*->französisch*
+franzöisch*->französisch*
+französich*->französisch*
+dem französischem->dem französischen
+einem französischem->einem französischen
+im französischem->im französischen
+Freidrich->Friedrich
+frei gestellt->freigestellt
+Freimauerei->Freimaurerei
+Fremsprache->Fremdsprache
+Friedenschluss->Friedensschluss
+Friedich->Friedrich
+Frima->Firma
+fröhnen->frönen
+Frühjar->Frühjahr
+frühre->frühere
+fuer->für
+füher*->früher*,Führer*
+Fuktion*->Funktion*
+Funier*->Furnier*
+für für->für
+Fuss->Fuß
+Fussball->Fußball
+Fussballer->Fußballer
+Fussballerin->Fußballerin
+Fussballspieler->Fußballspieler
+Fussballspielerin->Fußballspielerin
+Fußballstadium->Fußballstadion
+Fusse->Fuße
+Füsse->Füße
+Füst->Fürst
+gabe es->gab es
+Gallerie->Galerie
+Gallerien->Galerien
+Gallionsfigur->Galionsfigur
+garnicht->gar nicht
+Garnision->Garnison
+Garnision*->Garnison*
+Gebäde->Gebäude
+Gebahren->Gebaren
+gebähren->gebären
+Gebaüde->Gebäude
+Gebaude->Gebäude
+Gebäuder->Gebäude
+gebornen->geborenen
+Gedult->Geduld
+Gedänk*->Gedenk*
+einem geeignetem->einem geeigneten
+Gefäss->Gefäß
+gegebenfalls->gegebenenfalls
+gegen einander->gegeneinander
+gegenüber gestellt->gegenübergestellt
+gegn->gegen
+gegnüber->gegenüber
+gehöhren->gehören
+gehöhrt*->gehört*
+gekührt->gekürt
+gelanden->geladen
+gemäss->gemäß
+gemeinsammen->gemeinsamen
+gemeisam->gemeinsam
+genant->genannt
+genanten->genannten
+Genaral*->General*
+geniessen->genießen
+gennant*->genannt*
+gennannt*->genannt*
+Gerneral*->General*
+gesäht->gesät
+gesammt->gesamt
+gesammten->gesamten
+gesammter->gesamter
+Gesandschaft*->Gesandtschaft*
+Geschichtschreiber->Geschichtsschreiber
+Geschichtschreibung->Geschichtsschreibung
+geschiet->geschieht
+geschlosssen->geschlossen
+gesetztlich->gesetzlich
+Gesichtpunkt->Gesichtspunkt
+gesponsort->gesponsert
+gesteift->gestreift
+gewan->gewann
+gewissermassen->gewissermaßen
+gewunken->gewinkt
+Ghandi->Gandhi
+giebt->gibt
+Giessen->Gießen
+gleichbleiben->gleich bleiben
+gleich zu tun->gleichzutun
+Gogle->Google
+Goldmedaillie*->Goldmedaille*
+Goldmedallie*->Goldmedaille*
+Gothik->Gotik
+gothisch->gotisch
+Grabmahl->Grabmal
+Gradwanderung->Gratwanderung
+Graftschaft*->Grafschaft*
+groesse->größe
+groeße->größe
+gröhlen->grölen
+Grossaufgebot->Großaufgebot
+Grossbritanien->Großbritannien
+Großbritanien->Großbritannien
+Grossbritannien->Großbritannien
+Grossbrittanien->Großbritannien
+Großbrittanien->Großbritannien
+Grossbrittannien->Großbritannien
+Großbrittannien->Großbritannien
+grosse->große
+grösse->größe
+grossem->großem
+einem großem->einem großen
+grossen->großen
+grossenteils->großenteils
+größenteils->größtenteils
+grosser->großer
+grösser->größer
+grössere->größere
+grösserem->größerem
+grösseren->größeren
+grösserer->größerer
+grösseres->größeres
+grosses->großes
+grösste->größte
+Grossteil->Großteil
+grossteils->großteils
+grössten->größten
+grösstenteils->größtenteils
+grösster->größter
+grösstes->größtes
+Gründstück*->Grundstück*
+einem grünem->einem grünen
+Guerrillakampf->Guerillakampf
+Guiness->Guinness
+Guiseppe->Giuseppe
+einem gutem->einem guten
+Güterloh*->Gütersloh*
+Häckchen->Häkchen
+haetten->hätten
+Handelschiff->Handelsschiff
+Handies->Handys
+hahnebüchen->hanebüchen
+hattte->hatte,hatten
+Haupstadt->Hauptstadt
+haupsächlich->hauptsächlich
+Haupstädte->Hauptstädte
+des Haus->des Hauses
+heiratetet->heiratet
+heiss->heiß
+heisser->heißer
+heisst->heißt
+heraus gebracht->herausgebracht
+herausragenste->herausragendste
+Herausvorderung->Herausforderung
+herraus->heraus
+herrausragend->herausragend
+Herrrschaft->Herrschaft
+Herrrscher->Herrscher
+Herschaft->Herrschaft
+Herscher->Herrscher
+hervoragen->hervorragen
+hervoragend->hervorragend
+hervor gegangen*->hervorgegangen*
+hervor ging->hervorging
+hervorragenste->hervorragendste
+Hierachie->Hierarchie
+hierachisch->hierarchisch
+hiess->hieß
+hinaus gehende*->hinausgehende*
+hingegegen->hingegen
+Hintegrund->Hintergrund
+Hintergund->Hintergrund
+hinterliess->hinterließ
+hinterliessen->hinterließen
+hinweg täuschen->hinwegtäuschen
+hinzu gefügt*->hinzugefügt*
+hinzu gekommen*->hinzugekommen*
+Hobbies->Hobbys
+Hochaus->Hochhaus
+Hochäuser->Hochhäuser
+höchst gelegene*->höchstgelegene*
+Hofffnung->Hoffnung
+Hoffung->Hoffnung
+höherere*->höhere*
+höherwertigere*->höherwertige*
+höhren->hören,höheren
+höhrt->hört
+Homage->Hommage
+hunderste*->hundertste*
+idendifiziert->identifiziert
+idenfiziert->identifiziert
+idiopatisch->idiopathisch
+im besonderen Maße->in besonderem Maße
+im Bezug auf->in Bezug auf
+Imbus->Inbus
+im dem->in dem,im
+im den->in den,in dem,ihm den
+im der->in der,im,ihm der
+im deutschsprachigem->im deutschsprachigen
+im einem->in einem
+im großem->in großem,im großen
+im großen Umfang->in großem Umfang
+im hohen Maße->in hohem Maße
+immernoch->immer noch
+immmer->immer
+Impendanz->Impedanz
+im seinem->in seinem
+im selbem->im selben
+inbesondere->insbesondere
+inclusive->inklusive
+Independet->Independent
+indeß->indes
+individiuell->individuell
+Industie->Industrie
+Industriealisierung->Industrialisierung
+in englisch->in Englisch
+inerhalb->innerhalb
+Infantrie->Infanterie
+infiszieren->infizieren
+in Folge->infolge
+in Folge der->infolge der
+in Folge des->infolge des
+in Folge einer->infolge einer
+in Folge eines->infolge eines
+in Folge von->infolge von
+in Folge dessen->infolgedessen,infolge dessen,in dessen Folge
+Ingeneur->Ingenieur
+ingesamt->insgesamt
+Ingredenzien->Ingredienzien
+Inhaltstoff->Inhaltsstoff
+Initation->Initiation,Imitation
+Initative->Initiative
+Initator->Initiator
+Initialie->Initiale
+Initialien->Initialen
+initieren->initiieren
+initiert->initiiert
+Inititative->Initiative
+Iniziative->Initiative
+in mitten->inmitten
+inne gehabt->innegehabt
+inne haben->innehaben
+inne hat->innehat
+inne hatte->innehatte
+inne hatten->innehatten
+Innenaustattung->Innenausstattung
+innnerhalb->innerhalb
+Insbruck->Innsbruck
+in selben Jahr->im selben Jahr
+insgeamt->insgesamt
+insgesammt->insgesamt
+Insitut->Institut
+Insitution->Institution
+in so fern->insofern
+in sofern->insofern
+instandgehalten->instand gehalten,in Stand gehalten
+instandgesetzt->instand gesetzt,in Stand gesetzt
+instandhalten->instand halten,in Stand halten
+instandsetzen->instand setzen,in Stand setzen
+instandzusetzen->instand zu setzen,in Stand zu setzen
+Instituion->Institution
+Instiut->Institut
+Instiution->Institution
+Instutition*->Institution*
+inszinieren->inszenieren
+Inszinierung->Inszenierung
+integiert->integriert
+intelektuell*->intellektuell*
+intenational->international
+intepretiert->interpretiert
+Interese->Interesse
+interesiert->interessiert
+Intergration->Integration
+intergriert->integriert
+Internetpräsens->Internetpräsenz
+interresiert->interessiert
+Interresse->Interesse
+interressiert->interessiert
+Intiative->Initiative
+intressiert->interessiert
+Intrument*->Instrument*
+Inverstor->Investor
+in wie weit->inwieweit
+in wieweit->inwieweit
+inwischen->inzwischen
+irgend ein->irgendein
+irgend eine->irgendeine
+irgend einem->irgendeinem
+irgend einen->irgendeinen
+irgend einer->irgendeiner
+irgend eines->irgendeines
+irgentwie->irgendwie
+irrtümlicher Weise->irrtümlicherweise
+ist meis->ist meist
+ist meisten->ist meistens
+italenisch->italienisch
+italiensch->italienisch
+italiensich->italienisch
+Jägerbatallion->Jägerbataillon
+Jahhundert->Jahrhundert
+Jahhunderte->Jahrhunderte
+Jahhunderts->Jahrhunderts
+des Jahre->des Jahres
+Jahrhudert->Jahrhundert
+Jahrhunder->Jahrhundert
+Jahrundert->Jahrhundert
+Jahrunderte->Jahrhunderte
+Jahrunderts->Jahrhunderts
+Jahrzent->Jahrzehnt
+Jahrzente->Jahrzehnte
+Jahundert->Jahrhundert
+Jahunderte->Jahrhunderte
+Jahunderts->Jahrhunderts
+Jäner->Jänner
+Janur->Januar
+Jarh->Jahr
+Jarhundert->Jahrhundert
+Jarhunderte->Jahrhunderte
+Jarhunderts->Jahrhunderts
+jdoch->jedoch
+jedch->jedoch
+jeoch->jedoch
+jeodch->jedoch
+jeweil->jeweils
+jeweis->jeweils
+Jounalist->Journalist
+Jubiliäum->Jubiläum
+Jungend*->Jugend*
+Justitz->Justiz
+Kabaret->Kabarett
+Kaiserlautern->Kaiserslautern
+Kandidad->Kandidat
+Kanditat->Kandidat
+Kappelle->Kapelle
+Karierre->Karriere
+Karrikaturist->Karikaturist
+karrikieren->karikieren
+Kasette*->Kassette*
+kathegorisch->kategorisch
+Kenntnise->Kenntnis
+Kenntniss->Kenntnis
+Kennzeichnug->Kennzeichnung
+Kentnis->Kenntnis
+Kentnisse->Kenntnisse
+Kirchtum->Kirchturm
+klassich->klassisch
+klassiche->klassische
+klassichen->klassischen
+klassicher->klassischer
+Klink->Klinik
+des Kloster->des Klosters
+km2->km²
+kmh->km/h
+Kofession*->Konfession*
+Kollission*->Kollision*
+Kollonade->Kolonnade
+Komandant->Kommandant
+Komandanten->Kommandanten
+Komando->Kommando
+Komandos->Kommandos
+komerziell->kommerziell
+Komissar->Kommissar
+Komissariat->Kommissariat
+komissarisch->kommissarisch
+Komission->Kommission
+komlett->komplett
+Kommilitionen->Kommilitonen
+Kommision->Kommission
+Kommitee->Komitee
+Kommittee->Komitee
+kommmen->kommen
+Kommunkation->Kommunikation
+Kompentenz->Kompetenz
+Könföderierte->Konföderierte
+Konförderierte->Konföderierte
+könglich->königlich
+Köngreich->Königreich
+Königsreich->Königreich
+Königstum->Königtum
+Konkurenz*->Konkurrenz*
+konkurieren*->konkurrieren*
+konkuriert*->konkurriert*
+könnnen->können,Können
+Konservationslexikon->Konversationslexikon
+Kontak->Kontakt
+konte->konnte
+Kontigent*->Kontingent*
+konventionnell->konventionell
+korregieren->korrigieren
+korregiert->korrigiert
+Krankeit*->Krankheit*
+Krankenaus->Krankenhaus
+Kreuzug*->Kreuzung*,Kreuzzug*
+Kriche->Kirche
+Kriegschiff->Kriegsschiff
+kummulieren->kumulieren
+Kunsstoff*->Kunststoff*
+Kunstaustellung*->Kunstausstellung*
+Kunstoff->Kunststoff
+Kunstoffe->Kunststoffe
+Kurfüst*->Kurfürst*
+kurzeitig*->kurzzeitig*
+läd->lädt
+Landesaustellung->Landesausstellung
+Landesprache->Landessprache
+Landwirschaft->Landwirtschaft
+landwirschaftlich->landwirtschaftlich
+langläufig->landläufig
+Lapalie->Lappalie
+Lassithi->Lasithi
+läst->lässt
+lateinsch->lateinisch
+lateinsche->lateinische
+lateinschen->lateinischen
+lateinscher->lateinischer
+lateinsches->lateinisches
+Lebenstil->Lebensstil
+Lebenweise->Lebensweise
+legänder->legendär
+Leibzig->Leipzig
+Leichathlet*->Leichtathlet*
+Leichnahm->Leichnam
+letze->letzte
+letzem->letztem
+letzen->letzten
+letzendlich->letztendlich
+letzer->letzter
+letzere->letztere
+letzerem->letzterem
+letzeren->letzteren
+letzerer->letzterer
+letzeres->letzteres
+letzes->letztes
+letzlich->letztlich
+letztenendes->letzten Endes
+Lexikas->Lexika
+Liason->Liaison
+liess->ließ
+liesse->ließe
+liessen->ließen
+ließt->er/sie/es liest; ließ; fließt
+Lilliputaner->Liliputaner
+literaisch->literarisch
+literatisch->literarisch
+lizensieren->lizenzieren
+lizensiert->lizenziert
+lizensierte->lizenzierte
+lizensiertem->lizenziertem
+lizensierten->lizenzierten
+lizensierter->lizenzierter
+lizensiertes->lizenziertes
+Lizensierung->Lizenzierung
+los zu werden->loszuwerden
+Louisana->Louisiana
+Lousiana->Louisiana
+Luwig->Ludwig
+Lybien->Libyen
+lybisch->libysch
+lybische->libysche
+lybischem->libyschem
+lybischen->libyschen
+lybischer->libyscher
+lybisches->libysches
+machmal->manchmal
+Manhatan->Manhattan
+Manhatta->Manhattan
+Manhatten->Manhattan
+Manhetten->Manhattan
+Manschaft->Mannschaft
+Manmschaft->Mannschaft
+Mannhattan->Manhattan
+Mannöver->Manöver
+Mannschaf->Mannschaft
+Mannschaftt->Mannschaft
+Mannshcaft->Mannschaft
+Mansardach->Mansarddach
+Mansardendach->Mansarddach
+Mansnchaften->Mannschaft
+Manssarddach->Mansarddach
+marrokanisch*->marokkanisch*
+marrokkanisch*->marokkanisch*
+Marrokko->Marokko
+Marroko->Marokko
+Marylin->meist Marilyn
+Marytrium->Martyrium
+Märtyrium->Martyrium
+Maschiene->Maschine
+Maschienen->Maschinen
+mässig->mäßig
+mässige->mäßige
+mässigem->mäßigem
+mässigen->mäßigen
+mässiger->mäßiger
+mässiges->mäßiges
+Mass->Maß
+Massgabe->Maßgabe
+Massgaben->Maßgaben
+massgebend->maßgebend
+massgebende->maßgebende
+massgebendem->maßgebendem
+massgebenden->maßgebenden
+massgebender->maßgebender
+massgebendes->maßgebendes
+massgeblich->maßgeblich
+massgebliche->maßgebliche
+massgeblichem->maßgeblichem
+massgeblichen->maßgeblichen
+massgeblicher->maßgeblicher
+massgebliches->maßgebliches
+masslos->maßlos
+masslose->maßlose
+masslosen->maßlosen
+massloser->maßloser
+massloses->maßloses
+Massnahme->Maßnahme
+Massnahmen->Maßnahmen
+Matraze->Matratze
+Matritze->Matrize,Matrix
+Maximillian->meist Maximilian
+Medailie->Medaille
+Medaillie->Medaille
+Medailliengewinner->Medaillengewinner
+Medailliengewinnerin->Medaillengewinnerin
+Medallie->Medaille
+Medalliengewinner->Medaillengewinner
+Medalliengewinnerin->Medaillengewinnerin
+medizinsch->medizinisch
+medizisch->medizinisch
+medizische->medizinische
+medizischem->medizinischem
+medizischen->medizinischen
+medizischer->medizinischer
+medizisches->medizinisches
+Meerespiegel->Meeresspiegel
+Meeresspegel->Meeresspiegel
+mehere->mehrere
+meheren->mehreren
+meherer->mehrerer
+mehre->meist mehrere
+mehren->gelegentlich mehreren
+mehrer->häufig mehrerer,mehrere
+mehrerere->mehrere
+mehrtätige->mehrtägige
+meisst->meist
+meißt->meist
+meißten->meisten
+meißtens->meistens
+meistbesuchtesten->meistbesuchten
+meist gelesene*->meistgelesene*
+meist gesehene*->meistgesehene*
+meist gesuchte*->meistgesuchte*
+meits->meist
+mengemässig->mengenmäßig
+mengenmässig->mengenmäßig
+Mensche->Menschen
+Menscheit->Menschheit
+Menschens->Menschen
+Meßgerät->Messgerät
+Meßgeräte->Messgeräte
+Messystem->Messsystem
+Meßsystem->Messsystem
+Metallegierung->Metalllegierung
+Metereologe->Meteorologe
+Metereologie->Meteorologie
+metereologisch->meteorologisch
+Meterologie->Meteorologie
+meterologisch->meteorologisch
+Mettal->Metall
+mhd->mittelhochdeutsch
+Micheal->meist Michael
+Miglied->Mitglied
+Milionen->Millionen
+Militärdikatur->Militärdiktatur
+Millarde->Milliarde
+Millarden*->Milliarden*
+Millenium->Millennium
+Millione->Millionen
+Millitär->Militär
+millitärisch->militärisch
+eine Millionen->eine Million
+Millon->Million
+Millonen->Millionen
+Miltär->Militär
+miltärisch->militärisch
+Miltitär->Militär
+miltitärisch->militärisch
+minimalste->minimale
+minimalster->minimaler
+minimalstes->minimales
+Ministerpäsident->Ministerpräsident
+mit einander->miteinander
+Mitgleid->Mitglied
+mitlerweile->mittlerweile
+mittlerweilen->mittlerweile
+Mitlgiled->Mitglied
+Mitlied->Mitglied
+mit samt->mitsamt
+Mittelater->Mittelalter
+mittelaterlich->mittelalterlich
+mittelständige->mittelständische
+mittelständigen->mittelständischen
+mittelständiger->mittelständischer
+mittelständiges->mittelständisches
+Mitteralter->Mittelalter
+mitteralterlich->mittelalterlich
+Mitterand->Mitterrand
+Mittglied->Mitglied
+Mittschnitt->Mitschnitt
+mnachmal->manchmal
+Mobiletelefon->Mobiltelefon
+moeglich->möglich
+moegliche->mögliche
+moeglichen->möglichen
+moeglicher->möglicher
+moegliches->mögliches
+möglicht->möglich,möglichst
+mordern->modern
+morderne->moderne
+mordernen->modernen
+morderner->moderner
+mordernes->modernes
+morgentlich*->morgendlich*
+morgends->morgens
+muß->muss
+mußte->musste
+mußten->mussten
+Museeum->Museum
+mutmasslich->mutmaßlich
+mutmassliche->mutmaßliche
+mutmasslichem->mutmaßlichem
+mutmasslichen->mutmaßlichen
+mutmasslicher->mutmaßlicher
+mutmassliches->mutmaßliches
+nachdem Krieg->nach dem Krieg
+Nachkommens->Nachkommen
+nächst gelegene*->nächstgelegene*
+nächst größere*->nächstgrößere*
+nächst höhere*->nächsthöhere*
+nächst kleinere*->nächstkleinere*
+nächst niedrigere*->nächstniedrigere*
+nächst tiefere*->nächsttiefere*
+Nahaufname->Nahaufnahme
+nahegelegenste->nächstgelegene
+naheste->nächste
+nahesten->nächsten
+nähmlich->nämlich
+namenlich->namentlich
+namenslos->namenlos
+des Names->des Namens
+Namne->Namen
+narzistisch->narzisstisch
+Natiomnal*->National*
+Nazionalsoz*->Nationalsoz*
+nciht->nicht
+Nervösität->Nervosität
+nich->nicht
+die Niederlanden->die Niederlande
+niedersächisch->niedersächsisch
+niedersächsiche->niedersächsische
+niedersächsichen->niedersächsischen
+niedrieg->niedrig
+Niesche->Nische
+nihct->nicht
+nix->nichts
+nocheinmal->noch einmal
+nordeutsch->norddeutsch
+Nordeutschland->Norddeutschland
+nordlich->nördlich
+nördöstlich*->nordöstlich*
+nördwestlich*->nordwestlich*
+normanisch*->normannisch*
+notwenig*->notwendig*
+numehr->nunmehr
+Numerus Clausus->Numerus clausus
+objekiv->objektiv
+obrige->obige
+obrigen->obigen
+obriger->obiger
+offizell*->offiziell*
+Offizer->Offizier
+offiziel->offiziell
+offiziele*->offizielle*
+offziell->offiziell
+offzielle->offizielle
+ofiziell->offiziell
+Olympiamedaillie*->Olympiamedaille*
+Olympiamedallie*->Olympiamedaille*
+Olympische Bronzemedaille->olympische Bronzemedaille
+Olympische Goldmedaille->olympische Goldmedaille
+Olympische Silbermedaille->olympische Silbermedaille
+Omlett->Omelett
+optimalste->optimale
+optimalster->optimaler
+optimalstes->optimales
+Ordnug->Ordnung
+Ordung->Ordnung
+Orgeon->Oregon
+Organistion->Organisation
+Organsiation->Organisation
+organsich->organisch
+Organsisation->Organisation
+organisert->organisiert
+orginal->original
+orginale->originale
+orginalen->originalen
+orginell->originell
+orignal->original
+orignell->originell
+Orsteil->Ortsteil
+Orsteile->Ortsteile
+Ortteil->Ortsteil
+ouml->Ö/ö
+Overtüre->Ouvertüre
+öffenlich->öffentlich
+Ökö->Öko
+Östereich->Österreich
+Österrreich->Österreich
+Österreisch->Österreich
+östereichisch*->österreichisch*
+österreichich->österreichisch
+Packet->Paket
+palästinesisch->palästinensisch
+Palete->Palette
+Paleten->Paletten
+Pallete->Palette
+Palleten->Paletten
+Pallette->Palette
+Palletten->Paletten
+paralell->parallel
+Parcour->Parcours
+parralel->parallel
+parrallel->parallel
+Päsident->Präsident
+patroullieren->patrouillieren
+patroulliert->patrouilliert
+Pavillion->Pavillon
+Peleponnes*->Peloponnes*
+Pepperoni->Peperoni
+Perlmut->Perlmutt
+perönlich*->persönlich*
+persöhnlich*->persönlich*
+Persönlichleit->Persönlichkeit
+Philantrop*->Philanthrop*
+Philipinen->Philippinen
+Philipinisch->Philippinisch
+philipinischer->philippinischer
+Philippienen->Philippinen
+Philisoph->Philosoph
+Philisophie->Philosophie
+philisophisch->philosophisch
+Phillipinen->Philippinen
+Philosopie->Philosophie
+Philosph->Philosoph
+Philosphie->Philosophie
+philosphisch->philosophisch
+Philsophie->Philosophie
+philsophisch->philosophisch
+photografiert->fotografiert,photographiert
+piktoresk->pittoresk
+Planze->Pflanze
+Planzen*->Pflanzen*
+Politk->Politik
+Politker->Politiker
+politsch->politisch
+politsche->politische
+politschen->politischen
+politscher->politischer
+politsches->politisches
+poltisch*->politisch*
+portugiesich*->portugiesisch*
+Positon->Position
+postiv->positiv
+prinzipell*->prinzipiell*
+Prinzipen->Prinzipien
+Priveleg->Privileg
+priveligiert->privilegiert
+Priviligien*->Privilegien*
+priviligiert->privilegiert
+Progrom->Pogrom
+projezieren->projizieren
+projeziert->projiziert
+Prophezeihung*->Prophezeiung*
+Provinzhaupstadt->Provinzhauptstadt
+Prozeße->Prozesse
+Psychatrie->Psychiatrie
+pysikalisch->physikalisch
+Quattrologie->Tetralogie
+Ralley->Rallye
+Ralleyfahrer->Rallyefahrer
+rechlich->rechtlich
+Rechtsprache->Rechtssprache
+Rechtspruch->Rechtsspruch
+Rechtssprechung->Rechtsprechung
+Rechtstaat->Rechtsstaat
+rechtstaatlich->rechtsstaatlich
+rechtwinklich->rechtwinklig
+rechtwinkling->rechtwinklig
+rechzeitig->rechtzeitig
+Reeling->Reling
+Reflektion->Reflexion
+regelmässig->regelmäßig
+regelmässige->regelmäßige
+regelmässigen->regelmäßigen
+regelmässiger->regelmäßiger
+regelmässiges->regelmäßiges
+Reichtags*->Reichstags*
+Relgion*->Religion*
+relgiös->religiös
+Religiösität->Religiosität
+Religon->Religion
+Religonen->Religionen
+religös->religiös
+religösen->religiösen
+Relion->Religion
+reliösen->religiösen
+Remineszenz->Reminiszenz
+Rendevous->Rendezvous
+Rennaisance->Renaissance
+Rennaissance->Renaissance
+des Rennes->des Rennens
+Renomee->Renommee
+renomiert->renommiert
+Renomme->Renommee
+repäsentieren->repräsentieren
+repäsentiert->repräsentiert
+Reperatur->Reparatur
+Resourcen->Ressourcen
+Rhytmen->Rhythmen
+rhytmisch->rhythmisch
+rhytmische->rhythmische
+Rhytmus->Rhythmus
+Richtline->Richtlinie
+Richung->Richtung
+rigde->ridge
+rihgt->right
+Riskio->Risiko
+Risko->Risiko
+Rossevelt->Roosevelt
+Rückgrad->Rückgrat
+Rückrad->Rückgrat
+Rückrat->Rückgrat
+russich->russisch
+russiche->russische
+russichen->russischen
+russicher->russischer
+russsich->russisch
+russsisch->russisch
+russsische->russische
+russsischen->russischen
+Rythmen->Rhythmen
+rythmisch->rhythmisch
+rythmische->rhythmische
+Rythmus->Rhythmus
+sächisch->sächsisch
+sächsich->sächsisch
+sächsiche->sächsische
+sächsichen->sächsischen
+Santiago de Compostella->Santiago de Compostela
+Sarkopharg->Sarkophag
+sassen->saßen
+satzungsgemäss->satzungsgemäß
+S-Bahnstation->S-Bahn-Station
+schafte->schaffte
+Schaupiel*->Schauspiel*
+Scheiz->Schweiz
+schillernste*->schillerndste*
+schliessen->schließen
+schliesslich->schließlich
+schliesst->schließt
+Schrifsteller*->Schriftsteller*
+Schriftseller->Schriftsteller
+schweizer->Schweizer
+Seeman->Seemann
+seemänisch->seemännisch
+sehenwert->sehenswert
+Sehenwürdigkeit->Sehenswürdigkeit
+Sehenwürdigkeiten->Sehenswürdigkeiten
+seit dem->seitdem
+seit dem die->seitdem die
+seit dem ein->seitdem ein
+seit dem hat->seitdem hat
+seit dem ist->seitdem ist
+seit dem war->seitdem war
+seperat->separat
+seperate->separate
+seperatem->separatem
+seperaten->separaten
+Seperation->Separation
+Seperatist*->Separatist*
+Septmber->September
+Septmeber->September
+Seriösität->Seriosität
+sicher gestellt->sichergestellt
+sich er sich->er sich
+sicher stellen->sicherstellen
+sicher stellt*->sicherstellt*
+sicher zu stellen->sicherzustellen
+Silbermedaillie*->Silbermedaille*
+Silbermedallie*->Silbermedaille*
+Siluette->Silhouette
+sinvoll->sinnvoll
+Situtation->Situation
+Skagerak->Skagerrak
+sobald wie möglich->so bald wie möglich
+sobald als möglich->so bald als möglich
+sodas->sodass,so dass
+sodaß->sodass,so dass
+sogenante->sogenannte
+sogenanten->sogenannten
+sonder->sondern
+Souveranität->Souveränität
+soweit wie->so weit wie
+Sowietunion->Sowjetunion
+spezialiseren->spezialisieren
+spezialisert*->spezialisiert*
+speziel->speziell
+sponsorte->sponserte
+Spritualität->Spiritualität
+sprituell->spirituell
+Staatstreich->Staatsstreich
+Stadbild->Stadtbild
+Staddteil->Stadtteil
+Stadteil->Stadtteil
+Stadteile->Stadtteile
+Stadteilen->Stadtteilen
+Stadteils->Stadtteils
+Standart->Standard
+Standarts->Standards
+statt fand->stattfand
+statt finden->stattfinden
+statt findet->stattfindet
+statt gegeben->stattgegeben
+Stehgreif->Stegreif
+stellverteten->stellvertreten
+Stellverteter->Stellvertreter
+stiess->stieß
+Stimmulation->Stimulation
+Stömung->Strömung
+Stoss->Stoß
+stossen->stoßen
+Stossfänger->Stoßfänger
+Stossstange->Stoßstange
+stösst->stößt
+Strasse->Straße
+strukur*->struktur*
+subsummieren->subsumieren
+subsummiert->subsumiert
+sumieren->summieren
+sumiert->summiert
+svw->svw., bzw., so viel wie
+symetrisch->symmetrisch
+symphatisiert->sympathisiert
+Synomym->Synonym
+Synomyn->Synonym
+Syphon->Siphon
+Sytem->System
+Sytematik->Systematik
+sytematisch->systematisch
+Tag- und Nachtgleiche->Tagundnachtgleiche,Tag-und-Nacht-Gleiche
+Taiwanese->Taiwaner
+Taiwanesen->Taiwaner
+tasächlich->tatsächlich
+tatächlich->tatsächlich
+Teakwondo->Taekwondo
+teiweise->teilweise
+Temparatur->Temperatur
+tendentiell*->tendenziell*
+Terasse->Terrasse
+Terassen->Terrassen
+Terrabyte->Terabyte
+Tocher->Tochter
+Tolleranz->Toleranz
+tollerieren->tolerieren
+tolleriert->toleriert
+Tradion*->Tradition*
+traditionel->traditionell
+Traditon*->Tradition*
+Tradtion*->Tradition*
+Trainig*->Training*
+Transskript->Transkript
+Triologie->Trilogie
+Triumpf->Triumph
+trotzdessen->trotzdem
+trozdem->trotzdem
+Tryptichon->Triptychon
+Triptichon->Triptychon
+Tryptychon->Triptychon
+Tunier->Turnier
+Turismus->Tourismus
+Turist->Tourist
+U-Bahnnetz->U-Bahn-Netz
+U-Bahnstation->U-Bahn-Station
+U-Bahntunnel->U-Bahn-Tunnel
+überarbeitetet->überarbeitet
+überlegende->überlegene
+überlegenden->überlegenen
+überlicherweise->üblicherweise
+Überwachungstaat->Überwachungsstaat
+U-Bootkrieg->U-Boot-Krieg
+umbennen->umbenennen
+umbennenen->umbenennen
+umbennennen->umbenennen
+umbennant->umbenannt
+Umbennennung->Umbenennung
+Umbennenung->Umbenennung
+Umbennung->Umbenennung,Umnennung
+umd->und,um
+Umgangsprache->Umgangssprache
+umgangsprachlich->umgangssprachlich
+umgangsprachliche->umgangssprachliche
+umgangsprachlicher->umgangssprachlicher
+umgenannt->umbenannt
+umittelbar->unmittelbar
+umstrittend*->umstritten*
+umzubennen->umzubenennen,umzunennen
+Unabhängikeit->Unabhängigkeit
+Unabhängkeit->Unabhängigkeit
+unabhänig->unabhängig
+Unabhänigkeit->Unabhängigkeit
+unauthorisiert->unautorisiert
+unbenannt wurde->umbenannt wurde
+und sowie->und/sowie
+und und->und
+Unfang->Umfang
+ungekehrt->umgekehrt
+Univerität->Universität
+Universiät->Universität
+Universtät->Universität
+Universtität->Universität
+unsymetrisch->unsymmetrisch
+unteranderem->unter anderem
+Untergund->Untergrund
+Untericht->Unterricht
+unterichtet->unterrichtet
+unteriridisch->unterirdisch
+Unternehmes*->Unternehmens*
+Unternehms*->Unternehmens*
+unterstüzt->unterstützt
+Unterstüzung->Unterstützung
+Unversität->Universität
+unwegbar->unwägbar,unwegsam
+Urprung->Ursprung
+urprünglich*->ursprünglich*
+ürsprünglich*->ursprünglich*
+urspünglich*->ursprünglich*
+Ursurpator->Usurpator
+us-amerikanischen->US-amerikanischen,amerikanischen
+usprünglich*->ursprünglich*
+variert->variiert
+varrieren->variieren
+Vehrkehr*->Verkehr*
+Vekehr*->Verkehr*
+venezuelanisch*->venezolanisch*
+venizianisch*->venezianisch*
+verabeitet->verarbeitet
+Verabeitung*->Verarbeitung*
+veraltert*->veraltet*
+verantworlich*->verantwortlich*
+Veranwtortung->Verantwortung
+Verbauch*->Verbrauch*
+verbeitet*->verbreitet*
+Verbeitung*->Verbreitung*
+verbreiteste*->verbreitetste*
+verbreiteteste*->verbreitetste*
+vereingt*->vereinigt*
+vereiningt->vereinigt
+vergleichweise->vergleichsweise
+vergößert*->vergrößert*
+Vergößerung->Vergrößerung
+vergrössern->vergrößern
+vergrössert->vergrößert
+vergrösserte->vergrößerte
+vergrösserten->vergrößerten
+vergrösserter->vergrößerter
+Vergrösserung->Vergrößerung
+verhaeltnismaessig->verhältnismäßig
+verhältnismässig->verhältnismäßig
+verheiratetet->verheiratet
+verkündetet->verkündet
+verliess->verließ
+veröffendlicht->veröffentlicht
+Veröffendlichung->Veröffentlichung
+veröffentlich->veröffentlicht
+verplichtet->verpflichtet
+verschiedende*->verschiedene*
+verschiedendste*->verschiedenste*
+Verschleiss->Verschleiß
+verschohnen->verschonen
+verspühren->verspüren
+verspührt->verspürt
+Verständis->Verständnis
+Vertäge->Verträge
+vertaglich->vertraglich
+Verteidung->Verteidigung
+Verwaltungsitz->Verwaltungssitz
+Verwandschaft->Verwandtschaft
+verwandschaftlich*->verwandtschaftlich*
+Vetrag->Vertrag
+Veträge->Verträge
+vetraglich->vertraglich
+vetraut->vertraut
+vieleicht->vielleicht
+vom dem->von dem,vom
+vom der->von der,vom,der
+von einander->voneinander
+getrennt von einander->getrennt voneinander
+unabhängig von einander->unabhängig voneinander
+von einander entfernt->voneinander entfernt
+von einander getrennt->voneinander getrennt
+von einander unterscheiden->voneinander unterscheiden
+von einander unterschieden->voneinander unterschieden
+von einander zu->voneinander zu
+von nöten->vonnöten,z. B. vonnöten sein
+von statten->vonstatten
+von von->von
+vorallem->vor allem
+vorallen->vor allem
+vor allen in->vor allem in
+voran bringen->voranbringen
+Vorang->Vorrang
+voran gegangen*->vorangegangen*
+vorangig->vorrangig
+voran zu bringen->voranzubringen
+voran zu treiben->voranzutreiben
+Vorausetzung->Voraussetzung
+Vorausetzungen->Voraussetzungen
+voraus gegangen*->vorausgegangen*
+vorausichtlich->voraussichtlich
+Vorfahrens->Vorfahren
+Vorgesetze->Vorgesetzte
+vorkommene->vorkommende
+Vormachtsstellung->Vormachtstellung
+vorranging->vorrangig
+vorraus*->voraus*
+vorrüber*->vorüber*
+vorweg genommen*->vorweggenommen*
+Wachholder->Wacholder
+wachesen->wachsen
+währe->wäre
+währendessen->währenddessen
+wahr genommen->wahrgenommen
+Walfahrer->Wallfahrer
+Walfahrt->Wallfahrt
+Walfahrtskirche->Wallfahrtskirche
+Walfahrtsort->Wallfahrtsort
+wärend->während
+Warheit->Wahrheit
+warscheinlich->wahrscheinlich
+Webblog*->Weblog*
+Webpräsens->Webpräsenz
+Wehrmutstropfen->Wermutstropfen
+weiss->weiß
+Weisswein->Weißwein
+einem weiterem->einem weiteren
+im weiterem->im weiteren
+weiterere->weitere
+weitereren->weiteren
+weitesgehend->weitestgehend
+Weltanschaung->Weltanschauung
+Wepräsenz->Webpräsenz
+wesendlich->wesentlich
+im Wesentlichem->im Wesentlichen
+wichig->wichtig
+wichtigeste->wichtigste
+Widerstandkämpfer->Widerstandskämpfer
+widerum->wiederum
+Wiedererichtung->Wiedererrichtung
+wieder kehrend*->wiederkehrend*
+Wiedersacher->Widersacher
+wiedersetzen->widersetzen
+wiederspiegeln->widerspiegeln
+wiederspiegelt->widerspiegelt
+wiederspiegelte->widerspiegelte
+wiederspiegelten->widerspiegelten
+wiedersprechen->widersprechen
+wiedersprechend->widersprechend
+wiedersprechende->widersprechende
+Wiederspruch->Widerspruch
+Wiedersprüche->Widersprüche
+wiedersprüchlich->widersprüchlich
+wiedersprüchliche->widersprüchliche
+wiedersprüchlichen->widersprüchlichen
+Wiederstand->Widerstand
+Wiederstandskampf->Widerstandskampf
+wiederstehen->widerstehen
+wiederzuspiegeln->widerzuspiegeln
+Wihelm->Wilhelm
+Wikipeda->Wikipedia
+Wikpedia->Wikipedia
+wirtschaflich->wirtschaftlich
+wissenschaflich->wissenschaftlich
+wissenschafltich->wissenschaftlich
+Wissentschaft->Wissenschaft
+wissentschaftlich->wissenschaftlich
+Wochende->Wochenende
+woduch->wodurch
+Wolfang->Wolfgang
+wurd->wurde
+wurde wurde->wurde
+Würtemberg->Württemberg
+würtembergische->württembergische
+zahreich->zahlreich
+zeimlich->ziemlich
+der Zeit seines Lebens->der zeit seines Lebens
+er Zeit seines Lebens->er zeit seines Lebens
+sie Zeit ihres Lebens->sie zeit ihres Lebens
+war Zeit ihres Lebens->war zeit ihres Lebens
+war Zeit seines Lebens->war zeit seines Lebens
+zeitgenösisch->zeitgenössisch
+zeitgenössich->zeitgenössisch
+zerissen->zerrissen
+Ziffernblatt->Zifferblatt
+Zohne->Zone
+zu allererst->zuallererst
+zuammen->zusammen
+Zuammenhang->Zusammenhang
+zueigen->zu eigen
+zuende->zu Ende
+zu Folge->zufolge,zur Folge
+zufrieden geben->zufriedengeben
+zugrundeliegen->zugrunde liegen,zu Grunde liegen
+zugrundeliegt->zugrunde liegt,zu Grunde liegt
+zu letzt->zuletzt
+zum dem->zu dem,zum
+zum den->zu den,zu dem,zum
+zum erstem->zum ersten
+zumindestens->zumindest
+in zunehmenden Maße->in zunehmendem Maße
+mit zunehmenden Alter->mit zunehmendem Alter
+zunehmends->zunehmend
+zur der->zu der,zur
+zur dieser->zu dieser
+zur einem->zu einem
+zur einer->zu einer,zur
+zur ihr->zu ihr
+zur ihrem->zu ihrem
+zur ihren->zu ihren
+zur ihrer->zu ihrer,zur
+zur seiner->zu seiner,zur
+zurecht->zurecht
+zurecht finden->zurechtfinden
+zurecht kam->zurechtkam
+zurecht kommen->zurechtkommen
+zurecht kommt->zurechtkommt
+zurecht zu finden->zurechtzufinden
+zurecht zu kommen->zurechtzukommen
+zurfolge->zur Folge,zufolge
+zurück ge*->zurückge*
+zurück gegangen*->zurückgegangen*
+zurück blicken->zurückblicken
+zurück erobert->zurückerobert
+zurück ging->zurückging
+zurück greif*->zurückgreif*
+zurück kehrte->zurückkehrte
+zurück trat->zurücktrat
+zurück verfolgen->zurückverfolgen
+zurück verfolgt->zurückverfolgt
+zurück ziehen->zurückziehen
+zurück zog->zurückzog
+zurück zu bekommen->zurückzubekommen
+zurück zu bringen->zurückzubringen
+zurück zu drängen->zurückzudrängen
+zurück zu erobern->zurückzuerobern
+zurück zu führen->zurückzuführen
+zurück zuführen->zurückzuführen
+zurück zu gewinnen->zurückzugewinnen
+zurück zu holen->zurückzuholen
+zurück zu kehren->zurückzukehren
+zurück zu ziehen->zurückzuziehen
+zusamen->zusammen
+Zusamenhang->Zusammenhang
+zusammen arbeiten->zusammenarbeiten
+zusammen arbeitete->zusammenarbeitete
+zusammen arbeiteten->zusammenarbeiteten
+zusammen gearbeitet->zusammengearbeitet
+zusammen gefasst->zusammengefasst
+zusammen geschlossen*->zusammengeschlossen*
+zusammen schloss*->zusammenschloss*
+zusammen zu arbeiten->zusammenzuarbeiten
+zusammen zu schließen->zusammenzuschließen
+zusammmen->zusammen
+zusätlich->zusätzlich
+zusehens->zusehends
+zustandegekommen->zustande gekommen,zu Stande gekommen
+zustandekam->zustande kam,zu Stande kam
+zustandekommt->zustande kommt,zu Stande kommt
+zustätzlich->zusätzlich
+zu teil werden->zuteilwerden
+zu teil wird->zuteilwird
+zu teil wurde->zuteilwurde
+zu zu->zu,zuzu
+zu zuordnen*->zuzuordnen*
+zu zuwenden*->zuzuwenden*
+Zweidrittel->zwei Drittel
+Zweidrittel-Mehrheit->Zweidrittelmehrheit
+Zweiliga*->Zweitliga*
+dem zweitem->dem zweiten
+im zweitem->im zweiten
diff --git a/files/typos-en.txt b/files/typos/typos-en.txt
index 85c72ce..74fbd08 100644
--- a/files/typos-en.txt
+++ b/files/typos/typos-en.txt
@@ -3,6 +3,7 @@ andriod->android
# The remainder of this file contains misspellings from
# http://en.wikipedia.org/wiki/Wikipedia:Lists_of_common_misspellings/For_machines
+# plus some post-processing to fix invalid entries, remove duplicates, etc.
#
# The content is available under the
# "Creative Commons Attribution-ShareAlike License"
@@ -2774,8 +2775,7 @@ modle->model
moent->moment
moeny->money
mohammedans->muslims
-moil->mohel
-moil->soil
+moil->mohel,soil
moleclues->molecules
momento->memento
monestaries->monasteries
@@ -3543,8 +3543,7 @@ refereneced->referenced
refereneces->references
referiang->referring
refering->referring
-refernce->reference
-refernce->references
+refernce->reference,references
refernces->references
referrence->reference
referrences->references
diff --git a/files/typos/typos-es.txt b/files/typos/typos-es.txt
new file mode 100644
index 0000000..af2bccb
--- /dev/null
+++ b/files/typos/typos-es.txt
@@ -0,0 +1,733 @@
+# This file contains a number of common Spanish typos:
+andriod->android
+
+# The remainder of this file contains misspellings from
+# http://es.wikipedia.org/wiki/Wikipedia:Lista_de_errores_ortogr%C3%A1ficos_comunes/M%C3%A1quinas
+# plus some post-processing to fix invalid entries, remove duplicates, etc.
+#
+# The content is available under the
+# "Creative Commons Attribution-ShareAlike License"
+# http://creativecommons.org/licenses/by-sa/3.0/
+#
+# THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
+# COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
+# COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
+# AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
+#
+# BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE
+# TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY
+# BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS
+# CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
+# CONDITIONS.
+#
+# *1. Definitions*
+#
+# 1. *"Adaptation"* means a work based upon the Work, or upon the Work
+# and other pre-existing works, such as a translation, adaptation,
+# derivative work, arrangement of music or other alterations of a
+# literary or artistic work, or phonogram or performance and includes
+# cinematographic adaptations or any other form in which the Work may
+# be recast, transformed, or adapted including in any form
+# recognizably derived from the original, except that a work that
+# constitutes a Collection will not be considered an Adaptation for
+# the purpose of this License. For the avoidance of doubt, where the
+# Work is a musical work, performance or phonogram, the
+# synchronization of the Work in timed-relation with a moving image
+# ("synching") will be considered an Adaptation for the purpose of
+# this License.
+# 2. *"Collection"* means a collection of literary or artistic works,
+# such as encyclopedias and anthologies, or performances, phonograms
+# or broadcasts, or other works or subject matter other than works
+# listed in Section 1(f) below, which, by reason of the selection and
+# arrangement of their contents, constitute intellectual creations, in
+# which the Work is included in its entirety in unmodified form along
+# with one or more other contributions, each constituting separate and
+# independent works in themselves, which together are assembled into a
+# collective whole. A work that constitutes a Collection will not be
+# considered an Adaptation (as defined below) for the purposes of this
+# License.
+# 3. *"Creative Commons Compatible License"* means a license that is
+# listed at http://creativecommons.org/compatiblelicenses that has
+# been approved by Creative Commons as being essentially equivalent to
+# this License, including, at a minimum, because that license: (i)
+# contains terms that have the same purpose, meaning and effect as the
+# License Elements of this License; and, (ii) explicitly permits the
+# relicensing of adaptations of works made available under that
+# license under this License or a Creative Commons jurisdiction
+# license with the same License Elements as this License.
+# 4. *"Distribute"* means to make available to the public the original
+# and copies of the Work or Adaptation, as appropriate, through sale
+# or other transfer of ownership.
+# 5. *"License Elements"* means the following high-level license
+# attributes as selected by Licensor and indicated in the title of
+# this License: Attribution, ShareAlike.
+# 6. *"Licensor"* means the individual, individuals, entity or entities
+# that offer(s) the Work under the terms of this License.
+# 7. *"Original Author"* means, in the case of a literary or artistic
+# work, the individual, individuals, entity or entities who created
+# the Work or if no individual or entity can be identified, the
+# publisher; and in addition (i) in the case of a performance the
+# actors, singers, musicians, dancers, and other persons who act,
+# sing, deliver, declaim, play in, interpret or otherwise perform
+# literary or artistic works or expressions of folklore; (ii) in the
+# case of a phonogram the producer being the person or legal entity
+# who first fixes the sounds of a performance or other sounds; and,
+# (iii) in the case of broadcasts, the organization that transmits the
+# broadcast.
+# 8. *"Work"* means the literary and/or artistic work offered under the
+# terms of this License including without limitation any production in
+# the literary, scientific and artistic domain, whatever may be the
+# mode or form of its expression including digital form, such as a
+# book, pamphlet and other writing; a lecture, address, sermon or
+# other work of the same nature; a dramatic or dramatico-musical work;
+# a choreographic work or entertainment in dumb show; a musical
+# composition with or without words; a cinematographic work to which
+# are assimilated works expressed by a process analogous to
+# cinematography; a work of drawing, painting, architecture,
+# sculpture, engraving or lithography; a photographic work to which
+# are assimilated works expressed by a process analogous to
+# photography; a work of applied art; an illustration, map, plan,
+# sketch or three-dimensional work relative to geography, topography,
+# architecture or science; a performance; a broadcast; a phonogram; a
+# compilation of data to the extent it is protected as a copyrightable
+# work; or a work performed by a variety or circus performer to the
+# extent it is not otherwise considered a literary or artistic work.
+# 9. *"You"* means an individual or entity exercising rights under this
+# License who has not previously violated the terms of this License
+# with respect to the Work, or who has received express permission
+# from the Licensor to exercise rights under this License despite a
+# previous violation.
+# 10. *"Publicly Perform"* means to perform public recitations of the Work
+# and to communicate to the public those public recitations, by any
+# means or process, including by wire or wireless means or public
+# digital performances; to make available to the public Works in such
+# a way that members of the public may access these Works from a place
+# and at a place individually chosen by them; to perform the Work to
+# the public by any means or process and the communication to the
+# public of the performances of the Work, including by public digital
+# performance; to broadcast and rebroadcast the Work by any means
+# including signs, sounds or images.
+# 11. *"Reproduce"* means to make copies of the Work by any means
+# including without limitation by sound or visual recordings and the
+# right of fixation and reproducing fixations of the Work, including
+# storage of a protected performance or phonogram in digital form or
+# other electronic medium.
+#
+# *2. Fair Dealing Rights.* Nothing in this License is intended to reduce,
+# limit, or restrict any uses free from copyright or rights arising from
+# limitations or exceptions that are provided for in connection with the
+# copyright protection under copyright law or other applicable laws.
+#
+# *3. License Grant.* Subject to the terms and conditions of this License,
+# Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
+# perpetual (for the duration of the applicable copyright) license to
+# exercise the rights in the Work as stated below:
+#
+# 1. to Reproduce the Work, to incorporate the Work into one or more
+# Collections, and to Reproduce the Work as incorporated in the
+# Collections;
+# 2. to create and Reproduce Adaptations provided that any such
+# Adaptation, including any translation in any medium, takes
+# reasonable steps to clearly label, demarcate or otherwise identify
+# that changes were made to the original Work. For example, a
+# translation could be marked "The original work was translated from
+# English to Spanish," or a modification could indicate "The original
+# work has been modified.";
+# 3. to Distribute and Publicly Perform the Work including as
+# incorporated in Collections; and,
+# 4. to Distribute and Publicly Perform Adaptations.
+# 5.
+#
+# For the avoidance of doubt:
+#
+# 1. *Non-waivable Compulsory License Schemes*. In those
+# jurisdictions in which the right to collect royalties through
+# any statutory or compulsory licensing scheme cannot be waived,
+# the Licensor reserves the exclusive right to collect such
+# royalties for any exercise by You of the rights granted under
+# this License;
+# 2. *Waivable Compulsory License Schemes*. In those jurisdictions in
+# which the right to collect royalties through any statutory or
+# compulsory licensing scheme can be waived, the Licensor waives
+# the exclusive right to collect such royalties for any exercise
+# by You of the rights granted under this License; and,
+# 3. *Voluntary License Schemes*. The Licensor waives the right to
+# collect royalties, whether individually or, in the event that
+# the Licensor is a member of a collecting society that
+# administers voluntary licensing schemes, via that society, from
+# any exercise by You of the rights granted under this License.
+#
+# The above rights may be exercised in all media and formats whether now
+# known or hereafter devised. The above rights include the right to make
+# such modifications as are technically necessary to exercise the rights
+# in other media and formats. Subject to Section 8(f), all rights not
+# expressly granted by Licensor are hereby reserved.
+#
+# *4. Restrictions.* The license granted in Section 3 above is expressly
+# made subject to and limited by the following restrictions:
+#
+# 1. You may Distribute or Publicly Perform the Work only under the terms
+# of this License. You must include a copy of, or the Uniform Resource
+# Identifier (URI) for, this License with every copy of the Work You
+# Distribute or Publicly Perform. You may not offer or impose any
+# terms on the Work that restrict the terms of this License or the
+# ability of the recipient of the Work to exercise the rights granted
+# to that recipient under the terms of the License. You may not
+# sublicense the Work. You must keep intact all notices that refer to
+# this License and to the disclaimer of warranties with every copy of
+# the Work You Distribute or Publicly Perform. When You Distribute or
+# Publicly Perform the Work, You may not impose any effective
+# technological measures on the Work that restrict the ability of a
+# recipient of the Work from You to exercise the rights granted to
+# that recipient under the terms of the License. This Section 4(a)
+# applies to the Work as incorporated in a Collection, but this does
+# not require the Collection apart from the Work itself to be made
+# subject to the terms of this License. If You create a Collection,
+# upon notice from any Licensor You must, to the extent practicable,
+# remove from the Collection any credit as required by Section 4(c),
+# as requested. If You create an Adaptation, upon notice from any
+# Licensor You must, to the extent practicable, remove from the
+# Adaptation any credit as required by Section 4(c), as requested.
+# 2. You may Distribute or Publicly Perform an Adaptation only under the
+# terms of: (i) this License; (ii) a later version of this License
+# with the same License Elements as this License; (iii) a Creative
+# Commons jurisdiction license (either this or a later license
+# version) that contains the same License Elements as this License
+# (e.g., Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons
+# Compatible License. If you license the Adaptation under one of the
+# licenses mentioned in (iv), you must comply with the terms of that
+# license. If you license the Adaptation under the terms of any of the
+# licenses mentioned in (i), (ii) or (iii) (the "Applicable License"),
+# you must comply with the terms of the Applicable License generally
+# and the following provisions: (I) You must include a copy of, or the
+# URI for, the Applicable License with every copy of each Adaptation
+# You Distribute or Publicly Perform; (II) You may not offer or impose
+# any terms on the Adaptation that restrict the terms of the
+# Applicable License or the ability of the recipient of the Adaptation
+# to exercise the rights granted to that recipient under the terms of
+# the Applicable License; (III) You must keep intact all notices that
+# refer to the Applicable License and to the disclaimer of warranties
+# with every copy of the Work as included in the Adaptation You
+# Distribute or Publicly Perform; (IV) when You Distribute or Publicly
+# Perform the Adaptation, You may not impose any effective
+# technological measures on the Adaptation that restrict the ability
+# of a recipient of the Adaptation from You to exercise the rights
+# granted to that recipient under the terms of the Applicable License.
+# This Section 4(b) applies to the Adaptation as incorporated in a
+# Collection, but this does not require the Collection apart from the
+# Adaptation itself to be made subject to the terms of the Applicable
+# License.
+# 3. If You Distribute, or Publicly Perform the Work or any Adaptations
+# or Collections, You must, unless a request has been made pursuant to
+# Section 4(a), keep intact all copyright notices for the Work and
+# provide, reasonable to the medium or means You are utilizing: (i)
+# the name of the Original Author (or pseudonym, if applicable) if
+# supplied, and/or if the Original Author and/or Licensor designate
+# another party or parties (e.g., a sponsor institute, publishing
+# entity, journal) for attribution ("Attribution Parties") in
+# Licensor's copyright notice, terms of service or by other reasonable
+# means, the name of such party or parties; (ii) the title of the Work
+# if supplied; (iii) to the extent reasonably practicable, the URI, if
+# any, that Licensor specifies to be associated with the Work, unless
+# such URI does not refer to the copyright notice or licensing
+# information for the Work; and (iv) , consistent with Ssection 3(b),
+# in the case of an Adaptation, a credit identifying the use of the
+# Work in the Adaptation (e.g., "French translation of the Work by
+# Original Author," or "Screenplay based on original Work by Original
+# Author"). The credit required by this Section 4(c) may be
+# implemented in any reasonable manner; provided, however, that in the
+# case of a Adaptation or Collection, at a minimum such credit will
+# appear, if a credit for all contributing authors of the Adaptation
+# or Collection appears, then as part of these credits and in a manner
+# at least as prominent as the credits for the other contributing
+# authors. For the avoidance of doubt, You may only use the credit
+# required by this Section for the purpose of attribution in the
+# manner set out above and, by exercising Your rights under this
+# License, You may not implicitly or explicitly assert or imply any
+# connection with, sponsorship or endorsement by the Original Author,
+# Licensor and/or Attribution Parties, as appropriate, of You or Your
+# use of the Work, without the separate, express prior written
+# permission of the Original Author, Licensor and/or Attribution Parties.
+# 4. Except as otherwise agreed in writing by the Licensor or as may be
+# otherwise permitted by applicable law, if You Reproduce, Distribute
+# or Publicly Perform the Work either by itself or as part of any
+# Adaptations or Collections, You must not distort, mutilate, modify
+# or take other derogatory action in relation to the Work which would
+# be prejudicial to the Original Author's honor or reputation.
+# Licensor agrees that in those jurisdictions (e.g. Japan), in which
+# any exercise of the right granted in Section 3(b) of this License
+# (the right to make Adaptations) would be deemed to be a distortion,
+# mutilation, modification or other derogatory action prejudicial to
+# the Original Author's honor and reputation, the Licensor will waive
+# or not assert, as appropriate, this Section, to the fullest extent
+# permitted by the applicable national law, to enable You to
+# reasonably exercise Your right under Section 3(b) of this License
+# (right to make Adaptations) but not otherwise.
+#
+# *5. Representations, Warranties and Disclaimer*
+#
+# UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR
+# OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY
+# KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,
+# INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF
+# LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS,
+# WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE
+# EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
+#
+# *6. Limitation on Liability.* EXCEPT TO THE EXTENT REQUIRED BY
+# APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL
+# THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY
+# DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF
+# LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+#
+# *7. Termination*
+#
+# 1. This License and the rights granted hereunder will terminate
+# automatically upon any breach by You of the terms of this License.
+# Individuals or entities who have received Adaptations or Collections
+# from You under this License, however, will not have their licenses
+# terminated provided such individuals or entities remain in full
+# compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
+# survive any termination of this License.
+# 2. Subject to the above terms and conditions, the license granted here
+# is perpetual (for the duration of the applicable copyright in the
+# Work). Notwithstanding the above, Licensor reserves the right to
+# release the Work under different license terms or to stop
+# distributing the Work at any time; provided, however that any such
+# election will not serve to withdraw this License (or any other
+# license that has been, or is required to be, granted under the terms
+# of this License), and this License will continue in full force and
+# effect unless terminated as stated above.
+#
+# *8. Miscellaneous*
+#
+# 1. Each time You Distribute or Publicly Perform the Work or a
+# Collection, the Licensor offers to the recipient a license to the
+# Work on the same terms and conditions as the license granted to You
+# under this License.
+# 2. Each time You Distribute or Publicly Perform an Adaptation, Licensor
+# offers to the recipient a license to the original Work on the same
+# terms and conditions as the license granted to You under this License.
+# 3. If any provision of this License is invalid or unenforceable under
+# applicable law, it shall not affect the validity or enforceability
+# of the remainder of the terms of this License, and without further
+# action by the parties to this agreement, such provision shall be
+# reformed to the minimum extent necessary to make such provision
+# valid and enforceable.
+# 4. No term or provision of this License shall be deemed waived and no
+# breach consented to unless such waiver or consent shall be in
+# writing and signed by the party to be charged with such waiver or
+# consent.
+# 5. This License constitutes the entire agreement between the parties
+# with respect to the Work licensed here. There are no understandings,
+# agreements or representations with respect to the Work not specified
+# here. Licensor shall not be bound by any additional provisions that
+# may appear in any communication from You. This License may not be
+# modified without the mutual written agreement of the Licensor and You.
+# 6. The rights granted under, and the subject matter referenced, in this
+# License were drafted utilizing the terminology of the Berne
+# Convention for the Protection of Literary and Artistic Works (as
+# amended on September 28, 1979), the Rome Convention of 1961, the
+# WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms
+# Treaty of 1996 and the Universal Copyright Convention (as revised on
+# July 24, 1971). These rights and subject matter take effect in the
+# relevant jurisdiction in which the License terms are sought to be
+# enforced according to the corresponding provisions of the
+# implementation of those treaty provisions in the applicable national
+# law. If the standard suite of rights granted under applicable
+# copyright law includes additional rights not granted under this
+# License, such additional rights are deemed to be included in the
+# License; this License is not intended to restrict the license of any
+# rights under applicable law.
+absorver->absorber
+absorviendo->absorbiendo
+aca->acá
+academica->académica
+academicamente->académicamente
+academico->académico
+accion->acción
+aceptacion->aceptación
+acetado->aceptado
+ademas->además
+administracion->administración
+aerea->aérea
+aereo->aéreo
+aficion->afición
+aficcion->afición
+aficción->afición
+ahi->ahí
+al Cairo->a El Cairo
+album->álbum
+alevin->alevín
+algun->algún
+alli->allí
+alla->allá
+al rededor->alrededor
+aprobechar->aprovechar
+aqui->aquí
+arabe->árabe
+arbol->árbol
+area->área
+articulacion->articulación
+asi->así
+atencion->atención
+atlantico->atlántico
+automovil->automóvil
+avion->avión
+azucar->azúcar
+bibliografia->bibliografía
+bién->bien
+Bogota->Bogotá
+Brasilero->brasileño
+Brasilera->brasileña
+buho->búho
+cadaver->cadáver
+cafe->café
+cafeteria->cafetería
+camaleon->camaleón
+camara->cámara
+cancion->canción
+candadear->candear
+caracter->carácter
+caracteristica->característica
+carroceria->carrocería
+catastrofe->catástrofe
+catastrofica->catastrófica
+catastrofico->catastrófico
+categoria->categoría
+cién->cien
+CD's->CD
+CDs->CD
+cogeran->cogerán
+cogia->cogía
+cogian->cogían
+cojer->coger
+cojen->cogen
+cojerán->cogerán
+cojía->cogía
+cojia->cogía
+cojían->cogían
+cojió->cogió
+companía->compañía
+compañia->compañía
+compasion->compasión
+comun->común
+comunmente->comúnmente
+conección->conexión
+cono urbano->conurbano
+consideracion->consideración
+constituída->constituida
+constituído->constituido
+construído->construido
+construír->construir
+continuan->continúan
+contínuo->continuo
+convirtio->convirtió
+cortesmente->cortésmente
+cronologica->cronológica
+cronologicamente->cronológicamente
+cronologico->cronológico
+da a lugar a->da lugar a
+dar a lugar a->dar lugar a
+daría a lugar a->daría lugar a
+dá->da
+definio->definió
+del Cairo->de El Cairo
+del interfaz->de la interfaz
+delfin->delfín
+desconto->descontó
+desovediente->desobediente
+deshechar->desechar
+deshechando->desechando
+despues->después
+dia->día
+dias->días
+dieciseis->dieciséis
+diéz->diez
+dificil->difícil
+dificilmente->difícilmente
+dio a lugar a->dio lugar a
+dió->dio
+discusion->discusión
+disolucion->disolución
+distorción->distorsión
+distorcionado->distorsionado
+distribuído->distribuido
+duodecimo->duodécimo
+e hielo->y hielo
+e hierro->y hierro
+e iones->y iones
+ebano->ébano
+eclesiastico->eclesiástico
+eclesiasticos->eclesiásticos
+el fue->él fue
+el interfaz->la interfaz
+el Osasuna->Osasuna
+embarcacion->embarcación
+enbarcacion->embarcación
+enbarcación->embarcación
+empezo->empezó
+enlaze->enlace
+eolico->eólico
+equalización->ecualización
+equalizador->ecualizador
+equalizar->ecualizar
+espiritu->espíritu
+estan->están
+estandard->estándar
+estándard->estándar
+etc...->etc.
+etimologia->etimología
+exámen->examen
+examenes->exámenes
+exitar->excitar
+exito->éxito
+exemplo->ejemplo
+explendor->esplendor
+extrangero->extranjero
+estranjero->extranjero
+estrangero->extranjero
+extricta->estricta
+extricto->estricto
+extrictamente->estrictamente
+espia->espía
+esprecion->expresión
+espreción->expresión
+espresion->expresión
+espresión->expresión
+expresion->expresión
+facil->fácil
+facilmente->fácilmente
+fanatica->fanática
+fanaticamente->fanáticamente
+fanatico->fanático
+fé->fe
+ficcion->ficción
+fisica->física
+fluído->fluido
+fricion->fricción
+frición->fricción
+friccion->fricción
+fucion->fusión
+fución->fusión
+fué->fue
+fuí->fui
+funcion->función
+fusion->fusión
+futbol->fútbol
+futil->fútil
+garage->garaje
+guión->guion
+Guipuzcoa->Guipúzcoa
+gustaria->gustaría
+Gutierrez->Gutiérrez
+habia->había
+haiga->haya
+habian->habían
+hechar->echar
+hechado->echado
+herbivoro->herbívoro
+herviboro->herbívoro
+hervíboro->herbívoro
+hervivoro->herbívoro
+hervívoro->herbívoro
+hermita->ermita
+heroe->héroe
+heróica->heroica
+heróico->heroico
+hibridización->hibridación
+hinduísmo->hinduismo
+hinduísta->hinduista
+homogenea->homogénea
+homogeneo->homogéneo
+hormigon->hormigón
+ideologia->ideología
+ideologica->ideológica
+ideologicamente->ideológicamente
+ideologico->ideológico
+imágen->imagen
+imagenes->imágenes
+IMDB->IMDb
+incluído->incluido
+incluír->incluir
+indice->índice
+interface->interfaz
+interperie->intemperie
+inutil->inútil
+invasion->invasión
+israeli->israelí
+israelies->israelíes
+jardin->jardín
+jente->gente
+jóven->joven
+judia->judía
+judias->judías
+judio->judío
+judios->judíos
+Km->km
+km2->km²
+lampara->lámpara
+le hecha->le echa
+leido->leído
+leon->león
+lider->líder
+linea->línea
+lineas->líneas
+linia->línea
+llendo->yendo
+llevada acabo->llevada a cabo
+llevado acabo->llevado a cabo
+llevaron acabo->llevaron a cabo
+llevó acabo->llevó a cabo
+logica->lógica
+logicamente->lógicamente
+logico->lógico
+lo hecha->lo echa
+lonjeva->longeva
+lonjevo->longevo
+mecanica->mecánica
+mecanicamente->mecánicamente
+mecanico->mecánico
+magica->mágica
+magico->mágico
+martir->mártir
+maxima->máxima
+maximo->máximo
+mayoria->mayoría
+mayuscula->mayúscula
+mayusculo->mayúsculo
+metodologia->metodología
+Mexico->México
+míl->mil
+minima->mínima
+minimo->mínimo
+minoria->minoría
+minuscula->minúscula
+minusculo->minúsculo
+mitologia->mitología
+mitologica->mitológica
+mitologico->mitológico
+mitomana->mitómana
+mitomania->mitomanía
+mitomano->mitómano
+monton->montón
+movil->móvil
+murciegalo->murciélago
+murciégalo->murciélago
+murio->murió
+musica->música
+nacio->nació
+nadien->nadie
+ningun->ningún
+oceano->océano
+olimpica->olímpica
+olimpicamente->olímpicamente
+olimpico->olímpico
+operacion->operación
+oraculo->oráculo
+órden->orden
+organica->orgánica
+organico->orgánico
+organo->órgano
+orígen->origen
+origenes->orígenes
+osea->o sea
+oceano pacifico->océano pacífico
+ONG's->ONG
+ONGs-> ONG
+OVNI's->OVNI
+OVNIs->OVNI
+pagina->página
+pais->país
+paparazzis->paparazzi
+participacion->participación
+pasion->pasión
+pelicula->película
+peloton->pelotón
+perfíl->perfil
+persuación->persuasión
+politica->política
+politicamente->políticamente
+politico->político
+por contra-> por el contrario
+practicamente->prácticamente
+prerequisito->prerrequisito
+pre-requisito->prerrequisito
+preveer->prever
+prevencion->prevención
+programacion->programación
+promocion->promoción
+protejer->proteger
+publicamente->públicamente
+quiza->quizá
+quizas->quizás
+rapido->rápido
+rapida->rápida
+regilla->rejilla
+remplazar->reemplazar
+republica->república
+resolucion->resolución
+restaurant->restaurante
+revizado->revisado
+revizar->revisar
+revolucion->revolución
+rocin->rocín
+ruído->ruido
+sacerdotiza->sacerdotisa
+sazon->sazón
+se a->se ha
+séis->seis
+segun->según
+sera->será
+serpentin->serpentín
+sinembargo->sin embargo
+sinfin->sinfín
+slogan->eslogan
+sóla->sola
+sólamente->solamente
+solucion->solución
+stándard->estándar
+subrraya->subraya
+subrrayado->subrayado
+subrrayar->subrayar
+superfície->superficie
+supérflua->superflua
+tagea->tajea
+talvez->tal vez
+tambien->también
+tanbien->también
+tanbién->también
+tecnica->técnica
+tecnicamente->técnicamente
+tecnico->técnico
+tí->ti
+tia->tía
+tio->tío
+tipica->típica
+tipicamente->típicamente
+tipico->típico
+tradució->tradujo,traducción
+traducion->traducción
+tradución->traducción
+traduccion->traducción
+traf->tráf
+tunel->túnel
+ubicacion->ubicación
+ultimamente->últimamente
+ultimo->último
+ultimos->últimos
+un interfaz->una interfaz
+undecimo->undécimo
+unica->única
+unicamente->únicamente
+unico->único
+util->útil
+vease->véase
+veintidos->veintidós
+veintiseis->veintiséis
+veintitres->veintitrés
+vision->visión
+via->vía
+vió->vio
+watios->vatios
diff --git a/files/typos/typos-hu.txt b/files/typos/typos-hu.txt
new file mode 100644
index 0000000..e0586bf
--- /dev/null
+++ b/files/typos/typos-hu.txt
@@ -0,0 +1,431 @@
+# This file contains a number of common Hungarian typos:
+andriod->android
+
+# The remainder of this file contains misspellings from
+# http://hu.wikipedia.org/wiki/Szerkeszt%C5%91:AntiVandal/Hiba
+# plus some post-processing to fix invalid entries, remove duplicates, etc.
+#
+# The content is available under the
+# "Creative Commons Attribution-ShareAlike License"
+# http://creativecommons.org/licenses/by-sa/3.0/
+#
+# THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
+# COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
+# COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
+# AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
+#
+# BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE
+# TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY
+# BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS
+# CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
+# CONDITIONS.
+#
+# *1. Definitions*
+#
+# 1. *"Adaptation"* means a work based upon the Work, or upon the Work
+# and other pre-existing works, such as a translation, adaptation,
+# derivative work, arrangement of music or other alterations of a
+# literary or artistic work, or phonogram or performance and includes
+# cinematographic adaptations or any other form in which the Work may
+# be recast, transformed, or adapted including in any form
+# recognizably derived from the original, except that a work that
+# constitutes a Collection will not be considered an Adaptation for
+# the purpose of this License. For the avoidance of doubt, where the
+# Work is a musical work, performance or phonogram, the
+# synchronization of the Work in timed-relation with a moving image
+# ("synching") will be considered an Adaptation for the purpose of
+# this License.
+# 2. *"Collection"* means a collection of literary or artistic works,
+# such as encyclopedias and anthologies, or performances, phonograms
+# or broadcasts, or other works or subject matter other than works
+# listed in Section 1(f) below, which, by reason of the selection and
+# arrangement of their contents, constitute intellectual creations, in
+# which the Work is included in its entirety in unmodified form along
+# with one or more other contributions, each constituting separate and
+# independent works in themselves, which together are assembled into a
+# collective whole. A work that constitutes a Collection will not be
+# considered an Adaptation (as defined below) for the purposes of this
+# License.
+# 3. *"Creative Commons Compatible License"* means a license that is
+# listed at http://creativecommons.org/compatiblelicenses that has
+# been approved by Creative Commons as being essentially equivalent to
+# this License, including, at a minimum, because that license: (i)
+# contains terms that have the same purpose, meaning and effect as the
+# License Elements of this License; and, (ii) explicitly permits the
+# relicensing of adaptations of works made available under that
+# license under this License or a Creative Commons jurisdiction
+# license with the same License Elements as this License.
+# 4. *"Distribute"* means to make available to the public the original
+# and copies of the Work or Adaptation, as appropriate, through sale
+# or other transfer of ownership.
+# 5. *"License Elements"* means the following high-level license
+# attributes as selected by Licensor and indicated in the title of
+# this License: Attribution, ShareAlike.
+# 6. *"Licensor"* means the individual, individuals, entity or entities
+# that offer(s) the Work under the terms of this License.
+# 7. *"Original Author"* means, in the case of a literary or artistic
+# work, the individual, individuals, entity or entities who created
+# the Work or if no individual or entity can be identified, the
+# publisher; and in addition (i) in the case of a performance the
+# actors, singers, musicians, dancers, and other persons who act,
+# sing, deliver, declaim, play in, interpret or otherwise perform
+# literary or artistic works or expressions of folklore; (ii) in the
+# case of a phonogram the producer being the person or legal entity
+# who first fixes the sounds of a performance or other sounds; and,
+# (iii) in the case of broadcasts, the organization that transmits the
+# broadcast.
+# 8. *"Work"* means the literary and/or artistic work offered under the
+# terms of this License including without limitation any production in
+# the literary, scientific and artistic domain, whatever may be the
+# mode or form of its expression including digital form, such as a
+# book, pamphlet and other writing; a lecture, address, sermon or
+# other work of the same nature; a dramatic or dramatico-musical work;
+# a choreographic work or entertainment in dumb show; a musical
+# composition with or without words; a cinematographic work to which
+# are assimilated works expressed by a process analogous to
+# cinematography; a work of drawing, painting, architecture,
+# sculpture, engraving or lithography; a photographic work to which
+# are assimilated works expressed by a process analogous to
+# photography; a work of applied art; an illustration, map, plan,
+# sketch or three-dimensional work relative to geography, topography,
+# architecture or science; a performance; a broadcast; a phonogram; a
+# compilation of data to the extent it is protected as a copyrightable
+# work; or a work performed by a variety or circus performer to the
+# extent it is not otherwise considered a literary or artistic work.
+# 9. *"You"* means an individual or entity exercising rights under this
+# License who has not previously violated the terms of this License
+# with respect to the Work, or who has received express permission
+# from the Licensor to exercise rights under this License despite a
+# previous violation.
+# 10. *"Publicly Perform"* means to perform public recitations of the Work
+# and to communicate to the public those public recitations, by any
+# means or process, including by wire or wireless means or public
+# digital performances; to make available to the public Works in such
+# a way that members of the public may access these Works from a place
+# and at a place individually chosen by them; to perform the Work to
+# the public by any means or process and the communication to the
+# public of the performances of the Work, including by public digital
+# performance; to broadcast and rebroadcast the Work by any means
+# including signs, sounds or images.
+# 11. *"Reproduce"* means to make copies of the Work by any means
+# including without limitation by sound or visual recordings and the
+# right of fixation and reproducing fixations of the Work, including
+# storage of a protected performance or phonogram in digital form or
+# other electronic medium.
+#
+# *2. Fair Dealing Rights.* Nothing in this License is intended to reduce,
+# limit, or restrict any uses free from copyright or rights arising from
+# limitations or exceptions that are provided for in connection with the
+# copyright protection under copyright law or other applicable laws.
+#
+# *3. License Grant.* Subject to the terms and conditions of this License,
+# Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
+# perpetual (for the duration of the applicable copyright) license to
+# exercise the rights in the Work as stated below:
+#
+# 1. to Reproduce the Work, to incorporate the Work into one or more
+# Collections, and to Reproduce the Work as incorporated in the
+# Collections;
+# 2. to create and Reproduce Adaptations provided that any such
+# Adaptation, including any translation in any medium, takes
+# reasonable steps to clearly label, demarcate or otherwise identify
+# that changes were made to the original Work. For example, a
+# translation could be marked "The original work was translated from
+# English to Spanish," or a modification could indicate "The original
+# work has been modified.";
+# 3. to Distribute and Publicly Perform the Work including as
+# incorporated in Collections; and,
+# 4. to Distribute and Publicly Perform Adaptations.
+# 5.
+#
+# For the avoidance of doubt:
+#
+# 1. *Non-waivable Compulsory License Schemes*. In those
+# jurisdictions in which the right to collect royalties through
+# any statutory or compulsory licensing scheme cannot be waived,
+# the Licensor reserves the exclusive right to collect such
+# royalties for any exercise by You of the rights granted under
+# this License;
+# 2. *Waivable Compulsory License Schemes*. In those jurisdictions in
+# which the right to collect royalties through any statutory or
+# compulsory licensing scheme can be waived, the Licensor waives
+# the exclusive right to collect such royalties for any exercise
+# by You of the rights granted under this License; and,
+# 3. *Voluntary License Schemes*. The Licensor waives the right to
+# collect royalties, whether individually or, in the event that
+# the Licensor is a member of a collecting society that
+# administers voluntary licensing schemes, via that society, from
+# any exercise by You of the rights granted under this License.
+#
+# The above rights may be exercised in all media and formats whether now
+# known or hereafter devised. The above rights include the right to make
+# such modifications as are technically necessary to exercise the rights
+# in other media and formats. Subject to Section 8(f), all rights not
+# expressly granted by Licensor are hereby reserved.
+#
+# *4. Restrictions.* The license granted in Section 3 above is expressly
+# made subject to and limited by the following restrictions:
+#
+# 1. You may Distribute or Publicly Perform the Work only under the terms
+# of this License. You must include a copy of, or the Uniform Resource
+# Identifier (URI) for, this License with every copy of the Work You
+# Distribute or Publicly Perform. You may not offer or impose any
+# terms on the Work that restrict the terms of this License or the
+# ability of the recipient of the Work to exercise the rights granted
+# to that recipient under the terms of the License. You may not
+# sublicense the Work. You must keep intact all notices that refer to
+# this License and to the disclaimer of warranties with every copy of
+# the Work You Distribute or Publicly Perform. When You Distribute or
+# Publicly Perform the Work, You may not impose any effective
+# technological measures on the Work that restrict the ability of a
+# recipient of the Work from You to exercise the rights granted to
+# that recipient under the terms of the License. This Section 4(a)
+# applies to the Work as incorporated in a Collection, but this does
+# not require the Collection apart from the Work itself to be made
+# subject to the terms of this License. If You create a Collection,
+# upon notice from any Licensor You must, to the extent practicable,
+# remove from the Collection any credit as required by Section 4(c),
+# as requested. If You create an Adaptation, upon notice from any
+# Licensor You must, to the extent practicable, remove from the
+# Adaptation any credit as required by Section 4(c), as requested.
+# 2. You may Distribute or Publicly Perform an Adaptation only under the
+# terms of: (i) this License; (ii) a later version of this License
+# with the same License Elements as this License; (iii) a Creative
+# Commons jurisdiction license (either this or a later license
+# version) that contains the same License Elements as this License
+# (e.g., Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons
+# Compatible License. If you license the Adaptation under one of the
+# licenses mentioned in (iv), you must comply with the terms of that
+# license. If you license the Adaptation under the terms of any of the
+# licenses mentioned in (i), (ii) or (iii) (the "Applicable License"),
+# you must comply with the terms of the Applicable License generally
+# and the following provisions: (I) You must include a copy of, or the
+# URI for, the Applicable License with every copy of each Adaptation
+# You Distribute or Publicly Perform; (II) You may not offer or impose
+# any terms on the Adaptation that restrict the terms of the
+# Applicable License or the ability of the recipient of the Adaptation
+# to exercise the rights granted to that recipient under the terms of
+# the Applicable License; (III) You must keep intact all notices that
+# refer to the Applicable License and to the disclaimer of warranties
+# with every copy of the Work as included in the Adaptation You
+# Distribute or Publicly Perform; (IV) when You Distribute or Publicly
+# Perform the Adaptation, You may not impose any effective
+# technological measures on the Adaptation that restrict the ability
+# of a recipient of the Adaptation from You to exercise the rights
+# granted to that recipient under the terms of the Applicable License.
+# This Section 4(b) applies to the Adaptation as incorporated in a
+# Collection, but this does not require the Collection apart from the
+# Adaptation itself to be made subject to the terms of the Applicable
+# License.
+# 3. If You Distribute, or Publicly Perform the Work or any Adaptations
+# or Collections, You must, unless a request has been made pursuant to
+# Section 4(a), keep intact all copyright notices for the Work and
+# provide, reasonable to the medium or means You are utilizing: (i)
+# the name of the Original Author (or pseudonym, if applicable) if
+# supplied, and/or if the Original Author and/or Licensor designate
+# another party or parties (e.g., a sponsor institute, publishing
+# entity, journal) for attribution ("Attribution Parties") in
+# Licensor's copyright notice, terms of service or by other reasonable
+# means, the name of such party or parties; (ii) the title of the Work
+# if supplied; (iii) to the extent reasonably practicable, the URI, if
+# any, that Licensor specifies to be associated with the Work, unless
+# such URI does not refer to the copyright notice or licensing
+# information for the Work; and (iv) , consistent with Ssection 3(b),
+# in the case of an Adaptation, a credit identifying the use of the
+# Work in the Adaptation (e.g., "French translation of the Work by
+# Original Author," or "Screenplay based on original Work by Original
+# Author"). The credit required by this Section 4(c) may be
+# implemented in any reasonable manner; provided, however, that in the
+# case of a Adaptation or Collection, at a minimum such credit will
+# appear, if a credit for all contributing authors of the Adaptation
+# or Collection appears, then as part of these credits and in a manner
+# at least as prominent as the credits for the other contributing
+# authors. For the avoidance of doubt, You may only use the credit
+# required by this Section for the purpose of attribution in the
+# manner set out above and, by exercising Your rights under this
+# License, You may not implicitly or explicitly assert or imply any
+# connection with, sponsorship or endorsement by the Original Author,
+# Licensor and/or Attribution Parties, as appropriate, of You or Your
+# use of the Work, without the separate, express prior written
+# permission of the Original Author, Licensor and/or Attribution Parties.
+# 4. Except as otherwise agreed in writing by the Licensor or as may be
+# otherwise permitted by applicable law, if You Reproduce, Distribute
+# or Publicly Perform the Work either by itself or as part of any
+# Adaptations or Collections, You must not distort, mutilate, modify
+# or take other derogatory action in relation to the Work which would
+# be prejudicial to the Original Author's honor or reputation.
+# Licensor agrees that in those jurisdictions (e.g. Japan), in which
+# any exercise of the right granted in Section 3(b) of this License
+# (the right to make Adaptations) would be deemed to be a distortion,
+# mutilation, modification or other derogatory action prejudicial to
+# the Original Author's honor and reputation, the Licensor will waive
+# or not assert, as appropriate, this Section, to the fullest extent
+# permitted by the applicable national law, to enable You to
+# reasonably exercise Your right under Section 3(b) of this License
+# (right to make Adaptations) but not otherwise.
+#
+# *5. Representations, Warranties and Disclaimer*
+#
+# UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR
+# OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY
+# KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,
+# INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF
+# LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS,
+# WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE
+# EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
+#
+# *6. Limitation on Liability.* EXCEPT TO THE EXTENT REQUIRED BY
+# APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL
+# THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY
+# DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF
+# LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+#
+# *7. Termination*
+#
+# 1. This License and the rights granted hereunder will terminate
+# automatically upon any breach by You of the terms of this License.
+# Individuals or entities who have received Adaptations or Collections
+# from You under this License, however, will not have their licenses
+# terminated provided such individuals or entities remain in full
+# compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
+# survive any termination of this License.
+# 2. Subject to the above terms and conditions, the license granted here
+# is perpetual (for the duration of the applicable copyright in the
+# Work). Notwithstanding the above, Licensor reserves the right to
+# release the Work under different license terms or to stop
+# distributing the Work at any time; provided, however that any such
+# election will not serve to withdraw this License (or any other
+# license that has been, or is required to be, granted under the terms
+# of this License), and this License will continue in full force and
+# effect unless terminated as stated above.
+#
+# *8. Miscellaneous*
+#
+# 1. Each time You Distribute or Publicly Perform the Work or a
+# Collection, the Licensor offers to the recipient a license to the
+# Work on the same terms and conditions as the license granted to You
+# under this License.
+# 2. Each time You Distribute or Publicly Perform an Adaptation, Licensor
+# offers to the recipient a license to the original Work on the same
+# terms and conditions as the license granted to You under this License.
+# 3. If any provision of this License is invalid or unenforceable under
+# applicable law, it shall not affect the validity or enforceability
+# of the remainder of the terms of this License, and without further
+# action by the parties to this agreement, such provision shall be
+# reformed to the minimum extent necessary to make such provision
+# valid and enforceable.
+# 4. No term or provision of this License shall be deemed waived and no
+# breach consented to unless such waiver or consent shall be in
+# writing and signed by the party to be charged with such waiver or
+# consent.
+# 5. This License constitutes the entire agreement between the parties
+# with respect to the Work licensed here. There are no understandings,
+# agreements or representations with respect to the Work not specified
+# here. Licensor shall not be bound by any additional provisions that
+# may appear in any communication from You. This License may not be
+# modified without the mutual written agreement of the Licensor and You.
+# 6. The rights granted under, and the subject matter referenced, in this
+# License were drafted utilizing the terminology of the Berne
+# Convention for the Protection of Literary and Artistic Works (as
+# amended on September 28, 1979), the Rome Convention of 1961, the
+# WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms
+# Treaty of 1996 and the Universal Copyright Convention (as revised on
+# July 24, 1971). These rights and subject matter take effect in the
+# relevant jurisdiction in which the License terms are sought to be
+# enforced according to the corresponding provisions of the
+# implementation of those treaty provisions in the applicable national
+# law. If the standard suite of rights granted under applicable
+# copyright law includes additional rights not granted under this
+# License, such additional rights are deemed to be included in the
+# License; this License is not intended to restrict the license of any
+# rights under applicable law.
+0-át->0-t
+1.-én->1-jén
+10.-én->10-én
+11.-én->11-én
+12.-én->12-én
+13.-án->13-án
+14.-én->14-én
+15.-én->15-én
+16.-án->16-án
+17.-én->17-én
+18.-án->18-án
+19.-én->19-én
+1-e->1-je
+1-el->1-gyel
+1-én->1-jén
+2.-án->2-án
+20.-án->20-án
+21.-én->21-én
+22.-én->22-én
+23.-án->23-án
+24.-én->24-én
+25.-én->25-én
+26.-án->26-án
+27.-én->27-én
+28.-án->28-án
+29.-én->29-én
+2-őt->2-t
+3.-án->3-án
+30.-án->30-án
+31.-én->31-én
+4.-én->4-én
+5.-én->5-én
+6.-án->6-án
+7.-én->7-én
+8.-án->8-án
+9.-én->9-én
+abszolut->abszolút
+ambíciózus->ambiciózus
+asszimetrikus->aszimmetrikus
+árú->áru
+azomban->azonban
+bejjebb->beljebb
+bisztos->biztos
+brilliáns->briliáns
+cimke->címke
+dícséret->dicséret
+egyenlőre->egyelőre
+egyértelmüsítő->egyértelműsítő
+eggyütt->együtt
+elipszis->ellipszis
+follyon->folyjon
+hektóliter->hektoliter
+hellénista->hellenista
+hellénisztikus->hellenisztikus
+hellénizmus->hellenizmus
+Horatiussal->Horatiusszal
+igéret->ígéret
+irígy->irigy
+kálcium->kalcium
+kellet->kellett
+keveseb->kevesebb
+kilóméter->kilométer
+kisseb->kisebb
+kissebb->kisebb
+konkurrencia->konkurencia
+konkurrens->konkurens
+könnyeb->könnyebb
+könyebb->könnyebb
+kultura->kultúra
+kultúrális->kulturális
+külömbség->különbség
+külömböző->különböző
+legjob->legjobb
+legkeveseb->legkevesebb
+legnagyob->legnagyobb
+lessz->lesz
+mellet->mellett
+mindíg->mindig
+muszály->muszáj
+new yorki->New York-i
+orzság->ország
+önnálló->önálló
+raffinált->rafinált
+szinvonal->színvonal
+Szovjetúnió->Szovjetunió
+Torino-i->torinói
+únió->unió
+vákum->vákuum
+Vietnám->Vietnam
diff --git a/files/typos/typos-it.txt b/files/typos/typos-it.txt
new file mode 100644
index 0000000..5c2d496
--- /dev/null
+++ b/files/typos/typos-it.txt
@@ -0,0 +1,665 @@
+# This file contains a number of common Italian typos:
+andriod->android
+
+# The remainder of this file contains misspellings from
+# http://it.m.wikipedia.org/wiki/Utente:Senpai/Lista_degli_errori_comuni/Formato_macchina
+# plus some post-processing to fix invalid entries, remove duplicates, etc.
+#
+# The content is available under the
+# "Creative Commons Attribution-ShareAlike License"
+# http://creativecommons.org/licenses/by-sa/3.0/
+#
+# THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
+# COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
+# COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
+# AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
+#
+# BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE
+# TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY
+# BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS
+# CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
+# CONDITIONS.
+#
+# *1. Definitions*
+#
+# 1. *"Adaptation"* means a work based upon the Work, or upon the Work
+# and other pre-existing works, such as a translation, adaptation,
+# derivative work, arrangement of music or other alterations of a
+# literary or artistic work, or phonogram or performance and includes
+# cinematographic adaptations or any other form in which the Work may
+# be recast, transformed, or adapted including in any form
+# recognizably derived from the original, except that a work that
+# constitutes a Collection will not be considered an Adaptation for
+# the purpose of this License. For the avoidance of doubt, where the
+# Work is a musical work, performance or phonogram, the
+# synchronization of the Work in timed-relation with a moving image
+# ("synching") will be considered an Adaptation for the purpose of
+# this License.
+# 2. *"Collection"* means a collection of literary or artistic works,
+# such as encyclopedias and anthologies, or performances, phonograms
+# or broadcasts, or other works or subject matter other than works
+# listed in Section 1(f) below, which, by reason of the selection and
+# arrangement of their contents, constitute intellectual creations, in
+# which the Work is included in its entirety in unmodified form along
+# with one or more other contributions, each constituting separate and
+# independent works in themselves, which together are assembled into a
+# collective whole. A work that constitutes a Collection will not be
+# considered an Adaptation (as defined below) for the purposes of this
+# License.
+# 3. *"Creative Commons Compatible License"* means a license that is
+# listed at http://creativecommons.org/compatiblelicenses that has
+# been approved by Creative Commons as being essentially equivalent to
+# this License, including, at a minimum, because that license: (i)
+# contains terms that have the same purpose, meaning and effect as the
+# License Elements of this License; and, (ii) explicitly permits the
+# relicensing of adaptations of works made available under that
+# license under this License or a Creative Commons jurisdiction
+# license with the same License Elements as this License.
+# 4. *"Distribute"* means to make available to the public the original
+# and copies of the Work or Adaptation, as appropriate, through sale
+# or other transfer of ownership.
+# 5. *"License Elements"* means the following high-level license
+# attributes as selected by Licensor and indicated in the title of
+# this License: Attribution, ShareAlike.
+# 6. *"Licensor"* means the individual, individuals, entity or entities
+# that offer(s) the Work under the terms of this License.
+# 7. *"Original Author"* means, in the case of a literary or artistic
+# work, the individual, individuals, entity or entities who created
+# the Work or if no individual or entity can be identified, the
+# publisher; and in addition (i) in the case of a performance the
+# actors, singers, musicians, dancers, and other persons who act,
+# sing, deliver, declaim, play in, interpret or otherwise perform
+# literary or artistic works or expressions of folklore; (ii) in the
+# case of a phonogram the producer being the person or legal entity
+# who first fixes the sounds of a performance or other sounds; and,
+# (iii) in the case of broadcasts, the organization that transmits the
+# broadcast.
+# 8. *"Work"* means the literary and/or artistic work offered under the
+# terms of this License including without limitation any production in
+# the literary, scientific and artistic domain, whatever may be the
+# mode or form of its expression including digital form, such as a
+# book, pamphlet and other writing; a lecture, address, sermon or
+# other work of the same nature; a dramatic or dramatico-musical work;
+# a choreographic work or entertainment in dumb show; a musical
+# composition with or without words; a cinematographic work to which
+# are assimilated works expressed by a process analogous to
+# cinematography; a work of drawing, painting, architecture,
+# sculpture, engraving or lithography; a photographic work to which
+# are assimilated works expressed by a process analogous to
+# photography; a work of applied art; an illustration, map, plan,
+# sketch or three-dimensional work relative to geography, topography,
+# architecture or science; a performance; a broadcast; a phonogram; a
+# compilation of data to the extent it is protected as a copyrightable
+# work; or a work performed by a variety or circus performer to the
+# extent it is not otherwise considered a literary or artistic work.
+# 9. *"You"* means an individual or entity exercising rights under this
+# License who has not previously violated the terms of this License
+# with respect to the Work, or who has received express permission
+# from the Licensor to exercise rights under this License despite a
+# previous violation.
+# 10. *"Publicly Perform"* means to perform public recitations of the Work
+# and to communicate to the public those public recitations, by any
+# means or process, including by wire or wireless means or public
+# digital performances; to make available to the public Works in such
+# a way that members of the public may access these Works from a place
+# and at a place individually chosen by them; to perform the Work to
+# the public by any means or process and the communication to the
+# public of the performances of the Work, including by public digital
+# performance; to broadcast and rebroadcast the Work by any means
+# including signs, sounds or images.
+# 11. *"Reproduce"* means to make copies of the Work by any means
+# including without limitation by sound or visual recordings and the
+# right of fixation and reproducing fixations of the Work, including
+# storage of a protected performance or phonogram in digital form or
+# other electronic medium.
+#
+# *2. Fair Dealing Rights.* Nothing in this License is intended to reduce,
+# limit, or restrict any uses free from copyright or rights arising from
+# limitations or exceptions that are provided for in connection with the
+# copyright protection under copyright law or other applicable laws.
+#
+# *3. License Grant.* Subject to the terms and conditions of this License,
+# Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
+# perpetual (for the duration of the applicable copyright) license to
+# exercise the rights in the Work as stated below:
+#
+# 1. to Reproduce the Work, to incorporate the Work into one or more
+# Collections, and to Reproduce the Work as incorporated in the
+# Collections;
+# 2. to create and Reproduce Adaptations provided that any such
+# Adaptation, including any translation in any medium, takes
+# reasonable steps to clearly label, demarcate or otherwise identify
+# that changes were made to the original Work. For example, a
+# translation could be marked "The original work was translated from
+# English to Spanish," or a modification could indicate "The original
+# work has been modified.";
+# 3. to Distribute and Publicly Perform the Work including as
+# incorporated in Collections; and,
+# 4. to Distribute and Publicly Perform Adaptations.
+# 5.
+#
+# For the avoidance of doubt:
+#
+# 1. *Non-waivable Compulsory License Schemes*. In those
+# jurisdictions in which the right to collect royalties through
+# any statutory or compulsory licensing scheme cannot be waived,
+# the Licensor reserves the exclusive right to collect such
+# royalties for any exercise by You of the rights granted under
+# this License;
+# 2. *Waivable Compulsory License Schemes*. In those jurisdictions in
+# which the right to collect royalties through any statutory or
+# compulsory licensing scheme can be waived, the Licensor waives
+# the exclusive right to collect such royalties for any exercise
+# by You of the rights granted under this License; and,
+# 3. *Voluntary License Schemes*. The Licensor waives the right to
+# collect royalties, whether individually or, in the event that
+# the Licensor is a member of a collecting society that
+# administers voluntary licensing schemes, via that society, from
+# any exercise by You of the rights granted under this License.
+#
+# The above rights may be exercised in all media and formats whether now
+# known or hereafter devised. The above rights include the right to make
+# such modifications as are technically necessary to exercise the rights
+# in other media and formats. Subject to Section 8(f), all rights not
+# expressly granted by Licensor are hereby reserved.
+#
+# *4. Restrictions.* The license granted in Section 3 above is expressly
+# made subject to and limited by the following restrictions:
+#
+# 1. You may Distribute or Publicly Perform the Work only under the terms
+# of this License. You must include a copy of, or the Uniform Resource
+# Identifier (URI) for, this License with every copy of the Work You
+# Distribute or Publicly Perform. You may not offer or impose any
+# terms on the Work that restrict the terms of this License or the
+# ability of the recipient of the Work to exercise the rights granted
+# to that recipient under the terms of the License. You may not
+# sublicense the Work. You must keep intact all notices that refer to
+# this License and to the disclaimer of warranties with every copy of
+# the Work You Distribute or Publicly Perform. When You Distribute or
+# Publicly Perform the Work, You may not impose any effective
+# technological measures on the Work that restrict the ability of a
+# recipient of the Work from You to exercise the rights granted to
+# that recipient under the terms of the License. This Section 4(a)
+# applies to the Work as incorporated in a Collection, but this does
+# not require the Collection apart from the Work itself to be made
+# subject to the terms of this License. If You create a Collection,
+# upon notice from any Licensor You must, to the extent practicable,
+# remove from the Collection any credit as required by Section 4(c),
+# as requested. If You create an Adaptation, upon notice from any
+# Licensor You must, to the extent practicable, remove from the
+# Adaptation any credit as required by Section 4(c), as requested.
+# 2. You may Distribute or Publicly Perform an Adaptation only under the
+# terms of: (i) this License; (ii) a later version of this License
+# with the same License Elements as this License; (iii) a Creative
+# Commons jurisdiction license (either this or a later license
+# version) that contains the same License Elements as this License
+# (e.g., Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons
+# Compatible License. If you license the Adaptation under one of the
+# licenses mentioned in (iv), you must comply with the terms of that
+# license. If you license the Adaptation under the terms of any of the
+# licenses mentioned in (i), (ii) or (iii) (the "Applicable License"),
+# you must comply with the terms of the Applicable License generally
+# and the following provisions: (I) You must include a copy of, or the
+# URI for, the Applicable License with every copy of each Adaptation
+# You Distribute or Publicly Perform; (II) You may not offer or impose
+# any terms on the Adaptation that restrict the terms of the
+# Applicable License or the ability of the recipient of the Adaptation
+# to exercise the rights granted to that recipient under the terms of
+# the Applicable License; (III) You must keep intact all notices that
+# refer to the Applicable License and to the disclaimer of warranties
+# with every copy of the Work as included in the Adaptation You
+# Distribute or Publicly Perform; (IV) when You Distribute or Publicly
+# Perform the Adaptation, You may not impose any effective
+# technological measures on the Adaptation that restrict the ability
+# of a recipient of the Adaptation from You to exercise the rights
+# granted to that recipient under the terms of the Applicable License.
+# This Section 4(b) applies to the Adaptation as incorporated in a
+# Collection, but this does not require the Collection apart from the
+# Adaptation itself to be made subject to the terms of the Applicable
+# License.
+# 3. If You Distribute, or Publicly Perform the Work or any Adaptations
+# or Collections, You must, unless a request has been made pursuant to
+# Section 4(a), keep intact all copyright notices for the Work and
+# provide, reasonable to the medium or means You are utilizing: (i)
+# the name of the Original Author (or pseudonym, if applicable) if
+# supplied, and/or if the Original Author and/or Licensor designate
+# another party or parties (e.g., a sponsor institute, publishing
+# entity, journal) for attribution ("Attribution Parties") in
+# Licensor's copyright notice, terms of service or by other reasonable
+# means, the name of such party or parties; (ii) the title of the Work
+# if supplied; (iii) to the extent reasonably practicable, the URI, if
+# any, that Licensor specifies to be associated with the Work, unless
+# such URI does not refer to the copyright notice or licensing
+# information for the Work; and (iv) , consistent with Ssection 3(b),
+# in the case of an Adaptation, a credit identifying the use of the
+# Work in the Adaptation (e.g., "French translation of the Work by
+# Original Author," or "Screenplay based on original Work by Original
+# Author"). The credit required by this Section 4(c) may be
+# implemented in any reasonable manner; provided, however, that in the
+# case of a Adaptation or Collection, at a minimum such credit will
+# appear, if a credit for all contributing authors of the Adaptation
+# or Collection appears, then as part of these credits and in a manner
+# at least as prominent as the credits for the other contributing
+# authors. For the avoidance of doubt, You may only use the credit
+# required by this Section for the purpose of attribution in the
+# manner set out above and, by exercising Your rights under this
+# License, You may not implicitly or explicitly assert or imply any
+# connection with, sponsorship or endorsement by the Original Author,
+# Licensor and/or Attribution Parties, as appropriate, of You or Your
+# use of the Work, without the separate, express prior written
+# permission of the Original Author, Licensor and/or Attribution Parties.
+# 4. Except as otherwise agreed in writing by the Licensor or as may be
+# otherwise permitted by applicable law, if You Reproduce, Distribute
+# or Publicly Perform the Work either by itself or as part of any
+# Adaptations or Collections, You must not distort, mutilate, modify
+# or take other derogatory action in relation to the Work which would
+# be prejudicial to the Original Author's honor or reputation.
+# Licensor agrees that in those jurisdictions (e.g. Japan), in which
+# any exercise of the right granted in Section 3(b) of this License
+# (the right to make Adaptations) would be deemed to be a distortion,
+# mutilation, modification or other derogatory action prejudicial to
+# the Original Author's honor and reputation, the Licensor will waive
+# or not assert, as appropriate, this Section, to the fullest extent
+# permitted by the applicable national law, to enable You to
+# reasonably exercise Your right under Section 3(b) of this License
+# (right to make Adaptations) but not otherwise.
+#
+# *5. Representations, Warranties and Disclaimer*
+#
+# UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR
+# OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY
+# KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,
+# INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF
+# LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS,
+# WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE
+# EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
+#
+# *6. Limitation on Liability.* EXCEPT TO THE EXTENT REQUIRED BY
+# APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL
+# THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY
+# DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF
+# LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+#
+# *7. Termination*
+#
+# 1. This License and the rights granted hereunder will terminate
+# automatically upon any breach by You of the terms of this License.
+# Individuals or entities who have received Adaptations or Collections
+# from You under this License, however, will not have their licenses
+# terminated provided such individuals or entities remain in full
+# compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
+# survive any termination of this License.
+# 2. Subject to the above terms and conditions, the license granted here
+# is perpetual (for the duration of the applicable copyright in the
+# Work). Notwithstanding the above, Licensor reserves the right to
+# release the Work under different license terms or to stop
+# distributing the Work at any time; provided, however that any such
+# election will not serve to withdraw this License (or any other
+# license that has been, or is required to be, granted under the terms
+# of this License), and this License will continue in full force and
+# effect unless terminated as stated above.
+#
+# *8. Miscellaneous*
+#
+# 1. Each time You Distribute or Publicly Perform the Work or a
+# Collection, the Licensor offers to the recipient a license to the
+# Work on the same terms and conditions as the license granted to You
+# under this License.
+# 2. Each time You Distribute or Publicly Perform an Adaptation, Licensor
+# offers to the recipient a license to the original Work on the same
+# terms and conditions as the license granted to You under this License.
+# 3. If any provision of this License is invalid or unenforceable under
+# applicable law, it shall not affect the validity or enforceability
+# of the remainder of the terms of this License, and without further
+# action by the parties to this agreement, such provision shall be
+# reformed to the minimum extent necessary to make such provision
+# valid and enforceable.
+# 4. No term or provision of this License shall be deemed waived and no
+# breach consented to unless such waiver or consent shall be in
+# writing and signed by the party to be charged with such waiver or
+# consent.
+# 5. This License constitutes the entire agreement between the parties
+# with respect to the Work licensed here. There are no understandings,
+# agreements or representations with respect to the Work not specified
+# here. Licensor shall not be bound by any additional provisions that
+# may appear in any communication from You. This License may not be
+# modified without the mutual written agreement of the Licensor and You.
+# 6. The rights granted under, and the subject matter referenced, in this
+# License were drafted utilizing the terminology of the Berne
+# Convention for the Protection of Literary and Artistic Works (as
+# amended on September 28, 1979), the Rome Convention of 1961, the
+# WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms
+# Treaty of 1996 and the Universal Copyright Convention (as revised on
+# July 24, 1971). These rights and subject matter take effect in the
+# relevant jurisdiction in which the License terms are sought to be
+# enforced according to the corresponding provisions of the
+# implementation of those treaty provisions in the applicable national
+# law. If the standard suite of rights granted under applicable
+# copyright law includes additional rights not granted under this
+# License, such additional rights are deemed to be included in the
+# License; this License is not intended to restrict the license of any
+# rights under applicable law.
+accellerare->accelerare
+acellerare->accelerare
+accellerata->accelerata
+accellerato->accelerato
+accellerazione->accelerazione
+aereonautica->aeronautica
+aereoporti->aeroporti
+aereoporto->aeroporto
+aereosilurante->aerosilurante
+aereosiluranti->aerosiluranti
+affianco->a fianco
+affilliate->affiliate
+aggiottaggio->aggiotaggio
+aggresive->aggressive
+agravate->aggravate
+alse->else
+appropiata->appropriata
+appropiate->appropriate
+appropiati->appropriati
+appropiato->appropriato
+approposito->a proposito
+appropraite->appropriate
+appropropiate->appropriate
+approvigionamento->approvvigionamento
+apropriate->appropriate
+areazione->aerazione
+areoporti->aeroporti
+areoporto->aeroporto
+assisnate->assassinate
+assit->assist
+asume->assume
+audeince->audience
+austrailia->Australia
+automibile->automobile
+avvallo->avallo
+backgorund->background
+backrounds->backgrounds
+benchè->benché
+Bernouilli->Bernoulli
+biricchino->birichino
+bizzare->bizzarre
+Buddah->Buddha
+buisness->business
+busness->business
+bussiness->business
+caffé->caffè
+Caltanisetta->Caltanissetta
+Cambrige->Cambridge
+candadate->candidate
+candiate->candidate
+candidiate->candidate
+casette->cassette
+Celcius->Celsius
+Champange->Champagne
+cioé->cioè
+ciriculum->curriculum
+cmoputer->computer
+coctail->cocktail
+coefficente->coefficiente
+coefficenti->coefficienti
+collaberative->collaborative
+collutazione->colluttazione
+commemerative->commemorative
+commemmorate->commemorate
+comparitive->comparative
+competative->competitive
+competive->competitive
+comprimise->compromise
+compropietari->comproprietari
+compropietaria->comproprietaria
+compropietarie->comproprietarie
+compropietario->comproprietario
+Conneticut->Connecticut
+conosciente->conoscente
+conoscienti->conoscenti
+conoscienza->conoscenza
+consectutive->consecutive
+consentrate->concentrate
+conservitive->conservative
+consolodate->consolidate
+contaiminate->contaminate
+contendor->contender
+coputer->computer
+copywrite->copyright
+corelate->correlate
+correzzione->correzione
+coscente->cosciente
+coscenti->coscienti
+coscenza->coscienza
+cosi->così
+cosidetto->cosiddetto
+cumulatative->cumulative
+curch->church
+curriculem->curriculum
+dasse->desse
+decomposit->decompose
+deficente->deficiente
+deficenti->deficienti
+deficenza->deficienza
+definate->definite
+derivitive->derivative
+deside->decide
+desktiop->desktop
+deteriate->deteriorate
+devide->divide
+diminuitive->diminutive
+dispence->dispense
+doesnt->doesn't
+dosen't->doesn't
+drnik->drink
+dupicate->duplicate
+E'->È
+É->È
+etc.->ecc.
+eccezzionale->eccezionale
+eccezzionali->eccezionali
+eccezzione->eccezione
+ect->etc
+eminate->emanate
+enduce->induce
+esle->else
+esterefatto->esterrefatto
+faciliate->facilitate
+facillitate->facilitate
+Farenheit->Fahrenheit
+fianite->finite
+foootball->football
+foucs->focus
+Gameboy->Game Boy
+ganerate->generate
+Ghandi->Gandhi
+gia->già
+gia'->già
+giacchè->giacché
+giaccue->giacque
+grafitti->graffiti
+Guilia->Giulia
+Guilio->Giulio
+Guiness->Guinness
+Guiseppe->Giuseppe
+halp->help
+hapening->happening
+hertzs->hertz
+imcomplete->incomplete
+imense->immense
+immitate->imitate
+inappropiate->inappropriate
+includ->include
+incoscente->incosciente
+incoscenti->incoscienti
+incoscenza->incoscienza
+inctroduce->introduce
+indulgue->indulge
+infilitrate->infiltrate
+infinit->infinite
+ingegniere->ingegnere
+innoquo->innocuo
+inpolite->impolite
+inquanto->in quanto
+insufficente->insufficiente
+insufficenti->insufficienti
+insufficenza->insufficienza
+interm->interim
+interrim->interim
+intutive->intuitive
+investingate->investigate
+iunior->junior
+knwo->know
+konw->know
+kwno->know
+levetate->levitate
+loev->love
+lveo->love
+lvoe->love
+Macchiavelli->Machiavelli
+maggiorparte->maggior parte
+magolia->magnolia
+managment->management
+marketting->marketing
+Massachussets->Massachusetts
+Massachussetts->Massachusetts
+medacine->medicine
+mercentile->mercantile
+messanger->messenger
+metereologia->meteorologia
+metereologico->meteorologico
+Michagan->Michigan
+minature->miniature
+misile->missile
+Misouri->Missouri
+Missisipi->Mississippi
+Missisippi->Mississippi
+missle->missile
+moderm->modem
+modle->model
+Monserrat->Montserrat
+mroe->more
+muscial->musical
+mussulmano->musulmano
+naturual->natural
+Nazereth->Nazareth
+necessiate->necessitate
+nkow->know
+nkwo->know
+noveau->nouveau
+ocuntry->country
+omlette->omelette
+omre->more
+onniscente->onnisciente
+onniscenti->onniscienti
+onoreficenze->onorificenze
+onyl->only
+ovverossia->ovverosia
+pallete->palette
+pantomine->pantomime
+pary->party
+penatly->penalty
+perchè->perché
+perche'->perché
+percui->per cui
+performence->performance
+pero'->però
+perogative->prerogative
+peronospera->peronospora
+piu->più
+piu'->più
+plateu->plateau
+pò->po'
+poiche'->poiché
+poichè->poiché
+preceed->precede
+pressocche'->pressoché
+pressocché->pressoché
+preverse->perverse
+primative->primitive
+privte->private
+proceedure->procedure
+processer->processor
+profesor->professor
+professer->professor
+proffesed->professed
+proffesor->professor
+profiquo->proficuo
+proove->prove
+propietà->proprietà
+propietari->proprietari
+propietaria->proprietaria
+propietarie->proprietarie
+propietario->proprietario
+propio->proprio
+propoganda->propaganda
+propogate->propagate
+prospicente->prospiciente
+prospicenti->prospicienti
+provacative->provocative
+psuedo->pseudo
+Pucini->Puccini
+pursuade->persuade
+pwoer->power
+recrod->record
+redarre->redigere
+refedendum->referendum
+rela->real
+riconosciente->riconoscente
+riconoscienti->riconoscenti
+riconoscienza->riconoscenza
+rocord->record
+rubgy->rugby
+sandwhich->sandwich
+satelite->satellite
+sattelite->satellite
+scandanavia->Scandinavia
+scenza->scienza
+scenze->scienze
+scirpt->script
+se'->sé
+sè->sé
+sensa->senza
+senstive->sensitive
+sensure->censure
+senzo->senso
+smoe->some
+soem->some
+sofware->software
+sohw->show
+sopratutto->soprattutto
+soudn->sound
+speci->specie
+spoace->space
+sponser->sponsor
+staion->station
+stasse->stesse
+stong->strong
+stpo->stop
+strazzio->strazio
+su'->sù
+succesiva->successiva
+succesive->successive
+succesivi->successivi
+succesivo->successivo
+sucessiva->successiva
+sucessive->successive
+sucessivi->successivi
+sucessivo->successivo
+sufficente->sufficiente
+sufficenti->sufficienti
+sufficenza->sufficienza
+sytem->system
+tast->taste
+té->tè
+tghe->the
+timne->time
+tje->the
+tjhe->the
+transare->transigere
+tremelo->tremolo
+troup->troupe
+tust->trust
+vadino->vadano
+valetta->valletta
+ventitrè->ventitré
+vicere->viceré
+zeebra->zebra
diff --git a/files/typos-nb.txt b/files/typos/typos-nb.txt
index a662d9a..1043627 100644
--- a/files/typos-nb.txt
+++ b/files/typos/typos-nb.txt
@@ -3,6 +3,7 @@ andriod->android
# The remainder of this file contains misspellings from
# http://no.wikipedia.org/wiki/Wikipedia:Liste_over_alminnelige_stavefeil/Maskinform
+# plus some post-processing to fix invalid entries, remove duplicates, etc.
#
# The content is available under the
# "Creative Commons Attribution-ShareAlike License"
@@ -445,4 +446,4 @@ underholdene->underholdende
vakum->vakuum
viderekommende->viderekomne
værre->verre
-værste->verste \ No newline at end of file
+værste->verste
diff --git a/files/typos/typos-pt.txt b/files/typos/typos-pt.txt
new file mode 100644
index 0000000..6285d37
--- /dev/null
+++ b/files/typos/typos-pt.txt
@@ -0,0 +1,1647 @@
+# This file contains a number of common Portuguese typos:
+andriod->android
+
+# The remainder of this file contains misspellings from
+# http://pt.wikipedia.org/wiki/Wikip%C3%A9dia:Software/Anti-vandal_tool/Ortografia
+# plus some post-processing to fix invalid entries, remove duplicates, etc.
+#
+# The content is available under the
+# "Creative Commons Attribution-ShareAlike License"
+# http://creativecommons.org/licenses/by-sa/3.0/
+#
+# THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
+# COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
+# COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
+# AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
+#
+# BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE
+# TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY
+# BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS
+# CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
+# CONDITIONS.
+#
+# *1. Definitions*
+#
+# 1. *"Adaptation"* means a work based upon the Work, or upon the Work
+# and other pre-existing works, such as a translation, adaptation,
+# derivative work, arrangement of music or other alterations of a
+# literary or artistic work, or phonogram or performance and includes
+# cinematographic adaptations or any other form in which the Work may
+# be recast, transformed, or adapted including in any form
+# recognizably derived from the original, except that a work that
+# constitutes a Collection will not be considered an Adaptation for
+# the purpose of this License. For the avoidance of doubt, where the
+# Work is a musical work, performance or phonogram, the
+# synchronization of the Work in timed-relation with a moving image
+# ("synching") will be considered an Adaptation for the purpose of
+# this License.
+# 2. *"Collection"* means a collection of literary or artistic works,
+# such as encyclopedias and anthologies, or performances, phonograms
+# or broadcasts, or other works or subject matter other than works
+# listed in Section 1(f) below, which, by reason of the selection and
+# arrangement of their contents, constitute intellectual creations, in
+# which the Work is included in its entirety in unmodified form along
+# with one or more other contributions, each constituting separate and
+# independent works in themselves, which together are assembled into a
+# collective whole. A work that constitutes a Collection will not be
+# considered an Adaptation (as defined below) for the purposes of this
+# License.
+# 3. *"Creative Commons Compatible License"* means a license that is
+# listed at http://creativecommons.org/compatiblelicenses that has
+# been approved by Creative Commons as being essentially equivalent to
+# this License, including, at a minimum, because that license: (i)
+# contains terms that have the same purpose, meaning and effect as the
+# License Elements of this License; and, (ii) explicitly permits the
+# relicensing of adaptations of works made available under that
+# license under this License or a Creative Commons jurisdiction
+# license with the same License Elements as this License.
+# 4. *"Distribute"* means to make available to the public the original
+# and copies of the Work or Adaptation, as appropriate, through sale
+# or other transfer of ownership.
+# 5. *"License Elements"* means the following high-level license
+# attributes as selected by Licensor and indicated in the title of
+# this License: Attribution, ShareAlike.
+# 6. *"Licensor"* means the individual, individuals, entity or entities
+# that offer(s) the Work under the terms of this License.
+# 7. *"Original Author"* means, in the case of a literary or artistic
+# work, the individual, individuals, entity or entities who created
+# the Work or if no individual or entity can be identified, the
+# publisher; and in addition (i) in the case of a performance the
+# actors, singers, musicians, dancers, and other persons who act,
+# sing, deliver, declaim, play in, interpret or otherwise perform
+# literary or artistic works or expressions of folklore; (ii) in the
+# case of a phonogram the producer being the person or legal entity
+# who first fixes the sounds of a performance or other sounds; and,
+# (iii) in the case of broadcasts, the organization that transmits the
+# broadcast.
+# 8. *"Work"* means the literary and/or artistic work offered under the
+# terms of this License including without limitation any production in
+# the literary, scientific and artistic domain, whatever may be the
+# mode or form of its expression including digital form, such as a
+# book, pamphlet and other writing; a lecture, address, sermon or
+# other work of the same nature; a dramatic or dramatico-musical work;
+# a choreographic work or entertainment in dumb show; a musical
+# composition with or without words; a cinematographic work to which
+# are assimilated works expressed by a process analogous to
+# cinematography; a work of drawing, painting, architecture,
+# sculpture, engraving or lithography; a photographic work to which
+# are assimilated works expressed by a process analogous to
+# photography; a work of applied art; an illustration, map, plan,
+# sketch or three-dimensional work relative to geography, topography,
+# architecture or science; a performance; a broadcast; a phonogram; a
+# compilation of data to the extent it is protected as a copyrightable
+# work; or a work performed by a variety or circus performer to the
+# extent it is not otherwise considered a literary or artistic work.
+# 9. *"You"* means an individual or entity exercising rights under this
+# License who has not previously violated the terms of this License
+# with respect to the Work, or who has received express permission
+# from the Licensor to exercise rights under this License despite a
+# previous violation.
+# 10. *"Publicly Perform"* means to perform public recitations of the Work
+# and to communicate to the public those public recitations, by any
+# means or process, including by wire or wireless means or public
+# digital performances; to make available to the public Works in such
+# a way that members of the public may access these Works from a place
+# and at a place individually chosen by them; to perform the Work to
+# the public by any means or process and the communication to the
+# public of the performances of the Work, including by public digital
+# performance; to broadcast and rebroadcast the Work by any means
+# including signs, sounds or images.
+# 11. *"Reproduce"* means to make copies of the Work by any means
+# including without limitation by sound or visual recordings and the
+# right of fixation and reproducing fixations of the Work, including
+# storage of a protected performance or phonogram in digital form or
+# other electronic medium.
+#
+# *2. Fair Dealing Rights.* Nothing in this License is intended to reduce,
+# limit, or restrict any uses free from copyright or rights arising from
+# limitations or exceptions that are provided for in connection with the
+# copyright protection under copyright law or other applicable laws.
+#
+# *3. License Grant.* Subject to the terms and conditions of this License,
+# Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
+# perpetual (for the duration of the applicable copyright) license to
+# exercise the rights in the Work as stated below:
+#
+# 1. to Reproduce the Work, to incorporate the Work into one or more
+# Collections, and to Reproduce the Work as incorporated in the
+# Collections;
+# 2. to create and Reproduce Adaptations provided that any such
+# Adaptation, including any translation in any medium, takes
+# reasonable steps to clearly label, demarcate or otherwise identify
+# that changes were made to the original Work. For example, a
+# translation could be marked "The original work was translated from
+# English to Spanish," or a modification could indicate "The original
+# work has been modified.";
+# 3. to Distribute and Publicly Perform the Work including as
+# incorporated in Collections; and,
+# 4. to Distribute and Publicly Perform Adaptations.
+# 5.
+#
+# For the avoidance of doubt:
+#
+# 1. *Non-waivable Compulsory License Schemes*. In those
+# jurisdictions in which the right to collect royalties through
+# any statutory or compulsory licensing scheme cannot be waived,
+# the Licensor reserves the exclusive right to collect such
+# royalties for any exercise by You of the rights granted under
+# this License;
+# 2. *Waivable Compulsory License Schemes*. In those jurisdictions in
+# which the right to collect royalties through any statutory or
+# compulsory licensing scheme can be waived, the Licensor waives
+# the exclusive right to collect such royalties for any exercise
+# by You of the rights granted under this License; and,
+# 3. *Voluntary License Schemes*. The Licensor waives the right to
+# collect royalties, whether individually or, in the event that
+# the Licensor is a member of a collecting society that
+# administers voluntary licensing schemes, via that society, from
+# any exercise by You of the rights granted under this License.
+#
+# The above rights may be exercised in all media and formats whether now
+# known or hereafter devised. The above rights include the right to make
+# such modifications as are technically necessary to exercise the rights
+# in other media and formats. Subject to Section 8(f), all rights not
+# expressly granted by Licensor are hereby reserved.
+#
+# *4. Restrictions.* The license granted in Section 3 above is expressly
+# made subject to and limited by the following restrictions:
+#
+# 1. You may Distribute or Publicly Perform the Work only under the terms
+# of this License. You must include a copy of, or the Uniform Resource
+# Identifier (URI) for, this License with every copy of the Work You
+# Distribute or Publicly Perform. You may not offer or impose any
+# terms on the Work that restrict the terms of this License or the
+# ability of the recipient of the Work to exercise the rights granted
+# to that recipient under the terms of the License. You may not
+# sublicense the Work. You must keep intact all notices that refer to
+# this License and to the disclaimer of warranties with every copy of
+# the Work You Distribute or Publicly Perform. When You Distribute or
+# Publicly Perform the Work, You may not impose any effective
+# technological measures on the Work that restrict the ability of a
+# recipient of the Work from You to exercise the rights granted to
+# that recipient under the terms of the License. This Section 4(a)
+# applies to the Work as incorporated in a Collection, but this does
+# not require the Collection apart from the Work itself to be made
+# subject to the terms of this License. If You create a Collection,
+# upon notice from any Licensor You must, to the extent practicable,
+# remove from the Collection any credit as required by Section 4(c),
+# as requested. If You create an Adaptation, upon notice from any
+# Licensor You must, to the extent practicable, remove from the
+# Adaptation any credit as required by Section 4(c), as requested.
+# 2. You may Distribute or Publicly Perform an Adaptation only under the
+# terms of: (i) this License; (ii) a later version of this License
+# with the same License Elements as this License; (iii) a Creative
+# Commons jurisdiction license (either this or a later license
+# version) that contains the same License Elements as this License
+# (e.g., Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons
+# Compatible License. If you license the Adaptation under one of the
+# licenses mentioned in (iv), you must comply with the terms of that
+# license. If you license the Adaptation under the terms of any of the
+# licenses mentioned in (i), (ii) or (iii) (the "Applicable License"),
+# you must comply with the terms of the Applicable License generally
+# and the following provisions: (I) You must include a copy of, or the
+# URI for, the Applicable License with every copy of each Adaptation
+# You Distribute or Publicly Perform; (II) You may not offer or impose
+# any terms on the Adaptation that restrict the terms of the
+# Applicable License or the ability of the recipient of the Adaptation
+# to exercise the rights granted to that recipient under the terms of
+# the Applicable License; (III) You must keep intact all notices that
+# refer to the Applicable License and to the disclaimer of warranties
+# with every copy of the Work as included in the Adaptation You
+# Distribute or Publicly Perform; (IV) when You Distribute or Publicly
+# Perform the Adaptation, You may not impose any effective
+# technological measures on the Adaptation that restrict the ability
+# of a recipient of the Adaptation from You to exercise the rights
+# granted to that recipient under the terms of the Applicable License.
+# This Section 4(b) applies to the Adaptation as incorporated in a
+# Collection, but this does not require the Collection apart from the
+# Adaptation itself to be made subject to the terms of the Applicable
+# License.
+# 3. If You Distribute, or Publicly Perform the Work or any Adaptations
+# or Collections, You must, unless a request has been made pursuant to
+# Section 4(a), keep intact all copyright notices for the Work and
+# provide, reasonable to the medium or means You are utilizing: (i)
+# the name of the Original Author (or pseudonym, if applicable) if
+# supplied, and/or if the Original Author and/or Licensor designate
+# another party or parties (e.g., a sponsor institute, publishing
+# entity, journal) for attribution ("Attribution Parties") in
+# Licensor's copyright notice, terms of service or by other reasonable
+# means, the name of such party or parties; (ii) the title of the Work
+# if supplied; (iii) to the extent reasonably practicable, the URI, if
+# any, that Licensor specifies to be associated with the Work, unless
+# such URI does not refer to the copyright notice or licensing
+# information for the Work; and (iv) , consistent with Ssection 3(b),
+# in the case of an Adaptation, a credit identifying the use of the
+# Work in the Adaptation (e.g., "French translation of the Work by
+# Original Author," or "Screenplay based on original Work by Original
+# Author"). The credit required by this Section 4(c) may be
+# implemented in any reasonable manner; provided, however, that in the
+# case of a Adaptation or Collection, at a minimum such credit will
+# appear, if a credit for all contributing authors of the Adaptation
+# or Collection appears, then as part of these credits and in a manner
+# at least as prominent as the credits for the other contributing
+# authors. For the avoidance of doubt, You may only use the credit
+# required by this Section for the purpose of attribution in the
+# manner set out above and, by exercising Your rights under this
+# License, You may not implicitly or explicitly assert or imply any
+# connection with, sponsorship or endorsement by the Original Author,
+# Licensor and/or Attribution Parties, as appropriate, of You or Your
+# use of the Work, without the separate, express prior written
+# permission of the Original Author, Licensor and/or Attribution Parties.
+# 4. Except as otherwise agreed in writing by the Licensor or as may be
+# otherwise permitted by applicable law, if You Reproduce, Distribute
+# or Publicly Perform the Work either by itself or as part of any
+# Adaptations or Collections, You must not distort, mutilate, modify
+# or take other derogatory action in relation to the Work which would
+# be prejudicial to the Original Author's honor or reputation.
+# Licensor agrees that in those jurisdictions (e.g. Japan), in which
+# any exercise of the right granted in Section 3(b) of this License
+# (the right to make Adaptations) would be deemed to be a distortion,
+# mutilation, modification or other derogatory action prejudicial to
+# the Original Author's honor and reputation, the Licensor will waive
+# or not assert, as appropriate, this Section, to the fullest extent
+# permitted by the applicable national law, to enable You to
+# reasonably exercise Your right under Section 3(b) of this License
+# (right to make Adaptations) but not otherwise.
+#
+# *5. Representations, Warranties and Disclaimer*
+#
+# UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR
+# OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY
+# KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,
+# INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF
+# LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS,
+# WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE
+# EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
+#
+# *6. Limitation on Liability.* EXCEPT TO THE EXTENT REQUIRED BY
+# APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL
+# THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY
+# DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF
+# LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+#
+# *7. Termination*
+#
+# 1. This License and the rights granted hereunder will terminate
+# automatically upon any breach by You of the terms of this License.
+# Individuals or entities who have received Adaptations or Collections
+# from You under this License, however, will not have their licenses
+# terminated provided such individuals or entities remain in full
+# compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
+# survive any termination of this License.
+# 2. Subject to the above terms and conditions, the license granted here
+# is perpetual (for the duration of the applicable copyright in the
+# Work). Notwithstanding the above, Licensor reserves the right to
+# release the Work under different license terms or to stop
+# distributing the Work at any time; provided, however that any such
+# election will not serve to withdraw this License (or any other
+# license that has been, or is required to be, granted under the terms
+# of this License), and this License will continue in full force and
+# effect unless terminated as stated above.
+#
+# *8. Miscellaneous*
+#
+# 1. Each time You Distribute or Publicly Perform the Work or a
+# Collection, the Licensor offers to the recipient a license to the
+# Work on the same terms and conditions as the license granted to You
+# under this License.
+# 2. Each time You Distribute or Publicly Perform an Adaptation, Licensor
+# offers to the recipient a license to the original Work on the same
+# terms and conditions as the license granted to You under this License.
+# 3. If any provision of this License is invalid or unenforceable under
+# applicable law, it shall not affect the validity or enforceability
+# of the remainder of the terms of this License, and without further
+# action by the parties to this agreement, such provision shall be
+# reformed to the minimum extent necessary to make such provision
+# valid and enforceable.
+# 4. No term or provision of this License shall be deemed waived and no
+# breach consented to unless such waiver or consent shall be in
+# writing and signed by the party to be charged with such waiver or
+# consent.
+# 5. This License constitutes the entire agreement between the parties
+# with respect to the Work licensed here. There are no understandings,
+# agreements or representations with respect to the Work not specified
+# here. Licensor shall not be bound by any additional provisions that
+# may appear in any communication from You. This License may not be
+# modified without the mutual written agreement of the Licensor and You.
+# 6. The rights granted under, and the subject matter referenced, in this
+# License were drafted utilizing the terminology of the Berne
+# Convention for the Protection of Literary and Artistic Works (as
+# amended on September 28, 1979), the Rome Convention of 1961, the
+# WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms
+# Treaty of 1996 and the Universal Copyright Convention (as revised on
+# July 24, 1971). These rights and subject matter take effect in the
+# relevant jurisdiction in which the License terms are sought to be
+# enforced according to the corresponding provisions of the
+# implementation of those treaty provisions in the applicable national
+# law. If the standard suite of rights granted under applicable
+# copyright law includes additional rights not granted under this
+# License, such additional rights are deemed to be included in the
+# License; this License is not intended to restrict the license of any
+# rights under applicable law.
+a a->a
+à cavalo->a cavalo
+a muito tempo->há muito tempo
+à muito tempo->há muito tempo
+a nível de->em nível de, ao nível de
+à pé->a pé
+aandeija->bandeja
+abitual->habitual
+acêrca->acerca
+àcerca->acerca
+acessiveis->acessíveis
+acessivel->acessível
+acessor->assessor
+acessora->assessora
+acessoras->assessoras
+acessores->assessores
+acessoria->assessoria
+acessorio->acessório
+acessorios->acessórios
+acesssada->acessada
+acesssadas->acessadas
+acesssado->acessado
+acesssados->acessados
+açoes->acções
+aconselhaveis->aconselháveis
+aconselhavel->aconselhável
+açoreana->açoriana
+açoreanas->açorianas
+açoreano->açoriano
+açoreanos->açorianos
+actris->atriz
+açucar ->açúcar
+acustica->acústica
+acusticas->acústicas
+acustico->acústico
+acusticos->acústicos
+adimite->admite
+adimitir->admitir
+adimitiram->admitiram
+adimitiu->admitiu
+admnistração->administração
+admnistrar->administrar
+adolescencia->adolescência
+afim->a fim
+Africa->Ãfrica
+agencia->agência
+agradaveis->agradáveis
+agradavel->agradável
+agricola->agrícola
+agricolas->agrícolas
+agua->água
+aguas->águas
+aki->aqui
+album->álbum
+albúm->álbum
+albùm->álbum
+albums->álbuns
+albun->álbum
+albuns->álbuns
+albúns->álbuns
+albùns->álbuns
+alcolémia->alcoolemia
+alcolico->alcoólico
+alcólico->alcoólico
+alcolicos->alcoólicos
+alcólicos->alcoólicos
+alcoolémia->alcoolemia
+alcóolica->alcoólica
+alcoolico->alcoólico
+alcóolico->alcoólico
+alcoolicos->alcoólicos
+aleatorios->aleatórios
+algeriano->argelino
+algorítmo->algoritmo
+algorítmos->algoritmos
+alguem->alguém
+altoridade->autoridade
+altoridades->autoridades
+amanha->amanhã
+amargúra->amargura
+amargúria->amargura
+ambulancia->ambulância
+ambulancias->ambulâncias
+anciosa->ansiosa
+ancioso->ansioso
+anciosas->ansiosas
+anciosos->ansiosos
+anciosamente->ansiosamente
+anemona->anémona,anêmona
+anglofona->anglófona
+anglófonas->anglófonas
+anglofono->anglófono
+anglofonos->anglófonos
+angulo->ângulo
+angulos->ângulos
+anonimo->anónimo, anônimo
+antepôr->antepor
+anti aéreo->antiaéreo
+anti depressivo->antidepressivo
+anti-vírus->antivírus
+anuncio->anúncio
+ao meu ver->a meu ver
+aparencia->aparência, aparecia
+aparencias->aparências
+aplicaçao->aplicação
+Aracajú->Aracaju
+arco-iris->arco-íris
+arcoiris->arco-íris
+arcoíris->arco-íris
+areas->áreas
+argerino->argelino
+aristocratica->aristocrática
+aristocraticas->aristocráticas
+aristocratico->aristocrático
+aristocraticos->aristocráticos
+armonia->harmonia
+arquipelago->arquipélago
+arquipelagos->arquipélagos
+arquipelogo->arquipélago
+artistica->artística
+artisticas->artísticas
+artistico->artístico
+artisticos->artísticos
+ascençao->ascensão
+ascenção->ascensão
+ascensao->ascensão
+Asia->Ãsia
+asiatica->asiática
+asim->assim
+assasinato->assassinato
+assistencia->assistência
+associção->associação
+aste->haste
+ateismo->ateísmo
+aterisagem->aterrissagem
+aterissagem->aterrissagem
+aterrisagem->aterrissagem
+aterrizagem->aterrissagem
+atras->atrás
+atraves->através
+atravez->através
+atravéz->através
+atraz->atrás
+atráz->atrás
+atribuida->atribuída
+atribuidas->atribuídas
+atribuido->atribuído
+atribuidos->atribuídos
+atris->atriz, actriz, atris
+audiencia->audiência
+audiencias->audiências
+ausencia->ausência
+ausencias->ausências
+autentica->autêntica
+autenticas->autênticas
+autentico->autêntico
+autenticos->autênticos
+automoveis->automóveis
+automovel->automóvel
+autonoma->autónoma, autônoma
+autonomas->autónomas, autônomas
+autonomo->autónomo, autônomo
+autonomos->autónomos, autônomos
+autopsia->autópsia
+aver->haver
+aviacao->aviação
+aviacão->aviação
+aviasão->aviação
+avogrado->Avogadro
+avulsso->avulso
+azaléia->azaléa
+azas->asas
+bahiana->baiana
+bahiano->baiano
+baínha->bainha
+baínhas->bainhas
+banca-rota->bancarrota
+banca-rrota->bancarrota
+bancarota->bancarrota
+barbarie->barbárie
+barbaries->barbáries
+bébe->bebé
+bébé->bebé
+bébes->bebés
+bébés->bebés
+beige->bege
+beiges->beges
+beije->bege
+beijes->beges
+bem vindo->bem-vindo
+benção->bênção
+bençãos->bênçãos
+beneficencia->beneficência
+beneficio->benefício
+beneficios->benefícios
+benvindo->bem-vindo
+Bertold Brecht->Bertolt Brecht
+bevocar->invocar
+bi-campeão->bicampeão
+bibliografica->bibliográfica
+bibliograficas->bibliográficas
+bibliografico->bibliográfico
+bibliograficos->bibliográficos
+biografico->biográfico
+biograficos->biográficos
+biograifa->biografia
+biograifas->biografias
+biópsia->biopsia
+biópsias->biopsias
+boas vindas->Boas-vindas
+boeiro->bueiro
+borburinho->burburinho
+brasao->brasão
+brazão->brasão
+Brazil->Brasil
+britanico->britânico
+burborinho->burburinho
+bussula->bússola
+cadaço->cadarço
+caiem->caem
+calsado->calçado
+calvice->calvície
+calvíce->calvície
+camara->câmara
+camera->câmera
+caminhoes->caminhões, camiões
+camioes->camiões, caminhões
+campeao->campeão
+campeoes->campeões
+campiao->campeão
+campião->campeão
+campioes->campeões
+campiões->campeões
+campionato->campeonato
+campionatos->campeonatos
+cançao->canção
+cansão->canção
+capitão mor->capitão-mor
+capitulo->capítulo
+capitulos->capítulos
+caracteristica->característica
+caracteristicas->características
+caracteristico->característico
+caracteristicos->característicos
+carissimo->caríssimo
+cassar->caçar, casar, cassar
+catalizador->catalisador
+catalogo->catálogo
+catalogos->catálogos
+catequisador->catequizador
+catequisar->catequizar
+cazamento->casamento
+cazar->casar
+cazara->casara
+cazaram->casaram
+cazou->casou
+Ceara->Ceará
+celebro->cérebro
+cemiterio->cemitério
+cemiterios->cemitérios
+cenario->cenário
+cenarios->cenários
+cerebro->cérebro
+cerebros->cérebros
+chopp->chope
+ciclano->sicrano
+cidadães->cidadãos
+cidadões->cidadãos
+ciencia->ciência
+ciencias->ciências
+cientifica->científica
+cientificas->científicas
+cientifico->científico
+cientificos->científicos
+circulo->círculo
+circulos->círculos
+classica->clássica
+classicas->clássicas
+classico->clássico
+classicos->clássicos
+clinica->clínica
+cms->cm
+co-habitação->coabitação
+coalisão->coalizão
+côco->coco
+coerencia->coerência
+coerencias->coerências
+cohabitação->coabitação
+comcerteza->com certeza
+comecou->começou
+comedia->comédia
+comercio->comércio
+comercios->comércios
+comisão->comissão
+comisoes->comissões
+comisões->comissões
+comissao->comissão
+comnosco->connosco
+compôr->compor
+compreenção->compreensão
+compreenções->compreensões
+compreenssão->compreensão
+compreenssões->compreensões
+concerteza->com certeza
+conciderada->considerada
+concideradas->consideradas
+conciderado->considerado
+conciderados->considerados
+concluíndo->concluindo
+concretisar->concretizar
+condiçao->condição
+condissao->condição
+condissão->condição
+conseguírem->conseguirem
+constituia->constituía
+constituiam->constituíam
+constituiram->constituíram
+constroi->constrói
+construia->construía
+construida->construída
+construidas->construídas
+construido->construído
+construidos->construído
+contemporaneo->contemporâneo
+contemporaneos->contemporâneos
+contribue->contribui
+contrução->construção
+contruído->construído
+contruir->construir
+converçao->conversão
+converção->conversão
+conversao->conversão
+converssão->conversão
+côr->cor
+corçario->corsário
+côres->cores
+cornea->córnea
+corneas->córneas
+corografico->corográfico
+corograficos->corográficos
+correiro eletronico->correio electrónico, correio eletrônico
+corrijiam->corrigiam
+corrijir->corrigir
+corrijiram->corrigiram
+crâneo->crânio
+crâneos->crânios
+criaça->criança
+criacao->criação
+criaçao->criação
+criaças->crianças
+crianca->criança
+criancas->crianças
+cristianizacao->cristianização
+cristianizacão->cristianização
+cristianizacoes->cristianizações
+cristianizacões->cristianizações
+criticas->críticas
+critícas->críticas
+criticos->críticos
+critícos->críticos
+crueis->cruéis
+culinaria->culinária
+custuma->costuma
+custumava->costumava
+custumavam->costumavam
+custume->costume
+custumes->costumes
+decada->década
+decadas->décadas
+decadencia->decadência
+decadencias->decadências
+decer->descer
+deceram->desceram
+declinio->declínio
+declinios->declínios
+defeniçao->definição
+defenição->definição
+defenições->definições
+defenido->definido
+defenir->definir
+definitamente->definitivamente
+deiche->deixe
+deisponiveis->disponíveis
+deisponivel->disponível
+democratica->democrática
+demonio->demónio, demônio
+demonios->demónios, demônios
+depedente->dependente
+depedentes->dependentes
+deposito->depósito
+depositos->depósitos
+desagradaveis->desagradáveis
+desagradavel->desagradável
+descubrimento->descobrimento
+descubrimentos->descobrimentos
+descubrir->descobrir
+descubriram->descobriram
+descubrire->descobrire
+deseçeis->dezesseis
+desembro->Dezembro
+desesseis->dezesseis
+desnecessario->desnecessário
+despensaveis->dispensáveis
+despensáveis->dispensáveis
+despensavel->dispensável
+despensável->dispensável
+desprotejida->desprotegida
+desprotejidas->desprotegidas
+desprotejido->desprotegido
+desprotejidos->desprotegidos
+destruida->destruída
+devocao->devoção
+devocão->devoção
+devoçao->devoção
+diagnostico->diagnóstico
+diagnosticos->diagnósticos
+diaria->diária
+diáriamente->diariamente
+diario->diário
+dibre->drible
+diferencas->diferenças
+díficeis->difíceis
+dificil->difícil
+díficil->difícil
+dificulidade->dificuldade
+difusao->difusão
+dignatária->dignitária
+dignatárias->dignitárias
+dignatário->dignitário
+dignatários->dignitários
+dijita->digita
+dijitar->digitar
+dijitara->digitara
+dijitaram->digitaram
+dijitou->digitou
+diminue->diminui
+dinamico->dinâmico
+discuções->discussões
+discursso->discurso
+dispender->despender
+dispenderam->despenderam
+dispendio->dispêndio
+dispendios->dispêndios
+dispensaveis->dispensáveis
+dispensavel->dispensável
+disponiveis->disponíveis
+disponivel->disponível
+distribuida->distribuída
+distribuidas->distribuídas
+distribuido->distribuído
+distribuidos->distribuídos
+disturbio->distúrbio
+disturbios->distúrbios
+diverssas->diversas
+diverssos->diversos
+documentario->documentário
+documentarios->documentários
+dragao->dragão
+druída->druida
+druídas->druidas
+dsenho->desenho
+duvidas->dúvidas
+ecessão->exceção
+ecessões->exceções
+eciclopedia->enciclopédia
+eciclopédia->enciclopédia
+economica->económica, econômica
+ect->etc
+egipcios->egípcios
+egipsio->egípcio
+elacção->elação
+electrônica->electrónica, eletrônica
+electrônicas->electrónicas, eletrônicas
+electrônico->electrónico, eletrônico
+electrônicos->electrónicos, eletrônicos
+eletroima->eletroímã
+eletroimã->eletroímã
+eletronica->electrónica, eletrônica
+eletrónica->electrónica, eletrônica
+eletronicas->electrónicas, eletrônicas
+eletrónicas->electrónicas, eletrônicas
+eletronico->electrónico, eletrônico
+eletrónico->electrónico, eletrônico
+eletronicos->electrónicos, eletrônicos
+eletrónicos->electrónicos, eletrônicos
+elice->hélice
+emaili->e-mail, email, correio electrónico, correio eletrônico
+eminencia->eminência
+eminencias->eminências
+empresario->empresário
+empresarios->empresários
+enciclopedia->enciclopédia
+enciclopedias->enciclopédias
+enfase->ênfase
+enfases->ênfases
+entao->então
+entertido->entretido
+entitular->intitular
+entretando->entretanto
+entreteram->entretiveram
+entreterimento->entretenimento
+entreteu->entreteve
+epecial->especial
+epica->épica
+epicas->épicas
+epico->épico
+epicos->épicos
+eplepsia->epilepsia
+epoca->época
+epocas->épocas
+equilibrio->equilíbrio
+ernegia->energia
+erói->herói
+errupção->erupção
+escerda->esquerda
+escerdas->esquerdas
+esitaram->hesitaram
+esitou->hesitou
+especialisada->especializada
+especialisadas->especializadas
+especialisado->especializado
+especialisados->especializados
+espectativa->expectativa
+espectativas->expectativas
+esperanca->esperança
+esperancas->esperanças
+espetativa->expectativa
+espetativas->expectativas
+espirita->espírita
+espiritas->espíritas
+espirito->espírito
+espiritos->espíritos
+espulsou->expulsou
+esquesita->esquisita
+esquesitas->esquisitas
+esquesito->esquisito
+esquesitos->esquisitos
+estabelecimente->estabelecimento
+estabelecimentes->estabelecimentos
+estaçãoos->estações
+estadio->estádio
+estadios->estádios
+estao->estão
+esteje->esteja
+estinto->extinto
+estintos->extintos
+estorquir->extorquir
+estorquiram->extorquiram
+estorquiu->extorquiu
+estudio->estúdio
+estudios->estúdios
+esturquir->extorquir
+esturquiram->extorquiram
+esturquiu->extorquiu
+ethanol->etanol
+etica->ética
+eticas->éticas
+excavação->escavação
+excavar->escavar
+excessão->exceção
+exdrúxula->esdrúxula
+exdrúxulas->esdrúxulas
+exdrúxulo->esdrúxulo
+exdrúxulos->esdrúxulos
+exepto->excepto, exceto
+exercicio->exercício
+exercicios->exercícios
+exeto->exceto, excepto
+exijência->exigência
+exijências->exigências
+exitar->hesitar
+exitaram->hesitaram
+exitou->hesitou
+expectador->espectador
+expontânea->espontânea
+expontâneas->espontâneas
+expontâneo->espontâneo
+expontâneos->espontâneos
+extende-se->estende-se
+extender->estender
+extenderam->estenderam
+facil->fácil
+familia->família
+familias->famílias
+farmaceutica->farmacêutica
+farmaceuticas->farmacêuticas
+farmaceutico->farmacêutico
+farmaceuticos->farmacêuticos
+faser->fazer
+fecula->fécula
+fémea->fêmea
+femeninismo->femininismo
+femeninismos->femininismos
+femenino->feminino
+femeninos->femininos
+ferverosos->fervorosos
+fimeninismo->femininismo
+fimeninismos->femininismos
+fimenino->feminino
+fimeninos->femininos
+Finlandia->finlândia
+fisica->física
+fizestes->fizeste
+flôr->flor
+flôres->flores
+flôrs->flores
+fluído->fluido
+fluídos->fluidos
+forão->foram
+fortuíto->fortuito
+fortuítos->fortuitos
+fotografica->fotográfica
+frageis->frágeis
+fragil->frágil
+Frankstein->Frankenstein
+funeraria->funerária
+funerarias->funerárias
+funerario->funerário
+funerarios->funerários
+furá->furar
+furacao->furacão
+furacoes->furacões
+galaxia->galáxia
+gas->gás
+gaz->gás
+gáz->gás
+geito->jeito
+geneceu->gineceu
+generico->genérico
+genericos->genéricos
+genero->género
+generos->géneros
+genio->génio, gênio
+geometrica->geométrico
+geometricas->geométricos
+geometrico->geométrico
+geometricos->geométricos
+gipe->jipe
+gipes->jipes
+giria->gíria
+girias->gírias
+giroscopico->giroscópio
+giroscopio->giroscópio
+gorgeta->gorjeta
+gorgetas->gorjetas
+Grã Bretanha->Grã-Bretanha
+graca->graça
+gracas->graças
+grafico->gráfico
+graficos->gráficos
+grangear->granjear
+gratuíto->gratuito
+gratuítos->gratuitos
+grau centigrado->grau Celsius
+grau centígrado->grau Celsius
+grau centígrados->grau Celsius
+grau kelvin->kelvin
+guizar->guisar
+hà->há
+hambiente->ambiente
+hambientes->ambientes
+haviam muitos->havia muitos
+haviam poucos->havia poucos
+hectar->hectare
+heraldica->heráldica
+heraldico->heráldico
+heranca->herança
+Herodoto->Heródoto
+heróico->heroico
+hexa-campeão->hexacampeão
+hilariedade->hilaridade
+historia->história
+historica->histórica
+historicas->históricas
+historico->histórico
+historicos->históricos
+homosexual->homossexual
+homosexualidade->homossexualidade
+horario->horário
+horarios->horários
+hoxigenio->oxigênio
+hoxigênio->oxigênio
+humoristica->humorística
+humoristico->humorístico
+ideología->ideologia
+idolo->ídolo
+idolos->ídolos
+igiene->higiene
+igienico->higiênico
+iguasu->Iguaçu
+ilacção->ilação
+imenência->iminência
+imenente->iminente
+imoveis->imóveis
+imovel->imóvel
+imperio->império
+imperios->impérios
+importancia->importância
+importancias->importâncias
+impresa->empresa
+imuno-deficiência->imunodeficiência
+imuno-deficiências->imunodeficiências
+incluiam->incluíam
+inclusivé->inclusive
+indefenição->indefinição
+indefenições->indefinições
+indefenir->indefinir
+indentidade->identidade
+indentidades->identidades
+India->Ãndia
+indice->índice
+indigena->indígena
+indiguinação->indignação
+indiguinado->indignado
+indiguinar->indignar
+indioma->idioma
+indiomas->idiomas
+individada->endividada
+individadas->endividadas
+individado->endividado
+individados->endividados
+individuo->indivíduo
+individuos->indivíduos
+inedita->inédita
+ineditas->inéditas
+inedito->inédito
+ineditos->inéditos
+infancia->infância
+infelismente->infelizmente
+inflacção->inflação
+infra vermelho->infravermelho
+infra vermelhos->infravermelhos
+infra-vermelho->infravermelho
+infra-vermelhos->infravermelhos
+ingenuo->ingénuo
+ingles->inglês
+inglêsa->inglesa
+inglêsas->inglesas
+inglêses->ingleses
+ingreja->igreja
+inícia->inicia
+inicio->início
+inicios->inícios
+inteligencia->inteligência
+inteligencias->inteligências
+intensão->intenção
+intertido->entretido
+intervemos->intervimos
+intervi->intervim
+intervido->intervindo
+interviram->intervieram
+interviste->intervieste
+interviu->interveio
+intigração->integração
+intrumental->instrumental
+intrumento->instrumento
+inumeras->inúmeras
+inumeros->inúmeros
+invensivel->invencível
+invensível->invencível
+invenssível->invencível
+inves->invés
+invez->invés
+invéz->invés
+iorgute->iogurte
+iper->hiper
+ipopótamo->hipopótamo
+ipslon->ípslon
+irisar->irizar
+irmao->irmão
+irmaos->irmãos
+irupção->irrupção
+ispirar->inspirar
+ispirou->inspirou
+issu->isso
+jamelão->jamelada,rabada
+japones->japonês
+jeropiga->geropiga
+Joana d´Arc->Joana d'Arc
+judiciaria->judiciária
+judiciarias->judiciárias
+juíz->juiz
+juiza->juíza
+juizas->juízas
+juizes->juízes
+junior->júnior
+júniores->juniores
+juridica->jurídica
+juridição->jurisdição
+juridicas->jurídicas
+juridico->jurídico
+juridicos->jurídicos
+juz->jus
+kilo->quilograma
+kilômetro->quilômetro
+kilometro->quilómetro, quilômetro
+kilómetro->quilómetro, quilômetro
+kilometros->quilómetros, quilômetros
+kilómetros->quilómetros, quilômetros
+km2->km²
+largartixa->lagartixa
+largarto->lagarto
+leem->lêem
+leêm->lêem
+lêm->lêem
+lendaria->lendária
+lendarias->lendárias
+lendario->lendário
+lendarios->lendários
+leucémia->leucemia
+licenca->licença
+licencas->licenças
+licensa->licença
+lider->líder
+lideres->líderes
+lingua->língua
+linguas->línguas
+linguísta->linguista
+línguísta->linguista
+linguístas->linguistas
+línguístas->linguistas
+lisongea->lisonjeia
+lisongear->lisonjear
+lisongeara->lisonjeara
+lisongearam->lisonjearam
+lisongearou->lisonjearou
+lisonjea->lisonjeia
+logica->lógica
+lógicamente->logicamente
+logista->lojista
+logistas->lojistas
+lojica->lógica
+lójica->lógica
+lusofona->lusófona
+lusofonas->lusófonas
+lusofono->lusófono
+lusofonos->lusófonos
+magestade->majestade
+magestades->majestades
+magica->mágica
+magico->mágico
+mangerico->manjerico
+mangericos->manjericos
+manteram->mantiveram
+manteu->manteve
+maritima->marítima
+maritimas->marítimas
+maritimo->marítimo
+maritimos->marítimos
+massiça->maciça
+massiças->maciças
+massiço->maciço
+massiços->maciços
+meche->mexe
+mecher->mexer
+mecheram->mexeram
+mecheu->mexeu
+médico cirurgião->médico-cirurgião
+memoria->memória
+memorias->memórias
+menas->menos
+mercenaria->mercenária
+mercenarias->mercenárias
+mercenario->mercenário
+mercenarios->mercenários
+mêses->meses
+metereologia->meteorologia
+metodo->método
+metodos->métodos
+miceis->mísseis
+míceis->mísseis
+micil->míssil
+mícil->míssil
+minerio->minério
+minimo->mínimo
+missao->missão
+mistica->mística
+misticas->místicas
+mistico->místico
+misticos->místicos
+miticas->míticas
+molar->mol/L
+molaridade->concentração em quantidade de matéria
+muinto->muito
+muintos->muitos
+multi-uso-> multiúso
+multimedia->multimedia, multimídia
+multimedias->multimédias, multimídias
+multimidia->multimídia, multimédia
+multimidias-> multimídias, multimédias
+multiuso-> multiúso
+municipio->município
+munícipio->município
+munícípio->município
+municipios->municípios
+munícipios->municípios
+munícípios->municípios
+munto->muito
+muntos->muitos
+musica->música
+musicas->músicas
+musico->músico
+musicos->músicos
+ñ->não
+nanômetro->nanometro
+nao->não
+naum->não
+negocios->negócios
+nenum->nenhum
+neo darwinismo->neodarwinismo
+neo liberais->neoliberais
+neo liberal->neoliberal
+neo liberalismo->neoliberalismo
+neo zelandês->neozelandês
+neo zelandesa->neozelandesa
+neo-darwinismo->neodarwinismo
+neo-liberais->neoliberais
+neo-liberal->neoliberal
+neo-liberalismo->neoliberalismo
+neo-zelandês->neozelandês
+neo-zelandesa->neozelandesa
+nescessário->necessário
+ninguem->ninguém
+nivel->nível
+nonagesima->nonagésima
+nonagesimo->nonagésimo
+nonagessima->nonagésima
+nonagéssima->nonagésima
+nonagessimo->nonagésimo
+nonagéssimo->nonagésimo
+nostalgico->nostálgico
+nostalgicos->nostálgicos
+notávelmente->notavelmente
+númerais->numerais
+númeral->numeral
+número de Avogadro->constante de Avogadro
+número de moles->quantidade de matéria
+número de mols->quantidade de matéria
+numero->número
+numeros->números
+numismatica->numismática
+numismatico->numismático
+núvem->nuvem
+núvens->nuvens
+obrigatoria->obrigatória
+obrigatorias->obrigatórias
+obrigatorio->obrigatório
+obrigatorios->obrigatórios
+obtem->obtém, obtêm
+obteram->obtiveram
+obteu->obteve
+ºC->°C
+odio->ódio
+ºF->°F
+oje->hoje
+olimpico->olímpico
+olimpicos->olímpicos
+omem->homem
+optima->óptima, ótima
+optimo->óptimo, ótimo
+orta->horta
+otima->ótima, óptima
+otimisadas->otimizadas, optimizadas
+otimo->ótimo, óptimo
+oxido-redução->oxirredução
+pagaos->pagãos
+pagina->página
+paises->países
+paleolitica->paleolítica
+paleolitico->paleolítico
+papeis->papéis
+para mim fazer->para eu fazer
+paraiso->paraíso
+paraisos->paraísos
+paraizo->paraíso
+paraízo->paraíso
+paraizos->paraísos
+paraízos->paraísos
+paralização->paralisação
+paralizado->paralisado
+paralizar->paralisar
+paroco->pároco
+parocos->párocos
+pascais->pascals
+patria->pátria
+Paulinia->Paulínia
+pedigri->pedigree
+penta-campeão->pentacampeão
+percursora->precursora
+percursoras->precursoras
+periodo->período
+periodos->períodos
+periudo->período
+períudo->período
+periudos->períodos
+períudos->períodos
+permenor->pormenor
+permenores->pormenores
+perola->pérola
+perolas->pérolas
+personalisação->personalização
+personalisar->personalizar
+personalisou->personalizou
+pertubar->perturbar
+peso atômico->massa atômica
+peso molecular->massa molecular
+pesquiza->pesquisa
+picômetro->picometro
+plásticamente->plasticamente
+plasticas->plásticas
+plastico->plástico
+plasticos->plásticos
+poblema->problema
+pobrema->problema
+politica->política
+politicas->políticas
+politico->político
+politicos->políticos
+poluicao->poluição
+Portugual->Portugal
+posivel->possível
+possiveis->possíveis
+possivel->possível
+possue->possui
+pq->porque,porquê,por que,por quê
+praca->praça
+prefêrencias->preferências
+prescisa->precisa
+prestaçãões->prestações
+pretenção->pretensão
+pretenssão->pretensão
+previlegio->privilégio
+previlégio->privilégio
+previlegios->privilégios
+previlégios->privilégios
+primaria->primária
+primarias->primárias
+primario->primário
+primarios->primários
+primeiro ministro->primeiro-ministro
+princípalmente->principalmente
+príncipalmente->principalmente
+principios->princípios
+prisao->prisão
+prisoes->prisões
+privatizaçao->privatização
+privilegio->privilégio
+privilegios->privilégios
+proceço->processo
+proceços->processos
+proceso->processo
+procesos->processos
+producao->produção
+progama->programa
+progamas->programas
+proibe->proíbe
+proíbido->proibido
+propia->própria
+própia->própria
+propias->próprias
+propiedade->propriedade
+propio->próprio
+própio->próprio
+propios->próprios
+proposito->propósito
+prosceço->processo
+prosceços->processos
+prosceso->processo
+proscesos->processos
+proseço->processo
+proseços->processos
+prosseço->processo
+prosseços->processos
+protejida->protegida
+protejidas->protegidas
+protejido->protegido
+protejidos->protegidos
+prototipo->protótipo
+prototipos->protótipos
+provincia->província
+provincias->províncias
+proxima->próxima
+proximas->próximas
+proximo->próximo
+proximos->próximos
+pseudo-ciência->pseudociência
+publico->público
+publicos->públicos
+qeu->que
+questao->questão
+quilómetro->quilômetro
+quilometro->quilómetro, quilômetro
+quilometros->quilómetros, quilômetros
+quimica->química
+quimicas->químicas
+quimico->químico
+quimicos->químicos
+quizer->quiser
+quizesse->quisesse
+quizessem->quisessem
+radiaçao->radiação
+radio->rádio
+raíz->raiz
+raizes->raízes
+rarissimo->raríssimo
+rarissimos->raríssimos
+razao->razão
+razoes->razões
+récorde->recorde
+referencia->referência
+referencias->referências
+reibi->râguebi
+reinterar->reiterar
+reinvidicação->reivindicação
+reinvidicar->reivindicar
+renovaveis->renováveis
+repertorio->repertório
+repertorios->repertórios
+reportorio->reportório
+reportorios->reportórios
+requesito->requisito
+responsaveis->responsáveis
+responsavel->responsável
+retem->retém, retêm
+reteram->retiveram
+reteu->reteve
+reune->reúne
+reunem->reúnem
+reuniao->reunião
+reunioes->reuniões
+reuso-> reúso
+riquissimo->riquíssimo
+riquissimos->riquíssimos
+ritualistico->ritualístico
+rúbrica->rubrica
+rúbricas->rubricas
+sacerdocio->sacerdócio
+sacrificio->sacrifício
+saira->saíra, sairá
+santuario->santuário
+sao->são
+saude->saúde
+secudaria->secudária
+secudarias->secudárias
+secudario->secudário
+secudarios->secudários
+seculo->século
+seculos->séculos
+seissentos->seiscentos
+seje->seja
+semaforo->semáforo
+semaforos->semáforos
+semi círculo->semicírculo
+semi círculos->semicírculos
+semi finais->semifinais
+semi final->semifinal
+semi precioso->semiprecioso
+semi preciosos->semipreciosos
+semi presidencialismos->semipresidencialismos
+semi presidencialistas->semipresidencialistas
+semi-círculo->semicírculo
+semi-círculos->semicírculos
+semi-finais->semifinais
+semi-final->semifinal
+semi-precioso->semiprecioso
+semi-preciosos->semipreciosos
+semi-presidencialismos->semipresidencialismos
+semi-presidencialistas->semipresidencialistas
+sensiveis->sensíveis
+sensivel->sensível
+separaçoes->separações
+serie->série
+serio->sério, série, seriado
+setessentos->setecentos
+siclano->sicrano
+simbolo->símbolo
+simbolos->símbolos
+simplemente->simplesmente
+sindrome->síndrome
+sinonimo->sinónimo, sinônimo
+síntaze->síntaxe
+sistemico->sistémico
+sobrevivencia->sobrevivência
+sombrancelha->sobrancelha
+subdivisáo->subdivisão
+substituida->substituída
+substituidas->substituídas
+substituido->substituído
+substituidos->substituídos
+suçeso->sucesso
+suçesos->sucessos
+suçesso->sucesso
+suçessos->sucessos
+Suiça->Suíça
+suiço->suíço
+suino->suíno
+suseço->sucesso
+suseços->sucessos
+susseço->sucesso
+susseços->sucessos
+sussesso->sucesso
+sussessos->sucessos
+tambem->também
+támbem->também
+támbém->também
+tao->tão
+tb->também
+tbm->também
+tecnica->técnica
+tecnico->técnico
+têmporo-mandibular->temporomandibular
+tendencia->tendência
+tendencias->tendências
+tetra-hidrofurano->tetraidrofurano
+tipica->típica
+tipicas->típicas
+tipico->típico
+tipicos->típicos
+titulos->títulos
+tracao->tracção, tração
+tranformar->transformar
+transmissiveis->transmissíveis
+transmissivel->transmissível
+traser->trazer
+trasnporta->transporta
+trasnporte->transporte
+trasnportes->transportes
+tratrahidrofurano->tetraidrofurano
+tres->três
+treslagoense->três-lagoense
+tri-campeão->tricampeão
+trovao->trovão
+Tupí-guarani->Tupi-guarani
+turistico->turístico
+turisticos->turísticos
+u.m.a->u
+ultima->última
+ultimo->último
+ultimos->últimos
+um um->um
+úmidade->umidade, humidade
+unica->única
+unicas->únicas
+unico->único
+unicos->únicos
+univercidade->universidade
+univercidades->universidades
+universitaria->universitária
+universitarias->universitárias
+universitario->universitário
+universitarios->universitários
+uqe->que
+usuario->usuário, utilizador
+util->útil
+utilisador->utilizador, usuário
+uzada->usada
+uzadas->usadas
+uzado->usado
+uzados->usados
+uzar->usar
+uzo->uso
+uzou->usou
+váriados->variados
+varias->várias
+varios->vários
+vc->você
+veiculo->veículo
+veiculos->veículos
+verçao->versão
+verção->versão
+verçoes->versões
+verções->versões
+ves->vez, vês
+veses->vezes
+vestigio->vestígio
+vestigios->vestígios
+vezis->vezes
+viajem->viagem
+vice governador->vice-governador
+vice governadores->vice-governadores
+vice prefeito->vice-prefeito
+vice prefeitos->vice-prefeitos
+vice presidente->vice-presidente
+vice presidentes->vice-presidentes
+video game->videogame
+video->vídeo
+videoclip->videoclipe
+vigilancia->vigilância
+violencia->violência
+viros->vírus
+víros->vírus
+virus->vírus
+virús->vírus
+vírús->vírus
+vitoria->vitória
+vitorias->vitórias
+viuva->viúva
+voçe->você
+voçê->você
+Wikimapa->WikiMapia
+Wikimapia->WikiMapia
+xafariz->chafariz
+xuxu->chuchu
+yoga->ioga
+yôga->ioga
diff --git a/files/typos/typos-tr.txt b/files/typos/typos-tr.txt
new file mode 100644
index 0000000..4db11e7
--- /dev/null
+++ b/files/typos/typos-tr.txt
@@ -0,0 +1,604 @@
+# This file contains a number of common Turkish typos:
+andriod->android
+
+# The remainder of this file contains misspellings from
+# http://tr.wikipedia.org/wiki/Vikipedi:Yaygin_kelime_hatalari/makinalar_icin
+# plus some post-processing to fix invalid entries, remove duplicates, etc.
+#
+# The content is available under the
+# "Creative Commons Attribution-ShareAlike License"
+# http://creativecommons.org/licenses/by-sa/3.0/
+#
+# THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
+# COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
+# COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
+# AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
+#
+# BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE
+# TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY
+# BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS
+# CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
+# CONDITIONS.
+#
+# *1. Definitions*
+#
+# 1. *"Adaptation"* means a work based upon the Work, or upon the Work
+# and other pre-existing works, such as a translation, adaptation,
+# derivative work, arrangement of music or other alterations of a
+# literary or artistic work, or phonogram or performance and includes
+# cinematographic adaptations or any other form in which the Work may
+# be recast, transformed, or adapted including in any form
+# recognizably derived from the original, except that a work that
+# constitutes a Collection will not be considered an Adaptation for
+# the purpose of this License. For the avoidance of doubt, where the
+# Work is a musical work, performance or phonogram, the
+# synchronization of the Work in timed-relation with a moving image
+# ("synching") will be considered an Adaptation for the purpose of
+# this License.
+# 2. *"Collection"* means a collection of literary or artistic works,
+# such as encyclopedias and anthologies, or performances, phonograms
+# or broadcasts, or other works or subject matter other than works
+# listed in Section 1(f) below, which, by reason of the selection and
+# arrangement of their contents, constitute intellectual creations, in
+# which the Work is included in its entirety in unmodified form along
+# with one or more other contributions, each constituting separate and
+# independent works in themselves, which together are assembled into a
+# collective whole. A work that constitutes a Collection will not be
+# considered an Adaptation (as defined below) for the purposes of this
+# License.
+# 3. *"Creative Commons Compatible License"* means a license that is
+# listed at http://creativecommons.org/compatiblelicenses that has
+# been approved by Creative Commons as being essentially equivalent to
+# this License, including, at a minimum, because that license: (i)
+# contains terms that have the same purpose, meaning and effect as the
+# License Elements of this License; and, (ii) explicitly permits the
+# relicensing of adaptations of works made available under that
+# license under this License or a Creative Commons jurisdiction
+# license with the same License Elements as this License.
+# 4. *"Distribute"* means to make available to the public the original
+# and copies of the Work or Adaptation, as appropriate, through sale
+# or other transfer of ownership.
+# 5. *"License Elements"* means the following high-level license
+# attributes as selected by Licensor and indicated in the title of
+# this License: Attribution, ShareAlike.
+# 6. *"Licensor"* means the individual, individuals, entity or entities
+# that offer(s) the Work under the terms of this License.
+# 7. *"Original Author"* means, in the case of a literary or artistic
+# work, the individual, individuals, entity or entities who created
+# the Work or if no individual or entity can be identified, the
+# publisher; and in addition (i) in the case of a performance the
+# actors, singers, musicians, dancers, and other persons who act,
+# sing, deliver, declaim, play in, interpret or otherwise perform
+# literary or artistic works or expressions of folklore; (ii) in the
+# case of a phonogram the producer being the person or legal entity
+# who first fixes the sounds of a performance or other sounds; and,
+# (iii) in the case of broadcasts, the organization that transmits the
+# broadcast.
+# 8. *"Work"* means the literary and/or artistic work offered under the
+# terms of this License including without limitation any production in
+# the literary, scientific and artistic domain, whatever may be the
+# mode or form of its expression including digital form, such as a
+# book, pamphlet and other writing; a lecture, address, sermon or
+# other work of the same nature; a dramatic or dramatico-musical work;
+# a choreographic work or entertainment in dumb show; a musical
+# composition with or without words; a cinematographic work to which
+# are assimilated works expressed by a process analogous to
+# cinematography; a work of drawing, painting, architecture,
+# sculpture, engraving or lithography; a photographic work to which
+# are assimilated works expressed by a process analogous to
+# photography; a work of applied art; an illustration, map, plan,
+# sketch or three-dimensional work relative to geography, topography,
+# architecture or science; a performance; a broadcast; a phonogram; a
+# compilation of data to the extent it is protected as a copyrightable
+# work; or a work performed by a variety or circus performer to the
+# extent it is not otherwise considered a literary or artistic work.
+# 9. *"You"* means an individual or entity exercising rights under this
+# License who has not previously violated the terms of this License
+# with respect to the Work, or who has received express permission
+# from the Licensor to exercise rights under this License despite a
+# previous violation.
+# 10. *"Publicly Perform"* means to perform public recitations of the Work
+# and to communicate to the public those public recitations, by any
+# means or process, including by wire or wireless means or public
+# digital performances; to make available to the public Works in such
+# a way that members of the public may access these Works from a place
+# and at a place individually chosen by them; to perform the Work to
+# the public by any means or process and the communication to the
+# public of the performances of the Work, including by public digital
+# performance; to broadcast and rebroadcast the Work by any means
+# including signs, sounds or images.
+# 11. *"Reproduce"* means to make copies of the Work by any means
+# including without limitation by sound or visual recordings and the
+# right of fixation and reproducing fixations of the Work, including
+# storage of a protected performance or phonogram in digital form or
+# other electronic medium.
+#
+# *2. Fair Dealing Rights.* Nothing in this License is intended to reduce,
+# limit, or restrict any uses free from copyright or rights arising from
+# limitations or exceptions that are provided for in connection with the
+# copyright protection under copyright law or other applicable laws.
+#
+# *3. License Grant.* Subject to the terms and conditions of this License,
+# Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
+# perpetual (for the duration of the applicable copyright) license to
+# exercise the rights in the Work as stated below:
+#
+# 1. to Reproduce the Work, to incorporate the Work into one or more
+# Collections, and to Reproduce the Work as incorporated in the
+# Collections;
+# 2. to create and Reproduce Adaptations provided that any such
+# Adaptation, including any translation in any medium, takes
+# reasonable steps to clearly label, demarcate or otherwise identify
+# that changes were made to the original Work. For example, a
+# translation could be marked "The original work was translated from
+# English to Spanish," or a modification could indicate "The original
+# work has been modified.";
+# 3. to Distribute and Publicly Perform the Work including as
+# incorporated in Collections; and,
+# 4. to Distribute and Publicly Perform Adaptations.
+# 5.
+#
+# For the avoidance of doubt:
+#
+# 1. *Non-waivable Compulsory License Schemes*. In those
+# jurisdictions in which the right to collect royalties through
+# any statutory or compulsory licensing scheme cannot be waived,
+# the Licensor reserves the exclusive right to collect such
+# royalties for any exercise by You of the rights granted under
+# this License;
+# 2. *Waivable Compulsory License Schemes*. In those jurisdictions in
+# which the right to collect royalties through any statutory or
+# compulsory licensing scheme can be waived, the Licensor waives
+# the exclusive right to collect such royalties for any exercise
+# by You of the rights granted under this License; and,
+# 3. *Voluntary License Schemes*. The Licensor waives the right to
+# collect royalties, whether individually or, in the event that
+# the Licensor is a member of a collecting society that
+# administers voluntary licensing schemes, via that society, from
+# any exercise by You of the rights granted under this License.
+#
+# The above rights may be exercised in all media and formats whether now
+# known or hereafter devised. The above rights include the right to make
+# such modifications as are technically necessary to exercise the rights
+# in other media and formats. Subject to Section 8(f), all rights not
+# expressly granted by Licensor are hereby reserved.
+#
+# *4. Restrictions.* The license granted in Section 3 above is expressly
+# made subject to and limited by the following restrictions:
+#
+# 1. You may Distribute or Publicly Perform the Work only under the terms
+# of this License. You must include a copy of, or the Uniform Resource
+# Identifier (URI) for, this License with every copy of the Work You
+# Distribute or Publicly Perform. You may not offer or impose any
+# terms on the Work that restrict the terms of this License or the
+# ability of the recipient of the Work to exercise the rights granted
+# to that recipient under the terms of the License. You may not
+# sublicense the Work. You must keep intact all notices that refer to
+# this License and to the disclaimer of warranties with every copy of
+# the Work You Distribute or Publicly Perform. When You Distribute or
+# Publicly Perform the Work, You may not impose any effective
+# technological measures on the Work that restrict the ability of a
+# recipient of the Work from You to exercise the rights granted to
+# that recipient under the terms of the License. This Section 4(a)
+# applies to the Work as incorporated in a Collection, but this does
+# not require the Collection apart from the Work itself to be made
+# subject to the terms of this License. If You create a Collection,
+# upon notice from any Licensor You must, to the extent practicable,
+# remove from the Collection any credit as required by Section 4(c),
+# as requested. If You create an Adaptation, upon notice from any
+# Licensor You must, to the extent practicable, remove from the
+# Adaptation any credit as required by Section 4(c), as requested.
+# 2. You may Distribute or Publicly Perform an Adaptation only under the
+# terms of: (i) this License; (ii) a later version of this License
+# with the same License Elements as this License; (iii) a Creative
+# Commons jurisdiction license (either this or a later license
+# version) that contains the same License Elements as this License
+# (e.g., Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons
+# Compatible License. If you license the Adaptation under one of the
+# licenses mentioned in (iv), you must comply with the terms of that
+# license. If you license the Adaptation under the terms of any of the
+# licenses mentioned in (i), (ii) or (iii) (the "Applicable License"),
+# you must comply with the terms of the Applicable License generally
+# and the following provisions: (I) You must include a copy of, or the
+# URI for, the Applicable License with every copy of each Adaptation
+# You Distribute or Publicly Perform; (II) You may not offer or impose
+# any terms on the Adaptation that restrict the terms of the
+# Applicable License or the ability of the recipient of the Adaptation
+# to exercise the rights granted to that recipient under the terms of
+# the Applicable License; (III) You must keep intact all notices that
+# refer to the Applicable License and to the disclaimer of warranties
+# with every copy of the Work as included in the Adaptation You
+# Distribute or Publicly Perform; (IV) when You Distribute or Publicly
+# Perform the Adaptation, You may not impose any effective
+# technological measures on the Adaptation that restrict the ability
+# of a recipient of the Adaptation from You to exercise the rights
+# granted to that recipient under the terms of the Applicable License.
+# This Section 4(b) applies to the Adaptation as incorporated in a
+# Collection, but this does not require the Collection apart from the
+# Adaptation itself to be made subject to the terms of the Applicable
+# License.
+# 3. If You Distribute, or Publicly Perform the Work or any Adaptations
+# or Collections, You must, unless a request has been made pursuant to
+# Section 4(a), keep intact all copyright notices for the Work and
+# provide, reasonable to the medium or means You are utilizing: (i)
+# the name of the Original Author (or pseudonym, if applicable) if
+# supplied, and/or if the Original Author and/or Licensor designate
+# another party or parties (e.g., a sponsor institute, publishing
+# entity, journal) for attribution ("Attribution Parties") in
+# Licensor's copyright notice, terms of service or by other reasonable
+# means, the name of such party or parties; (ii) the title of the Work
+# if supplied; (iii) to the extent reasonably practicable, the URI, if
+# any, that Licensor specifies to be associated with the Work, unless
+# such URI does not refer to the copyright notice or licensing
+# information for the Work; and (iv) , consistent with Ssection 3(b),
+# in the case of an Adaptation, a credit identifying the use of the
+# Work in the Adaptation (e.g., "French translation of the Work by
+# Original Author," or "Screenplay based on original Work by Original
+# Author"). The credit required by this Section 4(c) may be
+# implemented in any reasonable manner; provided, however, that in the
+# case of a Adaptation or Collection, at a minimum such credit will
+# appear, if a credit for all contributing authors of the Adaptation
+# or Collection appears, then as part of these credits and in a manner
+# at least as prominent as the credits for the other contributing
+# authors. For the avoidance of doubt, You may only use the credit
+# required by this Section for the purpose of attribution in the
+# manner set out above and, by exercising Your rights under this
+# License, You may not implicitly or explicitly assert or imply any
+# connection with, sponsorship or endorsement by the Original Author,
+# Licensor and/or Attribution Parties, as appropriate, of You or Your
+# use of the Work, without the separate, express prior written
+# permission of the Original Author, Licensor and/or Attribution Parties.
+# 4. Except as otherwise agreed in writing by the Licensor or as may be
+# otherwise permitted by applicable law, if You Reproduce, Distribute
+# or Publicly Perform the Work either by itself or as part of any
+# Adaptations or Collections, You must not distort, mutilate, modify
+# or take other derogatory action in relation to the Work which would
+# be prejudicial to the Original Author's honor or reputation.
+# Licensor agrees that in those jurisdictions (e.g. Japan), in which
+# any exercise of the right granted in Section 3(b) of this License
+# (the right to make Adaptations) would be deemed to be a distortion,
+# mutilation, modification or other derogatory action prejudicial to
+# the Original Author's honor and reputation, the Licensor will waive
+# or not assert, as appropriate, this Section, to the fullest extent
+# permitted by the applicable national law, to enable You to
+# reasonably exercise Your right under Section 3(b) of this License
+# (right to make Adaptations) but not otherwise.
+#
+# *5. Representations, Warranties and Disclaimer*
+#
+# UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR
+# OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY
+# KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,
+# INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
+# FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF
+# LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS,
+# WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE
+# EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
+#
+# *6. Limitation on Liability.* EXCEPT TO THE EXTENT REQUIRED BY
+# APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL
+# THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY
+# DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF
+# LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+#
+# *7. Termination*
+#
+# 1. This License and the rights granted hereunder will terminate
+# automatically upon any breach by You of the terms of this License.
+# Individuals or entities who have received Adaptations or Collections
+# from You under this License, however, will not have their licenses
+# terminated provided such individuals or entities remain in full
+# compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
+# survive any termination of this License.
+# 2. Subject to the above terms and conditions, the license granted here
+# is perpetual (for the duration of the applicable copyright in the
+# Work). Notwithstanding the above, Licensor reserves the right to
+# release the Work under different license terms or to stop
+# distributing the Work at any time; provided, however that any such
+# election will not serve to withdraw this License (or any other
+# license that has been, or is required to be, granted under the terms
+# of this License), and this License will continue in full force and
+# effect unless terminated as stated above.
+#
+# *8. Miscellaneous*
+#
+# 1. Each time You Distribute or Publicly Perform the Work or a
+# Collection, the Licensor offers to the recipient a license to the
+# Work on the same terms and conditions as the license granted to You
+# under this License.
+# 2. Each time You Distribute or Publicly Perform an Adaptation, Licensor
+# offers to the recipient a license to the original Work on the same
+# terms and conditions as the license granted to You under this License.
+# 3. If any provision of this License is invalid or unenforceable under
+# applicable law, it shall not affect the validity or enforceability
+# of the remainder of the terms of this License, and without further
+# action by the parties to this agreement, such provision shall be
+# reformed to the minimum extent necessary to make such provision
+# valid and enforceable.
+# 4. No term or provision of this License shall be deemed waived and no
+# breach consented to unless such waiver or consent shall be in
+# writing and signed by the party to be charged with such waiver or
+# consent.
+# 5. This License constitutes the entire agreement between the parties
+# with respect to the Work licensed here. There are no understandings,
+# agreements or representations with respect to the Work not specified
+# here. Licensor shall not be bound by any additional provisions that
+# may appear in any communication from You. This License may not be
+# modified without the mutual written agreement of the Licensor and You.
+# 6. The rights granted under, and the subject matter referenced, in this
+# License were drafted utilizing the terminology of the Berne
+# Convention for the Protection of Literary and Artistic Works (as
+# amended on September 28, 1979), the Rome Convention of 1961, the
+# WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms
+# Treaty of 1996 and the Universal Copyright Convention (as revised on
+# July 24, 1971). These rights and subject matter take effect in the
+# relevant jurisdiction in which the License terms are sought to be
+# enforced according to the corresponding provisions of the
+# implementation of those treaty provisions in the applicable national
+# law. If the standard suite of rights granted under applicable
+# copyright law includes additional rights not granted under this
+# License, such additional rights are deemed to be included in the
+# License; this License is not intended to restrict the license of any
+# rights under applicable law.
+acizane->âcizane
+alamanya->almanya
+aferim->aferin
+agrasif->agresif
+aÄŸostos->aÄŸustos
+ahret->ahiret
+ayle->aile
+alarım->alarm
+atmış->altmış
+alemiyon->alüminyum
+amarika->amerika
+anfi->amfi
+aparetif->aperitif
+arabeks->arabesk
+artiz->artist
+aşşağı->aşağı
+ahçı->aşçı
+avut->aut
+ayakıbı->ayakkabı
+azarbeycan->azerbaycan
+azerbeycan->azerbaycan
+avusturalya->avustralya
+bangledeÅŸ->bangladeÅŸ
+pıçak->bıçak
+bilmukavele->bilmukabele
+birÅŸey->bir ÅŸey
+bir kaç->birkaç
+bir çok->birçok
+pisiklet->bisiklet
+püsküüt->bisküvi
+canbaz->cambaz
+çoçuk->çocuk
+çoşku->coşku
+cıplak->çıplak
+çiflik->çiftlik
+çünki->çünkü
+dekarasyon->dekorasyon
+debrem->deprem
+dohtor->doktor
+doktur->doktor
+doktör->doktor
+tiken->diken
+dinazor->dinozor
+diplamat->diplomat
+distibütör->distribütör
+dinayet->diyanet
+domat->domates
+domtiz->domates
+domatis->domates
+domatiz->domates
+döküman->doküman
+döndermek->döndürmek
+dükkan->dükkân
+tukkan->dükkân
+egsos->egzoz
+egsoz->egzoz
+egsozt->egzoz
+egzos->egzoz
+egzost->egzoz
+eksos->egzoz
+eksoz->egzoz
+eksozt->egzoz
+ekzos->egzoz
+ekzost->egzoz
+eÅŸki->ekÅŸi
+eylence->eÄŸlence
+elenktirik->elektrik
+elenktrik->elektrik
+elektirik->elektrik
+entellektüel->entelektüel
+aÅŸortman->eÅŸofman
+eÅŸortman->eÅŸofman
+felan->falan
+filim->film
+formil->formül
+gardırop->gardrop
+gardolap->gardrop
+gaste->gazete
+goometri->geometri
+giriÅŸgen->giriÅŸken
+greyfirut->greyfurt
+greyfrut->greyfurt
+gürcüstan->gürcistan
+güzelgah->güzergâh
+güzergah->güzergâh
+harfiyat->hafriyat
+hastene->hastane
+havunç->havuç
+herhangibir->herhangi bir
+herÅŸey->her ÅŸey,her ÅŸey
+haparlör->hoparlör
+hopollo->hoparlör
+hoporlör->hoparlör
+operlo->hoparlör
+operlor->hoparlör
+hakkari->hakkâri
+heralda->herhalde
+herkez->herkes
+#hiç bir->hiçbir
+hiç birşey->hiçbir şey
+hükümet->hükûmet
+holanda->hollanda
+istakoz->ıstakoz
+imkan->imkân
+imlâ->imla
+inkilap->inkılap
+insiyatif->inisiyatif
+iskan->iskân
+ıstanbul->istanbul
+istambul->istanbul
+istinâden->istinaden
+itibariyle->itibarıyla
+celatin->jelatin
+capon->Japon
+ceton->jeton
+jöton->jeton
+kağıt->kâğıt
+kağat->kâğıt
+kayfaltı->kahvaltı
+gahfe->kahve
+gayfe->kahve
+kaave->kahve
+kayfe->kahve
+kave->kahve
+gangren->kangren
+kankıran->kangren
+karekter->karakter
+kaysı->kayısı
+kebelek->kelebek
+keÅŸki->keÅŸke
+kırahatane->kıraathane
+kirbit->kibrit
+kipri->kirpi
+kiprik->kirpik,kirpik
+kokreç->kokoreç
+komonis->komünist
+komonist->komünist
+komonizm->komünizm
+kontür->kontör
+kopye->kopya
+kareografi->koreografi
+gipür->kupür
+küpür->kupür
+lahap->lakap
+leplepi->leblebi
+nalet->lanet
+leyen->leÄŸen
+liÄŸen->leÄŸen
+liyen->leÄŸen
+lüx->lüks
+makadonya->makedonya
+makina->makine
+maaÅŸallah->maÅŸallah
+matamatik->matematik
+menejer->menajer
+menapoz->menopoz
+mentalite->mantalite
+meraba->merhaba
+meyva->meyve
+mihendis->mühendis
+moÄŸalistan->moÄŸolistan
+müdehale->müdahale
+münübüs->minibüs
+müracat->müracaat
+mütahit->müteahhit
+mütevazi->mütevazı
+nacizane->naçizane
+laylon->naylon
+nufüs->nüfus
+nülüfer->nilüfer
+netekim->nitekim
+oce->oje
+okÅŸizen->oksijen
+orjinal->orijinal
+otibis->otobüs
+#öğe->öge
+ötenazi->ötanazi
+palyanço->palyaço
+panaroma->panorama
+pantalon->pantolon
+pattes->patates
+pattis->patates
+peçeta->peçete
+penbe->pembe
+pelisilin->penilisin
+poaça->poğaça
+pohaça->poğaça
+poğçe->poğaça
+pırofösör->profesör
+prefesör->profesör
+profösör->profesör
+profütür->profiterol
+proÄŸram->program
+promasyon->promosyon
+radyosyon->radyasyon
+romenya->romanya
+ruc->ruj
+sandaviç->sandviç
+sandeviç->sandviç
+sandoviç->sandviç
+sandöviç->sandviç
+sarmısak->sarımsak
+sarumsak->sarımsak
+satlık->satılık
+santranç->satranç
+santraç->satranç
+satraç->satranç
+skayner->scanner
+zebze->sebze
+seramoni->seremoni
+seromoni->seremoni
+sikorta->sigorta
+sinama->sinema
+siyasî->siyasi
+sıkandal->skandal
+sovan->soÄŸan
+sosyel->sosyal
+sitretoskop->stetoskop
+siteteskop->stetoskop
+süpriz->sürpriz
+südyen->sütyen
+ÅŸartel->ÅŸalter
+ÅŸaltel->ÅŸalter
+ÅŸarz->ÅŸarj
+ÅŸindi->ÅŸimdi
+şöfer->şoför
+şöför->şoför
+tetbir->tedbir
+temis->temiz
+telafuz->telaffuz
+tenefüs->teneffüs
+tellik->terlik
+tranvay->tramvay
+törörist->terörist
+teşebüs->teşebbüs
+teşeppüs->teşebbüs
+tiskinmek->tiksinmek
+tos->tost
+tükrük->tükürük
+tüprük->tükürük
+traş->tıraş
+türkiya->türkiye
+ukele->ukala
+ükela->ukala
+ukranya->ukrayna
+ukrayin->ukrayna
+ünvan->unvan
+üçken->üçgen
+vucüt->vücut
+vucud->vücut
+vürüs->virüs
+fites->vites
+valeybol->voleybol
+veleybol->voleybol
+yada->ya da
+yanlız->yalnız
+yannış->yanlış
+yalnış->yanlış
+yimek->yemek
+yeni zellanda->yeni zelanda
+gine->yine
+zerafet->zarafet
diff --git a/lint/cli/src/com/android/tools/lint/HtmlReporter.java b/lint/cli/src/com/android/tools/lint/HtmlReporter.java
index e962fec..c3ed9d2 100644
--- a/lint/cli/src/com/android/tools/lint/HtmlReporter.java
+++ b/lint/cli/src/com/android/tools/lint/HtmlReporter.java
@@ -33,10 +33,10 @@ import com.google.common.base.Charsets;
import com.google.common.collect.Maps;
import com.google.common.io.ByteStreams;
import com.google.common.io.Closeables;
+import com.google.common.io.Files;
import java.io.BufferedWriter;
import java.io.File;
-import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
@@ -86,7 +86,7 @@ public class HtmlReporter extends Reporter {
*/
public HtmlReporter(Main client, File output) throws IOException {
super(client, output);
- mWriter = new BufferedWriter(new FileWriter(output));
+ mWriter = new BufferedWriter(Files.newWriter(output, Charsets.UTF_8));
}
@Override
@@ -96,6 +96,7 @@ public class HtmlReporter extends Reporter {
mWriter.write(
"<html>\n" + //$NON-NLS-1$
"<head>\n" + //$NON-NLS-1$
+ "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/>" + //$NON-NLS-1$
"<title>" + mTitle + "</title>\n"); //$NON-NLS-1$//$NON-NLS-2$
writeStyleSheet();
diff --git a/lint/cli/src/com/android/tools/lint/Main.java b/lint/cli/src/com/android/tools/lint/Main.java
index fbb0b16..6cdb689 100644
--- a/lint/cli/src/com/android/tools/lint/Main.java
+++ b/lint/cli/src/com/android/tools/lint/Main.java
@@ -41,6 +41,7 @@ import com.android.tools.lint.detector.api.Position;
import com.android.tools.lint.detector.api.Project;
import com.android.tools.lint.detector.api.Severity;
import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
import com.google.common.io.Closeables;
import java.io.BufferedWriter;
@@ -85,6 +86,8 @@ public class Main extends LintClient {
private static final String ARG_URL = "--url"; //$NON-NLS-1$
private static final String ARG_VERSION = "--version"; //$NON-NLS-1$
private static final String ARG_EXITCODE = "--exitcode"; //$NON-NLS-1$
+ private static final String ARG_CLASSES = "--classpath"; //$NON-NLS-1$
+ private static final String ARG_SOURCES = "--sources"; //$NON-NLS-1$
private static final String ARG_NOWARN2 = "--nowarn"; //$NON-NLS-1$
// GCC style flag names for options
@@ -118,6 +121,8 @@ public class Main extends LintClient {
private boolean mWarnAll;
private boolean mNoWarnings;
private boolean mAllErrors;
+ private List<File> mSources;
+ private List<File> mClasses;
private Configuration mDefaultConfiguration;
private IssueRegistry mRegistry;
@@ -456,6 +461,40 @@ public class Main extends LintClient {
mWarnAll = true;
} else if (arg.equals(ARG_ALLERROR)) {
mAllErrors = true;
+ } else if (arg.equals(ARG_CLASSES)) {
+ if (index == args.length - 1) {
+ System.err.println("Missing class folder name");
+ System.exit(ERRNO_INVALIDARGS);
+ }
+ String paths = args[++index];
+ for (String path : LintUtils.splitPath(paths)) {
+ File input = getInArgumentPath(path);
+ if (!input.exists()) {
+ System.err.println("Class path entry " + input + " does not exist.");
+ System.exit(ERRNO_INVALIDARGS);
+ }
+ if (mClasses == null) {
+ mClasses = new ArrayList<File>();
+ }
+ mClasses.add(input);
+ }
+ } else if (arg.equals(ARG_SOURCES)) {
+ if (index == args.length - 1) {
+ System.err.println("Missing source folder name");
+ System.exit(ERRNO_INVALIDARGS);
+ }
+ String paths = args[++index];
+ for (String path : LintUtils.splitPath(paths)) {
+ File input = getInArgumentPath(path);
+ if (!input.exists()) {
+ System.err.println("Source folder " + input + " does not exist.");
+ System.exit(ERRNO_INVALIDARGS);
+ }
+ if (mSources == null) {
+ mSources = new ArrayList<File>();
+ }
+ mSources.add(input);
+ }
} else if (arg.startsWith("--")) {
System.err.println("Invalid argument " + arg + "\n");
printUsage(System.err);
@@ -475,6 +514,10 @@ public class Main extends LintClient {
if (files.size() == 0) {
System.err.println("No files to analyze.");
System.exit(ERRNO_INVALIDARGS);
+ } else if (files.size() > 1 && (mClasses != null || mSources != null)) {
+ System.err.println("The " + ARG_SOURCES + " and " + ARG_CLASSES
+ + " can only be used with a single project");
+ System.exit(ERRNO_INVALIDARGS);
}
if (mReporters.isEmpty()) {
@@ -683,8 +726,18 @@ public class Main extends LintClient {
"\"lint --ignore UnusedResources,UselessLeaf /my/project/path\"\n";
}
- @SuppressWarnings("resource") // Eclipse doesn't know about Closeables.closeQuietly
private void printVersion() {
+ String revision = getRevision();
+ if (revision != null) {
+ System.out.println(String.format("lint: version %1$s", revision));
+ } else {
+ System.out.println("lint: unknown version");
+ }
+ }
+
+ @SuppressWarnings("resource") // Eclipse doesn't know about Closeables.closeQuietly
+ @Nullable
+ String getRevision() {
File file = findResource("tools" + File.separator + //$NON-NLS-1$
"source.properties"); //$NON-NLS-1$
if (file != null && file.exists()) {
@@ -696,8 +749,7 @@ public class Main extends LintClient {
String revision = properties.getProperty("Pkg.Revision"); //$NON-NLS-1$
if (revision != null && revision.length() > 0) {
- System.out.println(String.format("lint: version %1$s", revision));
- return;
+ return revision;
}
} catch (IOException e) {
// Couldn't find or read the version info: just print out unknown below
@@ -706,7 +758,7 @@ public class Main extends LintClient {
}
}
- System.out.println("lint: unknown version");
+ return null;
}
private void displayValidIds(IssueRegistry registry, PrintStream out) {
@@ -896,6 +948,12 @@ public class Main extends LintClient {
ARG_SIMPLEHTML + " <filename>", "Create a simple HTML report",
ARG_XML + " <filename>", "Create an XML report instead.",
+ "", "\nProject Options:",
+ ARG_SOURCES + " <dir>", "Add the given folder (or path) as a source directory for " +
+ "the project. Only valid when running lint on a single project.",
+ ARG_CLASSES + " <dir>", "Add the given folder (or jar file, or path) as a class " +
+ "directory for the project. Only valid when running lint on a single project.",
+
"", "\nExit Status:",
"0", "Success.",
Integer.toString(ERRNO_ERRORS), "Lint errors detected.",
@@ -1122,6 +1180,45 @@ public class Main extends LintClient {
return mCheck != null;
}
+ private Map<Project, ClassPathInfo> mProjectInfo;
+
+ @Override
+ @NonNull
+ protected ClassPathInfo getClassPath(@NonNull Project project) {
+ ClassPathInfo classPath = super.getClassPath(project);
+
+ if (mClasses == null && mSources == null) {
+ return classPath;
+ }
+
+ ClassPathInfo info;
+ if (mProjectInfo == null) {
+ mProjectInfo = Maps.newHashMap();
+ info = null;
+ } else {
+ info = mProjectInfo.get(project);
+ }
+
+ if (info == null) {
+ List<File> sources;
+ if (mSources != null) {
+ sources = mSources;
+ } else {
+ sources = classPath.getSourceFolders();
+ }
+ List<File> classes;
+ if (mClasses != null) {
+ classes = mClasses;
+ } else {
+ classes = classPath.getClassFolders();
+ }
+ info = new ClassPathInfo(sources, classes, classPath.getLibraries());
+ mProjectInfo.put(project, info);
+ }
+
+ return info;
+ }
+
/**
* Consult the lint.xml file, but override with the --enable and --disable
* flags supplied on the command line
diff --git a/lint/cli/src/com/android/tools/lint/XmlReporter.java b/lint/cli/src/com/android/tools/lint/XmlReporter.java
index f924def..04ac1d9 100644
--- a/lint/cli/src/com/android/tools/lint/XmlReporter.java
+++ b/lint/cli/src/com/android/tools/lint/XmlReporter.java
@@ -16,6 +16,8 @@
package com.android.tools.lint;
+import com.android.tools.lint.checks.BuiltinIssueRegistry;
+import com.android.tools.lint.detector.api.Issue;
import com.android.tools.lint.detector.api.Location;
import com.android.tools.lint.detector.api.Position;
import com.google.common.annotations.Beta;
@@ -52,18 +54,53 @@ public class XmlReporter extends Reporter {
@Override
public void write(int errorCount, int warningCount, List<Warning> issues) throws IOException {
- mWriter.write(
- "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + //$NON-NLS-1$
- "<issues>\n"); //$NON-NLS-1$
+ mWriter.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); //$NON-NLS-1$
+ mWriter.write("<issues format=\"3\""); //$NON-NLS-1$
+ String revision = mClient.getRevision();
+ if (revision != null) {
+ mWriter.write(String.format(" by=\"lint %1$s\"", revision)); //$NON-NLS-1$
+ }
+ mWriter.write(">\n"); //$NON-NLS-1$
if (issues.size() > 0) {
for (Warning warning : issues) {
mWriter.write('\n');
indent(mWriter, 1);
mWriter.write("<issue"); //$NON-NLS-1$
- writeAttribute(mWriter, 2, "id", warning.issue.getId()); //$NON-NLS-1$
- writeAttribute(mWriter, 2, "severity", warning.severity.getDescription()); //$NON-NLS-1$
- writeAttribute(mWriter, 2, "message", warning.message); //$NON-NLS-1$
+ Issue issue = warning.issue;
+ writeAttribute(mWriter, 2, "id", issue.getId()); //$NON-NLS-1$
+ writeAttribute(mWriter, 2, "severity",
+ warning.severity.getDescription());
+ writeAttribute(mWriter, 2, "message", warning.message); //$NON-NLS-1$
+
+ writeAttribute(mWriter, 2, "category", //$NON-NLS-1$
+ issue.getCategory().getFullName());
+ writeAttribute(mWriter, 2, "priority", //$NON-NLS-1$
+ Integer.toString(issue.getPriority()));
+ writeAttribute(mWriter, 2, "summary", issue.getDescription()); //$NON-NLS-1$
+ writeAttribute(mWriter, 2, "explanation", issue.getExplanation()); //$NON-NLS-1$
+ if (issue.getMoreInfo() != null) {
+ writeAttribute(mWriter, 2, "url", issue.getMoreInfo()); //$NON-NLS-1$
+ }
+ if (warning.errorLine != null && !warning.errorLine.isEmpty()) {
+ String line = warning.errorLine;
+ int index1 = line.indexOf('\n');
+ if (index1 != -1) {
+ int index2 = line.indexOf('\n', index1 + 1);
+ if (index2 != -1) {
+ String line1 = line.substring(0, index1);
+ String line2 = line.substring(index1 + 1, index2);
+ writeAttribute(mWriter, 2, "errorLine1", line1); //$NON-NLS-1$
+ writeAttribute(mWriter, 2, "errorLine2", line2); //$NON-NLS-1$
+ }
+ }
+ }
+ if (mClient.getRegistry() instanceof BuiltinIssueRegistry &&
+ ((BuiltinIssueRegistry) mClient.getRegistry()).hasAutoFix(
+ "adt", issue)) { //$NON-NLS-1$
+ writeAttribute(mWriter, 2, "quickfix", "adt"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
assert (warning.file != null) == (warning.location != null);
if (warning.file != null) {
diff --git a/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintClient.java b/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintClient.java
index 4cca31c..f168d7a 100644
--- a/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintClient.java
+++ b/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintClient.java
@@ -423,6 +423,45 @@ public abstract class LintClient {
}
}
+ if (classes.size() == 0) {
+ File folder = new File(projectDir, CLASS_FOLDER);
+ if (folder.exists()) {
+ classes.add(folder);
+ } else {
+ // Maven checks
+ folder = new File(projectDir,
+ "target" + File.separator + "classes"); //$NON-NLS-1$ //$NON-NLS-2$
+ if (folder.exists()) {
+ classes.add(folder);
+
+ // If it's maven, also correct the source path, "src" works but
+ // it's in a more specific subfolder
+ if (sources.size() == 0) {
+ File src = new File(projectDir,
+ "src" + File.separator //$NON-NLS-1$
+ + "main" + File.separator //$NON-NLS-1$
+ + "java"); //$NON-NLS-1$
+ if (src.exists()) {
+ sources.add(src);
+ } else {
+ src = new File(projectDir, SRC_FOLDER);
+ if (src.exists()) {
+ sources.add(src);
+ }
+ }
+
+ File gen = new File(projectDir,
+ "target" + File.separator //$NON-NLS-1$
+ + "generated-sources" + File.separator //$NON-NLS-1$
+ + "r"); //$NON-NLS-1$
+ if (gen.exists()) {
+ sources.add(gen);
+ }
+ }
+ }
+ }
+ }
+
// Fallback, in case there is no Eclipse project metadata here
if (sources.size() == 0) {
File src = new File(projectDir, SRC_FOLDER);
@@ -434,12 +473,6 @@ public abstract class LintClient {
sources.add(gen);
}
}
- if (classes.size() == 0) {
- File folder = new File(projectDir, CLASS_FOLDER);
- if (folder.exists()) {
- classes.add(folder);
- }
- }
info = new ClassPathInfo(sources, classes, libraries);
mProjectInfo.put(project, info);
diff --git a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintConstants.java b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintConstants.java
index 47a52c0..a0ff760 100644
--- a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintConstants.java
+++ b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintConstants.java
@@ -175,6 +175,7 @@ public class LintConstants {
public static final String ATTR_IME_ACTION_LABEL = "imeActionLabel"; //$NON-NLS-1$
public static final String ATTR_PRIVATE_IME_OPTIONS = "privateImeOptions"; //$NON-NLS-1$
public static final String VALUE_NONE = "none"; //$NON-NLS-1$
+ public static final String VALUE_NO = "no"; //$NON-NLS-1$
public static final String ATTR_NUMERIC = "numeric"; //$NON-NLS-1$
public static final String ATTR_IME_ACTION_ID = "imeActionId"; //$NON-NLS-1$
public static final String ATTR_IME_OPTIONS = "imeOptions"; //$NON-NLS-1$
@@ -190,7 +191,9 @@ public class LintConstants {
public static final String ATTR_AUTO_TEXT = "autoText"; //$NON-NLS-1$
public static final String ATTR_ENABLED = "enabled"; //$NON-NLS-1$
public static final String ATTR_SINGLE_LINE = "singleLine"; //$NON-NLS-1$
- public static final String ATTR_SCALE_TYPE = "scaleType"; //$NON-NLS-1$
+ public static final String ATTR_SCALE_TYPE = "scaleType"; //$NON-NLS-1$
+ public static final String ATTR_IMPORTANT_FOR_ACCESSIBILITY =
+ "importantForAccessibility"; //$NON-NLS-1$
// AbsoluteLayout layout params
public static final String ATTR_LAYOUT_Y = "layout_y"; //$NON-NLS-1$
diff --git a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintUtils.java b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintUtils.java
index ce64fe3..1d9ba2e 100644
--- a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintUtils.java
+++ b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintUtils.java
@@ -30,6 +30,8 @@ import com.android.resources.ResourceType;
import com.android.tools.lint.client.api.LintClient;
import com.android.util.PositionXmlParser;
import com.google.common.annotations.Beta;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
@@ -324,6 +326,41 @@ public class LintUtils {
}
/**
+ * Splits the given path into its individual parts, attempting to be
+ * tolerant about path separators (: or ;). It can handle possibly ambiguous
+ * paths, such as {@code c:\foo\bar:\other}, though of course these are to
+ * be avoided if possible.
+ *
+ * @param path the path variable to split, which can use both : and ; as
+ * path separators.
+ * @return the individual path components as an iterable of strings
+ */
+ public static Iterable<String> splitPath(String path) {
+ if (path.indexOf(';') != -1) {
+ return Splitter.on(';').omitEmptyStrings().trimResults().split(path);
+ }
+
+ List<String> combined = new ArrayList<String>();
+ Iterables.addAll(combined, Splitter.on(':').omitEmptyStrings().trimResults().split(path));
+ for (int i = 0, n = combined.size(); i < n; i++) {
+ String p = combined.get(i);
+ if (p.length() == 1 && i < n - 1 && Character.isLetter(p.charAt(0))
+ // Technically, Windows paths do not have to have a \ after the :,
+ // which means it would be using the current directory on that drive,
+ // but that's unlikely to be the case in a path since it would have
+ // unpredictable results
+ && !combined.get(i+1).isEmpty() && combined.get(i+1).charAt(0) == '\\') {
+ combined.set(i, p + ':' + combined.get(i+1));
+ combined.remove(i+1);
+ n--;
+ continue;
+ }
+ }
+
+ return combined;
+ }
+
+ /**
* Computes the shared parent among a set of files (which may be null).
*
* @param files the set of files to be checked
@@ -633,4 +670,41 @@ public class LintUtils {
return hasManifest;
}
+
+ /**
+ * Look up the locale and region from the given parent folder name and
+ * return it as a combined string, such as "en", "en-rUS", etc, or null if
+ * no language is specified.
+ *
+ * @param folderName the folder name
+ * @return the locale+region string or null
+ */
+ @Nullable
+ public static String getLocaleAndRegion(@NonNull String folderName) {
+ if (folderName.equals("values")) { //$NON-NLS-1$
+ return null;
+ }
+
+ String locale = null;
+
+ for (String qualifier : Splitter.on('-').split(folderName)) {
+ int qualifierLength = qualifier.length();
+ if (qualifierLength == 2) {
+ char first = qualifier.charAt(0);
+ char second = qualifier.charAt(1);
+ if (first >= 'a' && first <= 'z' && second >= 'a' && second <= 'z') {
+ locale = qualifier;
+ }
+ } else if (qualifierLength == 3 && qualifier.charAt(0) == 'r' && locale != null) {
+ char first = qualifier.charAt(1);
+ char second = qualifier.charAt(2);
+ if (first >= 'A' && first <= 'Z' && second >= 'A' && second <= 'Z') {
+ return locale + '-' + qualifier;
+ }
+ break;
+ }
+ }
+
+ return locale;
+ }
}
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/AccessibilityDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/AccessibilityDetector.java
index 323f88a..e1be383 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/AccessibilityDetector.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/AccessibilityDetector.java
@@ -18,8 +18,10 @@ package com.android.tools.lint.checks;
import static com.android.tools.lint.detector.api.LintConstants.ANDROID_URI;
import static com.android.tools.lint.detector.api.LintConstants.ATTR_CONTENT_DESCRIPTION;
+import static com.android.tools.lint.detector.api.LintConstants.ATTR_IMPORTANT_FOR_ACCESSIBILITY;
import static com.android.tools.lint.detector.api.LintConstants.IMAGE_BUTTON;
import static com.android.tools.lint.detector.api.LintConstants.IMAGE_VIEW;
+import static com.android.tools.lint.detector.api.LintConstants.VALUE_NO;
import com.android.annotations.NonNull;
import com.android.tools.lint.detector.api.Category;
@@ -78,6 +80,11 @@ public class AccessibilityDetector extends LayoutDetector {
@Override
public void visitElement(@NonNull XmlContext context, @NonNull Element element) {
if (!element.hasAttributeNS(ANDROID_URI, ATTR_CONTENT_DESCRIPTION)) {
+ // Ignore views that are explicitly not important for accessibility
+ if (VALUE_NO.equals(element.getAttributeNS(ANDROID_URI,
+ ATTR_IMPORTANT_FOR_ACCESSIBILITY))) {
+ return;
+ }
context.report(ISSUE, element, context.getLocation(element),
"[Accessibility] Missing contentDescription attribute on image", null);
} else {
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/TranslationDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/TranslationDetector.java
index f89fb81..391033e 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/TranslationDetector.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/TranslationDetector.java
@@ -30,6 +30,7 @@ import com.android.resources.ResourceFolderType;
import com.android.tools.lint.detector.api.Category;
import com.android.tools.lint.detector.api.Context;
import com.android.tools.lint.detector.api.Issue;
+import com.android.tools.lint.detector.api.LintUtils;
import com.android.tools.lint.detector.api.Location;
import com.android.tools.lint.detector.api.ResourceXmlDetector;
import com.android.tools.lint.detector.api.Scope;
@@ -73,6 +74,12 @@ public class TranslationDetector extends ResourceXmlDetector {
"If an application has more than one locale, then all the strings declared in " +
"one language should also be translated in all other languages.\n" +
"\n" +
+ "If the string should *not* be translated, you can add the attribute\n" +
+ "translatable=\"false\" on the <string> element, or you can define all " +
+ "your non-translatable strings in a resource file called \"donottranslate.xml\". " +
+ "Or, you can ignore the issue with a tools:ignore=\"MissingTranslation\" " +
+ "attribute.\n" +
+ "\n" +
"By default this detector allows regions of a language to just provide a " +
"subset of the strings and fall back to the standard language strings. " +
"You can require all regions to provide a full translation by setting the " +
@@ -90,15 +97,19 @@ public class TranslationDetector extends ResourceXmlDetector {
"If a string appears in a specific language translation file, but there is " +
"no corresponding string in the default locale, then this string is probably " +
"unused. (It's technically possible that your application is only intended to " +
- "run in a specific locale, but it's still a good idea to provide a fallback.)",
+ "run in a specific locale, but it's still a good idea to provide a fallback.).\n" +
+ "\n" +
+ "Note that these strings can lead to crashes if the string is looked up on any " +
+ "locale not providing a translation, so it's important to clean them up.",
Category.MESSAGES,
6,
- Severity.WARNING,
+ Severity.FATAL,
TranslationDetector.class,
Scope.ALL_RESOURCES_SCOPE);
private Set<String> mNames;
private Set<String> mTranslatedArrays;
+ private Set<String> mNonTranslatable;
private boolean mIgnoreFile;
private Map<File, Set<String>> mFileToNames;
@@ -457,6 +468,17 @@ public class TranslationDetector extends ResourceXmlDetector {
Attr translatable = element.getAttributeNode(ATTR_TRANSLATABLE);
if (translatable != null && !Boolean.valueOf(translatable.getValue())) {
+ String l = LintUtils.getLocaleAndRegion(context.file.getParentFile().getName());
+ if (l != null) {
+ context.report(EXTRA, context.getLocation(translatable),
+ "Non-translatable resources should only be defined in the base " +
+ "values/ folder", null);
+ } else {
+ if (mNonTranslatable == null) {
+ mNonTranslatable = new HashSet<String>();
+ }
+ mNonTranslatable.add(name);
+ }
return;
}
@@ -489,6 +511,12 @@ public class TranslationDetector extends ResourceXmlDetector {
mNames.add(name);
+ if (mNonTranslatable != null && mNonTranslatable.contains(name)) {
+ String message = String.format("The resource string \"%1$s\" has been marked as " +
+ "translatable=\"false\"", name);
+ context.report(EXTRA, context.getLocation(attribute), message, null);
+ }
+
// TBD: Also make sure that the strings are not empty or placeholders?
}
}
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/TypoDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/TypoDetector.java
index 5b50308..ad3b7a3 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/TypoDetector.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/TypoDetector.java
@@ -16,6 +16,7 @@
package com.android.tools.lint.checks;
+import static com.android.tools.lint.checks.TypoLookup.isLetter;
import static com.android.tools.lint.detector.api.LintConstants.TAG_STRING;
import static com.google.common.base.Objects.equal;
@@ -40,7 +41,6 @@ import org.w3c.dom.NodeList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.Iterator;
import java.util.List;
/**
@@ -76,8 +76,11 @@ import java.util.List;
* </ul>
*/
public class TypoDetector extends ResourceXmlDetector {
- private TypoLookup mLookup;
- private String mLastLanguage;
+ private @Nullable TypoLookup mLookup;
+ private @Nullable String mLastLanguage;
+ private @Nullable String mLastRegion;
+ private @Nullable String mLanguage;
+ private @Nullable String mRegion;
/** The main issue discovered by this detector */
public static final Issue ISSUE = Issue.create(
@@ -101,36 +104,46 @@ public class TypoDetector extends ResourceXmlDetector {
return folderType == ResourceFolderType.VALUES;
}
- /** Look up the locale from the given parent folder name, or null if there isn't one */
- @Nullable
- private String getLocale(@NonNull String parent) {
+ /** Look up the locale and region from the given parent folder name and store it
+ * in {@link #mLanguage} and {@link #mRegion} */
+ private void initLocale(@NonNull String parent) {
+ mLanguage = null;
+ mRegion = null;
+
if (parent.equals("values")) { //$NON-NLS-1$
- return null;
+ return;
}
for (String qualifier : Splitter.on('-').split(parent)) {
- if (qualifier.length() == 2) {
+ int qualifierLength = qualifier.length();
+ if (qualifierLength == 2) {
char first = qualifier.charAt(0);
- char second = qualifier.charAt(0);
+ char second = qualifier.charAt(1);
if (first >= 'a' && first <= 'z' && second >= 'a' && second <= 'z') {
- return qualifier;
+ mLanguage = qualifier;
+ }
+ } else if (qualifierLength == 3 && qualifier.charAt(0) == 'r') {
+ char first = qualifier.charAt(1);
+ char second = qualifier.charAt(2);
+ if (first >= 'A' && first <= 'Z' && second >= 'A' && second <= 'Z') {
+ mRegion = new String(new char[] { first, second }); // Don't include the "r"
}
+ break;
}
}
-
- return null;
}
@Override
public void beforeCheckFile(@NonNull Context context) {
- String language = getLocale(context.file.getParentFile().getName());
- if (language == null) {
- language = "en"; //$NON-NLS-1$
+ initLocale(context.file.getParentFile().getName());
+ if (mLanguage == null) {
+ mLanguage = "en"; //$NON-NLS-1$
}
- if (!equal(mLastLanguage, language)) {
- mLastLanguage = language;
- mLookup = TypoLookup.get(context.getClient(), language);
+ if (!equal(mLastLanguage, mLanguage) || !equal(mLastRegion, mRegion)) {
+ mLookup = TypoLookup.get(context.getClient(), mLanguage, mRegion);
+ mLastLanguage = mLanguage;
+ mLastRegion = mRegion;
}
}
@@ -177,7 +190,6 @@ public class TypoDetector extends ResourceXmlDetector {
return;
}
int begin = index;
- index++;
while (index < max && Character.isLetter(text.charAt(index))) {
if (text.charAt(index) >= 0x80) {
// Switch to UTF-8 handling for this string
@@ -200,10 +212,9 @@ public class TypoDetector extends ResourceXmlDetector {
int end = index;
checkedTypos = true;
- Iterable<String> replacements = mLookup.getTypos(text, begin, end);
+ List<String> replacements = mLookup.getTypos(text, begin, end);
if (replacements != null) {
- String word = text.substring(begin, end);
- reportTypo(context, node, word, begin, end, replacements);
+ reportTypo(context, node, text, begin, replacements);
}
index = end + 1;
@@ -214,10 +225,10 @@ public class TypoDetector extends ResourceXmlDetector {
int byteStart, int byteEnd, String text, int charStart) {
int index = byteStart;
while (index < byteEnd) {
- byte b = utf8Text[index];
// Find beginning of word
while (index < byteEnd) {
- if (b != ' ' && b != '\t' && b != '\n' && b != '\r') {
+ byte b = utf8Text[index];
+ if (isLetter(b)) {
break;
}
index++;
@@ -232,12 +243,12 @@ public class TypoDetector extends ResourceXmlDetector {
}
int charEnd = charStart;
int begin = index;
- index++;
// Find end of word. Unicode has the nice property that even 2nd, 3rd and 4th
// bytes won't match these ASCII characters (because the high bit must be set there)
while (index < byteEnd) {
- if (b == ' ' || b == '\t' || b == '\n' || b == '\r') {
+ byte b = utf8Text[index];
+ if (!isLetter(b)) {
break;
}
index++;
@@ -248,56 +259,62 @@ public class TypoDetector extends ResourceXmlDetector {
}
int end = index;
- Iterable<String> replacements = mLookup.getTypos(utf8Text, begin, end);
+ List<String> replacements = mLookup.getTypos(utf8Text, begin, end);
if (replacements != null) {
- String word = text.substring(charStart, charEnd);
- reportTypo(context, node, word, charStart, end, replacements);
+ reportTypo(context, node, text, charStart, replacements);
}
- index = end + 1;
+ charStart = charEnd;
}
}
-
/** Report the typo found at the given offset and suggest the given replacements */
- private void reportTypo(XmlContext context, Node node,
- String word, int begin, int end, Iterable<String> replacements) {
+ private void reportTypo(XmlContext context, Node node, String text, int begin,
+ List<String> replacements) {
+ if (replacements.size() < 2) {
+ return;
+ }
+
+ String typo = replacements.get(0);
+ String word = text.substring(begin, begin + typo.length());
+
String first = null;
String message;
- Iterator<String> iterator = replacements.iterator();
- if (iterator.hasNext()) {
- boolean isCapitalized = Character.isUpperCase(word.charAt(0));
- StringBuilder sb = new StringBuilder();
- for (String replacement : replacements) {
- if (first == null) {
- first = replacement;
- }
- if (sb.length() > 0) {
- sb.append(" or ");
- }
- sb.append('"');
- if (isCapitalized) {
- sb.append(Character.toUpperCase(replacement.charAt(0))
- + replacement.substring(1));
- } else {
- sb.append(replacement);
- }
- sb.append('"');
- }
- if (first != null && first.equalsIgnoreCase(word)) {
- message = String.format(
- "\"%1$s\" is usually capitalized as \"%2$s\"",
- word, first);
+ boolean isCapitalized = Character.isUpperCase(word.charAt(0));
+ StringBuilder sb = new StringBuilder();
+ for (int i = 1, n = replacements.size(); i < n; i++) {
+ String replacement = replacements.get(i);
+ if (first == null) {
+ first = replacement;
+ }
+ if (sb.length() > 0) {
+ sb.append(" or ");
+ }
+ sb.append('"');
+ if (isCapitalized) {
+ sb.append(Character.toUpperCase(replacement.charAt(0))
+ + replacement.substring(1));
} else {
- message = String.format(
- "\"%1$s\" is a common misspelling; did you mean %2$s ?",
- word, sb.toString());
+ sb.append(replacement);
+ }
+ sb.append('"');
+ }
+
+ if (first != null && first.equalsIgnoreCase(word)) {
+ if (first.equals(word)) {
+ return;
}
+ message = String.format(
+ "\"%1$s\" is usually capitalized as \"%2$s\"",
+ word, first);
} else {
- message = String.format("\"%1$s\" is a common misspelling", word);
+ message = String.format(
+ "\"%1$s\" is a common misspelling; did you mean %2$s ?",
+ word, sb.toString());
}
+ int end = begin + word.length();
context.report(ISSUE, node, context.getLocation(node, begin, end), message, null);
}
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/TypoLookup.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/TypoLookup.java
index 767a6ec..4a4591d 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/TypoLookup.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/TypoLookup.java
@@ -21,12 +21,12 @@ import static com.android.tools.lint.detector.api.LintUtils.assertionsEnabled;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
+import com.android.annotations.VisibleForTesting;
import com.android.tools.lint.client.api.LintClient;
import com.android.tools.lint.detector.api.LintUtils;
import com.google.common.base.Charsets;
import com.google.common.base.Splitter;
import com.google.common.io.Files;
-import com.google.common.primitives.UnsignedBytes;
import java.io.File;
import java.io.FileOutputStream;
@@ -79,16 +79,32 @@ public class TypoLookup {
* originally passed in. In other words, this parameter may be
* ignored if the client created is not new.
* @param locale the locale to look up a typo database for (should be a
- * language code (ISO 639-1, two lowercase character names)
+ * language code (ISO 639-1, two lowercase character names)
+ * @param region the region to look up a typo database for (should be a two
+ * letter ISO 3166-1 alpha-2 country code in upper case) language
+ * code
* @return a (possibly shared) instance of the typo database, or null if its
* data can't be found
*/
@Nullable
- public static TypoLookup get(@NonNull LintClient client, @NonNull String locale) {
+ public static TypoLookup get(@NonNull LintClient client, @NonNull String locale,
+ @Nullable String region) {
synchronized (TypoLookup.class) {
- TypoLookup db = sInstanceMap.get(locale);
+ String key = locale;
+
+ if (region != null) {
+ // Allow for region-specific dictionaries. See for example
+ // http://en.wikipedia.org/wiki/American_and_British_English_spelling_differences
+ assert region.length() == 2
+ && Character.isUpperCase(region.charAt(0))
+ && Character.isUpperCase(region.charAt(1)) : region;
+ // Look for typos-en-rUS.txt etc
+ key = locale + 'r' + region;
+ }
+
+ TypoLookup db = sInstanceMap.get(key);
if (db == null) {
- String path = String.format(XML_FILE_PATH, locale);
+ String path = String.format(XML_FILE_PATH, key);
File file = client.findResource(path);
if (file == null) {
// AOSP build environment?
@@ -101,11 +117,16 @@ public class TypoLookup {
}
if (file == null || !file.exists()) {
+ if (region != null) {
+ // Fall back to the generic locale (non-region-specific) database
+ return get(client, locale, null);
+ }
db = NONE;
} else {
db = get(client, file);
+ assert db != null : file;
}
- sInstanceMap.put(locale, db);
+ sInstanceMap.put(key, db);
}
if (db == NONE) {
@@ -126,7 +147,8 @@ public class TypoLookup {
* @return a (possibly shared) instance of the typo database, or null
* if its data can't be found
*/
- public static TypoLookup get(LintClient client, File xmlFile) {
+ @Nullable
+ private static TypoLookup get(LintClient client, File xmlFile) {
if (!xmlFile.exists()) {
client.log(null, "The typo database file %1$s does not exist", xmlFile);
return null;
@@ -303,8 +325,12 @@ public class TypoLookup {
if (end == -1) {
end = line.trim().length();
}
- String typo = line.substring(0, end);
+ String typo = line.substring(0, end).trim();
String replacements = line.substring(end + WORD_SEPARATOR.length()).trim();
+ if (replacements.isEmpty()) {
+ // We don't support empty replacements
+ continue;
+ }
String combined = typo + (char) 0 + replacements;
words.add(combined);
@@ -398,36 +424,65 @@ public class TypoLookup {
// For debugging only
private String dumpEntry(int offset) {
if (DEBUG_SEARCH) {
- StringBuilder sb = new StringBuilder();
- for (int i = offset; i < mData.length; i++) {
- if (mData[i] == 0) {
- break;
- }
- char c = (char) UnsignedBytes.toInt(mData[i]);
- sb.append(c);
+ int end = offset;
+ while (mData[end] != 0) {
+ end++;
}
-
- return sb.toString();
+ return new String(mData, offset, end - offset, Charsets.UTF_8);
} else {
return "<disabled>"; //$NON-NLS-1$
}
}
/** Comparison function: *only* used for ASCII strings */
- private static int compare(byte[] data, int offset, byte terminator, CharSequence s,
+ @VisibleForTesting
+ static int compare(byte[] data, int offset, byte terminator, CharSequence s,
int begin, int end) {
int i = offset;
int j = begin;
- for (; j < end; i++, j++) {
+ for (; ; i++, j++) {
byte b = data[i];
+ if (b == ' ') {
+ // We've matched up to the space in a split-word typo, such as
+ // in German all zu=>allzu; here we've matched just past "all".
+ // Rather than terminating, attempt to continue in the buffer.
+ if (j == end) {
+ int max = s.length();
+ if (end < max && s.charAt(end) == ' ') {
+ // Find next word
+ for (; end < max; end++) {
+ char c = s.charAt(end);
+ if (!Character.isLetter(c)) {
+ if (c == ' ' && end == j) {
+ continue;
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (j == end) {
+ break;
+ }
+
+ if (b == '*') {
+ // Glob match (only supported at the end)
+ return 0;
+ }
char c = s.charAt(j);
byte cb = (byte) c;
int delta = b - cb;
if (delta != 0) {
cb = (byte) Character.toLowerCase(c);
- delta = b - cb;
- if (delta != 0) {
- return delta;
+ if (b != cb) {
+ // Ensure that it has the right sign
+ b = (byte) Character.toLowerCase(b);
+ delta = b - cb;
+ if (delta != 0) {
+ return delta;
+ }
}
}
}
@@ -436,22 +491,51 @@ public class TypoLookup {
}
/** Comparison function used for general UTF-8 encoded strings */
- private static int compare(byte[] data, int offset, byte terminator, byte[] s,
+ @VisibleForTesting
+ static int compare(byte[] data, int offset, byte terminator, byte[] s,
int begin, int end) {
int i = offset;
int j = begin;
- for (; j < end; i++, j++) {
+ for (; ; i++, j++) {
byte b = data[i];
+ if (b == ' ') {
+ // We've matched up to the space in a split-word typo, such as
+ // in German all zu=>allzu; here we've matched just past "all".
+ // Rather than terminating, attempt to continue in the buffer.
+ // We've matched up to the space in a split-word typo, such as
+ // in German all zu=>allzu; here we've matched just past "all".
+ // Rather than terminating, attempt to continue in the buffer.
+ if (j == end) {
+ int max = s.length;
+ if (end < max && s[end] == ' ') {
+ // Find next word
+ for (; end < max; end++) {
+ byte cb = s[end];
+ if (!isLetter(cb)) {
+ if (cb == ' ' && end == j) {
+ continue;
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (j == end) {
+ break;
+ }
+ if (b == '*') {
+ // Glob match (only supported at the end)
+ return 0;
+ }
byte cb = s[j];
int delta = b - cb;
if (delta != 0) {
- if (cb >= 'A' && cb <= 'Z') { // TODO: Generalize lower-casing here
- cb -= 'A' - 'a';
- delta = b - cb;
- if (delta != 0) {
- return delta;
- }
- } else {
+ cb = toLowerCase(cb);
+ b = toLowerCase(b);
+ delta = b - cb;
+ if (delta != 0) {
return delta;
}
}
@@ -465,17 +549,19 @@ public class TypoLookup {
}
/**
- * Look up whether this word is a typo, and if so, return one or more likely
- * meanings
+ * Look up whether this word is a typo, and if so, return the typo itself
+ * and one or more likely meanings
*
* @param text the string containing the word
* @param begin the index of the first character in the word
- * @param end the index of the first character after the word
- * @return an iterable of replacement strings if the word represents a typo,
- * and null otherwise
+ * @param end the index of the first character after the word. Note that the
+ * search may extend <b>beyond</b> this index, if for example the
+ * word matches a multi-word typo in the dictionary
+ * @return a list of the typo itself followed by the replacement strings if
+ * the word represents a typo, and null otherwise
*/
@Nullable
- public Iterable<String> getTypos(@NonNull CharSequence text, int begin, int end) {
+ public List<String> getTypos(@NonNull CharSequence text, int begin, int end) {
assert end <= text.length();
if (assertionsEnabled()) {
@@ -501,15 +587,36 @@ public class TypoLookup {
// Compare the word at the given index.
int compare = compare(mData, offset, (byte) 0, text, begin, end);
+
if (compare == 0) {
offset = mIndices[middle];
+ // Don't allow matching uncapitalized words, such as "enlish", when
+ // the dictionary word is capitalized, "Enlish".
+ if (mData[offset] != text.charAt(begin)
+ && Character.isLowerCase(text.charAt(begin))) {
+ return null;
+ }
+
// Make sure there is a case match; we only want to allow
// matching capitalized words to capitalized typos or uncapitalized typos
// (e.g. "Teh" and "teh" to "the"), but not uncapitalized words to capitalized
// typos (e.g. "enlish" to "Enlish").
- for (int i = begin; i < end; i++) {
+ String glob = null;
+ for (int i = begin; ; i++) {
byte b = mData[offset++];
+ if (b == 0) {
+ offset--;
+ break;
+ } else if (b == '*') {
+ int globEnd = i;
+ while (globEnd < text.length()
+ && Character.isLetter(text.charAt(globEnd))) {
+ globEnd++;
+ }
+ glob = text.subSequence(i, globEnd).toString();
+ break;
+ }
char c = text.charAt(i);
byte cb = (byte) c;
if (b != cb && i > begin) {
@@ -517,15 +624,7 @@ public class TypoLookup {
}
}
- assert mData[offset] == 0;
- offset++;
- int replacementEnd = offset;
- while (mData[replacementEnd] != 0) {
- replacementEnd++;
- }
- String replacements = new String(mData, offset, replacementEnd - offset,
- Charsets.UTF_8);
- return Splitter.on(',').omitEmptyStrings().trimResults().split(replacements);
+ return computeSuggestions(mIndices[middle], offset, glob);
}
if (compare < 0) {
@@ -542,17 +641,19 @@ public class TypoLookup {
}
/**
- * Look up whether this word is a typo, and if so, return one or more likely
- * meanings
+ * Look up whether this word is a typo, and if so, return the typo itself
+ * and one or more likely meanings
*
* @param utf8Text the string containing the word, encoded as UTF-8
* @param begin the index of the first character in the word
- * @param end the index of the first character after the word
- * @return an iterable of replacement strings if the word represents a typo,
- * and null otherwise
+ * @param end the index of the first character after the word. Note that the
+ * search may extend <b>beyond</b> this index, if for example the
+ * word matches a multi-word typo in the dictionary
+ * @return a list of the typo itself followed by the replacement strings if
+ * the word represents a typo, and null otherwise
*/
@Nullable
- public Iterable<String> getTypos(@NonNull byte[] utf8Text, int begin, int end) {
+ public List<String> getTypos(@NonNull byte[] utf8Text, int begin, int end) {
assert end <= utf8Text.length;
int low = 0;
@@ -562,36 +663,53 @@ public class TypoLookup {
int offset = mIndices[middle];
if (DEBUG_SEARCH) {
- System.out.println("Comparing string " + utf8Text +" with entry at " + offset
+ String s = new String(Arrays.copyOfRange(utf8Text, begin, end), Charsets.UTF_8);
+ System.out.println("Comparing string " + s +" with entry at " + offset
+ ": " + dumpEntry(offset));
+ System.out.println(" middle=" + middle + ", low=" + low + ", high=" + high);
}
// Compare the word at the given index.
int compare = compare(mData, offset, (byte) 0, utf8Text, begin, end);
+
+ if (DEBUG_SEARCH) {
+ System.out.println(" signum=" + (int)Math.signum(compare) + ", delta=" + compare);
+ }
+
if (compare == 0) {
offset = mIndices[middle];
+ // Don't allow matching uncapitalized words, such as "enlish", when
+ // the dictionary word is capitalized, "Enlish".
+ if (mData[offset] != utf8Text[begin] && isUpperCase(mData[offset])) {
+ return null;
+ }
+
// Make sure there is a case match; we only want to allow
// matching capitalized words to capitalized typos or uncapitalized typos
// (e.g. "Teh" and "teh" to "the"), but not uncapitalized words to capitalized
// typos (e.g. "enlish" to "Enlish").
- for (int i = begin; i < end; i++) {
+ String glob = null;
+ for (int i = begin; ; i++) {
byte b = mData[offset++];
+ if (b == 0) {
+ offset--;
+ break;
+ } else if (b == '*') {
+ int globEnd = i;
+ while (globEnd < utf8Text.length && isLetter(utf8Text[globEnd])) {
+ globEnd++;
+ }
+ glob = new String(utf8Text, i, globEnd - i, Charsets.UTF_8);
+ break;
+ }
byte cb = utf8Text[i];
if (b != cb && i > begin) {
return null;
}
}
- assert mData[offset] == 0;
- offset++;
- int replacementEnd = offset;
- while (mData[replacementEnd] != 0) {
- replacementEnd++;
- }
- String replacements = new String(mData, offset, replacementEnd - offset,
- Charsets.UTF_8);
- return Splitter.on(',').omitEmptyStrings().trimResults().split(replacements);
+ return computeSuggestions(mIndices[middle], offset, glob);
}
if (compare < 0) {
@@ -606,4 +724,62 @@ public class TypoLookup {
return null;
}
+
+ private List<String> computeSuggestions(int begin, int offset, String glob) {
+ String typo = new String(mData, begin, offset - begin, Charsets.UTF_8);
+
+ if (glob != null) {
+ typo = typo.replaceAll("\\*", glob); //$NON-NLS-1$
+ }
+
+ assert mData[offset] == 0;
+ offset++;
+ int replacementEnd = offset;
+ while (mData[replacementEnd] != 0) {
+ replacementEnd++;
+ }
+ String replacements = new String(mData, offset, replacementEnd - offset, Charsets.UTF_8);
+ List<String> words = new ArrayList<String>();
+ words.add(typo);
+
+ // The first entry should be the typo itself. We need to pass this back since due
+ // to multi-match words and globbing it could extend beyond the initial word range
+
+ for (String s : Splitter.on(',').omitEmptyStrings().trimResults().split(replacements)) {
+ if (glob != null) {
+ // Need to append the glob string to each result
+ words.add(s.replaceAll("\\*", glob)); //$NON-NLS-1$
+ } else {
+ words.add(s);
+ }
+ }
+
+ return words;
+ }
+
+ // "Character" handling for bytes. This assumes that the bytes correspond to Unicode
+ // characters in the ISO 8859-1 range, which is are encoded the same way in UTF-8.
+ // This obviously won't work to for example uppercase to lowercase conversions for
+ // multi byte characters, which means we simply won't catch typos if the dictionaries
+ // contain these. None of the currently included dictionaries do. However, it does
+ // help us properly deal with punctuation and spacing characters.
+
+ static final boolean isUpperCase(byte b) {
+ return Character.isUpperCase((char) b);
+ }
+
+ static final byte toLowerCase(byte b) {
+ return (byte) Character.toLowerCase((char) b);
+ }
+
+ static final boolean isSpace(byte b) {
+ return Character.isWhitespace((char) b);
+ }
+
+ static final boolean isLetter(byte b) {
+ // Assume that multi byte characters represent letters in other languages.
+ // Obviously, it could be unusual punctuation etc but letters are more likely
+ // in this context.
+ return Character.isLetter((char) b) || (b & 0x80) != 0;
+ }
}
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/XmlReporterTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/XmlReporterTest.java
new file mode 100644
index 0000000..4206161
--- /dev/null
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/XmlReporterTest.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tools.lint;
+
+import com.android.tools.lint.checks.AbstractCheckTest;
+import com.android.tools.lint.checks.HardcodedValuesDetector;
+import com.android.tools.lint.checks.ManifestOrderDetector;
+import com.android.tools.lint.detector.api.DefaultPosition;
+import com.android.tools.lint.detector.api.Detector;
+import com.android.tools.lint.detector.api.Location;
+import com.android.tools.lint.detector.api.Project;
+import com.android.tools.lint.detector.api.Severity;
+import com.android.util.PositionXmlParser;
+import com.google.common.base.Charsets;
+import com.google.common.io.Files;
+
+import org.w3c.dom.Document;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+@SuppressWarnings("javadoc")
+public class XmlReporterTest extends AbstractCheckTest {
+ public void test() throws Exception {
+ File file = new File(getTargetDir(), "report");
+ try {
+ Main client = new Main() {
+ @Override
+ String getRevision() {
+ return "unittest"; // Hardcode version to keep unit test output stable
+ }
+ };
+ file.getParentFile().mkdirs();
+ XmlReporter reporter = new XmlReporter(client, file);
+ Project project = Project.create(client, new File("/foo/bar/Foo"),
+ new File("/foo/bar/Foo"));
+
+ Warning warning1 = new Warning(ManifestOrderDetector.USES_SDK,
+ "<uses-sdk> tag should specify a target API level (the highest verified " +
+ "version; when running on later versions, compatibility behaviors may " +
+ "be enabled) with android:targetSdkVersion=\"?\"",
+ Severity.WARNING, project, null);
+ warning1.line = 6;
+ warning1.file = new File("/foo/bar/Foo/AndroidManifest.xml");
+ warning1.errorLine = " <uses-sdk android:minSdkVersion=\"8\" />\n ^\n";
+ warning1.path = "AndroidManifest.xml";
+ warning1.location = Location.create(warning1.file,
+ new DefaultPosition(6, 4, 198), new DefaultPosition(6, 42, 236));
+
+ Warning warning2 = new Warning(HardcodedValuesDetector.ISSUE,
+ "[I18N] Hardcoded string \"Fooo\", should use @string resource",
+ Severity.WARNING, project, null);
+ warning2.line = 11;
+ warning2.file = new File("/foo/bar/Foo/res/layout/main.xml");
+ warning2.errorLine = " (java.lang.String) android:text=\"Fooo\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~\n";
+ warning2.path = "res/layout/main.xml";
+ warning2.location = Location.create(warning2.file,
+ new DefaultPosition(11, 8, 377), new DefaultPosition(11, 27, 396));
+
+ List<Warning> warnings = new ArrayList<Warning>();
+ warnings.add(warning1);
+ warnings.add(warning2);
+
+ reporter.write(0, 2, warnings);
+
+ String report = Files.toString(file, Charsets.UTF_8);
+ assertEquals(
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+ "<issues format=\"3\" by=\"lint unittest\">\n" +
+ "\n" +
+ " <issue\n" +
+ " id=\"UsesMinSdkAttributes\"\n" +
+ " severity=\"Warning\"\n" +
+ " message=\"&lt;uses-sdk> tag should specify a target API level (the highest verified version; when running on later versions, compatibility behaviors may be enabled) with android:targetSdkVersion=&quot;?&quot;\"\n" +
+ " category=\"Correctness\"\n" +
+ " priority=\"2\"\n" +
+ " summary=\"Checks that the minimum SDK and target SDK attributes are defined\"\n" +
+ " explanation=\"The manifest should contain a &lt;uses-sdk> element which defines the minimum minimum API Level required for the application to run, as well as the target version (the highest API level you have tested the version for.)\"\n" +
+ " url=\"http://developer.android.com/guide/topics/manifest/uses-sdk-element.html\"\n" +
+ " errorLine1=\" &lt;uses-sdk android:minSdkVersion=&quot;8&quot; />\"\n" +
+ " errorLine2=\" ^\">\n" +
+ " <location\n" +
+ " file=\"AndroidManifest.xml\"\n" +
+ " line=\"7\"\n" +
+ " column=\"5\"/>\n" +
+ " </issue>\n" +
+ "\n" +
+ " <issue\n" +
+ " id=\"HardcodedText\"\n" +
+ " severity=\"Warning\"\n" +
+ " message=\"[I18N] Hardcoded string &quot;Fooo&quot;, should use @string resource\"\n" +
+ " category=\"Internationalization\"\n" +
+ " priority=\"5\"\n" +
+ " summary=\"Looks for hardcoded text attributes which should be converted to resource lookup\"\n" +
+ " explanation=\"Hardcoding text attributes directly in layout files is bad for several reasons:\n" +
+ "\n" +
+ "* When creating configuration variations (for example for landscape or portrait)you have to repeat the actual text (and keep it up to date when making changes)\n" +
+ "\n" +
+ "* The application cannot be translated to other languages by just adding new translations for existing string resources.\"\n" +
+ " errorLine1=\" (java.lang.String) android:text=&quot;Fooo&quot; />\"\n" +
+ " errorLine2=\" ~~~~~~~~~~~~~~~~~~~\">\n" +
+ " <location\n" +
+ " file=\"res/layout/main.xml\"\n" +
+ " line=\"12\"\n" +
+ " column=\"9\"/>\n" +
+ " </issue>\n" +
+ "\n" +
+ "</issues>\n",
+ report);
+
+ // Make sure the XML is valid
+ Document document = new PositionXmlParser().parse(report);
+ assertNotNull(document);
+ assertEquals(2, document.getElementsByTagName("issue").getLength());
+ } finally {
+ file.delete();
+ }
+ }
+
+ @Override
+ protected Detector getDetector() {
+ fail("Not used in this test");
+ return null;
+ }
+}
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AbstractCheckTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AbstractCheckTest.java
index 90bb29b..da84ae1 100644
--- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AbstractCheckTest.java
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/AbstractCheckTest.java
@@ -408,6 +408,7 @@ public abstract class AbstractCheckTest extends TestCase {
File sdkDir = dir.getParentFile().getParentFile().getParentFile()
.getParentFile().getParentFile().getParentFile();
File file = new File(sdkDir, "sdk" + File.separator + "files"
+ + File.separator + "typos"
+ File.separator + base);
return file;
} catch (URISyntaxException e) {
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/TranslationDetectorTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/TranslationDetectorTest.java
index 6f1c2e6..39231dd 100644
--- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/TranslationDetectorTest.java
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/TranslationDetectorTest.java
@@ -34,9 +34,9 @@ public class TranslationDetectorTest extends AbstractCheckTest {
TranslationDetector.COMPLETE_REGIONS = false;
assertEquals(
// Sample files from the Home app
- "values-cs/arrays.xml:3: Warning: \"security_questions\" is translated here but not found in default locale\n" +
+ "values-cs/arrays.xml:3: Error: \"security_questions\" is translated here but not found in default locale\n" +
"=> values-es/strings.xml:12: Also translated here\n" +
- "values-de-rDE/strings.xml:11: Warning: \"continue_skip_label\" is translated here but not found in default locale\n" +
+ "values-de-rDE/strings.xml:11: Error: \"continue_skip_label\" is translated here but not found in default locale\n" +
"values/strings.xml:20: Error: \"show_all_apps\" is not translated in nl-rNL\n" +
"values/strings.xml:23: Error: \"menu_wallpaper\" is not translated in nl-rNL\n" +
"values/strings.xml:25: Error: \"menu_settings\" is not translated in cs, de-rDE, es, es-rUS, nl-rNL",
@@ -57,7 +57,7 @@ public class TranslationDetectorTest extends AbstractCheckTest {
TranslationDetector.COMPLETE_REGIONS = true;
assertEquals(
// Sample files from the Home app
- "values-de-rDE/strings.xml:11: Warning: \"continue_skip_label\" is translated here but not found in default locale\n" +
+ "values-de-rDE/strings.xml:11: Error: \"continue_skip_label\" is translated here but not found in default locale\n" +
"values/strings.xml:19: Error: \"home_title\" is not translated in es-rUS\n" +
"values/strings.xml:20: Error: \"show_all_apps\" is not translated in es-rUS, nl-rNL\n" +
"values/strings.xml:23: Error: \"menu_wallpaper\" is not translated in es-rUS, nl-rNL\n" +
@@ -137,4 +137,25 @@ public class TranslationDetectorTest extends AbstractCheckTest {
"res/values-cs/strings.xml=>../LibraryProject/res/values-nl/strings.xml"
));
}
+
+ public void testNonTranslatable1() throws Exception {
+ TranslationDetector.COMPLETE_REGIONS = true;
+ assertEquals(
+ // Sample files from the Home app
+ "values-nb/nontranslatable.xml:3: Error: The resource string \"dummy\" has been " +
+ "marked as translatable=\"false\"",
+
+ lintProject("res/values/nontranslatable.xml",
+ "res/values/nontranslatable2.xml=>res/values-nb/nontranslatable.xml"));
+ }
+
+ public void testNonTranslatable2() throws Exception {
+ TranslationDetector.COMPLETE_REGIONS = true;
+ assertEquals(
+ // Sample files from the Home app
+ "values-nb/nontranslatable.xml:3: Error: Non-translatable resources should only " +
+ "be defined in the base values/ folder",
+
+ lintProject("res/values/nontranslatable.xml=>res/values-nb/nontranslatable.xml"));
+ }
}
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/TypoDetectorTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/TypoDetectorTest.java
index 646f032..864c065 100644
--- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/TypoDetectorTest.java
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/TypoDetectorTest.java
@@ -63,10 +63,19 @@ public class TypoDetectorTest extends AbstractCheckTest {
lintProject("res/values-nb/typos.xml"));
}
+ public void testGerman() throws Exception {
+ // Test globbing and multiple word matching
+ assertEquals(
+ "typos.xml:10: Warning: \"zurŸck gefoobaren\" is a common misspelling; did you mean \"zurŸckgefoobaren\" ?\n" +
+ "typos.xml:6: Warning: \"befindet eine\" is a common misspelling; did you mean \"befindet sich eine\" ?\n" +
+ "typos.xml:9: Warning: \"Authorisierungscode\" is a common misspelling; did you mean \"Autorisierungscode\" ?",
+ lintProject("res/values-de/typos.xml"));
+ }
+
public void testOk() throws Exception {
assertEquals(
"No warnings.",
- lintProject("res/values/typos.xml=>res/values-de/strings.xml"));
+ lintProject("res/values/typos.xml=>res/values-xy/strings.xml"));
}
public void testGetReplacements() {
@@ -75,6 +84,5 @@ public class TypoDetectorTest extends AbstractCheckTest {
assertEquals("throught", TypoDetector.getTypo(s));
assertEquals(Arrays.asList("thought", "through", "throughout"),
TypoDetector.getSuggestions(s));
-
}
}
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/TypoLookupTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/TypoLookupTest.java
index 0f4e15a..e57b8ce 100644
--- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/TypoLookupTest.java
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/TypoLookupTest.java
@@ -16,47 +16,110 @@
package com.android.tools.lint.checks;
+import com.android.tools.lint.client.api.LintClient;
import com.android.tools.lint.detector.api.Detector;
import com.google.common.base.Charsets;
+import com.google.common.base.Splitter;
+import com.google.common.io.Files;
-import java.util.Iterator;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
@SuppressWarnings("javadoc")
public class TypoLookupTest extends AbstractCheckTest {
+ private static final String SEPARATOR = "->";
+
+ public void testCapitalization() throws Exception {
+ LintClient client = new TestLintClient();
+ // Make sure it can be read in
+ TypoLookup db = TypoLookup.get(client, "de", null);
+ assertNotNull(db);
+ assertNotNull(db.getTypos("Andriod".getBytes(Charsets.UTF_8), 0, "Andriod".length()));
+ }
+
+ public void testDictionary_English() throws Exception {
+ validateDictionary("en");
+ }
+
+ public void testDictionary_German() throws Exception {
+ validateDictionary("de");
+ }
+
+ public void testDictionary_Spanish() throws Exception {
+ validateDictionary("es");
+ }
+
+ public void testDictionary_Hungarian() throws Exception {
+ validateDictionary("hu");
+ }
+
+ public void testDictionary_Italian() throws Exception {
+ validateDictionary("it");
+ }
+
+ public void testDictionary_Norwegian() throws Exception {
+ validateDictionary("nb");
+ }
+
+ public void testDictionary_Portuguese() throws Exception {
+ validateDictionary("pt");
+ }
+
+ public void testDictionary_Turkish() throws Exception {
+ validateDictionary("tr");
+ }
public void test1() {
- TypoLookup db = TypoLookup.get(new TestLintClient(), "en");
+ TypoLookup db = TypoLookup.get(new TestLintClient(), "en", null);
assertNull(db.getTypos("hello", 0, "hello".length()));
assertNull(db.getTypos("this", 0, "this".length()));
assertNotNull(db.getTypos("wiht", 0, "wiht".length()));
assertNotNull(db.getTypos("woudl", 0, "woudl".length()));
- assertEquals("would", db.getTypos("woudl", 0, "woudl".length()).iterator().next());
- assertEquals("would", db.getTypos(" woudl ", 2, 7).iterator().next());
+ assertEquals("would", db.getTypos("woudl", 0, "woudl".length()).get(1));
+ assertEquals("would", db.getTypos(" woudl ", 2, 7).get(1));
assertNotNull(db.getTypos("foo wiht bar", 4, 8));
- Iterator<String> typos = db.getTypos("throught", 0, "throught".length()).iterator();
- assertEquals("thought", typos.next());
- assertEquals("through", typos.next());
- assertEquals("throughout", typos.next());
+ List<String> typos = db.getTypos("throught", 0, "throught".length());
+ assertEquals("throught", typos.get(0)); // the typo
+ assertEquals("thought", typos.get(1));
+ assertEquals("through", typos.get(2));
+ assertEquals("throughout", typos.get(3));
// Capitalization handling
assertNotNull(db.getTypos("Woudl", 0, "Woudl".length()));
assertNotNull(db.getTypos("Enlish", 0, "Enlish".length()));
assertNull(db.getTypos("enlish", 0, "enlish".length()));
+ assertNull(db.getTypos("enlish".getBytes(Charsets.UTF_8), 0, "enlish".length()));
assertNotNull(db.getTypos("ok", 0, "ok".length()));
assertNotNull(db.getTypos("Ok", 0, "Ok".length()));
assertNull(db.getTypos("OK", 0, "OK".length()));
}
+ public void testRegion() {
+ TypoLookup db = TypoLookup.get(new TestLintClient(), "en", "US");
+ assertNotNull(db.getTypos("wiht", 0, "wiht".length()));
+ db = TypoLookup.get(new TestLintClient(), "en", "GB");
+ assertNotNull(db.getTypos("wiht", 0, "wiht".length()));
+ }
+
public void test2() {
- TypoLookup db = TypoLookup.get(new TestLintClient(), "nb"); //$NON-NLS-1$
+ TypoLookup db = TypoLookup.get(new TestLintClient(), "nb", null); //$NON-NLS-1$
assertNull(db.getTypos("hello", 0, "hello".length()));
assertNull(db.getTypos("this", 0, "this".length()));
assertNotNull(db.getTypos("altid", 0, "altid".length()));
- assertEquals("alltid", db.getTypos("altid", 0, "altid".length()).iterator().next());
- assertEquals("alltid", db.getTypos(" altid ", 2, 7).iterator().next());
+ assertEquals("alltid", db.getTypos("altid", 0, "altid".length()).get(1));
+ assertEquals("alltid", db.getTypos(" altid ", 2, 7).get(1));
assertNotNull(db.getTypos("foo altid bar", 4, 9));
// Test utf-8 string which isn't ASCII
@@ -64,7 +127,392 @@ public class TypoLookupTest extends AbstractCheckTest {
byte[] sb = s.getBytes(Charsets.UTF_8);
assertNotNull(db.getTypos(sb, 0, sb.length));
- assertEquals("karrière", db.getTypos(sb, 0, sb.length).iterator().next());
+ assertEquals("karrière", db.getTypos(sb, 0, sb.length).get(1));
+ }
+
+ public void testMultiWords() {
+ // Some language dictionaries contain multi-word sequences (e.g. where there's a
+ // space on the left hand side). This needs some particular care in the lookup
+ // which is usually word oriented.
+ TypoLookup db = TypoLookup.get(new TestLintClient(), "de", "DE"); //$NON-NLS-1$
+
+ // all zu->allzu
+
+ // Text handling
+ String t = "all zu";
+ assertNotNull(db.getTypos(t, 0, t.length()));
+ assertEquals("allzu", db.getTypos(t, 0, t.length()).get(1));
+
+ // Byte handling
+ byte[] text = "all zu".getBytes(Charsets.UTF_8);
+ assertNotNull(db.getTypos(text, 0, text.length));
+ assertEquals("allzu", db.getTypos(text, 0, text.length).get(1));
+
+ // Test automatically extending search beyond current word
+ text = "all zu".getBytes(Charsets.UTF_8);
+ assertNotNull(db.getTypos(text, 0, 3));
+ assertEquals("allzu", db.getTypos(text, 0, text.length).get(1));
+
+
+ text = ") all zu (".getBytes(Charsets.UTF_8);
+ assertNotNull(db.getTypos(text, 2, 8));
+ assertEquals("allzu", db.getTypos(text, 2, 8).get(1));
+
+ text = "am einem".getBytes(Charsets.UTF_8);
+ assertNotNull(db.getTypos(text, 0, text.length));
+ assertEquals("an einem", db.getTypos(text, 0, text.length).get(1));
+ }
+
+ public void testGlobbing() {
+ TypoLookup db = TypoLookup.get(new TestLintClient(), "de", null);
+
+ // Authorisierung*->Autorisierung*
+ String text = "Authorisierungscode";
+ byte[] bytes = text.getBytes(Charsets.UTF_8);
+
+ assertNotNull(db.getTypos(text, 0, text.length()));
+ assertEquals("Autorisierungscode", db.getTypos(text, 0, text.length()).get(1));
+ assertEquals(text, db.getTypos(text, 0, text.length()).get(0));
+
+ assertNotNull(db.getTypos(bytes, 0, bytes.length));
+ assertEquals("Autorisierungscode", db.getTypos(bytes, 0, bytes.length).get(1));
+
+ // befindet ein*->befindet sich ein*
+ text = "wo befindet eine ip";
+ assertEquals("befindet sich eine", db.getTypos(text, 3, 16).get(1));
+
+ // zurück ge*->zurückge*
+ text = "zurück gefoobaren";
+ bytes = text.getBytes(Charsets.UTF_8);
+ assertNotNull(db.getTypos(bytes, 0, bytes.length));
+ assertEquals("zurückgefoobaren", db.getTypos(bytes, 0, bytes.length).get(1));
+ }
+
+ public void testComparisons() throws Exception {
+ // Ensure that the two comparison methods agree
+
+ LintClient client = new TestLintClient();
+ for (String locale : new String[] { "de", "nb", "es", "en", "pt", "hu", "it", "tr" }) {
+ File f = client.findResource(String.format("tools/support/typos-%1$s.txt", locale));
+ assertTrue(locale, f != null && f.exists());
+
+ Set<String> typos = new HashSet<String>(2000);
+ List<String> lines = Files.readLines(f, Charsets.UTF_8);
+ for (int i = 0, n = lines.size(); i < n; i++) {
+ String line = lines.get(i);
+ if (line.isEmpty() || line.trim().startsWith("#")) { //$NON-NLS-1$
+ continue;
+ }
+
+ int index = line.indexOf(SEPARATOR);
+ if (index == -1) {
+ continue;
+ }
+ String typo = line.substring(0, index).trim();
+ typos.add(typo);
+ }
+
+ List<String> words = new ArrayList<String>(typos);
+
+ // Make sure that the two comparison methods agree on all the strings
+ // (which should be in a semi-random order now that they're in a set ordered
+ // by their hash codes)
+
+ String prevText = words.get(0) + '\000';
+ byte[] prevBytes = prevText.getBytes(Charsets.UTF_8);
+
+ for (int i = 1; i < words.size(); i++) {
+ String text = words.get(i) + '\000';;
+ byte[] bytes = text.getBytes(Charsets.UTF_8);
+
+ int textCompare = TypoLookup.compare(prevBytes, 0, (byte) 0, text, 0,
+ text.length());
+ int byteCompare = TypoLookup.compare(prevBytes, 0, (byte) 0, bytes, 0,
+ bytes.length);
+ assertEquals("Word " + text + " versus prev " + prevText + " at " + i,
+ Math.signum(textCompare), Math.signum(byteCompare));
+ }
+ }
+ }
+
+ public void testComparison1() throws Exception {
+ String prevText = "heraus gebracht\u0000";
+ byte[] prevBytes = prevText.getBytes(Charsets.UTF_8);
+
+ String text = "Päsident\u0000";
+ byte[] bytes = text.getBytes(Charsets.UTF_8);
+
+
+ int textCompare = TypoLookup.compare(prevBytes, 0, (byte) 0, text, 0,
+ text.length());
+ int byteCompare = TypoLookup.compare(prevBytes, 0, (byte) 0, bytes, 0,
+ bytes.length);
+ assertTrue(byteCompare < 0);
+ assertTrue(textCompare < 0);
+ assertEquals("Word " + text + " versus prev " + prevText,
+ Math.signum(textCompare), Math.signum(byteCompare));
+ }
+
+ public void testComparison2() throws Exception {
+ String prevText = "intepretation\u0000";
+ byte[] prevBytes = prevText.getBytes(Charsets.UTF_8);
+
+ String text = "Woudl\u0000";
+ byte[] bytes = text.getBytes(Charsets.UTF_8);
+
+ int textCompare = TypoLookup.compare(prevBytes, 0, (byte) 0, text, 0, text.length());
+ int byteCompare = TypoLookup.compare(prevBytes, 0, (byte) 0, bytes, 0, bytes.length);
+ assertTrue(byteCompare < 0);
+ assertTrue(textCompare < 0);
+ assertEquals("Word " + text + " versus prev " + prevText,
+ Math.signum(textCompare), Math.signum(byteCompare));
+
+ // Reverse capitalization and ensure that it's still the same
+ prevText = "Intepretation\u0000";
+ prevBytes = prevText.getBytes(Charsets.UTF_8);
+
+ text = "woudl\u0000";
+ bytes = text.getBytes(Charsets.UTF_8);
+
+ textCompare = TypoLookup.compare(prevBytes, 0, (byte) 0, text, 0, text.length());
+ byteCompare = TypoLookup.compare(prevBytes, 0, (byte) 0, bytes, 0, bytes.length);
+ assertTrue(byteCompare < 0);
+ assertTrue(textCompare < 0);
+ assertEquals("Word " + text + " versus prev " + prevText,
+ Math.signum(textCompare), Math.signum(byteCompare));
+ }
+
+ // Some dictionaries contain actual sentences regarding usage; these must be stripped out.
+ // They're just hardcoded here as we find them
+ private static final String[] sRemove = new String[] {
+ "- besser ganz darauf verzichten",
+ "oft fälschlich für \"angekündigt\"",
+ "hinausgehende* − insb. „darüber hinausgehende“",
+ " - besser ganz darauf verzichten",
+ "svw. bzw. so viel wie bzw. sprachverwandt"
+ };
+
+ private void validateDictionary(String locale) throws Exception {
+ // Check that all the typo files are well formed
+ LintClient client = new TestLintClient();
+ File f = client.findResource(String.format("tools/support/typos-%1$s.txt", locale));
+ assertTrue(locale, f != null && f.exists());
+
+ Set<String> typos = new HashSet<String>(2000);
+ List<Pattern> patterns = new ArrayList<Pattern>(100);
+
+ List<String> lines = Files.readLines(f, Charsets.UTF_8);
+ for (int i = 0, n = lines.size(); i < n; i++) {
+ String line = lines.get(i);
+ if (line.isEmpty() || line.trim().startsWith("#")) { //$NON-NLS-1$
+ continue;
+ }
+
+ assertTrue(msg(f, i, "Line should contain '->': %1$s", line),
+ line.contains(SEPARATOR));
+ int index = line.indexOf(SEPARATOR);
+ String typo = line.substring(0, index).trim();
+ String replacements = line.substring(index + SEPARATOR.length()).trim();
+
+ if (typo.contains("*") && !typo.endsWith("*")) {
+ fixDictionary(f);
+ fail(msg(f, i, "Globbing (*) not supported anywhere but at the tail: %1$s", line));
+ } else if (typo.contains("*") && !replacements.contains("*")) {
+ fail(msg(f, i, "No glob found in the replacements for %1$s", line));
+ }
+
+ if (replacements.indexOf(',') != -1) {
+ Set<String> seen = new HashSet<String>();
+ for (String s : Splitter.on(',').omitEmptyStrings().split(replacements)) {
+ if (seen.contains(s)) {
+ fixDictionary(f);
+ fail(msg(f, i, "For typo " + typo
+ + " there are repeated replacements (" + s + "): " + line));
+ }
+ }
+ }
+
+ assertTrue(msg(f, i, "Typo entry was empty: %1$s", line), !typo.isEmpty());
+ assertTrue(msg(f, i, "Typo replacements was empty: %1$s", line),
+ !replacements.isEmpty());
+
+ for (String blacklist : sRemove) {
+ if (replacements.contains(blacklist)) {
+ fail(msg(f, i, "Replacements for typo %1$s contain description: %2$s",
+ typo, replacements));
+ }
+ }
+ if (typo.equals("sólo") && locale.equals("es")) {
+ // sólo->solo
+ // This seems to trigger a lot of false positives
+ fail(msg(f, i, "Typo %1$s triggers a lot of false positives, should be omitted",
+ typo));
+ }
+ if (locale.equals("tr") && (typo.equals("hiç bir")|| typo.equals("öğe"))) {
+ // hiç bir->hiçbir
+ // öğe->öge
+ // According to a couple of native speakers these are not necessarily
+ // typos
+ fail(msg(f, i, "Typo %1$s triggers a lot of false positives, should be omitted",
+ typo));
+ }
+
+ if (typo.contains("*")) {
+ patterns.add(Pattern.compile(typo.replace("*", ".*")));
+ } else if (!patterns.isEmpty()) {
+ for (Pattern pattern : patterns) {
+ if (pattern.matcher(typo).matches()) {
+ fixDictionary(f);
+ fail(msg(f, i, "The typo " + typo + " matches an earlier glob: ignoring"));
+ continue;
+ }
+ }
+ }
+
+
+ if (typos.contains(typo)) {
+ fixDictionary(f);
+ fail(msg(f, i, "Typo appeared more than once on lhs: %1$s", typo));
+ }
+ typos.add(typo);
+ }
+
+ // Make sure it can be read in
+ TypoLookup db = TypoLookup.get(client, locale, null);
+ assertNotNull(db);
+ assertNull(db.getTypos("abcdefghijklmnopqrstuvxyz", 0, 25));
+ assertNull(db.getTypos("abcdefghijklmnopqrstuvxyz".getBytes(Charsets.UTF_8), 0, 25));
+ assertNotNull(db.getTypos("Andriod", 0, "Andriod".length()));
+ assertNotNull(db.getTypos("Andriod".getBytes(Charsets.UTF_8), 0, "Andriod".length()));
+ }
+
+ private void fixDictionary(File original) throws Exception {
+ File fixed = new File(original.getParentFile(), "fixed-" + original.getName());
+
+ Map<String, Integer> typos = new HashMap<String, Integer>(2000);
+ List<Pattern> patterns = new ArrayList<Pattern>(100);
+ List<String> lines = Files.readLines(original, Charsets.UTF_8);
+ List<String> output = new ArrayList<String>(lines.size());
+
+ wordLoop:
+ for (int i = 0, n = lines.size(); i < n; i++) {
+ String line = lines.get(i);
+ if (line.isEmpty() || line.trim().startsWith("#")) { //$NON-NLS-1$
+ output.add(line);
+ continue;
+ }
+
+ if (!line.contains(SEPARATOR)) {
+ System.err.println("Commented out line missing ->: " + line);
+ output.add("# " + line);
+ continue;
+ }
+ int index = line.indexOf(SEPARATOR);
+ String typo = line.substring(0, index).trim();
+ String replacements = line.substring(index + SEPARATOR.length()).trim();
+
+ if (typo.isEmpty()) {
+ System.err.println("Commented out line missing a typo on the lhs: " + line);
+ output.add("# " + line);
+ continue;
+ }
+ if (replacements.isEmpty()) {
+ System.err.println("Commented out line missing replacements on the rhs: " + line);
+ output.add("# " + line);
+ continue;
+ }
+
+ // Ensure that all the replacements are unique
+ if (replacements.indexOf(',') != -1) {
+ Set<String> seen = new HashSet<String>();
+ List<String> out = new ArrayList<String>();
+ boolean rewrite = false;
+ for (String s : Splitter.on(',').omitEmptyStrings().split(replacements)) {
+ if (seen.contains(s)) {
+ System.err.println("For typo " + typo
+ + " there are repeated replacements (" + s + "): " + line);
+ rewrite = true;
+ }
+ seen.add(s);
+ out.add(s);
+ }
+ if (rewrite) {
+ StringBuilder sb = new StringBuilder();
+ for (String s : out) {
+ if (sb.length() > 0) {
+ sb.append(",");
+ }
+ sb.append(s);
+ }
+ replacements = sb.toString();
+ line = typo + SEPARATOR + replacements;
+ }
+ }
+
+ if (typo.contains("*")) {
+ if (!typo.endsWith("*")) {
+ // Globbing not supported anywhere but the end
+ // Drop the whole word
+ System.err.println("Skipping typo " + typo
+ + " because globbing is only supported at the end of the word");
+ continue;
+ }
+ patterns.add(Pattern.compile(typo.replace("*", ".*")));
+ } else if (replacements.contains("*")) {
+ System.err.println("Skipping typo " + typo + " because unexpected " +
+ "globbing character found in replacements: "
+ + replacements);
+ continue;
+ } else if (!patterns.isEmpty()) {
+ for (Pattern pattern : patterns) {
+ if (pattern.matcher(typo).matches()) {
+ System.err.println("The typo " + typo
+ + " matches an earlier glob: ignoring");
+ continue wordLoop;
+ }
+ }
+ }
+
+ // TODO: Strip whitespace around ->, prefix of # etc such that reading in
+ // the databases needs to do less work at runtime
+
+ if (typos.containsKey(typo)) {
+ int l = typos.get(typo);
+ String prev = output.get(l);
+ assertTrue(prev.startsWith(typo));
+ // Append new replacements and put back into the list
+ // (unless they're already listed as replacements)
+ Set<String> seen = new HashSet<String>();
+ for (String s : Splitter.on(',').split(prev.substring(prev.indexOf(SEPARATOR)
+ + 2))) {
+ seen.add(s);
+ }
+ for (String s : Splitter.on(',').omitEmptyStrings().split(replacements)) {
+ if (!seen.contains(s)) {
+ prev = prev + "," + s;
+ }
+ seen.add(s);
+ }
+ output.set(l, prev);
+ } else {
+ typos.put(typo, output.size());
+ output.add(line);
+ }
+ }
+
+ Writer writer = new BufferedWriter(new FileWriter(fixed));
+ for (String line : output) {
+ writer.write(line);
+ writer.write('\n');
+ }
+ writer.close();
+
+ System.err.println("==> Wrote fixed typo file to " + fixed.getPath());
+ }
+
+ private static String msg(File file, int line, String message, Object... args) {
+ return file.getName() + ':' + Integer.toString(line + 1) + ':' + ' ' +
+ String.format(message, args);
}
@Override
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/accessibility.xml b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/accessibility.xml
index 7afb182..c00a880 100644
--- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/accessibility.xml
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/layout/accessibility.xml
@@ -2,7 +2,8 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/newlinear" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent">
<Button android:text="Button" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
<ImageView android:id="@+id/android_logo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/android_button" android:focusable="false" android:clickable="false" android:layout_weight="1.0" />
- <ImageButton android:id="@+id/android_logo2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/android_button" android:focusable="false" android:clickable="false" android:layout_weight="1.0" />
+ <ImageButton android:importantForAccessibility="yes" android:id="@+id/android_logo2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/android_button" android:focusable="false" android:clickable="false" android:layout_weight="1.0" />
<Button android:text="Button" android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
<Button android:id="@+android:id/summary" android:contentDescription="@string/label" />
+ <ImageButton android:importantForAccessibility="no" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/android_button" android:focusable="false" android:clickable="false" android:layout_weight="1.0" />
</LinearLayout>
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/values-de/typos.xml b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/values-de/typos.xml
new file mode 100644
index 0000000..9583fc7
--- /dev/null
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/values-de/typos.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="s1">
+
+ wo befindet eine ip
+
+ </string>
+ <string name="s2">(Authorisierungscode!)</string>
+ <string name="s3"> zurück gefoobaren!</string>
+
+</resources>
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/values-nb/typos.xml b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/values-nb/typos.xml
index d0f4a41..06cec0d 100644
--- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/values-nb/typos.xml
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/values-nb/typos.xml
@@ -16,5 +16,7 @@
<string name="s7">Midt-Østen midt-østen</string>
<!-- Non-ASCII UTF-8 string -->
<string name="s7">Koding er en spennende karriære</string>
+ <string name="internet">"Koble til Internett.</string>
+
</resources>
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/values/nontranslatable.xml b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/values/nontranslatable.xml
new file mode 100644
index 0000000..f608bff
--- /dev/null
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/values/nontranslatable.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="dummy" translatable="false">Ignore Me</string>
+</resources>
+
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/values/nontranslatable2.xml b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/values/nontranslatable2.xml
new file mode 100644
index 0000000..4fcfdc6
--- /dev/null
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/values/nontranslatable2.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="dummy">Ignore Me</string>
+</resources>
+
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/values/typos.xml b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/values/typos.xml
index a167e44..a94be49 100644
--- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/values/typos.xml
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/values/typos.xml
@@ -3,9 +3,9 @@
<!-- No typos -->
<string name="s1">Home Sample</string>
<!-- Plain typos -->
- <string name="s2">Andriod activites</string>
+ <string name="s2">Andriod activites!</string>
<!-- Make capitalization match typo -->
- <string name="s3"> Cmoputer </string>
+ <string name="s3"> (Cmoputer </string>
<!-- Markup indirection -->
<string name="s4"><b>throught</b></string>
<!-- Typo, match capitalized -->
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/detector/api/LintUtilsTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/detector/api/LintUtilsTest.java
index 4765f41..8379618 100644
--- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/detector/api/LintUtilsTest.java
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/detector/api/LintUtilsTest.java
@@ -16,7 +16,11 @@
package com.android.tools.lint.detector.api;
+import static com.android.tools.lint.detector.api.LintUtils.splitPath;
+import static com.android.tools.lint.detector.api.LintUtils.getLocaleAndRegion;
+
import com.android.tools.lint.Main;
+import com.google.common.collect.Iterables;
import java.io.BufferedOutputStream;
import java.io.File;
@@ -92,6 +96,31 @@ public class LintUtilsTest extends TestCase {
assertEquals(6, LintUtils.editDistance("radiobutton", "bitton"));
}
+ public void testSplitPath() throws Exception {
+ assertTrue(Arrays.equals(new String[] { "/foo", "/bar", "/baz" },
+ Iterables.toArray(splitPath("/foo:/bar:/baz"), String.class)));
+
+ assertTrue(Arrays.equals(new String[] { "/foo", "/bar" },
+ Iterables.toArray(splitPath("/foo;/bar"), String.class)));
+
+ assertTrue(Arrays.equals(new String[] { "/foo", "/bar:baz" },
+ Iterables.toArray(splitPath("/foo;/bar:baz"), String.class)));
+
+ assertTrue(Arrays.equals(new String[] { "\\foo\\bar", "\\bar\\foo" },
+ Iterables.toArray(splitPath("\\foo\\bar;\\bar\\foo"), String.class)));
+
+ assertTrue(Arrays.equals(new String[] { "${sdk.dir}\\foo\\bar", "\\bar\\foo" },
+ Iterables.toArray(splitPath("${sdk.dir}\\foo\\bar;\\bar\\foo"),
+ String.class)));
+
+ assertTrue(Arrays.equals(new String[] { "${sdk.dir}/foo/bar", "/bar/foo" },
+ Iterables.toArray(splitPath("${sdk.dir}/foo/bar:/bar/foo"),
+ String.class)));
+
+ assertTrue(Arrays.equals(new String[] { "C:\\foo", "/bar" },
+ Iterables.toArray(splitPath("C:\\foo:/bar"), String.class)));
+ }
+
public void testCommonParen1() {
assertEquals(new File("/a"), (LintUtils.getCommonParent(
new File("/a/b/c/d/e"), new File("/a/c"))));
@@ -246,4 +275,14 @@ public class LintUtilsTest extends TestCase {
checkEncoding("UTF_32", true /*bom*/, "\r\n");
checkEncoding("UTF_32LE", true /*bom*/, "\r\n");
}
+
+ public void testGetLocaleAndRegion() throws Exception {
+ assertNull(getLocaleAndRegion(""));
+ assertNull(getLocaleAndRegion("values"));
+ assertNull(getLocaleAndRegion("values-xlarge-port"));
+ assertEquals("en", getLocaleAndRegion("values-en"));
+ assertEquals("pt-rPT", getLocaleAndRegion("values-pt-rPT-nokeys"));
+ assertEquals("zh-rCN", getLocaleAndRegion("values-zh-rCN-keyshidden"));
+ assertEquals("ms", getLocaleAndRegion("values-ms-keyshidden"));
+ }
} \ No newline at end of file
diff --git a/manifmerger/src/com/android/manifmerger/ManifestMerger.java b/manifmerger/src/com/android/manifmerger/ManifestMerger.java
index 229faa3..d63ecd8 100755
--- a/manifmerger/src/com/android/manifmerger/ManifestMerger.java
+++ b/manifmerger/src/com/android/manifmerger/ManifestMerger.java
@@ -36,7 +36,7 @@ import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
@@ -742,8 +742,8 @@ public class ManifestMerger {
Element destUsesSdk = findFirstElement(mMainDoc, "/manifest/uses-sdk"); //$NON-NLS-1$
Element srcUsesSdk = findFirstElement(libDoc, "/manifest/uses-sdk"); //$NON-NLS-1$
- AtomicInteger destValue = new AtomicInteger(1);
- AtomicInteger srcValue = new AtomicInteger(1);
+ AtomicReference<Object> destValue = new AtomicReference<Object>(1); // String or Integer
+ AtomicReference<Object> srcValue = new AtomicReference<Object>(1);
AtomicBoolean destImplied = new AtomicBoolean(true);
AtomicBoolean srcImplied = new AtomicBoolean(true);
@@ -756,16 +756,17 @@ public class ManifestMerger {
destValue, srcValue,
destImplied, srcImplied);
- if (result) {
+ if (result && destValue.get() instanceof Integer && srcValue.get() instanceof Integer) {
// Make it an error for an application to use a library with a greater
// minSdkVersion. This means the library code may crash unexpectedly.
// TODO it would be nice to be able to work around this in case the
// user think s/he knows what s/he's doing.
// We could define a simple XML comment flag: <!-- @NoMinSdkVersionMergeError -->
- destMinSdk = destValue.get();
+ destMinSdk = (Integer) destValue.get();
- if (destMinSdk < srcValue.get()) {
+ int srcMinSdk = (Integer) srcValue.get();
+ if (destMinSdk < srcMinSdk) {
mLog.conflict(Severity.ERROR,
xmlFileAndLine(destUsesSdk == null ? mMainDoc : destUsesSdk),
xmlFileAndLine(srcUsesSdk == null ? libDoc : srcUsesSdk),
@@ -794,13 +795,14 @@ public class ManifestMerger {
destImplied, srcImplied);
result &= result2;
- if (result2) {
+ if (result2 && destValue.get() instanceof Integer && srcValue.get() instanceof Integer) {
// Make it a warning for an application to use a library with a greater
// targetSdkVersion.
- int destTargetSdk = destImplied.get() ? destMinSdk : destValue.get();
+ int destTargetSdk = destImplied.get() ? destMinSdk : (Integer) destValue.get();
- if (destTargetSdk < srcValue.get()) {
+ int srcMinSdk = (Integer) srcValue.get();
+ if (destTargetSdk < srcMinSdk) {
mLog.conflict(Severity.WARNING,
xmlFileAndLine(destUsesSdk == null ? mMainDoc : destUsesSdk),
xmlFileAndLine(srcUsesSdk == null ? libDoc : srcUsesSdk),
@@ -831,8 +833,8 @@ public class ManifestMerger {
Element destUsesSdk,
Element srcUsesSdk,
String attr,
- AtomicInteger destValue,
- AtomicInteger srcValue,
+ AtomicReference<Object> destValue,
+ AtomicReference<Object> srcValue,
AtomicBoolean destImplied,
AtomicBoolean srcImplied) {
String s = destUsesSdk == null ? "" //$NON-NLS-1$
@@ -846,14 +848,9 @@ public class ManifestMerger {
destImplied.set(false);
}
} catch (NumberFormatException e) {
- // Note: NumberFormatException.toString() has no interesting information
- // so we don't output it.
- mLog.error(Severity.ERROR,
- xmlFileAndLine(destUsesSdk == null ? mMainDoc : destUsesSdk),
- "Failed to parse <uses-sdk %1$sSdkVersion='%2$s'>: must be an integer number.",
- attr,
- s);
- return false;
+ // Versions can contain codenames such as "JellyBean"
+ destValue.set(s);
+ destImplied.set(false);
}
s = srcUsesSdk == null ? "" //$NON-NLS-1$
@@ -866,12 +863,9 @@ public class ManifestMerger {
srcImplied.set(false);
}
} catch (NumberFormatException e) {
- mLog.error(Severity.ERROR,
- xmlFileAndLine(srcUsesSdk == null ? libDoc : srcUsesSdk),
- "Failed to parse <uses-sdk %1$sSdkVersion='%2$s'>: must be an integer number.",
- attr,
- s);
- return false;
+ // Versions can contain codenames such as "JellyBean"
+ destValue.set(s);
+ destImplied.set(false);
}
return true;
diff --git a/monitor/Android.mk b/monitor/Android.mk
index 9973d64..fbf5a6d 100644
--- a/monitor/Android.mk
+++ b/monitor/Android.mk
@@ -1,7 +1,7 @@
# Copyright 2012 The Android Open Source Project
# Expose the Monitor RCP only for the SDK builds.
-ifneq (,$(is_sdk_build)$(filter sdk sdk_x86,$(TARGET_PRODUCT)))
+ifneq (,$(is_sdk_build)$(filter sdk sdk_x86 sdk_mips,$(TARGET_PRODUCT)))
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java
index 0f55eeb..21a2332 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java
@@ -17,6 +17,7 @@
package com.android.sdklib;
import com.android.annotations.NonNull;
+import com.android.annotations.Nullable;
import com.android.annotations.VisibleForTesting;
import com.android.annotations.VisibleForTesting.Visibility;
import com.android.io.FileWrapper;
@@ -30,6 +31,7 @@ import com.android.sdklib.internal.repository.NullTaskMonitor;
import com.android.sdklib.internal.repository.archives.Archive;
import com.android.sdklib.internal.repository.packages.ExtraPackage;
import com.android.sdklib.internal.repository.packages.Package;
+import com.android.sdklib.internal.repository.packages.PlatformToolPackage;
import com.android.sdklib.repository.PkgProps;
import com.android.util.Pair;
@@ -364,6 +366,21 @@ public class SdkManager {
return extraVersions;
}
+ /** Returns the platform tools version if installed, null otherwise. */
+ public @Nullable String getPlatformToolsVersion() {
+ LocalSdkParser parser = new LocalSdkParser();
+ Package[] packages = parser.parseSdk(mOsSdkPath, this, LocalSdkParser.PARSE_PLATFORM_TOOLS,
+ new NullTaskMonitor(new NullSdkLog()));
+
+ for (Package pkg : packages) {
+ if (pkg instanceof PlatformToolPackage && pkg.isLocal()) {
+ return pkg.getRevision().toShortString();
+ }
+ }
+
+ return null;
+ }
+
// -------- private methods ----------
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/DeviceManager.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/DeviceManager.java
index 61d8307..d46ca5f 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/DeviceManager.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/DeviceManager.java
@@ -68,6 +68,8 @@ public class DeviceManager {
private static List<Device> mUserDevices;
private static List<Device> mDefaultDevices;
private static final Object lock = new Object();
+ private static final List<DevicesChangeListener> listeners =
+ Collections.synchronizedList(new ArrayList<DevicesChangeListener>());
// TODO: Refactor this to look more like AvdManager so that we don't have
// multiple instances
@@ -79,6 +81,34 @@ public class DeviceManager {
}
/**
+ * Interface implemented by objects which want to know when changes occur to the {@link Device}
+ * lists.
+ */
+ public static interface DevicesChangeListener {
+ /**
+ * Called after one of the {@link Device} lists has been updated.
+ */
+ public void onDevicesChange();
+ }
+
+ /**
+ * Register a listener to be notified when the device lists are modified.
+ * @param listener The listener to add
+ */
+ public void registerListener(DevicesChangeListener listener) {
+ listeners.add(listener);
+ }
+
+ /**
+ * Removes a listener from the notification list such that it will no longer receive
+ * notifications when modifications to the {@link Device} list occur.
+ * @param listener The listener to remove.
+ */
+ public void unregisterListener(DevicesChangeListener listener) {
+ listeners.remove(listener);
+ }
+
+ /**
* Returns both vendor provided and user created {@link Device}s.
*
* @param sdkLocation Location of the Android SDK
@@ -111,6 +141,7 @@ public class DeviceManager {
mLog.error(null, "Error reading default devices");
mDefaultDevices = new ArrayList<Device>();
}
+ notifyListeners();
}
}
return Collections.unmodifiableList(mDefaultDevices);
@@ -125,6 +156,7 @@ public class DeviceManager {
public List<Device> getVendorDevices(String sdkLocation) {
synchronized (lock) {
if (mVendorDevices == null || !mVendorDevicesLocation.equals(sdkLocation)) {
+ mVendorDevicesLocation = sdkLocation;
List<Device> devices = new ArrayList<Device>();
File extrasFolder = new File(sdkLocation, SdkConstants.FD_EXTRAS);
List<File> deviceDirs = getExtraDirs(extrasFolder);
@@ -135,6 +167,7 @@ public class DeviceManager {
}
}
mVendorDevices = devices;
+ notifyListeners();
}
}
return Collections.unmodifiableList(mVendorDevices);
@@ -151,12 +184,29 @@ public class DeviceManager {
// User devices should be saved out to
// $HOME/.android/devices.xml
mUserDevices = new ArrayList<Device>();
+ File userDevicesFile = null;
try {
- File userDevicesFile = new File(AndroidLocation.getFolder(),
+ userDevicesFile = new File(AndroidLocation.getFolder(),
SdkConstants.FN_DEVICES_XML);
- mUserDevices.addAll(loadDevices(userDevicesFile));
+ mUserDevices.addAll(DeviceParser.parse(userDevicesFile));
+ notifyListeners();
} catch (AndroidLocationException e) {
mLog.warning("Couldn't load user devices: %1$s", e.getMessage());
+ } catch (SAXException e) {
+ // Probably an old config file which we don't want to overwrite.
+ String base = userDevicesFile.getAbsoluteFile()+".old";
+ File renamedConfig = new File(base);
+ int i = 0;
+ while (renamedConfig.exists()) {
+ renamedConfig = new File(base + "." + (i++));
+ }
+ mLog.error(null, "Error parsing %1$s, backing up to %2$s",
+ userDevicesFile.getAbsolutePath(), renamedConfig.getAbsolutePath());
+ userDevicesFile.renameTo(renamedConfig);
+ } catch (ParserConfigurationException e) {
+ mLog.error(null, "Error parsing %1$s", userDevicesFile.getAbsolutePath());
+ } catch (IOException e) {
+ mLog.error(null, "Error parsing %1$s", userDevicesFile.getAbsolutePath());
}
}
}
@@ -170,6 +220,7 @@ public class DeviceManager {
}
mUserDevices.add(d);
}
+ notifyListeners();
}
public void removeUserDevice(Device d) {
@@ -183,6 +234,7 @@ public class DeviceManager {
if (userDevice.getName().equals(d.getName())
&& userDevice.getManufacturer().equals(d.getManufacturer())) {
it.remove();
+ notifyListeners();
break;
}
@@ -253,17 +305,6 @@ public class DeviceManager {
Integer.toString(hw.getScreen().getPixelDensity().getDpiValue()));
props.put("hw.sensors.proximity",
getBooleanVal(sensors.contains(Sensor.PROXIMITY_SENSOR)));
-
- for (Camera c : hw.getCameras()) {
- String prop;
- if (c.getLocation().equals(CameraLocation.FRONT)) {
- prop = "hw.camera.front";
- } else {
- prop = "hw.camera.back";
- }
- props.put(prop, "emulated");
- }
-
return props;
}
@@ -281,7 +322,7 @@ public class DeviceManager {
props.put("hw.keyboard.lid", getBooleanVal(true));
}
}
- return getHardwareProperties(d.getDefaultState());
+ return props;
}
/**
@@ -317,6 +358,14 @@ public class DeviceManager {
return new ArrayList<Device>();
}
+ private void notifyListeners() {
+ synchronized (listeners) {
+ for (DevicesChangeListener listener : listeners) {
+ listener.onDevicesChange();
+ }
+ }
+ }
+
/* Returns all of DeviceProfiles in the extras/ folder */
private List<File> getExtraDirs(File extrasFolder) {
List<File> extraDirs = new ArrayList<File>();
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/DeviceParser.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/DeviceParser.java
index 43b63cb..dd63af2 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/DeviceParser.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/DeviceParser.java
@@ -304,6 +304,8 @@ public class DeviceParser {
} else {
mState.setNavState(NavigationState.getEnum(getString(mStringAccumulator)));
}
+ } else if (DeviceSchema.NODE_STATUS_BAR.equals(localName)) {
+ mSoftware.setStatusBar(getBool(mStringAccumulator));
}
}
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Software.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Software.java
index b89860f..a452b6e 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Software.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/Software.java
@@ -27,6 +27,7 @@ public class Software {
private Set<BluetoothProfile> mBluetoothProfiles = new HashSet<BluetoothProfile>();
private String mGlVersion;
private Set<String> mGlExtensions = new HashSet<String>();
+ private boolean mStatusBar;
public int getMinSdkLevel() {
return mMinSdkLevel;
@@ -84,6 +85,14 @@ public class Software {
mGlExtensions.addAll(extensions);
}
+ public void setStatusBar(boolean hasBar) {
+ mStatusBar = hasBar;
+ }
+
+ public boolean hasStatusBar() {
+ return mStatusBar;
+ }
+
public Software deepCopy() {
Software s = new Software();
s.setMinSdkLevel(getMinSdkLevel());
@@ -92,6 +101,7 @@ public class Software {
s.addAllBluetoothProfiles(getBluetoothProfiles());
s.setGlVersion(getGlVersion());
s.addAllGlExtensions(getGlExtensions());
+ s.setStatusBar(hasStatusBar());
return s;
}
@@ -110,7 +120,8 @@ public class Software {
&& mLiveWallpaperSupport == sw.hasLiveWallpaperSupport()
&& mBluetoothProfiles.equals(sw.getBluetoothProfiles())
&& mGlVersion.equals(sw.getGlVersion())
- && mGlExtensions.equals(sw.getGlExtensions());
+ && mGlExtensions.equals(sw.getGlExtensions())
+ && mStatusBar == sw.hasStatusBar();
}
@Override
@@ -122,6 +133,7 @@ public class Software {
hash = 31 * hash + mBluetoothProfiles.hashCode();
hash = 31 * hash + mGlVersion.hashCode();
hash = 31 * hash + mGlExtensions.hashCode();
+ hash = 31 * hash + (mStatusBar ? 1 : 0);
return hash;
}
}
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/devices.xml b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/devices.xml
index bc9ec91..e18280d 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/devices.xml
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/devices.xml
@@ -75,6 +75,7 @@
<d:bluetooth-profiles />
<d:gl-version>2.1</d:gl-version>
<d:gl-extensions />
+ <d:status-bar>true</d:status-bar>
</d:software>
<d:state name="Portrait" default="true">
@@ -163,6 +164,7 @@
<d:bluetooth-profiles />
<d:gl-version>2.1</d:gl-version>
<d:gl-extensions />
+ <d:status-bar>true</d:status-bar>
</d:software>
<d:state name="Portrait" default="true">
@@ -257,6 +259,7 @@
<d:bluetooth-profiles />
<d:gl-version>2.1</d:gl-version>
<d:gl-extensions />
+ <d:status-bar>true</d:status-bar>
</d:software>
<d:state name="Portrait" default="true">
@@ -351,6 +354,7 @@
<d:bluetooth-profiles />
<d:gl-version>2.1</d:gl-version>
<d:gl-extensions />
+ <d:status-bar>true</d:status-bar>
</d:software>
<d:state name="Portrait" default="true">
@@ -439,6 +443,7 @@
<d:bluetooth-profiles />
<d:gl-version>2.1</d:gl-version>
<d:gl-extensions />
+ <d:status-bar>true</d:status-bar>
</d:software>
<d:state name="Portrait" default="true">
@@ -526,6 +531,7 @@
<d:bluetooth-profiles />
<d:gl-version>2.1</d:gl-version>
<d:gl-extensions />
+ <d:status-bar>true</d:status-bar>
</d:software>
<d:state name="Portrait" default="true">
@@ -614,6 +620,7 @@
<d:bluetooth-profiles />
<d:gl-version>2.1</d:gl-version>
<d:gl-extensions />
+ <d:status-bar>true</d:status-bar>
</d:software>
<d:state name="Portrait" default="true">
@@ -702,6 +709,7 @@
<d:bluetooth-profiles />
<d:gl-version>2.1</d:gl-version>
<d:gl-extensions />
+ <d:status-bar>true</d:status-bar>
</d:software>
<d:state name="Portrait" default="true">
@@ -796,6 +804,7 @@
<d:bluetooth-profiles />
<d:gl-version>2.1</d:gl-version>
<d:gl-extensions />
+ <d:status-bar>true</d:status-bar>
</d:software>
<d:state name="Portrait" default="true">
@@ -934,6 +943,7 @@
GL_OES_vertex_array_object
GL_OES_vertex_half_float
</d:gl-extensions>
+ <d:status-bar>true</d:status-bar>
</d:software>
<d:state name="Portrait" default="true">
<d:description>The phone in portrait view</d:description>
@@ -1021,6 +1031,7 @@
<d:bluetooth-profiles />
<d:gl-version>2.1</d:gl-version>
<d:gl-extensions />
+ <d:status-bar>true</d:status-bar>
</d:software>
<d:state name="Portrait" default="true">
@@ -1109,6 +1120,7 @@
<d:bluetooth-profiles />
<d:gl-version>2.1</d:gl-version>
<d:gl-extensions />
+ <d:status-bar>true</d:status-bar>
</d:software>
<d:state name="Portrait" default="true">
@@ -1197,6 +1209,7 @@
<d:bluetooth-profiles />
<d:gl-version>2.1</d:gl-version>
<d:gl-extensions />
+ <d:status-bar>true</d:status-bar>
</d:software>
<d:state name="Portrait" default="true">
@@ -1285,6 +1298,7 @@
<d:bluetooth-profiles />
<d:gl-version>2.1</d:gl-version>
<d:gl-extensions />
+ <d:status-bar>true</d:status-bar>
</d:software>
<d:state name="Portrait" default="true">
@@ -1379,6 +1393,7 @@
<d:bluetooth-profiles />
<d:gl-version>2.1</d:gl-version>
<d:gl-extensions />
+ <d:status-bar>true</d:status-bar>
</d:software>
<d:state name="Portrait" default="true">
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java
index 46d3124..091dc0b 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java
@@ -152,6 +152,21 @@ public class AvdManager {
public final static String AVD_INI_SNAPSHOT_PRESENT = "snapshot.present"; //$NON-NLS-1$
/**
+ * AVD/config.ini key name representing whether hardware OpenGLES emulation is enabled
+ */
+ public final static String AVD_INI_GPU_EMULATION = "hw.gpu.enabled"; //$NON-NLS-1$
+
+ /**
+ * AVD/config.ini key name representing how to emulate the front facing camera
+ */
+ public final static String AVD_INI_CAMERA_FRONT = "hw.camera.front"; //$NON-NLS-1$
+
+ /**
+ * AVD/config.ini key name representing how to emulate the rear facing camera
+ */
+ public final static String AVD_INI_CAMERA_BACK = "hw.camera.back"; //$NON-NLS-1$
+
+ /**
* Pattern to match pixel-sized skin "names", e.g. "320x480".
*/
public final static Pattern NUMERIC_SKIN_SIZE = Pattern.compile("([0-9]{2,})x([0-9]{2,})"); //$NON-NLS-1$
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/sources/SdkSources.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/sources/SdkSources.java
index b1354c3..619d7b2 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/sources/SdkSources.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/sources/SdkSources.java
@@ -287,7 +287,21 @@ public class SdkSources {
for (int i = 0; i < count; i++) {
String url = props.getProperty(String.format("%s%02d", KEY_SRC, i)); //$NON-NLS-1$
if (url != null) {
- SdkSource s = new SdkAddonSource(url, null/*uiName*/);
+ // FIXME: this code originally only dealt with add-on XML sources.
+ // Now we'd like it to deal with system-image sources too, but we
+ // don't know which kind of object it is (at least not without
+ // trying to fetch it.) As a temporary workaround, just take a
+ // guess based on the leaf URI name. However ideally what we can
+ // simply do is add a checkbox "is system-image XML" in the user
+ // dialog and pass this info down here. Another alternative is to
+ // make a "dynamic" source object that tries to guess its type once
+ // the URI has been fetched.
+ SdkSource s;
+ if (url.endsWith("sys-img.xml")) {
+ s = new SdkSysImgSource(url, null/*uiName*/);
+ } else {
+ s = new SdkAddonSource(url, null/*uiName*/);
+ }
if (!hasSourceUrl(s)) {
add(SdkSourceCategory.USER_ADDONS, s);
}
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/AdtUpdateDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/AdtUpdateDialog.java
index ba9bce7..8e66c63 100755
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/AdtUpdateDialog.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/AdtUpdateDialog.java
@@ -130,6 +130,34 @@ public class AdtUpdateDialog extends SwtBaseDialog {
}
/**
+ * Displays the update dialog and triggers installation of platform-tools package.
+ * <p/>
+ * Callers must not try to reuse this dialog after this call.
+ *
+ * @return A boolean indicating whether the installation was successful (meaning the package
+ * was either already present, or got installed or updated properly) and a {@link File}
+ * with the path to the root folder of the package. The file is null when the boolean
+ * is false, otherwise it should point to an existing valid folder.
+ * @wbp.parser.entryPoint
+ */
+ public Pair<Boolean, File> installPlatformTools() {
+ mPackageFilter = createPlatformToolsFilter();
+ open();
+
+ File installPath = null;
+ if (mResultPaths != null) {
+ for (Entry<Package, File> entry : mResultPaths.entrySet()) {
+ if (entry.getKey() instanceof ExtraPackage) {
+ installPath = entry.getValue();
+ break;
+ }
+ }
+ }
+
+ return Pair.of(mResultCode, installPath);
+ }
+
+ /**
* Displays the update dialog and triggers installation of the requested platform
* package with the specified API level.
* <p/>
@@ -337,6 +365,25 @@ public class AdtUpdateDialog extends SwtBaseDialog {
};
}
+ private PackageFilter createPlatformToolsFilter() {
+ return new PackageFilter() {
+ @Override
+ boolean accept(Package pkg) {
+ return pkg instanceof PlatformToolPackage;
+ }
+
+ @Override
+ void visit(Package pkg) {
+ // nop
+ }
+
+ @Override
+ int installFlags() {
+ return UpdaterData.TOOLS_MSG_UPDATED_FROM_ADT;
+ }
+ };
+ }
+
public static PackageFilter createPlatformFilter(final int apiLevel) {
return new PackageFilter() {
int mApiLevel = apiLevel;
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/AvdManagerWindowImpl1.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/AvdManagerWindowImpl1.java
index c84506b..06cdc74 100755
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/AvdManagerWindowImpl1.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/AvdManagerWindowImpl1.java
@@ -362,7 +362,9 @@ public class AvdManagerWindowImpl1 {
public void widgetSelected(SelectionEvent e) {
DeviceCreationDialog dlg = new DeviceCreationDialog(
mShell, manager, mUpdaterData.getImageFactory(), null);
- dlg.open();
+ if (dlg.open() == Window.OK) {
+ setupDevices(menuBarDevices);
+ }
}
});
new MenuItem(menuDevices, SWT.SEPARATOR);
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java
index 39a2710..1c0b167 100644
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,43 +16,26 @@
package com.android.sdkuilib.internal.widgets;
-import com.android.io.FileWrapper;
import com.android.prefs.AndroidLocation.AndroidLocationException;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.ISdkLog;
import com.android.sdklib.ISystemImage;
import com.android.sdklib.SdkConstants;
import com.android.sdklib.SdkManager;
-import com.android.sdklib.devices.Abi;
+import com.android.sdklib.devices.Camera;
+import com.android.sdklib.devices.CameraLocation;
import com.android.sdklib.devices.Device;
import com.android.sdklib.devices.DeviceManager;
-import com.android.sdklib.devices.Hardware;
+import com.android.sdklib.devices.Screen;
import com.android.sdklib.internal.avd.AvdInfo;
import com.android.sdklib.internal.avd.AvdManager;
import com.android.sdklib.internal.avd.AvdManager.AvdConflict;
import com.android.sdklib.internal.avd.HardwareProperties;
-import com.android.sdklib.internal.avd.HardwareProperties.HardwareProperty;
-import com.android.sdklib.internal.project.ProjectProperties;
import com.android.sdkuilib.internal.repository.icons.ImageFactory;
import com.android.sdkuilib.ui.GridDialog;
import com.android.util.Pair;
import org.eclipse.jface.dialogs.IDialogConstants;
-import org.eclipse.jface.viewers.CellEditor;
-import org.eclipse.jface.viewers.CellLabelProvider;
-import org.eclipse.jface.viewers.ComboBoxCellEditor;
-import org.eclipse.jface.viewers.EditingSupport;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.ISelectionChangedListener;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jface.viewers.SelectionChangedEvent;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.TableViewerColumn;
-import org.eclipse.jface.viewers.TextCellEditor;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.jface.viewers.ViewerCell;
-import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
@@ -60,7 +43,6 @@ import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
-import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
@@ -71,90 +53,64 @@ import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import java.io.File;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
import java.util.TreeMap;
-import java.util.regex.Matcher;
-/**
- * AVD creation or edit dialog.
- *
- * TODO:
- * - use SdkTargetSelector instead of Combo
- * - tooltips on widgets.
- *
- */
-final class AvdCreationDialog extends GridDialog {
+public class AvdCreationDialog extends GridDialog {
- private final AvdManager mAvdManager;
+ private AvdManager mAvdManager;
+ private ImageFactory mImageFactory;
+ private ISdkLog mSdkLog;
+ private AvdInfo mAvdInfo;
+
+ // A map from manufacturers to their list of devices.
+ private Map<String, List<Device>> mDeviceMap;
private final TreeMap<String, IAndroidTarget> mCurrentTargets =
- new TreeMap<String, IAndroidTarget>();
-
- private final Map<String, HardwareProperty> mHardwareMap;
- private final Map<String, String> mProperties = new HashMap<String, String>();
- // a list of user-edited properties.
- private final ArrayList<String> mEditedProperties = new ArrayList<String>();
- private final ImageFactory mImageFactory;
- private final ISdkLog mSdkLog;
- private final DeviceManager mDeviceManager;
- private final List<Device> mDeviceList = new ArrayList<Device>();
- /**
- * The original AvdInfo if we're editing an existing AVD.
- * Null when we're creating a new AVD.
- */
- private final AvdInfo mEditAvdInfo;
+ new TreeMap<String, IAndroidTarget>();
+
+ private Button mOkButton;
private Text mAvdName;
- private Combo mTargetCombo;
- private Combo mAbiTypeCombo;
- private String mAbiType;
+ private Combo mDeviceManufacturer;
+ private Combo mDeviceName;
+
+ private Combo mTarget;
+ private Combo mAbi;
- private Combo mDeviceCombo;
+ private Combo mFrontCamera;
+ private Combo mBackCamera;
+
+ private Button mSnapshot;
+ private Button mGpuEmulation;
private Button mSdCardSizeRadio;
private Text mSdCardSize;
private Combo mSdCardSizeCombo;
-
+ private Button mSdCardFileRadio;
private Text mSdCardFile;
private Button mBrowseSdCard;
- private Button mSdCardFileRadio;
-
- private Button mSnapshotCheck;
-
- private Button mSkinListRadio;
- private Combo mSkinCombo;
-
- private Button mSkinSizeRadio;
- private Text mSkinSizeWidth;
- private Text mSkinSizeHeight;
-
- private TableViewer mHardwareViewer;
- private Button mDeleteHardwareProp;
private Button mForceCreation;
- private Button mOkButton;
+ private Composite mStatusComposite;
+
private Label mStatusIcon;
private Label mStatusLabel;
- private Composite mStatusComposite;
/**
- * {@link VerifyListener} for {@link Text} widgets that should only contains numbers.
+ * {@link VerifyListener} for {@link Text} widgets that should only contains
+ * numbers.
*/
private final VerifyListener mDigitVerifier = new VerifyListener() {
@Override
public void verifyText(VerifyEvent event) {
int count = event.text.length();
- for (int i = 0 ; i < count ; i++) {
+ for (int i = 0; i < count; i++) {
char c = event.text.charAt(i);
if (c < '0' || c > '9') {
event.doit = false;
@@ -164,202 +120,158 @@ final class AvdCreationDialog extends GridDialog {
}
};
- /**
- * Callback when the AVD name is changed.
- * When creating a new AVD, enables the force checkbox if the name is a duplicate.
- * When editing an existing AVD, it's OK for the name to match the existing AVD.
- */
- private class CreateNameModifyListener implements ModifyListener {
- @Override
- public void modifyText(ModifyEvent e) {
- String name = mAvdName.getText().trim();
- if (mEditAvdInfo == null || !name.equals(mEditAvdInfo.getName())) {
- // Case where we're creating a new AVD or editing an existing one
- // and the AVD name has been changed... check for name uniqueness.
-
- Pair<AvdConflict, String> conflict = mAvdManager.isAvdNameConflicting(name);
- if (conflict.getFirst() != AvdManager.AvdConflict.NO_CONFLICT) {
- // If we're changing the state from disabled to enabled, make sure
- // to uncheck the button, to force the user to voluntarily re-enforce it.
- // This happens when editing an existing AVD and changing the name from
- // the existing AVD to another different existing AVD.
- if (!mForceCreation.isEnabled()) {
- mForceCreation.setEnabled(true);
- mForceCreation.setSelection(false);
- }
- } else {
- mForceCreation.setEnabled(false);
- mForceCreation.setSelection(false);
- }
- } else {
- // Case where we're editing an existing AVD with the name unchanged.
-
- mForceCreation.setEnabled(false);
- mForceCreation.setSelection(false);
- }
- validatePage();
- }
- }
-
- /**
- * {@link ModifyListener} used for live-validation of the fields content.
- */
- private class ValidateListener extends SelectionAdapter implements ModifyListener {
- @Override
- public void modifyText(ModifyEvent e) {
- validatePage();
- }
-
- @Override
- public void widgetSelected(SelectionEvent e) {
- super.widgetSelected(e);
- validatePage();
- }
- }
-
- /**
- * Creates the dialog. Caller should then use {@link Window#open()} and
- * refresh if the status is {@link Window#OK}.
- *
- * @param parentShell The parent shell.
- * @param avdManager The existing {@link AvdManager} to use. Must not be null.
- * @param imageFactory An existing {@link ImageFactory} to use. Must not be null.
- * @param log An existing {@link ISdkLog} where output will go. Must not be null.
- * @param editAvdInfo An optional {@link AvdInfo}. When null, the dialog is used
- * to create a new AVD. When non-null, the dialog is used to <em>edit</em> this AVD.
- */
- protected AvdCreationDialog(Shell parentShell,
+ public AvdCreationDialog(Shell shell,
AvdManager avdManager,
ImageFactory imageFactory,
ISdkLog log,
AvdInfo editAvdInfo) {
- super(parentShell, 2, false);
+
+ super(shell, 2, false);
mAvdManager = avdManager;
mImageFactory = imageFactory;
mSdkLog = log;
- mEditAvdInfo = editAvdInfo;
+ mAvdInfo = editAvdInfo;
- File hardwareDefs = null;
- mDeviceManager = new DeviceManager(log);
- mDeviceList.addAll(mDeviceManager.getUserDevices());
- mDeviceList.addAll(mDeviceManager.getDefaultDevices());
+ mDeviceMap = new TreeMap<String, List<Device>>();
SdkManager sdkMan = avdManager.getSdkManager();
- if (sdkMan != null) {
- String sdkPath = sdkMan.getLocation();
- if (sdkPath != null) {
- hardwareDefs = new File (sdkPath + File.separator +
- SdkConstants.OS_SDK_TOOLS_LIB_FOLDER, SdkConstants.FN_HARDWARE_INI);
- mDeviceList.addAll(mDeviceManager.getVendorDevices(sdkPath));
+ if (sdkMan != null && sdkMan.getLocation() != null) {
+ List<Device> devices = (new DeviceManager(log)).getDevices(sdkMan.getLocation());
+ for (Device d : devices) {
+ List<Device> list;
+ if (mDeviceMap.containsKey(d.getManufacturer())) {
+ list = mDeviceMap.get(d.getManufacturer());
+ } else {
+ list = new ArrayList<Device>();
+ mDeviceMap.put(d.getManufacturer(), list);
+ }
+ list.add(d);
}
}
-
- if (hardwareDefs == null) {
- log.error(null, "Failed to load file %s from SDK", SdkConstants.FN_HARDWARE_INI);
- mHardwareMap = new HashMap<String, HardwareProperty>();
- } else {
- mHardwareMap = HardwareProperties.parseHardwareDefinitions(
- hardwareDefs, null /*sdkLog*/);
- }
- }
-
- @Override
- public void create() {
- super.create();
-
- Point p = getShell().getSize();
- if (p.x < 400) {
- p.x = 400;
- }
- getShell().setSize(p);
}
@Override
protected Control createContents(Composite parent) {
Control control = super.createContents(parent);
- getShell().setText(mEditAvdInfo == null ? "Create new Android Virtual Device (AVD)"
- : "Edit Android Virtual Device (AVD)");
+ getShell().setText(mAvdInfo == null ? "Create new Android Virtual Device (AVD)"
+ : "Edit Android Virtual Device (AVD)");
mOkButton = getButton(IDialogConstants.OK_ID);
- fillExistingAvdInfo();
- validatePage();
+ if (mAvdInfo != null) {
+ fillExistingAvdInfo(mAvdInfo);
+ }
+ validatePage();
return control;
}
@Override
- public void createDialogContent(final Composite parent) {
- GridData gd;
- GridLayout gl;
+ public void createDialogContent(Composite parent) {
- Label label = new Label(parent, SWT.NONE);
- label.setText("Name:");
- String tooltip = "Name of the new Android Virtual Device";
- label.setToolTipText(tooltip);
+ Label label;
+ String tooltip;
+ ValidateListener validateListener = new ValidateListener();
+ // --- avd name
+ label = new Label(parent, SWT.NONE);
+ label.setText("AVD Name:");
+ tooltip = "The name of the Android Virtual Device";
+ label.setToolTipText(tooltip);
mAvdName = new Text(parent, SWT.BORDER);
mAvdName.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
mAvdName.addModifyListener(new CreateNameModifyListener());
- mAvdName.setToolTipText(tooltip);
+ // --- device selection
label = new Label(parent, SWT.NONE);
- label.setText("Target:");
- tooltip = "The version of Android to use in the virtual device";
- label.setToolTipText(tooltip);
-
- mTargetCombo = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN);
- mTargetCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
- mTargetCombo.setToolTipText(tooltip);
- mTargetCombo.addSelectionListener(new SelectionAdapter() {
+ label.setText("Device\nManufacturer:");
+ tooltip = "The manufacturer of the device this AVD will be based on";
+ mDeviceManufacturer = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN);
+ for (String manufacturer : mDeviceMap.keySet()) {
+ mDeviceManufacturer.add(manufacturer);
+ }
+ mDeviceManufacturer.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ mDeviceManufacturer.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
- super.widgetSelected(e);
- reloadSkinCombo();
- reloadAbiTypeCombo();
- reloadDeviceCombo();
+ reloadDeviceNameCombo();
validatePage();
}
});
- // Device Selection
label = new Label(parent, SWT.NONE);
- label.setText("Device:");
- tooltip = "The device to base the AVD on. This is an optional setting and will merely " +
- "prefill the settings so they match the selected device as closely as possible.";
+ label.setText("Device Name:");
+ tooltip = "The name of the device this AVD will be based on";
+ mDeviceName = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN);
+ mDeviceName.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ mDeviceName.addSelectionListener(new DeviceSelectionListener());
+
+ // --- api target
+ label = new Label(parent, SWT.NONE);
+ label.setText("Target:");
+ tooltip = "The target API of the AVD";
label.setToolTipText(tooltip);
- mDeviceCombo = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN);
- mDeviceCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
- mDeviceCombo.setToolTipText(tooltip);
- mDeviceCombo.setEnabled(false);
- mDeviceCombo.addSelectionListener(new SelectionAdapter() {
+ mTarget = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN);
+ mTarget.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ mTarget.setToolTipText(tooltip);
+ mTarget.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
- super.widgetSelected(e);
- prefillWithDeviceConfig();
+ reloadAbiTypeCombo();
validatePage();
}
-
-
});
- //ABI group
+ reloadTargetCombo();
+
+ // --- avd ABIs
label = new Label(parent, SWT.NONE);
label.setText("CPU/ABI:");
- tooltip = "The CPU/ABI to use in the virtual device";
+ tooltip = "The CPU/ABI of the virtual device";
+ label.setToolTipText(tooltip);
+ mAbi = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN);
+ mAbi.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ mAbi.setToolTipText(tooltip);
+ mAbi.addSelectionListener(validateListener);
+
+ label = new Label(parent, SWT.NONE);
+ label.setText("Front Camera:");
+ tooltip = "";
label.setToolTipText(tooltip);
+ mFrontCamera = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN);
+ mFrontCamera.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ mFrontCamera.add("None");
+ mFrontCamera.add("Emulated");
+ mFrontCamera.add("Webcam0");
+ mFrontCamera.select(0);
+
+ label = new Label(parent, SWT.NONE);
+ label.setText("Back Camera:");
+ tooltip = "";
+ label.setToolTipText(tooltip);
+ mBackCamera = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN);
+ mBackCamera.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ mBackCamera.add("None");
+ mBackCamera.add("Emulated");
+ mBackCamera.add("Webcam0");
+ mBackCamera.select(0);
+
+ toggleCameras();
- mAbiTypeCombo = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN);
- mAbiTypeCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
- mAbiTypeCombo.setToolTipText(tooltip);
- mAbiTypeCombo.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- super.widgetSelected(e);
- validatePage();
- }
- });
- mAbiTypeCombo.setEnabled(false);
+ // --- avd options group
+ label = new Label(parent, SWT.NONE);
+ label.setText("Options:");
+ label.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING,
+ false, false));
+ Group optionsGroup = new Group(parent, SWT.NONE);
+ optionsGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ optionsGroup.setLayout(new GridLayout(2, true));
+ mSnapshot = new Button(optionsGroup, SWT.CHECK);
+ mSnapshot.setText("Snapshot");
+ mSnapshot.setToolTipText("Emulator's state will be persisted between emulator executions");
+ mGpuEmulation = new Button(optionsGroup, SWT.CHECK);
+ mGpuEmulation.setText("GPU Emulation");
+ mGpuEmulation.setToolTipText("Enable hardware OpenGLES emulation");
// --- sd card group
label = new Label(parent, SWT.NONE);
@@ -383,8 +295,6 @@ final class AvdCreationDialog extends GridDialog {
}
});
- ValidateListener validateListener = new ValidateListener();
-
mSdCardSize = new Text(sdCardGroup, SWT.BORDER);
mSdCardSize.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
mSdCardSize.addVerifyListener(mDigitVerifier);
@@ -411,144 +321,21 @@ final class AvdCreationDialog extends GridDialog {
mBrowseSdCard.setText("Browse...");
mBrowseSdCard.setToolTipText("Select the file to use for the SD Card");
mBrowseSdCard.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent arg0) {
- onBrowseSdCard();
- validatePage();
- }
- });
-
- mSdCardSizeRadio.setSelection(true);
- enableSdCardWidgets(true);
-
- // --- snapshot group
-
- label = new Label(parent, SWT.NONE);
- label.setText("Snapshot:");
- label.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING,
- false, false));
-
- final Group snapshotGroup = new Group(parent, SWT.NONE);
- snapshotGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
- snapshotGroup.setLayout(new GridLayout(3, false));
-
- mSnapshotCheck = new Button(snapshotGroup, SWT.CHECK);
- mSnapshotCheck.setText("Enabled");
- mSnapshotCheck.setToolTipText(
- "Emulator's state will be persisted between emulator executions");
-
- // --- skin group
- label = new Label(parent, SWT.NONE);
- label.setText("Skin:");
- label.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING,
- false, false));
-
- final Group skinGroup = new Group(parent, SWT.NONE);
- skinGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
- skinGroup.setLayout(new GridLayout(4, false));
-
- mSkinListRadio = new Button(skinGroup, SWT.RADIO);
- mSkinListRadio.setText("Built-in:");
- mSkinListRadio.setToolTipText("Select an emulated screen size provided by the current Android target");
- mSkinListRadio.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent arg0) {
- boolean listMode = mSkinListRadio.getSelection();
- enableSkinWidgets(listMode);
+ onBrowseSdCard();
validatePage();
}
});
- mSkinCombo = new Combo(skinGroup, SWT.READ_ONLY | SWT.DROP_DOWN);
- mSkinCombo.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
- gd.horizontalSpan = 3;
- mSkinCombo.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent arg0) {
- // get the skin info
- loadSkin();
- }
- });
-
- mSkinSizeRadio = new Button(skinGroup, SWT.RADIO);
- mSkinSizeRadio.setText("Resolution:");
- mSkinSizeRadio.setToolTipText("Select a custom emulated screen size");
-
- mSkinSizeWidth = new Text(skinGroup, SWT.BORDER);
- mSkinSizeWidth.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
- mSkinSizeWidth.addVerifyListener(mDigitVerifier);
- mSkinSizeWidth.addModifyListener(validateListener);
- mSkinSizeWidth.setToolTipText("Width in pixels of the emulated screen size");
-
- new Label(skinGroup, SWT.NONE).setText("x");
-
- mSkinSizeHeight = new Text(skinGroup, SWT.BORDER);
- mSkinSizeHeight.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
- mSkinSizeHeight.addVerifyListener(mDigitVerifier);
- mSkinSizeHeight.addModifyListener(validateListener);
- mSkinSizeHeight.setToolTipText("Height in pixels of the emulated screen size");
-
- mSkinListRadio.setSelection(true);
- enableSkinWidgets(true);
-
- // --- hardware group
- label = new Label(parent, SWT.NONE);
- label.setText("Hardware:");
- label.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING,
- false, false));
-
- final Group hwGroup = new Group(parent, SWT.NONE);
- hwGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
- hwGroup.setLayout(new GridLayout(2, false));
-
- createHardwareTable(hwGroup);
-
- // composite for the side buttons
- Composite hwButtons = new Composite(hwGroup, SWT.NONE);
- hwButtons.setLayoutData(new GridData(GridData.FILL_VERTICAL));
- hwButtons.setLayout(gl = new GridLayout(1, false));
- gl.marginHeight = gl.marginWidth = 0;
-
- Button b = new Button(hwButtons, SWT.PUSH | SWT.FLAT);
- b.setText("New...");
- b.setToolTipText("Add a new hardware property");
- b.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
- b.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent event) {
- HardwarePropertyChooser dialog = new HardwarePropertyChooser(parent.getShell(),
- mHardwareMap, mProperties.keySet());
- if (dialog.open() == Window.OK) {
- HardwareProperty choice = dialog.getProperty();
- if (choice != null) {
- mProperties.put(choice.getName(), choice.getDefault());
- mHardwareViewer.refresh();
- }
- }
- }
- });
- mDeleteHardwareProp = new Button(hwButtons, SWT.PUSH | SWT.FLAT);
- mDeleteHardwareProp.setText("Delete");
- mDeleteHardwareProp.setToolTipText("Delete the selected hardware property");
- mDeleteHardwareProp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
- mDeleteHardwareProp.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent arg0) {
- ISelection selection = mHardwareViewer.getSelection();
- if (selection instanceof IStructuredSelection) {
- String hwName = (String)((IStructuredSelection)selection).getFirstElement();
- mProperties.remove(hwName);
- mHardwareViewer.refresh();
- }
- }
- });
- mDeleteHardwareProp.setEnabled(false);
-
- // --- end hardware group
+ mSdCardSizeRadio.setSelection(true);
+ enableSdCardWidgets(true);
+ // --- force creation group
mForceCreation = new Button(parent, SWT.CHECK);
mForceCreation.setText("Override the existing AVD with the same name");
- mForceCreation.setToolTipText("There's already an AVD with the same name. Check this to delete it and replace it by the new AVD.");
+ mForceCreation
+ .setToolTipText("There's already an AVD with the same name. Check this to delete it and replace it by the new AVD.");
mForceCreation.setLayoutData(new GridData(GridData.BEGINNING, GridData.CENTER,
true, false, 2, 1));
mForceCreation.setEnabled(false);
@@ -562,6 +349,7 @@ final class AvdCreationDialog extends GridDialog {
mStatusComposite = new Composite(parent, SWT.NONE);
mStatusComposite.setLayoutData(new GridData(GridData.FILL, GridData.CENTER,
true, false, 3, 1));
+ GridLayout gl;
mStatusComposite.setLayout(gl = new GridLayout(2, false));
gl.marginHeight = gl.marginWidth = 0;
@@ -570,434 +358,119 @@ final class AvdCreationDialog extends GridDialog {
false, false));
mStatusLabel = new Label(mStatusComposite, SWT.NONE);
mStatusLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
- mStatusLabel.setText(" \n "); //$NON-NLS-1$
+ mStatusLabel.setText(""); //$NON-NLS-1$
- reloadTargetCombo();
- reloadDeviceCombo();
}
/**
- * Creates the UI for the hardware properties table.
- * This creates the {@link Table}, and several viewers ({@link TableViewer},
- * {@link TableViewerColumn}) and adds edit support for the 2nd column
+ * {@link ModifyListener} used for live-validation of the fields content.
*/
- private void createHardwareTable(Composite parent) {
- final Table hardwareTable = new Table(parent, SWT.SINGLE | SWT.FULL_SELECTION);
- GridData gd = new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL);
- gd.widthHint = 200;
- gd.heightHint = 100;
- hardwareTable.setLayoutData(gd);
- hardwareTable.setHeaderVisible(true);
- hardwareTable.setLinesVisible(true);
-
- // -- Table viewer
- mHardwareViewer = new TableViewer(hardwareTable);
- mHardwareViewer.addSelectionChangedListener(new ISelectionChangedListener() {
- @Override
- public void selectionChanged(SelectionChangedEvent event) {
- // it's a single selection mode, we can just access the selection index
- // from the table directly.
- mDeleteHardwareProp.setEnabled(hardwareTable.getSelectionIndex() != -1);
- }
- });
-
- // only a content provider. Use viewers per column below (for editing support)
- mHardwareViewer.setContentProvider(new IStructuredContentProvider() {
- @Override
- public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
- // we can just ignore this. we just use mProperties directly.
- }
-
- @Override
- public Object[] getElements(Object arg0) {
- return mProperties.keySet().toArray();
- }
-
- @Override
- public void dispose() {
- // pass
- }
- });
-
- // -- column 1: prop abstract name
- TableColumn col1 = new TableColumn(hardwareTable, SWT.LEFT);
- col1.setText("Property");
- col1.setWidth(150);
- TableViewerColumn tvc1 = new TableViewerColumn(mHardwareViewer, col1);
- tvc1.setLabelProvider(new CellLabelProvider() {
- @Override
- public void update(ViewerCell cell) {
- String name = cell.getElement().toString();
- HardwareProperty prop = mHardwareMap.get(name);
- if (prop != null) {
- cell.setText(prop.getAbstract());
- } else {
- cell.setText(String.format("%1$s (Unknown)", name));
- }
- }
- });
-
- // -- column 2: prop value
- TableColumn col2 = new TableColumn(hardwareTable, SWT.LEFT);
- col2.setText("Value");
- col2.setWidth(50);
- TableViewerColumn tvc2 = new TableViewerColumn(mHardwareViewer, col2);
- tvc2.setLabelProvider(new CellLabelProvider() {
- @Override
- public void update(ViewerCell cell) {
- String value = mProperties.get(cell.getElement());
- cell.setText(value != null ? value : "");
- }
- });
-
- // add editing support to the 2nd column
- tvc2.setEditingSupport(new EditingSupport(mHardwareViewer) {
- @Override
- protected void setValue(Object element, Object value) {
- String hardwareName = (String)element;
- HardwareProperty property = mHardwareMap.get(hardwareName);
- int index;
- switch (property.getType()) {
- case INTEGER:
- mProperties.put((String)element, (String)value);
- break;
- case DISKSIZE:
- if (HardwareProperties.DISKSIZE_PATTERN.matcher((String)value).matches()) {
- mProperties.put((String)element, (String)value);
- }
- break;
- case BOOLEAN:
- index = (Integer)value;
- mProperties.put((String)element, HardwareProperties.BOOLEAN_VALUES[index]);
- break;
- case STRING_ENUM:
- case INTEGER_ENUM:
- // For a combo, value is the index of the enum to use.
- index = (Integer)value;
- String[] values = property.getEnum();
- if (values != null && values.length > index) {
- mProperties.put((String)element, values[index]);
- }
- break;
- }
- mHardwareViewer.refresh(element);
- }
-
- @Override
- protected Object getValue(Object element) {
- String hardwareName = (String)element;
- HardwareProperty property = mHardwareMap.get(hardwareName);
- String value = mProperties.get(hardwareName);
- switch (property.getType()) {
- case INTEGER:
- // intended fall-through.
- case DISKSIZE:
- return value;
- case BOOLEAN:
- return HardwareProperties.getBooleanValueIndex(value);
- case STRING_ENUM:
- case INTEGER_ENUM:
- // For a combo, we need to return the index of the value in the enum
- String[] values = property.getEnum();
- if (values != null) {
- for (int i = 0; i < values.length; i++) {
- if (values[i].equals(value)) {
- return i;
- }
- }
- }
- }
-
- return null;
- }
-
- @Override
- protected CellEditor getCellEditor(Object element) {
- String hardwareName = (String)element;
- HardwareProperty property = mHardwareMap.get(hardwareName);
- switch (property.getType()) {
- // TODO: custom TextCellEditor that restrict input.
- case INTEGER:
- // intended fall-through.
- case DISKSIZE:
- return new TextCellEditor(hardwareTable);
- case BOOLEAN:
- return new ComboBoxCellEditor(hardwareTable,
- HardwareProperties.BOOLEAN_VALUES,
- SWT.READ_ONLY | SWT.DROP_DOWN);
- case STRING_ENUM:
- case INTEGER_ENUM:
- String[] values = property.getEnum();
- if (values != null && values.length > 0) {
- return new ComboBoxCellEditor(hardwareTable,
- values,
- SWT.READ_ONLY | SWT.DROP_DOWN);
- }
- }
- return null;
- }
-
- @Override
- protected boolean canEdit(Object element) {
- String hardwareName = (String)element;
- HardwareProperty property = mHardwareMap.get(hardwareName);
- return property != null;
- }
- });
-
+ private class ValidateListener extends SelectionAdapter implements ModifyListener {
+ @Override
+ public void modifyText(ModifyEvent e) {
+ validatePage();
+ }
- mHardwareViewer.setInput(mProperties);
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ super.widgetSelected(e);
+ validatePage();
+ }
}
- // -- Start of internal part ----------
- // Hide everything down-below from SWT designer
- //$hide>>$
-
/**
- * When editing an existing AVD info, fill the UI that has just been created with
- * the values from the AVD.
+ * Callback when the AVD name is changed. When creating a new AVD, enables
+ * the force checkbox if the name is a duplicate. When editing an existing
+ * AVD, it's OK for the name to match the existing AVD.
*/
- public void fillExistingAvdInfo() {
- if (mEditAvdInfo == null) {
- return;
- }
-
- mAvdName.setText(mEditAvdInfo.getName());
-
- Map<String, String> props = mEditAvdInfo.getProperties();
-
- if (props != null) {
- // Try to match it to a device
-
- // The device has to be set before everything else because
- // selecting a device will modify other options
- for (int i = 0; i < mDeviceList.size(); i++){
- Device d = mDeviceList.get(i);
- if(d.getManufacturer().equals(props.get(AvdManager.AVD_INI_DEVICE_MANUFACTURER))
- && d.getName().equals(props.get(AvdManager.AVD_INI_DEVICE_NAME))) {
- mDeviceCombo.select(i);
- break;
- }
- }
- }
-
- IAndroidTarget target = mEditAvdInfo.getTarget();
- if (target != null && !mCurrentTargets.isEmpty()) {
- // Try to select the target in the target combo.
- // This will fail if the AVD needs to be repaired.
- //
- // This is a linear search but the list is always
- // small enough and we only do this once.
- int n = mTargetCombo.getItemCount();
- for (int i = 0;i < n; i++) {
- if (target.equals(mCurrentTargets.get(mTargetCombo.getItem(i)))) {
- mTargetCombo.select(i);
- reloadAbiTypeCombo();
- reloadDeviceCombo();
- reloadSkinCombo();
- break;
- }
- }
- }
-
- // select the abi type
- ISystemImage[] systemImages = getSystemImages(target);
- if (target != null && systemImages.length > 0) {
- mAbiTypeCombo.setEnabled(systemImages.length > 1);
- String abiType = AvdInfo.getPrettyAbiType(mEditAvdInfo.getAbiType());
- int n = mAbiTypeCombo.getItemCount();
- for (int i = 0; i < n; i++) {
- if (abiType.equals(mAbiTypeCombo.getItem(i))) {
- mAbiTypeCombo.select(i);
- reloadSkinCombo();
- break;
- }
- }
- }
-
- if (props != null) {
-
- // First try the skin name and if it doesn't work fallback on the skin path
- nextSkin: for (int s = 0; s < 2; s++) {
- String skin = props.get(s == 0 ? AvdManager.AVD_INI_SKIN_NAME
- : AvdManager.AVD_INI_SKIN_PATH);
- if (skin != null && skin.length() > 0) {
- Matcher m = AvdManager.NUMERIC_SKIN_SIZE.matcher(skin);
- if (m.matches() && m.groupCount() == 2) {
- enableSkinWidgets(false);
- mSkinListRadio.setSelection(false);
- mSkinSizeRadio.setSelection(true);
- mSkinSizeWidth.setText(m.group(1));
- mSkinSizeHeight.setText(m.group(2));
- break nextSkin;
- } else {
- enableSkinWidgets(true);
- mSkinSizeRadio.setSelection(false);
- mSkinListRadio.setSelection(true);
-
- int n = mSkinCombo.getItemCount();
- for (int i = 0; i < n; i++) {
- if (skin.equals(mSkinCombo.getItem(i))) {
- mSkinCombo.select(i);
- break nextSkin;
- }
- }
- }
- }
- }
-
- String sdcard = props.get(AvdManager.AVD_INI_SDCARD_PATH);
- if (sdcard != null && sdcard.length() > 0) {
- enableSdCardWidgets(false);
- mSdCardSizeRadio.setSelection(false);
- mSdCardFileRadio.setSelection(true);
- mSdCardFile.setText(sdcard);
- }
-
- sdcard = props.get(AvdManager.AVD_INI_SDCARD_SIZE);
- if (sdcard != null && sdcard.length() > 0) {
- String[] values = new String[2];
- long sdcardSize = AvdManager.parseSdcardSize(sdcard, values);
-
- if (sdcardSize != AvdManager.SDCARD_NOT_SIZE_PATTERN) {
- enableSdCardWidgets(true);
- mSdCardFileRadio.setSelection(false);
- mSdCardSizeRadio.setSelection(true);
-
- mSdCardSize.setText(values[0]);
+ private class CreateNameModifyListener implements ModifyListener {
+ @Override
+ public void modifyText(ModifyEvent e) {
+ String name = mAvdName.getText().trim();
+ if (mAvdInfo == null || !name.equals(mAvdInfo.getName())) {
+ // Case where we're creating a new AVD or editing an existing
+ // one
+ // and the AVD name has been changed... check for name
+ // uniqueness.
- String suffix = values[1];
- int n = mSdCardSizeCombo.getItemCount();
- for (int i = 0; i < n; i++) {
- if (mSdCardSizeCombo.getItem(i).startsWith(suffix)) {
- mSdCardSizeCombo.select(i);
- }
+ Pair<AvdConflict, String> conflict = mAvdManager.isAvdNameConflicting(name);
+ if (conflict.getFirst() != AvdManager.AvdConflict.NO_CONFLICT) {
+ // If we're changing the state from disabled to enabled,
+ // make sure
+ // to uncheck the button, to force the user to voluntarily
+ // re-enforce it.
+ // This happens when editing an existing AVD and changing
+ // the name from
+ // the existing AVD to another different existing AVD.
+ if (!mForceCreation.isEnabled()) {
+ mForceCreation.setEnabled(true);
+ mForceCreation.setSelection(false);
}
+ } else {
+ mForceCreation.setEnabled(false);
+ mForceCreation.setSelection(false);
}
- }
+ } else {
+ // Case where we're editing an existing AVD with the name
+ // unchanged.
- String snapshots = props.get(AvdManager.AVD_INI_SNAPSHOT_PRESENT);
- if (snapshots != null && snapshots.length() > 0) {
- mSnapshotCheck.setSelection(snapshots.equals("true"));
+ mForceCreation.setEnabled(false);
+ mForceCreation.setSelection(false);
}
+ validatePage();
}
+ }
- mProperties.clear();
+ private class DeviceSelectionListener extends SelectionAdapter {
- if (props != null) {
- for (Entry<String, String> entry : props.entrySet()) {
- HardwareProperty prop = mHardwareMap.get(entry.getKey());
- if (prop != null && prop.isValidForUi()) {
- mProperties.put(entry.getKey(), entry.getValue());
- }
- }
+ @Override
+ public void widgetSelected(SelectionEvent arg0) {
+ toggleCameras();
+ validatePage();
}
- // Cleanup known non-hardware properties
- mProperties.remove(AvdManager.AVD_INI_ABI_TYPE);
- mProperties.remove(AvdManager.AVD_INI_CPU_ARCH);
- mProperties.remove(AvdManager.AVD_INI_SKIN_PATH);
- mProperties.remove(AvdManager.AVD_INI_SKIN_NAME);
- mProperties.remove(AvdManager.AVD_INI_SDCARD_SIZE);
- mProperties.remove(AvdManager.AVD_INI_SDCARD_PATH);
- mProperties.remove(AvdManager.AVD_INI_SNAPSHOT_PRESENT);
- mProperties.remove(AvdManager.AVD_INI_IMAGES_1);
- mProperties.remove(AvdManager.AVD_INI_IMAGES_2);
- mProperties.remove(AvdManager.AVD_INI_DEVICE_MANUFACTURER);
- mProperties.remove(AvdManager.AVD_INI_DEVICE_NAME);
-
- mHardwareViewer.refresh();
}
- // Sets all of the other options based on the device currently selected in mDeviceCombo
- private void prefillWithDeviceConfig() {
- Device d = getSelectedDevice();
- if (d != null) {
- Hardware hw = d.getDefaultHardware();
-
- // Try setting the CPU/ABI
- if (mAbiTypeCombo.isEnabled()) {
- Set<Abi> abis = hw.getSupportedAbis();
- // This is O(n*m), but the two lists should be sufficiently small.
- for (Abi abi : abis) {
- for (int i = 0; i < mAbiTypeCombo.getItemCount(); i++) {
- if (mAbiTypeCombo.getItem(i)
- .equals(AvdInfo.getPrettyAbiType(abi.toString()))){
- mAbiTypeCombo.select(i);
+ private void toggleCameras() {
+ mFrontCamera.setEnabled(false);
+ mBackCamera.setEnabled(false);
+ if (mDeviceName.getSelectionIndex() >= 0) {
+ List<Device> devices = mDeviceMap.get(mDeviceManufacturer.getText());
+ for (Device d : devices) {
+ if (mDeviceName.getText().equals(d.getName())) {
+ for (Camera c : d.getDefaultHardware().getCameras()) {
+ if (CameraLocation.FRONT.equals(c.getLocation())) {
+ mFrontCamera.setEnabled(true);
+ }
+ if (CameraLocation.BACK.equals(c.getLocation())) {
+ mBackCamera.setEnabled(true);
}
}
}
}
- // Set the screen resolution
- mSkinListRadio.setSelection(false);
- mSkinSizeRadio.setSelection(true);
- mSkinCombo.setEnabled(false);
- mSkinSizeWidth.setEnabled(true);
- mSkinSizeWidth.setText(Integer.toString(hw.getScreen().getXDimension()));
- mSkinSizeHeight.setEnabled(true);
- mSkinSizeHeight.setText(Integer.toString(hw.getScreen().getYDimension()));
-
- mProperties.putAll(DeviceManager.getHardwareProperties(d));
- mHardwareViewer.refresh();
-
}
}
- @Override
- protected void okPressed() {
- if (createAvd()) {
- super.okPressed();
+ private void reloadDeviceNameCombo() {
+ mDeviceName.removeAll();
+ if (mDeviceMap.containsKey(mDeviceManufacturer.getText())) {
+ for (final Device d : mDeviceMap.get(mDeviceManufacturer.getText())) {
+ mDeviceName.add(d.getName());
+ }
}
- }
-
- /**
- * Enable or disable the sd card widgets.
- * @param sizeMode if true the size-based widgets are to be enabled, and the file-based ones
- * disabled.
- */
- private void enableSdCardWidgets(boolean sizeMode) {
- mSdCardSize.setEnabled(sizeMode);
- mSdCardSizeCombo.setEnabled(sizeMode);
-
- mSdCardFile.setEnabled(!sizeMode);
- mBrowseSdCard.setEnabled(!sizeMode);
- }
-
- /**
- * Enable or disable the skin widgets.
- * @param listMode if true the list-based widgets are to be enabled, and the size-based ones
- * disabled.
- */
- private void enableSkinWidgets(boolean listMode) {
- mSkinCombo.setEnabled(listMode);
- mSkinSizeWidth.setEnabled(!listMode);
- mSkinSizeHeight.setEnabled(!listMode);
}
-
- private void onBrowseSdCard() {
- FileDialog dlg = new FileDialog(getContents().getShell(), SWT.OPEN);
- dlg.setText("Choose SD Card image file.");
-
- String fileName = dlg.open();
- if (fileName != null) {
- mSdCardFile.setText(fileName);
- }
- }
-
-
-
private void reloadTargetCombo() {
String selected = null;
- int index = mTargetCombo.getSelectionIndex();
+ int index = mTarget.getSelectionIndex();
if (index >= 0) {
- selected = mTargetCombo.getItem(index);
+ selected = mTarget.getItem(index);
}
mCurrentTargets.clear();
- mTargetCombo.removeAll();
+ mTarget.removeAll();
boolean found = false;
index = -1;
@@ -1017,7 +490,7 @@ final class AvdCreationDialog extends GridDialog {
target.getVersion().getApiString());
}
mCurrentTargets.put(name, target);
- mTargetCombo.add(name);
+ mTarget.add(name);
if (!found) {
index++;
found = name.equals(selected);
@@ -1025,283 +498,153 @@ final class AvdCreationDialog extends GridDialog {
}
}
- mTargetCombo.setEnabled(mCurrentTargets.size() > 0);
+ mTarget.setEnabled(mCurrentTargets.size() > 0);
if (found) {
- mTargetCombo.select(index);
- }
-
- reloadSkinCombo();
- }
-
-
- private void reloadDeviceCombo() {
- Device selectedDevice = getSelectedDevice();
-
- mDeviceCombo.removeAll();
- for (Device d : mDeviceList) {
- mDeviceCombo.add(d.getManufacturer() + " " + d.getName());
- }
-
- // Try to select the previously selected device if it still exists
- if (selectedDevice != null) {
- int index = mDeviceList.indexOf(selectedDevice);
- if (index >= 0) {
- mDeviceCombo.select(index);
- }
+ mTarget.select(index);
}
-
- mDeviceCombo.setEnabled(mTargetCombo.getSelectionIndex() >= 0);
}
- private void reloadSkinCombo() {
+ /**
+ * Reload all the abi types in the selection list
+ */
+ private void reloadAbiTypeCombo() {
String selected = null;
- int index = mSkinCombo.getSelectionIndex();
+ boolean found = false;
+
+ int index = mTarget.getSelectionIndex();
if (index >= 0) {
- selected = mSkinCombo.getItem(index);
- }
+ String targetName = mTarget.getItem(index);
+ IAndroidTarget target = mCurrentTargets.get(targetName);
- mSkinCombo.removeAll();
- mSkinCombo.setEnabled(false);
+ ISystemImage[] systemImages = getSystemImages(target);
- index = mTargetCombo.getSelectionIndex();
- if (index >= 0) {
+ mAbi.setEnabled(systemImages.length > 1);
+
+ // If user explicitly selected an ABI before, preserve that option
+ // If user did not explicitly select before (only one option before)
+ // force them to select
+ index = mAbi.getSelectionIndex();
+ if (index >= 0 && mAbi.getItemCount() > 1) {
+ selected = mAbi.getItem(index);
+ }
- String targetName = mTargetCombo.getItem(index);
+ mAbi.removeAll();
- boolean found = false;
- IAndroidTarget target = mCurrentTargets.get(targetName);
- if (target != null) {
- mSkinCombo.add(String.format("Default (%s)", target.getDefaultSkin()));
-
- index = -1;
- for (String skin : target.getSkins()) {
- mSkinCombo.add(skin);
- if (!found) {
- index++;
- found = skin.equals(selected);
+ int i;
+ for (i = 0; i < systemImages.length; i++) {
+ String prettyAbiType = AvdInfo.getPrettyAbiType(systemImages[i].getAbiType());
+ mAbi.add(prettyAbiType);
+ if (!found) {
+ found = prettyAbiType.equals(selected);
+ if (found) {
+ mAbi.select(i);
}
}
+ }
- mSkinCombo.setEnabled(true);
-
- if (found) {
- mSkinCombo.select(index);
- } else {
- mSkinCombo.select(0); // default
- loadSkin();
- }
+ if (systemImages.length == 1) {
+ mAbi.select(0);
}
}
}
/**
- * Reload all the abi types in the selection list
- */
- private void reloadAbiTypeCombo() {
- String selected = null;
- boolean found = false;
-
- int index = mTargetCombo.getSelectionIndex();
- if (index >= 0) {
- String targetName = mTargetCombo.getItem(index);
- IAndroidTarget target = mCurrentTargets.get(targetName);
-
- ISystemImage[] systemImages = getSystemImages(target);
-
- mAbiTypeCombo.setEnabled(systemImages.length > 1);
-
- // If user explicitly selected an ABI before, preserve that option
- // If user did not explicitly select before (only one option before)
- // force them to select
- index = mAbiTypeCombo.getSelectionIndex();
- if (index >= 0 && mAbiTypeCombo.getItemCount() > 1) {
- selected = mAbiTypeCombo.getItem(index);
- }
-
- mAbiTypeCombo.removeAll();
-
- int i;
- for ( i = 0; i < systemImages.length ; i++ ) {
- String prettyAbiType = AvdInfo.getPrettyAbiType(systemImages[i].getAbiType());
- mAbiTypeCombo.add(prettyAbiType);
- if (!found) {
- found = prettyAbiType.equals(selected);
- if (found) {
- mAbiTypeCombo.select(i);
- }
- }
- }
-
- if (systemImages.length == 1) {
- mAbiTypeCombo.select(0);
- }
- }
+ * Enable or disable the sd card widgets.
+ *
+ * @param sizeMode if true the size-based widgets are to be enabled, and the
+ * file-based ones disabled.
+ */
+ private void enableSdCardWidgets(boolean sizeMode) {
+ mSdCardSize.setEnabled(sizeMode);
+ mSdCardSizeCombo.setEnabled(sizeMode);
+
+ mSdCardFile.setEnabled(!sizeMode);
+ mBrowseSdCard.setEnabled(!sizeMode);
}
- /**
- * Validates the fields, displays errors and warnings.
- * Enables the finish button if there are no errors.
- */
- private void validatePage() {
- String error = null;
- String warning = null;
+ private void onBrowseSdCard() {
+ FileDialog dlg = new FileDialog(getContents().getShell(), SWT.OPEN);
+ dlg.setText("Choose SD Card image file.");
- // Validate AVD name
- String avdName = mAvdName.getText().trim();
- boolean hasAvdName = avdName.length() > 0;
- boolean isCreate = mEditAvdInfo == null || !avdName.equals(mEditAvdInfo.getName());
+ String fileName = dlg.open();
+ if (fileName != null) {
+ mSdCardFile.setText(fileName);
+ }
+ }
- if (hasAvdName && !AvdManager.RE_AVD_NAME.matcher(avdName).matches()) {
- error = String.format(
- "AVD name '%1$s' contains invalid characters.\nAllowed characters are: %2$s",
- avdName, AvdManager.CHARS_AVD_NAME);
+ @Override
+ public void okPressed() {
+ if (createAvd()) {
+ super.okPressed();
}
+ }
- // Validate target
- if (hasAvdName && error == null && mTargetCombo.getSelectionIndex() < 0) {
- error = "A target must be selected in order to create an AVD.";
+ private void validatePage() {
+ String error = null;
+ String warning = null;
+ boolean valid = true;
+ if (mAvdName.getText().isEmpty()) {
+ valid = false;
}
- // validate abi type if the selected target supports multi archs.
- if (hasAvdName && error == null && mTargetCombo.getSelectionIndex() > 0) {
- int index = mTargetCombo.getSelectionIndex();
- String targetName = mTargetCombo.getItem(index);
- IAndroidTarget target = mCurrentTargets.get(targetName);
- ISystemImage[] systemImages = getSystemImages(target);
- if (systemImages.length > 1 && mAbiTypeCombo.getSelectionIndex() < 0) {
- error = "An ABI type must be selected in order to create an AVD.";
- }
+ if (mDeviceManufacturer.getSelectionIndex() < 0 || mDeviceName.getSelectionIndex() < 0) {
+ valid = false;
}
- // Validate SDCard path or value
- if (error == null) {
- // get the mode. We only need to check the file since the
- // verifier on the size Text will prevent invalid input
- boolean sdcardFileMode = mSdCardFileRadio.getSelection();
- if (sdcardFileMode) {
- String sdName = mSdCardFile.getText().trim();
- if (sdName.length() > 0 && !new File(sdName).isFile()) {
- error = "SD Card path isn't valid.";
- }
- } else {
- String valueString = mSdCardSize.getText();
- if (valueString.length() > 0) {
- long value = 0;
- try {
- value = Long.parseLong(valueString);
-
- int sizeIndex = mSdCardSizeCombo.getSelectionIndex();
- if (sizeIndex >= 0) {
- // index 0 shifts by 10 (1024=K), index 1 by 20, etc.
- value <<= 10*(1 + sizeIndex);
- }
+ if (mTarget.getSelectionIndex() < 0 || mAbi.getSelectionIndex() < 0) {
+ valid = false;
+ }
- if (value < AvdManager.SDCARD_MIN_BYTE_SIZE ||
- value > AvdManager.SDCARD_MAX_BYTE_SIZE) {
- value = 0;
- }
- } catch (Exception e) {
- // ignore, we'll test value below.
+ // validate sdcard size or file
+ if (mSdCardSizeRadio.getSelection()) {
+ if (!mSdCardSize.getText().isEmpty() && mSdCardSizeCombo.getSelectionIndex() >= 0) {
+ try {
+ long sdSize = Long.parseLong(mSdCardSize.getText());
+
+ int sizeIndex = mSdCardSizeCombo.getSelectionIndex();
+ if (sizeIndex >= 0) {
+ // index 0 shifts by 10 (1024=K), index 1 by 20, etc.
+ sdSize <<= 10 * (1 + sizeIndex);
}
- if (value <= 0) {
+
+ if (sdSize < AvdManager.SDCARD_MIN_BYTE_SIZE ||
+ sdSize > AvdManager.SDCARD_MAX_BYTE_SIZE) {
+ valid = false;
error = "SD Card size is invalid. Range is 9 MiB..1023 GiB.";
- } else if (mEditAvdInfo != null) {
- // When editing an existing AVD, compare with the existing
- // sdcard size, if any. It only matters if there was an sdcard setting
- // before.
- Map<String, String> props = mEditAvdInfo.getProperties();
- if (props != null) {
- String original =
- mEditAvdInfo.getProperties().get(AvdManager.AVD_INI_SDCARD_SIZE);
- if (original != null && original.length() > 0) {
- long originalSize =
- AvdManager.parseSdcardSize(original, null/*parsedStrings*/);
- if (originalSize > 0 && value != originalSize) {
- warning = "A new SD Card file will be created.\nThe current SD Card file will be lost.";
- }
- }
- }
}
+ } catch (NumberFormatException e) {
+ valid = false;
+ error = " SD Card size must be a valid integer between 9 MiB and 1023 GiB";
}
}
- }
-
- // validate the skin
- if (error == null) {
- // get the mode, we should only check if it's in size mode since
- // the built-in list mode is always valid.
- if (mSkinSizeRadio.getSelection()) {
- // need both with and heigh to be non null
- String width = mSkinSizeWidth.getText(); // no need for trim, since the verifier
- String height = mSkinSizeHeight.getText(); // rejects non digit.
-
- if (width.length() == 0 || height.length() == 0) {
- error = "Skin size is incorrect.\nBoth dimensions must be > 0.";
- }
+ } else {
+ if (mSdCardFile.getText().isEmpty() || !new File(mSdCardFile.getText()).isFile()) {
+ valid = false;
+ error = "SD Card path isn't valid.";
}
}
- // Check for duplicate AVD name
- if (isCreate && hasAvdName && error == null && !mForceCreation.getSelection()) {
- Pair<AvdConflict, String> conflict = mAvdManager.isAvdNameConflicting(avdName);
- assert conflict != null;
- switch(conflict.getFirst()) {
- case NO_CONFLICT:
- break;
- case CONFLICT_EXISTING_AVD:
- case CONFLICT_INVALID_AVD:
- error = String.format(
- "The AVD name '%s' is already used.\n" +
- "Check \"Override the existing AVD\" to delete the existing one.",
- avdName);
- break;
- case CONFLICT_EXISTING_PATH:
- error = String.format(
- "Conflict with %s\n" +
- "Check \"Override the existing AVD\" to delete the existing one.",
- conflict.getSecond());
- break;
- default:
- // Hmm not supposed to happen... probably someone expanded the
- // enum without adding something here. In this case just do an
- // assert and use a generic error message.
- error = String.format(
- "Conflict %s with %s.\n" +
- "Check \"Override the existing AVD\" to delete the existing one.",
- conflict.getFirst().toString(),
- conflict.getSecond());
- assert false;
- break;
- }
+ if (mForceCreation.isEnabled() && !mForceCreation.getSelection()) {
+ valid = false;
+ error = String.format(
+ "The AVD name '%s' is already used.\n" +
+ "Check \"Override the existing AVD\" to delete the existing one.",
+ mAvdName.getText());
}
- if (error == null && mEditAvdInfo != null && isCreate) {
+ if (mAvdInfo != null && !mAvdInfo.getName().equals(mAvdName.getText())) {
warning = String.format("The AVD '%1$s' will be duplicated into '%2$s'.",
- mEditAvdInfo.getName(),
- avdName);
- }
-
- // Validate the create button
- boolean can_create = hasAvdName && error == null;
- if (can_create) {
- can_create &= mTargetCombo.getSelectionIndex() >= 0;
- }
- mOkButton.setEnabled(can_create);
-
- // Adjust the create button label as needed
- if (isCreate) {
- mOkButton.setText("Create AVD");
- } else {
- mOkButton.setText("Edit AVD");
+ mAvdInfo.getName(),
+ mAvdName.getText());
}
- // -- update UI
+ mOkButton.setEnabled(valid);
if (error != null) {
- mStatusIcon.setImage(mImageFactory.getImageByName("reject_icon16.png")); //$NON-NLS-1$
+ mStatusIcon.setImage(mImageFactory.getImageByName("reject_icon16.png")); //$NON-NLS-1$
mStatusLabel.setText(error);
} else if (warning != null) {
- mStatusIcon.setImage(mImageFactory.getImageByName("warning_icon16.png")); //$NON-NLS-1$
+ mStatusIcon.setImage(mImageFactory.getImageByName("warning_icon16.png")); //$NON-NLS-1$
mStatusLabel.setText(warning);
} else {
mStatusIcon.setImage(null);
@@ -1311,119 +654,30 @@ final class AvdCreationDialog extends GridDialog {
mStatusComposite.pack(true);
}
- private void loadSkin() {
- int targetIndex = mTargetCombo.getSelectionIndex();
- if (targetIndex < 0) {
- return;
- }
-
- // resolve the target.
- String targetName = mTargetCombo.getItem(targetIndex);
- IAndroidTarget target = mCurrentTargets.get(targetName);
- if (target == null) {
- return;
- }
-
- // get the skin name
- String skinName = null;
- int skinIndex = mSkinCombo.getSelectionIndex();
- if (skinIndex < 0) {
- return;
- } else if (skinIndex == 0) { // default skin for the target
- skinName = target.getDefaultSkin();
- } else {
- skinName = mSkinCombo.getItem(skinIndex);
- }
-
- // load the skin properties
- String path = target.getPath(IAndroidTarget.SKINS);
- File skin = new File(path, skinName);
- if (skin.isDirectory() == false && target.isPlatform() == false) {
- // it's possible the skin is in the parent target
- path = target.getParent().getPath(IAndroidTarget.SKINS);
- skin = new File(path, skinName);
- }
-
- if (skin.isDirectory() == false) {
- return;
- }
-
- // now get the hardware.ini from the add-on (if applicable) and from the skin
- // (if applicable)
- HashMap<String, String> hardwareValues = new HashMap<String, String>();
- if (target.isPlatform() == false) {
- FileWrapper targetHardwareFile = new FileWrapper(target.getLocation(),
- AvdManager.HARDWARE_INI);
- if (targetHardwareFile.isFile()) {
- Map<String, String> targetHardwareConfig = ProjectProperties.parsePropertyFile(
- targetHardwareFile, null /*log*/);
-
- if (targetHardwareConfig != null) {
- hardwareValues.putAll(targetHardwareConfig);
- }
- }
- }
-
- // from the skin
- FileWrapper skinHardwareFile = new FileWrapper(skin, AvdManager.HARDWARE_INI);
- if (skinHardwareFile.isFile()) {
- Map<String, String> skinHardwareConfig = ProjectProperties.parsePropertyFile(
- skinHardwareFile, null /*log*/);
-
- if (skinHardwareConfig != null) {
- hardwareValues.putAll(skinHardwareConfig);
- }
- }
-
- // now set those values in the list of properties for the AVD.
- // We just check that none of those properties have been edited by the user yet.
- for (Entry<String, String> entry : hardwareValues.entrySet()) {
- if (mEditedProperties.contains(entry.getKey()) == false) {
- mProperties.put(entry.getKey(), entry.getValue());
- }
- }
-
- mHardwareViewer.refresh();
- }
-
- /**
- * Creates an AVD from the values in the UI. Called when the user presses the OK button.
- */
private boolean createAvd() {
- String avdName = mAvdName.getText().trim();
- int index = mTargetCombo.getSelectionIndex();
- // quick check on the name and the target selection
- if (avdName.length() == 0 || index < 0) {
+ String avdName = mAvdName.getText();
+ if (avdName == null || avdName.isEmpty()) {
return false;
}
- // resolve the target.
- String targetName = mTargetCombo.getItem(index);
+ String targetName = mTarget.getItem(mTarget.getSelectionIndex());
IAndroidTarget target = mCurrentTargets.get(targetName);
if (target == null) {
return false;
}
- index = mDeviceCombo.getSelectionIndex();
- if (index >= 0 && index < mDeviceList.size()) {
- Device d = mDeviceList.get(index);
- // Set the properties so it gets saved to the avd's ini
- mProperties.put(AvdManager.AVD_INI_DEVICE_MANUFACTURER, d.getManufacturer());
- mProperties.put(AvdManager.AVD_INI_DEVICE_NAME, d.getName());
- }
-
// get the abi type
- mAbiType = SdkConstants.ABI_ARMEABI;
+ String abiType = SdkConstants.ABI_ARMEABI;
ISystemImage[] systemImages = getSystemImages(target);
if (systemImages.length > 0) {
- int abiIndex = mAbiTypeCombo.getSelectionIndex();
+ int abiIndex = mAbi.getSelectionIndex();
if (abiIndex >= 0) {
- String prettyname = mAbiTypeCombo.getItem(abiIndex);
- //Extract the abi type
+ String prettyname = mAbi.getItem(abiIndex);
+ // Extract the abi type
int firstIndex = prettyname.indexOf("(");
int lastIndex = prettyname.indexOf(")");
- mAbiType = prettyname.substring(firstIndex+1, lastIndex);
+ abiType = prettyname.substring(firstIndex + 1, lastIndex);
}
}
@@ -1437,13 +691,13 @@ final class AvdCreationDialog extends GridDialog {
// add the unit
switch (mSdCardSizeCombo.getSelectionIndex()) {
case 0:
- sdName += "K"; //$NON-NLS-1$
+ sdName += "K"; //$NON-NLS-1$
break;
case 1:
- sdName += "M"; //$NON-NLS-1$
+ sdName += "M"; //$NON-NLS-1$
break;
case 2:
- sdName += "G"; //$NON-NLS-1$
+ sdName += "G"; //$NON-NLS-1$
break;
default:
// shouldn't be here
@@ -1455,21 +709,27 @@ final class AvdCreationDialog extends GridDialog {
sdName = mSdCardFile.getText().trim();
}
- // get the Skin data from the UI
- String skinName = null;
- if (mSkinListRadio.getSelection()) {
- // built-in list provides the skin
- int skinIndex = mSkinCombo.getSelectionIndex();
- if (skinIndex > 0) {
- // index 0 is the default, we don't use it
- skinName = mSkinCombo.getItem(skinIndex);
+ // Get the device
+ List<Device> devices = mDeviceMap.get(mDeviceManufacturer.getText());
+ if (devices == null) {
+ return false;
+ }
+
+ Device device = null;
+ for (Device d : devices) {
+ if (mDeviceName.getText().equals(d.getName())) {
+ device = d;
+ break;
}
- } else {
- // size mode. get both size and writes it as a skin name
- // thanks to validatePage() we know the content of the fields is correct
- skinName = mSkinSizeWidth.getText() + "x" + mSkinSizeHeight.getText(); //$NON-NLS-1$
}
+ if (device == null) {
+ return false;
+ }
+
+ Screen s = device.getDefaultHardware().getScreen();
+ String skinName = s.getXDimension() + "x" + s.getYDimension();
+
ISdkLog log = mSdkLog;
if (log == null || log instanceof MessageBoxLog) {
// If the current logger is a message box, we use our own (to make sure
@@ -1477,7 +737,12 @@ final class AvdCreationDialog extends GridDialog {
log = new MessageBoxLog(
String.format("Result of creating AVD '%s':", avdName),
getContents().getDisplay(),
- false /*logErrorsOnly*/);
+ false /* logErrorsOnly */);
+ }
+
+ Map<String, String> hwProps = DeviceManager.getHardwareProperties(device);
+ if (mGpuEmulation.getSelection()) {
+ hwProps.put(AvdManager.AVD_INI_GPU_EMULATION, HardwareProperties.BOOLEAN_VALUES[0]);
}
File avdFolder = null;
@@ -1487,28 +752,32 @@ final class AvdCreationDialog extends GridDialog {
return false;
}
- boolean force = mForceCreation.getSelection();
- boolean snapshot = mSnapshotCheck.getSelection();
+ hwProps.put(AvdManager.AVD_INI_DEVICE_MANUFACTURER, mDeviceManufacturer.getText());
+ hwProps.put(AvdManager.AVD_INI_DEVICE_NAME, mDeviceName.getText());
+
+ if (mFrontCamera.isEnabled()) {
+ hwProps.put(AvdManager.AVD_INI_CAMERA_FRONT,
+ mFrontCamera.getText().toLowerCase());
+ }
- boolean success = false;
- AvdInfo avdInfo = mAvdManager.createAvd(
- avdFolder,
+ if (mBackCamera.isEnabled()) {
+ hwProps.put(AvdManager.AVD_INI_CAMERA_BACK,
+ mBackCamera.getText().toLowerCase());
+ }
+
+ AvdInfo avdInfo = mAvdManager.createAvd(avdFolder,
avdName,
target,
- mAbiType,
+ abiType,
skinName,
sdName,
- mProperties,
- snapshot,
- force,
- mEditAvdInfo != null, //edit existing
+ hwProps,
+ mSnapshot.getSelection(),
+ mForceCreation.getSelection(),
+ mAvdInfo != null, // edit existing
log);
- success = avdInfo != null;
-
- // Remove the device name and manufacturer properties so they don't show up in the hardware list
- mProperties.remove(AvdManager.AVD_INI_DEVICE_MANUFACTURER);
- mProperties.remove(AvdManager.AVD_INI_DEVICE_NAME);
+ boolean success = avdInfo != null;
if (log instanceof MessageBoxLog) {
((MessageBoxLog) log).displayResult(success);
@@ -1516,11 +785,128 @@ final class AvdCreationDialog extends GridDialog {
return success;
}
+ private void fillExistingAvdInfo(AvdInfo avd) {
+ mAvdName.setText(avd.getName());
+ String manufacturer = avd.getDeviceManufacturer();
+ for (int i = 0; i < mDeviceManufacturer.getItemCount(); i++) {
+ if (mDeviceManufacturer.getItem(i).equals(manufacturer)) {
+ mDeviceManufacturer.select(i);
+ break;
+ }
+ }
+ reloadDeviceNameCombo();
+
+ String deviceName = avd.getDeviceName();
+ for (int i = 0; i < mDeviceName.getItemCount(); i++) {
+ if (mDeviceName.getItem(i).equals(deviceName)) {
+ mDeviceName.select(i);
+ break;
+ }
+ }
+ toggleCameras();
+
+ IAndroidTarget target = avd.getTarget();
+
+ if (target != null && !mCurrentTargets.isEmpty()) {
+ // Try to select the target in the target combo.
+ // This will fail if the AVD needs to be repaired.
+ //
+ // This is a linear search but the list is always
+ // small enough and we only do this once.
+ int n = mTarget.getItemCount();
+ for (int i = 0; i < n; i++) {
+ if (target.equals(mCurrentTargets.get(mTarget.getItem(i)))) {
+ mTarget.select(i);
+ reloadAbiTypeCombo();
+ break;
+ }
+ }
+ }
+
+ ISystemImage[] systemImages = getSystemImages(target);
+ if (target != null && systemImages.length > 0) {
+ mAbi.setEnabled(systemImages.length > 1);
+ String abiType = AvdInfo.getPrettyAbiType(avd.getAbiType());
+ int n = mAbi.getItemCount();
+ for (int i = 0; i < n; i++) {
+ if (abiType.equals(mAbi.getItem(i))) {
+ mAbi.select(i);
+ break;
+ }
+ }
+ }
+
+ Map<String, String> props = avd.getProperties();
+
+ if (props != null) {
+ String snapshots = props.get(AvdManager.AVD_INI_SNAPSHOT_PRESENT);
+ if (snapshots != null && snapshots.length() > 0) {
+ mSnapshot.setSelection(snapshots.equals("true"));
+ }
+
+ String gpuEmulation = props.get(AvdManager.AVD_INI_GPU_EMULATION);
+ mGpuEmulation.setSelection(gpuEmulation != null &&
+ gpuEmulation.equals(HardwareProperties.BOOLEAN_VALUES[0]));
+
+ String sdcard = props.get(AvdManager.AVD_INI_SDCARD_PATH);
+ if (sdcard != null && sdcard.length() > 0) {
+ enableSdCardWidgets(false);
+ mSdCardSizeRadio.setSelection(false);
+ mSdCardFileRadio.setSelection(true);
+ mSdCardFile.setText(sdcard);
+ }
+
+ String cameraFront = props.get(AvdManager.AVD_INI_CAMERA_FRONT);
+ if (cameraFront != null) {
+ String[] items = mFrontCamera.getItems();
+ for (int i = 0; i < items.length; i++) {
+ if (items[i].toLowerCase().equals(cameraFront)) {
+ mFrontCamera.select(i);
+ break;
+ }
+ }
+ }
+
+ String cameraBack = props.get(AvdManager.AVD_INI_CAMERA_BACK);
+ if (cameraBack != null) {
+ String[] items = mBackCamera.getItems();
+ for (int i = 0; i < items.length; i++) {
+ if (items[i].toLowerCase().equals(cameraBack)) {
+ mBackCamera.select(i);
+ break;
+ }
+ }
+ }
+
+ sdcard = props.get(AvdManager.AVD_INI_SDCARD_SIZE);
+ if (sdcard != null && sdcard.length() > 0) {
+ String[] values = new String[2];
+ long sdcardSize = AvdManager.parseSdcardSize(sdcard, values);
+
+ if (sdcardSize != AvdManager.SDCARD_NOT_SIZE_PATTERN) {
+ enableSdCardWidgets(true);
+ mSdCardFileRadio.setSelection(false);
+ mSdCardSizeRadio.setSelection(true);
+
+ mSdCardSize.setText(values[0]);
+
+ String suffix = values[1];
+ int n = mSdCardSizeCombo.getItemCount();
+ for (int i = 0; i < n; i++) {
+ if (mSdCardSizeCombo.getItem(i).startsWith(suffix)) {
+ mSdCardSizeCombo.select(i);
+ }
+ }
+ }
+ }
+ }
+ }
+
/**
* Returns the list of system images of a target.
* <p/>
- * If target is null, returns an empty list.
- * If target is an add-on with no system images, return the list from its parent platform.
+ * If target is null, returns an empty list. If target is an add-on with no
+ * system images, return the list from its parent platform.
*
* @param target An IAndroidTarget. Can be null.
* @return A non-null ISystemImage array. Can be empty.
@@ -1530,7 +916,8 @@ final class AvdCreationDialog extends GridDialog {
ISystemImage[] images = target.getSystemImages();
if ((images == null || images.length == 0) && !target.isPlatform()) {
- // If an add-on does not provide any system images, use the ones from the parent.
+ // If an add-on does not provide any system images, use the ones
+ // from the parent.
images = target.getParent().getSystemImages();
}
@@ -1542,15 +929,4 @@ final class AvdCreationDialog extends GridDialog {
return new ISystemImage[0];
}
- private Device getSelectedDevice() {
- int targetIndex = mDeviceCombo.getSelectionIndex();
- if (targetIndex >= 0 && mDeviceList.size() > targetIndex){
- return mDeviceList.get(targetIndex);
- } else {
- return null;
- }
- }
-
- // End of hiding from SWT Designer
- //$hide<<$
}
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java
index 3a76b2a..58bacec 100644
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java
@@ -35,6 +35,7 @@ import com.android.sdkuilib.internal.repository.icons.ImageFactory;
import com.android.sdkuilib.internal.repository.sdkman2.AvdManagerWindowImpl1;
import com.android.sdkuilib.internal.tasks.ProgressTask;
import com.android.sdkuilib.repository.AvdManagerWindow.AvdInvocationContext;
+import com.android.sdkuilib.ui.GridDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.window.Window;
@@ -885,12 +886,21 @@ public final class AvdSelector {
private void onEdit() {
AvdInfo avdInfo = getTableSelection();
+ GridDialog dlg;
+ if(!avdInfo.getDeviceName().isEmpty()) {
+ dlg = new AvdCreationDialog(mTable.getShell(),
+ mAvdManager,
+ mImageFactory,
+ mSdkLog,
+ avdInfo);
+ } else {
+ dlg = new LegacyAvdEditDialog(mTable.getShell(),
+ mAvdManager,
+ mImageFactory,
+ mSdkLog,
+ avdInfo);
+ }
- AvdCreationDialog dlg = new AvdCreationDialog(mTable.getShell(),
- mAvdManager,
- mImageFactory,
- mSdkLog,
- avdInfo);
if (dlg.open() == Window.OK) {
refresh(false /*reload*/);
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/LegacyAvdEditDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/LegacyAvdEditDialog.java
new file mode 100644
index 0000000..dc6b459
--- /dev/null
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/LegacyAvdEditDialog.java
@@ -0,0 +1,1425 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.sdkuilib.internal.widgets;
+
+import com.android.io.FileWrapper;
+import com.android.prefs.AndroidLocation.AndroidLocationException;
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.ISdkLog;
+import com.android.sdklib.ISystemImage;
+import com.android.sdklib.SdkConstants;
+import com.android.sdklib.SdkManager;
+import com.android.sdklib.internal.avd.AvdInfo;
+import com.android.sdklib.internal.avd.AvdManager;
+import com.android.sdklib.internal.avd.AvdManager.AvdConflict;
+import com.android.sdklib.internal.avd.HardwareProperties;
+import com.android.sdklib.internal.avd.HardwareProperties.HardwareProperty;
+import com.android.sdklib.internal.project.ProjectProperties;
+import com.android.sdkuilib.internal.repository.icons.ImageFactory;
+import com.android.sdkuilib.ui.GridDialog;
+import com.android.util.Pair;
+
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.CellLabelProvider;
+import org.eclipse.jface.viewers.ComboBoxCellEditor;
+import org.eclipse.jface.viewers.EditingSupport;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.jface.viewers.TextCellEditor;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerCell;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.Text;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+
+/**
+ * AVD creation or edit dialog.
+ *
+ * TODO:
+ * - use SdkTargetSelector instead of Combo
+ * - tooltips on widgets.
+ *
+ */
+final class LegacyAvdEditDialog extends GridDialog {
+
+ private final AvdManager mAvdManager;
+ private final TreeMap<String, IAndroidTarget> mCurrentTargets =
+ new TreeMap<String, IAndroidTarget>();
+
+ private final Map<String, HardwareProperty> mHardwareMap;
+ private final Map<String, String> mProperties = new HashMap<String, String>();
+ // a list of user-edited properties.
+ private final ArrayList<String> mEditedProperties = new ArrayList<String>();
+ private final ImageFactory mImageFactory;
+ private final ISdkLog mSdkLog;
+ /**
+ * The original AvdInfo if we're editing an existing AVD.
+ * Null when we're creating a new AVD.
+ */
+ private final AvdInfo mEditAvdInfo;
+
+ private Text mAvdName;
+ private Combo mTargetCombo;
+
+ private Combo mAbiTypeCombo;
+ private String mAbiType;
+
+ private Button mSdCardSizeRadio;
+ private Text mSdCardSize;
+ private Combo mSdCardSizeCombo;
+
+ private Text mSdCardFile;
+ private Button mBrowseSdCard;
+ private Button mSdCardFileRadio;
+
+ private Button mSnapshotCheck;
+
+ private Button mSkinListRadio;
+ private Combo mSkinCombo;
+
+ private Button mSkinSizeRadio;
+ private Text mSkinSizeWidth;
+ private Text mSkinSizeHeight;
+
+ private TableViewer mHardwareViewer;
+ private Button mDeleteHardwareProp;
+
+ private Button mForceCreation;
+ private Button mOkButton;
+ private Label mStatusIcon;
+ private Label mStatusLabel;
+ private Composite mStatusComposite;
+
+ /**
+ * {@link VerifyListener} for {@link Text} widgets that should only contains numbers.
+ */
+ private final VerifyListener mDigitVerifier = new VerifyListener() {
+ @Override
+ public void verifyText(VerifyEvent event) {
+ int count = event.text.length();
+ for (int i = 0 ; i < count ; i++) {
+ char c = event.text.charAt(i);
+ if (c < '0' || c > '9') {
+ event.doit = false;
+ return;
+ }
+ }
+ }
+ };
+
+ /**
+ * Callback when the AVD name is changed.
+ * When creating a new AVD, enables the force checkbox if the name is a duplicate.
+ * When editing an existing AVD, it's OK for the name to match the existing AVD.
+ */
+ private class CreateNameModifyListener implements ModifyListener {
+ @Override
+ public void modifyText(ModifyEvent e) {
+ String name = mAvdName.getText().trim();
+ if (mEditAvdInfo == null || !name.equals(mEditAvdInfo.getName())) {
+ // Case where we're creating a new AVD or editing an existing one
+ // and the AVD name has been changed... check for name uniqueness.
+
+ Pair<AvdConflict, String> conflict = mAvdManager.isAvdNameConflicting(name);
+ if (conflict.getFirst() != AvdManager.AvdConflict.NO_CONFLICT) {
+ // If we're changing the state from disabled to enabled, make sure
+ // to uncheck the button, to force the user to voluntarily re-enforce it.
+ // This happens when editing an existing AVD and changing the name from
+ // the existing AVD to another different existing AVD.
+ if (!mForceCreation.isEnabled()) {
+ mForceCreation.setEnabled(true);
+ mForceCreation.setSelection(false);
+ }
+ } else {
+ mForceCreation.setEnabled(false);
+ mForceCreation.setSelection(false);
+ }
+ } else {
+ // Case where we're editing an existing AVD with the name unchanged.
+
+ mForceCreation.setEnabled(false);
+ mForceCreation.setSelection(false);
+ }
+ validatePage();
+ }
+ }
+
+ /**
+ * {@link ModifyListener} used for live-validation of the fields content.
+ */
+ private class ValidateListener extends SelectionAdapter implements ModifyListener {
+ @Override
+ public void modifyText(ModifyEvent e) {
+ validatePage();
+ }
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ super.widgetSelected(e);
+ validatePage();
+ }
+ }
+
+ /**
+ * Creates the dialog. Caller should then use {@link Window#open()} and
+ * refresh if the status is {@link Window#OK}.
+ *
+ * @param parentShell The parent shell.
+ * @param avdManager The existing {@link AvdManager} to use. Must not be null.
+ * @param imageFactory An existing {@link ImageFactory} to use. Must not be null.
+ * @param log An existing {@link ISdkLog} where output will go. Must not be null.
+ * @param editAvdInfo An optional {@link AvdInfo}. When null, the dialog is used
+ * to create a new AVD. When non-null, the dialog is used to <em>edit</em> this AVD.
+ */
+ protected LegacyAvdEditDialog(Shell parentShell,
+ AvdManager avdManager,
+ ImageFactory imageFactory,
+ ISdkLog log,
+ AvdInfo editAvdInfo) {
+ super(parentShell, 2, false);
+ mAvdManager = avdManager;
+ mImageFactory = imageFactory;
+ mSdkLog = log;
+ mEditAvdInfo = editAvdInfo;
+
+ File hardwareDefs = null;
+
+ SdkManager sdkMan = avdManager.getSdkManager();
+ if (sdkMan != null) {
+ String sdkPath = sdkMan.getLocation();
+ if (sdkPath != null) {
+ hardwareDefs = new File (sdkPath + File.separator +
+ SdkConstants.OS_SDK_TOOLS_LIB_FOLDER, SdkConstants.FN_HARDWARE_INI);
+ }
+ }
+
+ if (hardwareDefs == null) {
+ log.error(null, "Failed to load file %s from SDK", SdkConstants.FN_HARDWARE_INI);
+ mHardwareMap = new HashMap<String, HardwareProperty>();
+ } else {
+ mHardwareMap = HardwareProperties.parseHardwareDefinitions(
+ hardwareDefs, null /*sdkLog*/);
+ }
+ }
+
+ @Override
+ public void create() {
+ super.create();
+
+ Point p = getShell().getSize();
+ if (p.x < 400) {
+ p.x = 400;
+ }
+ getShell().setSize(p);
+ }
+
+ @Override
+ protected Control createContents(Composite parent) {
+ Control control = super.createContents(parent);
+ getShell().setText(mEditAvdInfo == null ? "Create new Android Virtual Device (AVD)"
+ : "Edit Android Virtual Device (AVD)");
+
+ mOkButton = getButton(IDialogConstants.OK_ID);
+
+ fillExistingAvdInfo();
+ validatePage();
+
+ return control;
+ }
+
+ @Override
+ public void createDialogContent(final Composite parent) {
+ GridData gd;
+ GridLayout gl;
+
+ Label label = new Label(parent, SWT.NONE);
+ label.setText("Name:");
+ String tooltip = "Name of the new Android Virtual Device";
+ label.setToolTipText(tooltip);
+
+ mAvdName = new Text(parent, SWT.BORDER);
+ mAvdName.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ mAvdName.addModifyListener(new CreateNameModifyListener());
+ mAvdName.setToolTipText(tooltip);
+
+ label = new Label(parent, SWT.NONE);
+ label.setText("Target:");
+ tooltip = "The version of Android to use in the virtual device";
+ label.setToolTipText(tooltip);
+
+ mTargetCombo = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN);
+ mTargetCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ mTargetCombo.setToolTipText(tooltip);
+ mTargetCombo.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ super.widgetSelected(e);
+ reloadSkinCombo();
+ reloadAbiTypeCombo();
+ validatePage();
+ }
+ });
+
+ //ABI group
+ label = new Label(parent, SWT.NONE);
+ label.setText("CPU/ABI:");
+ tooltip = "The CPU/ABI to use in the virtual device";
+ label.setToolTipText(tooltip);
+
+ mAbiTypeCombo = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN);
+ mAbiTypeCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ mAbiTypeCombo.setToolTipText(tooltip);
+ mAbiTypeCombo.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ super.widgetSelected(e);
+ validatePage();
+ }
+ });
+ mAbiTypeCombo.setEnabled(false);
+
+ // --- sd card group
+ label = new Label(parent, SWT.NONE);
+ label.setText("SD Card:");
+ label.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING,
+ false, false));
+
+ final Group sdCardGroup = new Group(parent, SWT.NONE);
+ sdCardGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ sdCardGroup.setLayout(new GridLayout(3, false));
+
+ mSdCardSizeRadio = new Button(sdCardGroup, SWT.RADIO);
+ mSdCardSizeRadio.setText("Size:");
+ mSdCardSizeRadio.setToolTipText("Create a new SD Card file");
+ mSdCardSizeRadio.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent arg0) {
+ boolean sizeMode = mSdCardSizeRadio.getSelection();
+ enableSdCardWidgets(sizeMode);
+ validatePage();
+ }
+ });
+
+ ValidateListener validateListener = new ValidateListener();
+
+ mSdCardSize = new Text(sdCardGroup, SWT.BORDER);
+ mSdCardSize.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ mSdCardSize.addVerifyListener(mDigitVerifier);
+ mSdCardSize.addModifyListener(validateListener);
+ mSdCardSize.setToolTipText("Size of the new SD Card file (must be at least 9 MiB)");
+
+ mSdCardSizeCombo = new Combo(sdCardGroup, SWT.DROP_DOWN | SWT.READ_ONLY);
+ mSdCardSizeCombo.add("KiB");
+ mSdCardSizeCombo.add("MiB");
+ mSdCardSizeCombo.add("GiB");
+ mSdCardSizeCombo.select(1);
+ mSdCardSizeCombo.addSelectionListener(validateListener);
+
+ mSdCardFileRadio = new Button(sdCardGroup, SWT.RADIO);
+ mSdCardFileRadio.setText("File:");
+ mSdCardFileRadio.setToolTipText("Use an existing file for the SD Card");
+
+ mSdCardFile = new Text(sdCardGroup, SWT.BORDER);
+ mSdCardFile.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ mSdCardFile.addModifyListener(validateListener);
+ mSdCardFile.setToolTipText("File to use for the SD Card");
+
+ mBrowseSdCard = new Button(sdCardGroup, SWT.PUSH);
+ mBrowseSdCard.setText("Browse...");
+ mBrowseSdCard.setToolTipText("Select the file to use for the SD Card");
+ mBrowseSdCard.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent arg0) {
+ onBrowseSdCard();
+ validatePage();
+ }
+ });
+
+ mSdCardSizeRadio.setSelection(true);
+ enableSdCardWidgets(true);
+
+ // --- snapshot group
+
+ label = new Label(parent, SWT.NONE);
+ label.setText("Snapshot:");
+ label.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING,
+ false, false));
+
+ final Group snapshotGroup = new Group(parent, SWT.NONE);
+ snapshotGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ snapshotGroup.setLayout(new GridLayout(3, false));
+
+ mSnapshotCheck = new Button(snapshotGroup, SWT.CHECK);
+ mSnapshotCheck.setText("Enabled");
+ mSnapshotCheck.setToolTipText(
+ "Emulator's state will be persisted between emulator executions");
+
+ // --- skin group
+ label = new Label(parent, SWT.NONE);
+ label.setText("Skin:");
+ label.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING,
+ false, false));
+
+ final Group skinGroup = new Group(parent, SWT.NONE);
+ skinGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ skinGroup.setLayout(new GridLayout(4, false));
+
+ mSkinListRadio = new Button(skinGroup, SWT.RADIO);
+ mSkinListRadio.setText("Built-in:");
+ mSkinListRadio.setToolTipText("Select an emulated screen size provided by the current Android target");
+ mSkinListRadio.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent arg0) {
+ boolean listMode = mSkinListRadio.getSelection();
+ enableSkinWidgets(listMode);
+ validatePage();
+ }
+ });
+
+ mSkinCombo = new Combo(skinGroup, SWT.READ_ONLY | SWT.DROP_DOWN);
+ mSkinCombo.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+ gd.horizontalSpan = 3;
+ mSkinCombo.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent arg0) {
+ // get the skin info
+ loadSkin();
+ }
+ });
+
+ mSkinSizeRadio = new Button(skinGroup, SWT.RADIO);
+ mSkinSizeRadio.setText("Resolution:");
+ mSkinSizeRadio.setToolTipText("Select a custom emulated screen size");
+
+ mSkinSizeWidth = new Text(skinGroup, SWT.BORDER);
+ mSkinSizeWidth.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ mSkinSizeWidth.addVerifyListener(mDigitVerifier);
+ mSkinSizeWidth.addModifyListener(validateListener);
+ mSkinSizeWidth.setToolTipText("Width in pixels of the emulated screen size");
+
+ new Label(skinGroup, SWT.NONE).setText("x");
+
+ mSkinSizeHeight = new Text(skinGroup, SWT.BORDER);
+ mSkinSizeHeight.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ mSkinSizeHeight.addVerifyListener(mDigitVerifier);
+ mSkinSizeHeight.addModifyListener(validateListener);
+ mSkinSizeHeight.setToolTipText("Height in pixels of the emulated screen size");
+
+ mSkinListRadio.setSelection(true);
+ enableSkinWidgets(true);
+
+ // --- hardware group
+ label = new Label(parent, SWT.NONE);
+ label.setText("Hardware:");
+ label.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING,
+ false, false));
+
+ final Group hwGroup = new Group(parent, SWT.NONE);
+ hwGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ hwGroup.setLayout(new GridLayout(2, false));
+
+ createHardwareTable(hwGroup);
+
+ // composite for the side buttons
+ Composite hwButtons = new Composite(hwGroup, SWT.NONE);
+ hwButtons.setLayoutData(new GridData(GridData.FILL_VERTICAL));
+ hwButtons.setLayout(gl = new GridLayout(1, false));
+ gl.marginHeight = gl.marginWidth = 0;
+
+ Button b = new Button(hwButtons, SWT.PUSH | SWT.FLAT);
+ b.setText("New...");
+ b.setToolTipText("Add a new hardware property");
+ b.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ b.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent event) {
+ HardwarePropertyChooser dialog = new HardwarePropertyChooser(parent.getShell(),
+ mHardwareMap, mProperties.keySet());
+ if (dialog.open() == Window.OK) {
+ HardwareProperty choice = dialog.getProperty();
+ if (choice != null) {
+ mProperties.put(choice.getName(), choice.getDefault());
+ mHardwareViewer.refresh();
+ }
+ }
+ }
+ });
+ mDeleteHardwareProp = new Button(hwButtons, SWT.PUSH | SWT.FLAT);
+ mDeleteHardwareProp.setText("Delete");
+ mDeleteHardwareProp.setToolTipText("Delete the selected hardware property");
+ mDeleteHardwareProp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ mDeleteHardwareProp.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent arg0) {
+ ISelection selection = mHardwareViewer.getSelection();
+ if (selection instanceof IStructuredSelection) {
+ String hwName = (String)((IStructuredSelection)selection).getFirstElement();
+ mProperties.remove(hwName);
+ mHardwareViewer.refresh();
+ }
+ }
+ });
+ mDeleteHardwareProp.setEnabled(false);
+
+ // --- end hardware group
+
+ mForceCreation = new Button(parent, SWT.CHECK);
+ mForceCreation.setText("Override the existing AVD with the same name");
+ mForceCreation.setToolTipText("There's already an AVD with the same name. Check this to delete it and replace it by the new AVD.");
+ mForceCreation.setLayoutData(new GridData(GridData.BEGINNING, GridData.CENTER,
+ true, false, 2, 1));
+ mForceCreation.setEnabled(false);
+ mForceCreation.addSelectionListener(validateListener);
+
+ // add a separator to separate from the ok/cancel button
+ label = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL);
+ label.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 3, 1));
+
+ // add stuff for the error display
+ mStatusComposite = new Composite(parent, SWT.NONE);
+ mStatusComposite.setLayoutData(new GridData(GridData.FILL, GridData.CENTER,
+ true, false, 3, 1));
+ mStatusComposite.setLayout(gl = new GridLayout(2, false));
+ gl.marginHeight = gl.marginWidth = 0;
+
+ mStatusIcon = new Label(mStatusComposite, SWT.NONE);
+ mStatusIcon.setLayoutData(new GridData(GridData.BEGINNING, GridData.BEGINNING,
+ false, false));
+ mStatusLabel = new Label(mStatusComposite, SWT.NONE);
+ mStatusLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ mStatusLabel.setText(" \n "); //$NON-NLS-1$
+
+ reloadTargetCombo();
+ }
+
+ /**
+ * Creates the UI for the hardware properties table.
+ * This creates the {@link Table}, and several viewers ({@link TableViewer},
+ * {@link TableViewerColumn}) and adds edit support for the 2nd column
+ */
+ private void createHardwareTable(Composite parent) {
+ final Table hardwareTable = new Table(parent, SWT.SINGLE | SWT.FULL_SELECTION);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL);
+ gd.widthHint = 200;
+ gd.heightHint = 100;
+ hardwareTable.setLayoutData(gd);
+ hardwareTable.setHeaderVisible(true);
+ hardwareTable.setLinesVisible(true);
+
+ // -- Table viewer
+ mHardwareViewer = new TableViewer(hardwareTable);
+ mHardwareViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+ @Override
+ public void selectionChanged(SelectionChangedEvent event) {
+ // it's a single selection mode, we can just access the selection index
+ // from the table directly.
+ mDeleteHardwareProp.setEnabled(hardwareTable.getSelectionIndex() != -1);
+ }
+ });
+
+ // only a content provider. Use viewers per column below (for editing support)
+ mHardwareViewer.setContentProvider(new IStructuredContentProvider() {
+ @Override
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ // we can just ignore this. we just use mProperties directly.
+ }
+
+ @Override
+ public Object[] getElements(Object arg0) {
+ return mProperties.keySet().toArray();
+ }
+
+ @Override
+ public void dispose() {
+ // pass
+ }
+ });
+
+ // -- column 1: prop abstract name
+ TableColumn col1 = new TableColumn(hardwareTable, SWT.LEFT);
+ col1.setText("Property");
+ col1.setWidth(150);
+ TableViewerColumn tvc1 = new TableViewerColumn(mHardwareViewer, col1);
+ tvc1.setLabelProvider(new CellLabelProvider() {
+ @Override
+ public void update(ViewerCell cell) {
+ String name = cell.getElement().toString();
+ HardwareProperty prop = mHardwareMap.get(name);
+ if (prop != null) {
+ cell.setText(prop.getAbstract());
+ } else {
+ cell.setText(String.format("%1$s (Unknown)", name));
+ }
+ }
+ });
+
+ // -- column 2: prop value
+ TableColumn col2 = new TableColumn(hardwareTable, SWT.LEFT);
+ col2.setText("Value");
+ col2.setWidth(50);
+ TableViewerColumn tvc2 = new TableViewerColumn(mHardwareViewer, col2);
+ tvc2.setLabelProvider(new CellLabelProvider() {
+ @Override
+ public void update(ViewerCell cell) {
+ String value = mProperties.get(cell.getElement());
+ cell.setText(value != null ? value : "");
+ }
+ });
+
+ // add editing support to the 2nd column
+ tvc2.setEditingSupport(new EditingSupport(mHardwareViewer) {
+ @Override
+ protected void setValue(Object element, Object value) {
+ String hardwareName = (String)element;
+ HardwareProperty property = mHardwareMap.get(hardwareName);
+ int index;
+ switch (property.getType()) {
+ case INTEGER:
+ mProperties.put((String)element, (String)value);
+ break;
+ case DISKSIZE:
+ if (HardwareProperties.DISKSIZE_PATTERN.matcher((String)value).matches()) {
+ mProperties.put((String)element, (String)value);
+ }
+ break;
+ case BOOLEAN:
+ index = (Integer)value;
+ mProperties.put((String)element, HardwareProperties.BOOLEAN_VALUES[index]);
+ break;
+ case STRING_ENUM:
+ case INTEGER_ENUM:
+ // For a combo, value is the index of the enum to use.
+ index = (Integer)value;
+ String[] values = property.getEnum();
+ if (values != null && values.length > index) {
+ mProperties.put((String)element, values[index]);
+ }
+ break;
+ }
+ mHardwareViewer.refresh(element);
+ }
+
+ @Override
+ protected Object getValue(Object element) {
+ String hardwareName = (String)element;
+ HardwareProperty property = mHardwareMap.get(hardwareName);
+ String value = mProperties.get(hardwareName);
+ switch (property.getType()) {
+ case INTEGER:
+ // intended fall-through.
+ case DISKSIZE:
+ return value;
+ case BOOLEAN:
+ return HardwareProperties.getBooleanValueIndex(value);
+ case STRING_ENUM:
+ case INTEGER_ENUM:
+ // For a combo, we need to return the index of the value in the enum
+ String[] values = property.getEnum();
+ if (values != null) {
+ for (int i = 0; i < values.length; i++) {
+ if (values[i].equals(value)) {
+ return i;
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ protected CellEditor getCellEditor(Object element) {
+ String hardwareName = (String)element;
+ HardwareProperty property = mHardwareMap.get(hardwareName);
+ switch (property.getType()) {
+ // TODO: custom TextCellEditor that restrict input.
+ case INTEGER:
+ // intended fall-through.
+ case DISKSIZE:
+ return new TextCellEditor(hardwareTable);
+ case BOOLEAN:
+ return new ComboBoxCellEditor(hardwareTable,
+ HardwareProperties.BOOLEAN_VALUES,
+ SWT.READ_ONLY | SWT.DROP_DOWN);
+ case STRING_ENUM:
+ case INTEGER_ENUM:
+ String[] values = property.getEnum();
+ if (values != null && values.length > 0) {
+ return new ComboBoxCellEditor(hardwareTable,
+ values,
+ SWT.READ_ONLY | SWT.DROP_DOWN);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ protected boolean canEdit(Object element) {
+ String hardwareName = (String)element;
+ HardwareProperty property = mHardwareMap.get(hardwareName);
+ return property != null;
+ }
+ });
+
+
+ mHardwareViewer.setInput(mProperties);
+ }
+
+ // -- Start of internal part ----------
+ // Hide everything down-below from SWT designer
+ //$hide>>$
+
+ /**
+ * When editing an existing AVD info, fill the UI that has just been created with
+ * the values from the AVD.
+ */
+ public void fillExistingAvdInfo() {
+ if (mEditAvdInfo == null) {
+ return;
+ }
+
+ mAvdName.setText(mEditAvdInfo.getName());
+
+ Map<String, String> props = mEditAvdInfo.getProperties();
+
+ IAndroidTarget target = mEditAvdInfo.getTarget();
+ if (target != null && !mCurrentTargets.isEmpty()) {
+ // Try to select the target in the target combo.
+ // This will fail if the AVD needs to be repaired.
+ //
+ // This is a linear search but the list is always
+ // small enough and we only do this once.
+ int n = mTargetCombo.getItemCount();
+ for (int i = 0;i < n; i++) {
+ if (target.equals(mCurrentTargets.get(mTargetCombo.getItem(i)))) {
+ mTargetCombo.select(i);
+ reloadAbiTypeCombo();
+ reloadSkinCombo();
+ break;
+ }
+ }
+ }
+
+ // select the abi type
+ ISystemImage[] systemImages = getSystemImages(target);
+ if (target != null && systemImages.length > 0) {
+ mAbiTypeCombo.setEnabled(systemImages.length > 1);
+ String abiType = AvdInfo.getPrettyAbiType(mEditAvdInfo.getAbiType());
+ int n = mAbiTypeCombo.getItemCount();
+ for (int i = 0; i < n; i++) {
+ if (abiType.equals(mAbiTypeCombo.getItem(i))) {
+ mAbiTypeCombo.select(i);
+ reloadSkinCombo();
+ break;
+ }
+ }
+ }
+
+ if (props != null) {
+
+ // First try the skin name and if it doesn't work fallback on the skin path
+ nextSkin: for (int s = 0; s < 2; s++) {
+ String skin = props.get(s == 0 ? AvdManager.AVD_INI_SKIN_NAME
+ : AvdManager.AVD_INI_SKIN_PATH);
+ if (skin != null && skin.length() > 0) {
+ Matcher m = AvdManager.NUMERIC_SKIN_SIZE.matcher(skin);
+ if (m.matches() && m.groupCount() == 2) {
+ enableSkinWidgets(false);
+ mSkinListRadio.setSelection(false);
+ mSkinSizeRadio.setSelection(true);
+ mSkinSizeWidth.setText(m.group(1));
+ mSkinSizeHeight.setText(m.group(2));
+ break nextSkin;
+ } else {
+ enableSkinWidgets(true);
+ mSkinSizeRadio.setSelection(false);
+ mSkinListRadio.setSelection(true);
+
+ int n = mSkinCombo.getItemCount();
+ for (int i = 0; i < n; i++) {
+ if (skin.equals(mSkinCombo.getItem(i))) {
+ mSkinCombo.select(i);
+ break nextSkin;
+ }
+ }
+ }
+ }
+ }
+
+ String sdcard = props.get(AvdManager.AVD_INI_SDCARD_PATH);
+ if (sdcard != null && sdcard.length() > 0) {
+ enableSdCardWidgets(false);
+ mSdCardSizeRadio.setSelection(false);
+ mSdCardFileRadio.setSelection(true);
+ mSdCardFile.setText(sdcard);
+ }
+
+ sdcard = props.get(AvdManager.AVD_INI_SDCARD_SIZE);
+ if (sdcard != null && sdcard.length() > 0) {
+ String[] values = new String[2];
+ long sdcardSize = AvdManager.parseSdcardSize(sdcard, values);
+
+ if (sdcardSize != AvdManager.SDCARD_NOT_SIZE_PATTERN) {
+ enableSdCardWidgets(true);
+ mSdCardFileRadio.setSelection(false);
+ mSdCardSizeRadio.setSelection(true);
+
+ mSdCardSize.setText(values[0]);
+
+ String suffix = values[1];
+ int n = mSdCardSizeCombo.getItemCount();
+ for (int i = 0; i < n; i++) {
+ if (mSdCardSizeCombo.getItem(i).startsWith(suffix)) {
+ mSdCardSizeCombo.select(i);
+ }
+ }
+ }
+ }
+
+ String snapshots = props.get(AvdManager.AVD_INI_SNAPSHOT_PRESENT);
+ if (snapshots != null && snapshots.length() > 0) {
+ mSnapshotCheck.setSelection(snapshots.equals("true"));
+ }
+ }
+
+ mProperties.clear();
+
+ if (props != null) {
+ for (Entry<String, String> entry : props.entrySet()) {
+ HardwareProperty prop = mHardwareMap.get(entry.getKey());
+ if (prop != null && prop.isValidForUi()) {
+ mProperties.put(entry.getKey(), entry.getValue());
+ }
+ }
+ }
+
+ // Cleanup known non-hardware properties
+ mProperties.remove(AvdManager.AVD_INI_ABI_TYPE);
+ mProperties.remove(AvdManager.AVD_INI_CPU_ARCH);
+ mProperties.remove(AvdManager.AVD_INI_SKIN_PATH);
+ mProperties.remove(AvdManager.AVD_INI_SKIN_NAME);
+ mProperties.remove(AvdManager.AVD_INI_SDCARD_SIZE);
+ mProperties.remove(AvdManager.AVD_INI_SDCARD_PATH);
+ mProperties.remove(AvdManager.AVD_INI_SNAPSHOT_PRESENT);
+ mProperties.remove(AvdManager.AVD_INI_IMAGES_1);
+ mProperties.remove(AvdManager.AVD_INI_IMAGES_2);
+
+ mHardwareViewer.refresh();
+ }
+
+ @Override
+ protected void okPressed() {
+ if (createAvd()) {
+ super.okPressed();
+ }
+ }
+
+ /**
+ * Enable or disable the sd card widgets.
+ * @param sizeMode if true the size-based widgets are to be enabled, and the file-based ones
+ * disabled.
+ */
+ private void enableSdCardWidgets(boolean sizeMode) {
+ mSdCardSize.setEnabled(sizeMode);
+ mSdCardSizeCombo.setEnabled(sizeMode);
+
+ mSdCardFile.setEnabled(!sizeMode);
+ mBrowseSdCard.setEnabled(!sizeMode);
+ }
+
+ /**
+ * Enable or disable the skin widgets.
+ * @param listMode if true the list-based widgets are to be enabled, and the size-based ones
+ * disabled.
+ */
+ private void enableSkinWidgets(boolean listMode) {
+ mSkinCombo.setEnabled(listMode);
+
+ mSkinSizeWidth.setEnabled(!listMode);
+ mSkinSizeHeight.setEnabled(!listMode);
+ }
+
+
+ private void onBrowseSdCard() {
+ FileDialog dlg = new FileDialog(getContents().getShell(), SWT.OPEN);
+ dlg.setText("Choose SD Card image file.");
+
+ String fileName = dlg.open();
+ if (fileName != null) {
+ mSdCardFile.setText(fileName);
+ }
+ }
+
+
+
+ private void reloadTargetCombo() {
+ String selected = null;
+ int index = mTargetCombo.getSelectionIndex();
+ if (index >= 0) {
+ selected = mTargetCombo.getItem(index);
+ }
+
+ mCurrentTargets.clear();
+ mTargetCombo.removeAll();
+
+ boolean found = false;
+ index = -1;
+
+ SdkManager sdkManager = mAvdManager.getSdkManager();
+ if (sdkManager != null) {
+ for (IAndroidTarget target : sdkManager.getTargets()) {
+ String name;
+ if (target.isPlatform()) {
+ name = String.format("%s - API Level %s",
+ target.getName(),
+ target.getVersion().getApiString());
+ } else {
+ name = String.format("%s (%s) - API Level %s",
+ target.getName(),
+ target.getVendor(),
+ target.getVersion().getApiString());
+ }
+ mCurrentTargets.put(name, target);
+ mTargetCombo.add(name);
+ if (!found) {
+ index++;
+ found = name.equals(selected);
+ }
+ }
+ }
+
+ mTargetCombo.setEnabled(mCurrentTargets.size() > 0);
+
+ if (found) {
+ mTargetCombo.select(index);
+ }
+
+ reloadSkinCombo();
+ }
+
+ private void reloadSkinCombo() {
+ String selected = null;
+ int index = mSkinCombo.getSelectionIndex();
+ if (index >= 0) {
+ selected = mSkinCombo.getItem(index);
+ }
+
+ mSkinCombo.removeAll();
+ mSkinCombo.setEnabled(false);
+
+ index = mTargetCombo.getSelectionIndex();
+ if (index >= 0) {
+
+ String targetName = mTargetCombo.getItem(index);
+
+ boolean found = false;
+ IAndroidTarget target = mCurrentTargets.get(targetName);
+ if (target != null) {
+ mSkinCombo.add(String.format("Default (%s)", target.getDefaultSkin()));
+
+ index = -1;
+ for (String skin : target.getSkins()) {
+ mSkinCombo.add(skin);
+ if (!found) {
+ index++;
+ found = skin.equals(selected);
+ }
+ }
+
+ mSkinCombo.setEnabled(true);
+
+ if (found) {
+ mSkinCombo.select(index);
+ } else {
+ mSkinCombo.select(0); // default
+ loadSkin();
+ }
+ }
+ }
+ }
+
+ /**
+ * Reload all the abi types in the selection list
+ */
+ private void reloadAbiTypeCombo() {
+ String selected = null;
+ boolean found = false;
+
+ int index = mTargetCombo.getSelectionIndex();
+ if (index >= 0) {
+ String targetName = mTargetCombo.getItem(index);
+ IAndroidTarget target = mCurrentTargets.get(targetName);
+
+ ISystemImage[] systemImages = getSystemImages(target);
+
+ mAbiTypeCombo.setEnabled(systemImages.length > 1);
+
+ // If user explicitly selected an ABI before, preserve that option
+ // If user did not explicitly select before (only one option before)
+ // force them to select
+ index = mAbiTypeCombo.getSelectionIndex();
+ if (index >= 0 && mAbiTypeCombo.getItemCount() > 1) {
+ selected = mAbiTypeCombo.getItem(index);
+ }
+
+ mAbiTypeCombo.removeAll();
+
+ int i;
+ for ( i = 0; i < systemImages.length ; i++ ) {
+ String prettyAbiType = AvdInfo.getPrettyAbiType(systemImages[i].getAbiType());
+ mAbiTypeCombo.add(prettyAbiType);
+ if (!found) {
+ found = prettyAbiType.equals(selected);
+ if (found) {
+ mAbiTypeCombo.select(i);
+ }
+ }
+ }
+
+ if (systemImages.length == 1) {
+ mAbiTypeCombo.select(0);
+ }
+ }
+ }
+
+ /**
+ * Validates the fields, displays errors and warnings.
+ * Enables the finish button if there are no errors.
+ */
+ private void validatePage() {
+ String error = null;
+ String warning = null;
+
+ // Validate AVD name
+ String avdName = mAvdName.getText().trim();
+ boolean hasAvdName = avdName.length() > 0;
+ boolean isCreate = mEditAvdInfo == null || !avdName.equals(mEditAvdInfo.getName());
+
+ if (hasAvdName && !AvdManager.RE_AVD_NAME.matcher(avdName).matches()) {
+ error = String.format(
+ "AVD name '%1$s' contains invalid characters.\nAllowed characters are: %2$s",
+ avdName, AvdManager.CHARS_AVD_NAME);
+ }
+
+ // Validate target
+ if (hasAvdName && error == null && mTargetCombo.getSelectionIndex() < 0) {
+ error = "A target must be selected in order to create an AVD.";
+ }
+
+ // validate abi type if the selected target supports multi archs.
+ if (hasAvdName && error == null && mTargetCombo.getSelectionIndex() > 0) {
+ int index = mTargetCombo.getSelectionIndex();
+ String targetName = mTargetCombo.getItem(index);
+ IAndroidTarget target = mCurrentTargets.get(targetName);
+ ISystemImage[] systemImages = getSystemImages(target);
+ if (systemImages.length > 1 && mAbiTypeCombo.getSelectionIndex() < 0) {
+ error = "An ABI type must be selected in order to create an AVD.";
+ }
+ }
+
+ // Validate SDCard path or value
+ if (error == null) {
+ // get the mode. We only need to check the file since the
+ // verifier on the size Text will prevent invalid input
+ boolean sdcardFileMode = mSdCardFileRadio.getSelection();
+ if (sdcardFileMode) {
+ String sdName = mSdCardFile.getText().trim();
+ if (sdName.length() > 0 && !new File(sdName).isFile()) {
+ error = "SD Card path isn't valid.";
+ }
+ } else {
+ String valueString = mSdCardSize.getText();
+ if (valueString.length() > 0) {
+ long value = 0;
+ try {
+ value = Long.parseLong(valueString);
+
+ int sizeIndex = mSdCardSizeCombo.getSelectionIndex();
+ if (sizeIndex >= 0) {
+ // index 0 shifts by 10 (1024=K), index 1 by 20, etc.
+ value <<= 10*(1 + sizeIndex);
+ }
+
+ if (value < AvdManager.SDCARD_MIN_BYTE_SIZE ||
+ value > AvdManager.SDCARD_MAX_BYTE_SIZE) {
+ value = 0;
+ }
+ } catch (Exception e) {
+ // ignore, we'll test value below.
+ }
+ if (value <= 0) {
+ error = "SD Card size is invalid. Range is 9 MiB..1023 GiB.";
+ } else if (mEditAvdInfo != null) {
+ // When editing an existing AVD, compare with the existing
+ // sdcard size, if any. It only matters if there was an sdcard setting
+ // before.
+ Map<String, String> props = mEditAvdInfo.getProperties();
+ if (props != null) {
+ String original =
+ mEditAvdInfo.getProperties().get(AvdManager.AVD_INI_SDCARD_SIZE);
+ if (original != null && original.length() > 0) {
+ long originalSize =
+ AvdManager.parseSdcardSize(original, null/*parsedStrings*/);
+ if (originalSize > 0 && value != originalSize) {
+ warning = "A new SD Card file will be created.\nThe current SD Card file will be lost.";
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // validate the skin
+ if (error == null) {
+ // get the mode, we should only check if it's in size mode since
+ // the built-in list mode is always valid.
+ if (mSkinSizeRadio.getSelection()) {
+ // need both with and heigh to be non null
+ String width = mSkinSizeWidth.getText(); // no need for trim, since the verifier
+ String height = mSkinSizeHeight.getText(); // rejects non digit.
+
+ if (width.length() == 0 || height.length() == 0) {
+ error = "Skin size is incorrect.\nBoth dimensions must be > 0.";
+ }
+ }
+ }
+
+ // Check for duplicate AVD name
+ if (isCreate && hasAvdName && error == null && !mForceCreation.getSelection()) {
+ Pair<AvdConflict, String> conflict = mAvdManager.isAvdNameConflicting(avdName);
+ assert conflict != null;
+ switch(conflict.getFirst()) {
+ case NO_CONFLICT:
+ break;
+ case CONFLICT_EXISTING_AVD:
+ case CONFLICT_INVALID_AVD:
+ error = String.format(
+ "The AVD name '%s' is already used.\n" +
+ "Check \"Override the existing AVD\" to delete the existing one.",
+ avdName);
+ break;
+ case CONFLICT_EXISTING_PATH:
+ error = String.format(
+ "Conflict with %s\n" +
+ "Check \"Override the existing AVD\" to delete the existing one.",
+ conflict.getSecond());
+ break;
+ default:
+ // Hmm not supposed to happen... probably someone expanded the
+ // enum without adding something here. In this case just do an
+ // assert and use a generic error message.
+ error = String.format(
+ "Conflict %s with %s.\n" +
+ "Check \"Override the existing AVD\" to delete the existing one.",
+ conflict.getFirst().toString(),
+ conflict.getSecond());
+ assert false;
+ break;
+ }
+ }
+
+ if (error == null && mEditAvdInfo != null && isCreate) {
+ warning = String.format("The AVD '%1$s' will be duplicated into '%2$s'.",
+ mEditAvdInfo.getName(),
+ avdName);
+ }
+
+ // Validate the create button
+ boolean can_create = hasAvdName && error == null;
+ if (can_create) {
+ can_create &= mTargetCombo.getSelectionIndex() >= 0;
+ }
+ mOkButton.setEnabled(can_create);
+
+ // Adjust the create button label as needed
+ if (isCreate) {
+ mOkButton.setText("Create AVD");
+ } else {
+ mOkButton.setText("Edit AVD");
+ }
+
+ // -- update UI
+ if (error != null) {
+ mStatusIcon.setImage(mImageFactory.getImageByName("reject_icon16.png")); //$NON-NLS-1$
+ mStatusLabel.setText(error);
+ } else if (warning != null) {
+ mStatusIcon.setImage(mImageFactory.getImageByName("warning_icon16.png")); //$NON-NLS-1$
+ mStatusLabel.setText(warning);
+ } else {
+ mStatusIcon.setImage(null);
+ mStatusLabel.setText(" \n "); //$NON-NLS-1$
+ }
+
+ mStatusComposite.pack(true);
+ }
+
+ private void loadSkin() {
+ int targetIndex = mTargetCombo.getSelectionIndex();
+ if (targetIndex < 0) {
+ return;
+ }
+
+ // resolve the target.
+ String targetName = mTargetCombo.getItem(targetIndex);
+ IAndroidTarget target = mCurrentTargets.get(targetName);
+ if (target == null) {
+ return;
+ }
+
+ // get the skin name
+ String skinName = null;
+ int skinIndex = mSkinCombo.getSelectionIndex();
+ if (skinIndex < 0) {
+ return;
+ } else if (skinIndex == 0) { // default skin for the target
+ skinName = target.getDefaultSkin();
+ } else {
+ skinName = mSkinCombo.getItem(skinIndex);
+ }
+
+ // load the skin properties
+ String path = target.getPath(IAndroidTarget.SKINS);
+ File skin = new File(path, skinName);
+ if (skin.isDirectory() == false && target.isPlatform() == false) {
+ // it's possible the skin is in the parent target
+ path = target.getParent().getPath(IAndroidTarget.SKINS);
+ skin = new File(path, skinName);
+ }
+
+ if (skin.isDirectory() == false) {
+ return;
+ }
+
+ // now get the hardware.ini from the add-on (if applicable) and from the skin
+ // (if applicable)
+ HashMap<String, String> hardwareValues = new HashMap<String, String>();
+ if (target.isPlatform() == false) {
+ FileWrapper targetHardwareFile = new FileWrapper(target.getLocation(),
+ AvdManager.HARDWARE_INI);
+ if (targetHardwareFile.isFile()) {
+ Map<String, String> targetHardwareConfig = ProjectProperties.parsePropertyFile(
+ targetHardwareFile, null /*log*/);
+
+ if (targetHardwareConfig != null) {
+ hardwareValues.putAll(targetHardwareConfig);
+ }
+ }
+ }
+
+ // from the skin
+ FileWrapper skinHardwareFile = new FileWrapper(skin, AvdManager.HARDWARE_INI);
+ if (skinHardwareFile.isFile()) {
+ Map<String, String> skinHardwareConfig = ProjectProperties.parsePropertyFile(
+ skinHardwareFile, null /*log*/);
+
+ if (skinHardwareConfig != null) {
+ hardwareValues.putAll(skinHardwareConfig);
+ }
+ }
+
+ // now set those values in the list of properties for the AVD.
+ // We just check that none of those properties have been edited by the user yet.
+ for (Entry<String, String> entry : hardwareValues.entrySet()) {
+ if (mEditedProperties.contains(entry.getKey()) == false) {
+ mProperties.put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ mHardwareViewer.refresh();
+ }
+
+ /**
+ * Creates an AVD from the values in the UI. Called when the user presses the OK button.
+ */
+ private boolean createAvd() {
+ String avdName = mAvdName.getText().trim();
+ int index = mTargetCombo.getSelectionIndex();
+
+ // quick check on the name and the target selection
+ if (avdName.length() == 0 || index < 0) {
+ return false;
+ }
+
+ // resolve the target.
+ String targetName = mTargetCombo.getItem(index);
+ IAndroidTarget target = mCurrentTargets.get(targetName);
+ if (target == null) {
+ return false;
+ }
+
+ // get the abi type
+ mAbiType = SdkConstants.ABI_ARMEABI;
+ ISystemImage[] systemImages = getSystemImages(target);
+ if (systemImages.length > 0) {
+ int abiIndex = mAbiTypeCombo.getSelectionIndex();
+ if (abiIndex >= 0) {
+ String prettyname = mAbiTypeCombo.getItem(abiIndex);
+ //Extract the abi type
+ int firstIndex = prettyname.indexOf("(");
+ int lastIndex = prettyname.indexOf(")");
+ mAbiType = prettyname.substring(firstIndex+1, lastIndex);
+ }
+ }
+
+ // get the SD card data from the UI.
+ String sdName = null;
+ if (mSdCardSizeRadio.getSelection()) {
+ // size mode
+ String value = mSdCardSize.getText().trim();
+ if (value.length() > 0) {
+ sdName = value;
+ // add the unit
+ switch (mSdCardSizeCombo.getSelectionIndex()) {
+ case 0:
+ sdName += "K"; //$NON-NLS-1$
+ break;
+ case 1:
+ sdName += "M"; //$NON-NLS-1$
+ break;
+ case 2:
+ sdName += "G"; //$NON-NLS-1$
+ break;
+ default:
+ // shouldn't be here
+ assert false;
+ }
+ }
+ } else {
+ // file mode.
+ sdName = mSdCardFile.getText().trim();
+ }
+
+ // get the Skin data from the UI
+ String skinName = null;
+ if (mSkinListRadio.getSelection()) {
+ // built-in list provides the skin
+ int skinIndex = mSkinCombo.getSelectionIndex();
+ if (skinIndex > 0) {
+ // index 0 is the default, we don't use it
+ skinName = mSkinCombo.getItem(skinIndex);
+ }
+ } else {
+ // size mode. get both size and writes it as a skin name
+ // thanks to validatePage() we know the content of the fields is correct
+ skinName = mSkinSizeWidth.getText() + "x" + mSkinSizeHeight.getText(); //$NON-NLS-1$
+ }
+
+ ISdkLog log = mSdkLog;
+ if (log == null || log instanceof MessageBoxLog) {
+ // If the current logger is a message box, we use our own (to make sure
+ // to display errors right away and customize the title).
+ log = new MessageBoxLog(
+ String.format("Result of creating AVD '%s':", avdName),
+ getContents().getDisplay(),
+ false /*logErrorsOnly*/);
+ }
+
+ File avdFolder = null;
+ try {
+ avdFolder = AvdInfo.getDefaultAvdFolder(mAvdManager, avdName);
+ } catch (AndroidLocationException e) {
+ return false;
+ }
+
+ boolean force = mForceCreation.getSelection();
+ boolean snapshot = mSnapshotCheck.getSelection();
+
+ boolean success = false;
+ AvdInfo avdInfo = mAvdManager.createAvd(
+ avdFolder,
+ avdName,
+ target,
+ mAbiType,
+ skinName,
+ sdName,
+ mProperties,
+ snapshot,
+ force,
+ mEditAvdInfo != null, //edit existing
+ log);
+
+ success = avdInfo != null;
+
+ if (log instanceof MessageBoxLog) {
+ ((MessageBoxLog) log).displayResult(success);
+ }
+ return success;
+ }
+
+ /**
+ * Returns the list of system images of a target.
+ * <p/>
+ * If target is null, returns an empty list.
+ * If target is an add-on with no system images, return the list from its parent platform.
+ *
+ * @param target An IAndroidTarget. Can be null.
+ * @return A non-null ISystemImage array. Can be empty.
+ */
+ private ISystemImage[] getSystemImages(IAndroidTarget target) {
+ if (target != null) {
+ ISystemImage[] images = target.getSystemImages();
+
+ if ((images == null || images.length == 0) && !target.isPlatform()) {
+ // If an add-on does not provide any system images, use the ones from the parent.
+ images = target.getParent().getSystemImages();
+ }
+
+ if (images != null) {
+ return images;
+ }
+ }
+
+ return new ISystemImage[0];
+ }
+
+ // End of hiding from SWT Designer
+ //$hide<<$
+}
diff --git a/templates/activities/BlankActivity/root/AndroidManifest.xml.ftl b/templates/activities/BlankActivity/root/AndroidManifest.xml.ftl
index 3aa1627..1c6fbd1 100644
--- a/templates/activities/BlankActivity/root/AndroidManifest.xml.ftl
+++ b/templates/activities/BlankActivity/root/AndroidManifest.xml.ftl
@@ -8,7 +8,7 @@
<meta-data android:name="android.support.PARENT_ACTIVITY"
android:value="${parentActivityClass}" />
</#if>
- <#if isLauncher>
+ <#if isLauncher?string == "true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
diff --git a/templates/activities/BlankActivity/root/res/layout/activity_simple.xml.ftl b/templates/activities/BlankActivity/root/res/layout/activity_simple.xml.ftl
index a472bfe..5f97369 100644
--- a/templates/activities/BlankActivity/root/res/layout/activity_simple.xml.ftl
+++ b/templates/activities/BlankActivity/root/res/layout/activity_simple.xml.ftl
@@ -1,5 +1,6 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
+ tools:context=".${activityClass}"
android:layout_width=<#if buildApi lt 8 >"fill_parent"<#else>"match_parent"</#if>
android:layout_height=<#if buildApi lt 8 >"fill_parent"<#else>"match_parent"</#if> >
@@ -8,7 +9,6 @@
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
- android:text="@string/hello_world"
- tools:context=".${activityClass}" />
+ android:text="@string/hello_world" />
</RelativeLayout>
diff --git a/templates/activities/FullscreenActivity/globals.xml.ftl b/templates/activities/FullscreenActivity/globals.xml.ftl
new file mode 100644
index 0000000..a416d3a
--- /dev/null
+++ b/templates/activities/FullscreenActivity/globals.xml.ftl
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<globals>
+ <global id="srcOut" value="src/${slashedPackageName(packageName)}" />
+ <global id="simpleName" value="${activityToLayout(activityClass)}" />
+</globals>
diff --git a/templates/activities/FullscreenActivity/recipe.xml.ftl b/templates/activities/FullscreenActivity/recipe.xml.ftl
new file mode 100644
index 0000000..ce1aa18
--- /dev/null
+++ b/templates/activities/FullscreenActivity/recipe.xml.ftl
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<recipe>
+ <merge from="AndroidManifest.xml.ftl" />
+
+ <merge from="res/values/colors.xml" />
+ <merge from="res/values/styles.xml" />
+ <merge from="res/values-v11/styles.xml" />
+ <instantiate from="res/layout/activity_fullscreen.xml.ftl"
+ to="res/layout/${layoutName}.xml" />
+
+ <merge from="res/values/strings.xml.ftl"
+ to="res/values/strings.xml" />
+
+ <instantiate from="src/app_package/FullscreenActivity.java.ftl"
+ to="${srcOut}/${activityClass}.java" />
+ <instantiate from="src/app_package/util/SystemUiHider.java.ftl"
+ to="${srcOut}/util/SystemUiHider.java" />
+ <instantiate from="src/app_package/util/SystemUiHiderBase.java.ftl"
+ to="${srcOut}/util/SystemUiHiderBase.java" />
+ <instantiate from="src/app_package/util/SystemUiHiderHoneycomb.java.ftl"
+ to="${srcOut}/util/SystemUiHiderHoneycomb.java" />
+
+ <open file="res/layout/${layoutName}.xml" />
+</recipe>
diff --git a/templates/activities/FullscreenActivity/root/AndroidManifest.xml.ftl b/templates/activities/FullscreenActivity/root/AndroidManifest.xml.ftl
new file mode 100644
index 0000000..3142546
--- /dev/null
+++ b/templates/activities/FullscreenActivity/root/AndroidManifest.xml.ftl
@@ -0,0 +1,22 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <application>
+ <activity android:name=".${activityClass}"
+ android:label="@string/title_${simpleName}"
+ android:configChanges="orientation|keyboardHidden|screenSize"
+ android:theme="@style/FullscreenTheme"
+ <#if buildApi gte 16 && parentActivityClass != "">android:parentActivityName="${parentActivityClass}"</#if>>
+ <#if parentActivityClass != "">
+ <meta-data android:name="android.support.PARENT_ACTIVITY"
+ android:value="${parentActivityClass}" />
+ </#if>
+ <#if isLauncher?string == "true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </#if>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/templates/activities/FullscreenActivity/root/res/layout/activity_fullscreen.xml.ftl b/templates/activities/FullscreenActivity/root/res/layout/activity_fullscreen.xml.ftl
new file mode 100755
index 0000000..bed4e68
--- /dev/null
+++ b/templates/activities/FullscreenActivity/root/res/layout/activity_fullscreen.xml.ftl
@@ -0,0 +1,49 @@
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="#0099cc"
+ tools:context=".${activityClass}">
+
+ <!-- The primary full-screen view. This can be replaced with whatever view
+ is needed to present your content, e.g. VideoView, SurfaceView,
+ TextureView, etc. -->
+ <TextView android:id="@+id/fullscreen_content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:keepScreenOn="true"
+ android:textColor="#33b5e5"
+ android:textStyle="bold"
+ android:textSize="50sp"
+ android:gravity="center"
+ android:text="@string/dummy_content" />
+
+ <!-- This FrameLayout insets its children based on system windows using
+ android:fitsSystemWindows. -->
+ <FrameLayout android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fitsSystemWindows="true">
+
+ <LinearLayout android:id="@+id/fullscreen_content_controls"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom|center_horizontal"
+ android:background="@color/black_overlay"
+ android:orientation="horizontal"
+ tools:ignore="UselessParent">
+
+ <Button android:id="@+id/button1"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/dummy_button1" />
+ <Button android:id="@+id/button2"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/dummy_button2" />
+
+ </LinearLayout>
+ </FrameLayout>
+
+</FrameLayout>
diff --git a/templates/activities/FullscreenActivity/root/res/values-v11/styles.xml b/templates/activities/FullscreenActivity/root/res/values-v11/styles.xml
new file mode 100644
index 0000000..11159aa
--- /dev/null
+++ b/templates/activities/FullscreenActivity/root/res/values-v11/styles.xml
@@ -0,0 +1,13 @@
+<resources>
+
+ <style name="FullscreenTheme" parent="android:Theme.Holo">
+ <item name="android:actionBarStyle">@style/FullscreenActionBarStyle</item>
+ <item name="android:windowActionBarOverlay">true</item>
+ <item name="android:windowBackground">@null</item>
+ </style>
+
+ <style name="FullscreenActionBarStyle" parent="android:Widget.Holo.ActionBar">
+ <item name="android:background">@color/black_overlay</item>
+ </style>
+
+</resources>
diff --git a/templates/activities/FullscreenActivity/root/res/values/colors.xml b/templates/activities/FullscreenActivity/root/res/values/colors.xml
new file mode 100644
index 0000000..327c060
--- /dev/null
+++ b/templates/activities/FullscreenActivity/root/res/values/colors.xml
@@ -0,0 +1,5 @@
+<resources>
+
+ <color name="black_overlay">#66000000</color>
+
+</resources>
diff --git a/templates/activities/FullscreenActivity/root/res/values/strings.xml.ftl b/templates/activities/FullscreenActivity/root/res/values/strings.xml.ftl
new file mode 100644
index 0000000..78275fa
--- /dev/null
+++ b/templates/activities/FullscreenActivity/root/res/values/strings.xml.ftl
@@ -0,0 +1,8 @@
+<resources>
+
+ <string name="title_${simpleName}">${activityTitle}</string>
+ <string name="dummy_button1">Button 1</string>
+ <string name="dummy_button2">Button 2</string>
+ <string name="dummy_content">DUMMY\nCONTENT</string>
+
+</resources>
diff --git a/templates/activities/FullscreenActivity/root/res/values/styles.xml b/templates/activities/FullscreenActivity/root/res/values/styles.xml
new file mode 100644
index 0000000..976b8e1
--- /dev/null
+++ b/templates/activities/FullscreenActivity/root/res/values/styles.xml
@@ -0,0 +1,8 @@
+<resources>
+
+ <style name="FullscreenTheme" parent="android:Theme.NoTitleBar">
+ <item name="android:windowContentOverlay">@null</item>
+ <item name="android:windowBackground">@null</item>
+ </style>
+
+</resources>
diff --git a/templates/activities/FullscreenActivity/root/src/app_package/FullscreenActivity.java.ftl b/templates/activities/FullscreenActivity/root/src/app_package/FullscreenActivity.java.ftl
new file mode 100755
index 0000000..88e6f44
--- /dev/null
+++ b/templates/activities/FullscreenActivity/root/src/app_package/FullscreenActivity.java.ftl
@@ -0,0 +1,197 @@
+package ${packageName};
+
+import ${packageName}.util.SystemUiHider;
+
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.MotionEvent;
+import android.view.View;
+<#if parentActivityClass != "">
+import android.view.MenuItem;
+import android.support.v4.app.NavUtils;
+</#if>
+
+/**
+ * An example full-screen activity that shows and hides the system UI (i.e.
+ * status bar and navigation/system bar) with user interaction.
+ *
+ * @see SystemUiHider
+ */
+public class ${activityClass} extends Activity {
+ /**
+ * Whether or not the system UI should be auto-hidden after
+ * {@link #AUTO_HIDE_DELAY_MILLIS} milliseconds.
+ */
+ private static final boolean AUTO_HIDE = true;
+
+ /**
+ * If {@link #AUTO_HIDE} is set, the number of milliseconds to wait after
+ * user interaction before hiding the system UI.
+ */
+ private static final int AUTO_HIDE_DELAY_MILLIS = 3000;
+
+ /**
+ * If set, will toggle the system UI visibility upon interaction. Otherwise,
+ * will show the system UI visibility upon interaction.
+ */
+ private static final boolean TOGGLE_ON_CLICK = true;
+
+ /**
+ * The flags to pass to {@link SystemUiHider#getInstance}.
+ */
+ private static final int HIDER_FLAGS = SystemUiHider.FLAG_HIDE_NAVIGATION;
+
+ /**
+ * The instance of the {@link SystemUiHider} for this activity.
+ */
+ private SystemUiHider mSystemUiHider;
+
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.${layoutName});
+ <#if parentActivityClass != "">
+ setupActionBar();
+ </#if>
+
+ final View controlsView = findViewById(R.id.fullscreen_content_controls);
+ final View contentView = findViewById(R.id.fullscreen_content);
+
+ // Set up an instance of SystemUiHider to control the system UI for
+ // this activity.
+ mSystemUiHider = SystemUiHider.getInstance(this, contentView, HIDER_FLAGS);
+ mSystemUiHider.setup();
+ mSystemUiHider
+ .setOnVisibilityChangeListener(new SystemUiHider.OnVisibilityChangeListener() {
+ // Cached values.
+ int mControlsHeight;
+ int mShortAnimTime;
+
+ @Override
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
+ public void onVisibilityChange(boolean visible) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
+ // If the ViewPropertyAnimator API is available
+ // (Honeycomb MR2 and later), use it to animate the
+ // in-layout UI controls at the bottom of the
+ // screen.
+ if (mControlsHeight == 0) {
+ mControlsHeight = controlsView.getHeight();
+ }
+ if (mShortAnimTime == 0) {
+ mShortAnimTime = getResources().getInteger(
+ android.R.integer.config_shortAnimTime);
+ }
+ controlsView.animate()
+ .translationY(visible ? 0 : mControlsHeight)
+ .setDuration(mShortAnimTime);
+ } else {
+ // If the ViewPropertyAnimator APIs aren't
+ // available, simply show or hide the in-layout UI
+ // controls.
+ controlsView.setVisibility(visible ? View.VISIBLE : View.GONE);
+ }
+
+ if (visible && AUTO_HIDE) {
+ // Schedule a hide().
+ delayedHide(AUTO_HIDE_DELAY_MILLIS);
+ }
+ }
+ });
+
+ // Set up the user interaction to manually show or hide the system UI.
+ contentView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (TOGGLE_ON_CLICK) {
+ mSystemUiHider.toggle();
+ } else {
+ mSystemUiHider.show();
+ }
+ }
+ });
+
+ // Upon interacting with UI controls, delay any scheduled hide()
+ // operations to prevent the jarring behavior of controls going away
+ // while interacting with the UI.
+ findViewById(R.id.button1).setOnTouchListener(mDelayHideTouchListener);
+ findViewById(R.id.button2).setOnTouchListener(mDelayHideTouchListener);
+ }
+
+ @Override
+ protected void onPostCreate(Bundle savedInstanceState) {
+ super.onPostCreate(savedInstanceState);
+
+ // Trigger the initial hide() shortly after the activity has been
+ // created, to briefly hint to the user that UI controls
+ // are available.
+ delayedHide(100);
+ }
+
+ <#if parentActivityClass != "">
+ /**
+ * Set up the {@link android.app.ActionBar}, if the API is available.
+ */
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ private void setupActionBar() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ // Show the Up button in the action bar.
+ getActionBar().setDisplayHomeAsUpEnabled(true);
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ // This ID represents the Home or Up button. In the case of this
+ // activity, the Up button is shown. Use NavUtils to allow users
+ // to navigate up one level in the application structure. For
+ // more details, see the Navigation pattern on Android Design:
+ //
+ // http://developer.android.com/design/patterns/navigation.html#up-vs-back
+ //
+ // TODO: If Settings has multiple levels, Up should navigate up
+ // that hierarchy.
+ NavUtils.navigateUpFromSameTask(this);
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+ </#if>
+
+ /**
+ * Touch listener to use for in-layout UI controls to delay hiding the
+ * system UI. This is to prevent the jarring behavior of controls going away
+ * while interacting with activity UI.
+ */
+ View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View view, MotionEvent motionEvent) {
+ if (AUTO_HIDE) {
+ delayedHide(AUTO_HIDE_DELAY_MILLIS);
+ }
+ return false;
+ }
+ };
+
+ Handler mHideHandler = new Handler();
+ Runnable mHideRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mSystemUiHider.hide();
+ }
+ };
+
+ /**
+ * Schedules a call to hide() in [delay] milliseconds, canceling any
+ * previously scheduled calls.
+ */
+ private void delayedHide(int delayMillis) {
+ mHideHandler.removeCallbacks(mHideRunnable);
+ mHideHandler.postDelayed(mHideRunnable, delayMillis);
+ }
+}
diff --git a/templates/activities/FullscreenActivity/root/src/app_package/util/SystemUiHider.java.ftl b/templates/activities/FullscreenActivity/root/src/app_package/util/SystemUiHider.java.ftl
new file mode 100644
index 0000000..28efb77
--- /dev/null
+++ b/templates/activities/FullscreenActivity/root/src/app_package/util/SystemUiHider.java.ftl
@@ -0,0 +1,172 @@
+package ${packageName}.util;
+
+import android.app.Activity;
+import android.os.Build;
+import android.view.View;
+
+/**
+ * A utility class that helps with showing and hiding system UI such as the
+ * status bar and navigation/system bar. This class uses backward-compatibility
+ * techniques described in <a href=
+ * "http://developer.android.com/training/backward-compatible-ui/index.html">
+ * Creating Backward-Compatible UIs</a> to ensure that devices running any
+ * version of ndroid OS are supported. More specifically, there are separate
+ * implementations of this abstract class: for newer devices,
+ * {@link #getInstance} will return a {@link SystemUiHiderHoneycomb} instance,
+ * while on older devices {@link #getInstance} will return a
+ * {@link SystemUiHiderBase} instance.
+ * <p>
+ * For more on system bars, see <a href=
+ * "http://developer.android.com/design/get-started/ui-overview.html#system-bars"
+ * > System Bars</a>.
+ *
+ * @see android.view.View#setSystemUiVisibility(int)
+ * @see android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
+ */
+public abstract class SystemUiHider {
+ /**
+ * When this flag is set, the
+ * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN}
+ * flag will be set on older devices, making the status bar "float" on top
+ * of the activity layout. This is most useful when there are no controls at
+ * the top of the activity layout.
+ * <p>
+ * This flag isn't used on newer devices because the <a
+ * href="http://developer.android.com/design/patterns/actionbar.html">action
+ * bar</a>, the most important structural element of an Android app, should
+ * be visible and not obscured by the system UI.
+ */
+ public static final int FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES = 0x1;
+
+ /**
+ * When this flag is set, {@link #show()} and {@link #hide()} will toggle
+ * the visibility of the status bar. If there is a navigation bar, show and
+ * hide will toggle low profile mode.
+ */
+ public static final int FLAG_FULLSCREEN = 0x2;
+
+ /**
+ * When this flag is set, {@link #show()} and {@link #hide()} will toggle
+ * the visibility of the navigation bar, if it's present on the device and
+ * the device allows hiding it. In cases where the navigation bar is present
+ * but cannot be hidden, show and hide will toggle low profile mode.
+ */
+ public static final int FLAG_HIDE_NAVIGATION = FLAG_FULLSCREEN | 0x4;
+
+ /**
+ * The activity associated with this UI hider object.
+ */
+ protected Activity mActivity;
+
+ /**
+ * The view on which {@link View#setSystemUiVisibility(int)} will be called.
+ */
+ protected View mAnchorView;
+
+ /**
+ * The current UI hider flags.
+ *
+ * @see #FLAG_FULLSCREEN
+ * @see #FLAG_HIDE_NAVIGATION
+ * @see #FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES
+ */
+ protected int mFlags;
+
+ /**
+ * The current visibility callback.
+ */
+ protected OnVisibilityChangeListener mOnVisibilityChangeListener = sDummyListener;
+
+ /**
+ * Creates and returns an instance of {@link SystemUiHider} that is
+ * appropriate for this device. The object will be either a
+ * {@link SystemUiHiderBase} or {@link SystemUiHiderHoneycomb} depending on
+ * the device.
+ *
+ * @param activity The activity whose window's system UI should be
+ * controlled by this class.
+ * @param anchorView The view on which
+ * {@link View#setSystemUiVisibility(int)} will be called.
+ * @param flags Either 0 or any combination of {@link #FLAG_FULLSCREEN},
+ * {@link #FLAG_HIDE_NAVIGATION}, and
+ * {@link #FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES}.
+ */
+ public static SystemUiHider getInstance(Activity activity, View anchorView, int flags) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ return new SystemUiHiderHoneycomb(activity, anchorView, flags);
+ } else {
+ return new SystemUiHiderBase(activity, anchorView, flags);
+ }
+ }
+
+ protected SystemUiHider(Activity activity, View anchorView, int flags) {
+ mActivity = activity;
+ mAnchorView = anchorView;
+ mFlags = flags;
+ }
+
+ /**
+ * Sets up the system UI hider. Should be called from
+ * {@link Activity#onCreate}.
+ */
+ public abstract void setup();
+
+ /**
+ * Returns whether or not the system UI is visible.
+ */
+ public abstract boolean isVisible();
+
+ /**
+ * Hide the system UI.
+ */
+ public abstract void hide();
+
+ /**
+ * Show the system UI.
+ */
+ public abstract void show();
+
+ /**
+ * Toggle the visibility of the system UI.
+ */
+ public void toggle() {
+ if (isVisible()) {
+ hide();
+ } else {
+ show();
+ }
+ }
+
+ /**
+ * Registers a callback, to be triggered when the system UI visibility
+ * changes.
+ */
+ public void setOnVisibilityChangeListener(OnVisibilityChangeListener listener) {
+ if (listener == null) {
+ listener = sDummyListener;
+ }
+
+ mOnVisibilityChangeListener = listener;
+ }
+
+ /**
+ * A dummy no-op callback for use when there is no other listener set.
+ */
+ private static OnVisibilityChangeListener sDummyListener = new OnVisibilityChangeListener() {
+ @Override
+ public void onVisibilityChange(boolean visible) {
+ }
+ };
+
+ /**
+ * A callback interface used to listen for system UI visibility changes.
+ */
+ public interface OnVisibilityChangeListener {
+ /**
+ * Called when the system UI visibility has changed.
+ *
+ * @param visible True if the system UI is visible.
+ */
+ public void onVisibilityChange(boolean visible);
+ }
+}
diff --git a/templates/activities/FullscreenActivity/root/src/app_package/util/SystemUiHiderBase.java.ftl b/templates/activities/FullscreenActivity/root/src/app_package/util/SystemUiHiderBase.java.ftl
new file mode 100644
index 0000000..da08842
--- /dev/null
+++ b/templates/activities/FullscreenActivity/root/src/app_package/util/SystemUiHiderBase.java.ftl
@@ -0,0 +1,63 @@
+package ${packageName}.util;
+
+import android.app.Activity;
+import android.view.View;
+import android.view.WindowManager;
+
+/**
+ * A base implementation of {@link SystemUiHider}. Uses APIs available in all
+ * API levels to show and hide the status bar.
+ */
+public class SystemUiHiderBase extends SystemUiHider {
+ /**
+ * Whether or not the system UI is currently visible. This is a cached value
+ * from calls to {@link #hide()} and {@link #show()}.
+ */
+ private boolean mVisible = true;
+
+ /**
+ * Constructor not intended to be called by clients. Use
+ * {@link SystemUiHider#getInstance} to obtain an instance.
+ */
+ protected SystemUiHiderBase(Activity activity, View anchorView, int flags) {
+ super(activity, anchorView, flags);
+ }
+
+ @Override
+ public void setup() {
+ if ((mFlags & FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES) == 0) {
+ mActivity.getWindow().setFlags(
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
+ }
+ }
+
+ @Override
+ public boolean isVisible() {
+ return mVisible;
+ }
+
+ @Override
+ public void hide() {
+ if ((mFlags & FLAG_FULLSCREEN) != 0) {
+ mActivity.getWindow().setFlags(
+ WindowManager.LayoutParams.FLAG_FULLSCREEN,
+ WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ }
+ mOnVisibilityChangeListener.onVisibilityChange(false);
+ mVisible = false;
+ }
+
+ @Override
+ public void show() {
+ if ((mFlags & FLAG_FULLSCREEN) != 0) {
+ mActivity.getWindow().setFlags(
+ 0,
+ WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ }
+ mOnVisibilityChangeListener.onVisibilityChange(true);
+ mVisible = true;
+ }
+}
diff --git a/templates/activities/FullscreenActivity/root/src/app_package/util/SystemUiHiderHoneycomb.java.ftl b/templates/activities/FullscreenActivity/root/src/app_package/util/SystemUiHiderHoneycomb.java.ftl
new file mode 100644
index 0000000..f2460eb
--- /dev/null
+++ b/templates/activities/FullscreenActivity/root/src/app_package/util/SystemUiHiderHoneycomb.java.ftl
@@ -0,0 +1,133 @@
+package ${packageName}.util;
+
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.os.Build;
+import android.view.View;
+import android.view.WindowManager;
+
+/**
+ * An API 11+ implementation of {@link SystemUiHider}. Uses APIs available in
+ * Honeycomb and later (specifically {@link View#setSystemUiVisibility(int)}) to
+ * show and hide the system UI.
+ */
+@TargetApi(Build.VERSION_CODES.HONEYCOMB)
+public class SystemUiHiderHoneycomb extends SystemUiHiderBase {
+ /**
+ * Flags for {@link View#setSystemUiVisibility(int)} to use when showing the
+ * system UI.
+ */
+ private int mShowFlags;
+
+ /**
+ * Flags for {@link View#setSystemUiVisibility(int)} to use when hiding the
+ * system UI.
+ */
+ private int mHideFlags;
+
+ /**
+ * Flags to test against the first parameter in
+ * {@link android.view.View.OnSystemUiVisibilityChangeListener#onSystemUiVisibilityChange(int)}
+ * to determine the system UI visibility state.
+ */
+ private int mTestFlags;
+
+ /**
+ * Whether or not the system UI is currently visible. This is cached from
+ * {@link android.view.View.OnSystemUiVisibilityChangeListener}.
+ */
+ private boolean mVisible = true;
+
+ /**
+ * Constructor not intended to be called by clients. Use
+ * {@link SystemUiHider#getInstance} to obtain an instance.
+ */
+ protected SystemUiHiderHoneycomb(Activity activity, View anchorView, int flags) {
+ super(activity, anchorView, flags);
+
+ mShowFlags = View.SYSTEM_UI_FLAG_VISIBLE;
+ mHideFlags = View.SYSTEM_UI_FLAG_LOW_PROFILE;
+ mTestFlags = View.SYSTEM_UI_FLAG_LOW_PROFILE;
+
+ if ((mFlags & FLAG_FULLSCREEN) != 0) {
+ // If the client requested fullscreen, add flags relevant to hiding
+ // the status bar. Note that some of these constants are new as of
+ // API 16 (Jelly Bean). It is safe to use them, as they are inlined
+ // at compile-time and do nothing on pre-Jelly Bean devices.
+ mShowFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+ mHideFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_FULLSCREEN;
+ }
+
+ if ((mFlags & FLAG_HIDE_NAVIGATION) != 0) {
+ // If the client requested hiding navigation, add relevant flags.
+ mShowFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+ mHideFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+ mTestFlags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void setup() {
+ mAnchorView.setOnSystemUiVisibilityChangeListener(mSystemUiVisibilityChangeListener);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void hide() {
+ mAnchorView.setSystemUiVisibility(mHideFlags);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void show() {
+ mAnchorView.setSystemUiVisibility(mShowFlags);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean isVisible() {
+ return mVisible;
+ }
+
+ private View.OnSystemUiVisibilityChangeListener mSystemUiVisibilityChangeListener
+ = new View.OnSystemUiVisibilityChangeListener() {
+ @Override
+ public void onSystemUiVisibilityChange(int vis) {
+ // Test against mTestFlags to see if the system UI is visible.
+ if ((vis & mTestFlags) != 0) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
+ // Pre-Jelly Bean, we must manually hide the action bar
+ // and use the old window flags API.
+ mActivity.getActionBar().hide();
+ mActivity.getWindow().setFlags(
+ WindowManager.LayoutParams.FLAG_FULLSCREEN,
+ WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ }
+
+ // Trigger the registered listener and cache the visibility
+ // state.
+ mOnVisibilityChangeListener.onVisibilityChange(false);
+ mVisible = false;
+
+ } else {
+ mAnchorView.setSystemUiVisibility(mShowFlags);
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
+ // Pre-Jelly Bean, we must manually show the action bar
+ // and use the old window flags API.
+ mActivity.getActionBar().show();
+ mActivity.getWindow().setFlags(
+ 0,
+ WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ }
+
+ // Trigger the registered listener and cache the visibility
+ // state.
+ mOnVisibilityChangeListener.onVisibilityChange(true);
+ mVisible = true;
+ }
+ }
+ };
+}
diff --git a/templates/activities/FullscreenActivity/template.xml b/templates/activities/FullscreenActivity/template.xml
new file mode 100644
index 0000000..90367dd
--- /dev/null
+++ b/templates/activities/FullscreenActivity/template.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0"?>
+<template
+ format="1"
+ revision="1"
+ name="New Fullscreen Activity"
+ description="Creates a new activity that shows and hides the system UI (status bar, navigation/system bar), and action bar, upon user interaction."
+ minApi="3"
+ minBuildApi="16">
+ <dependency name="android-support-v4" revision="8" />
+
+ <category value="Activities" />
+
+ <parameter
+ id="activityClass"
+ name="Activity Name"
+ type="string"
+ constraints="class|nonempty"
+ default="FullscreenActivity"
+ help="The name of the activity class to create" />
+
+ <parameter
+ id="layoutName"
+ name="Layout Name"
+ type="string"
+ constraints="layout|unique|nonempty"
+ suggest="${activityToLayout(activityClass)}"
+ default="activity_fullscreen"
+ help="The name of the layout to create for the activity" />
+
+ <parameter
+ id="activityTitle"
+ name="Title"
+ type="string"
+ constraints="nonempty"
+ default="FullscreenActivity"
+ suggest="${activityClass}"
+ help="The name of the activity." />
+
+ <parameter
+ id="isLauncher"
+ name="Launcher Activity"
+ type="boolean"
+ default="false"
+ help="If true, this activity will have a CATEGORY_LAUNCHER intent filter, making it visible in the launcher" />
+
+ <parameter
+ id="parentActivityClass"
+ name="Hierarchical Parent"
+ type="string"
+ constraints="activity|exists|empty"
+ default=""
+ help="The hierarchical parent activity, used to provide a default implementation for the 'Up' button" />
+
+ <parameter
+ id="packageName"
+ name="Package name"
+ type="string"
+ constraints="package"
+ default="com.mycompany.myapp" />
+
+ <thumbs>
+ <thumb>template_fullscreen_activity.png</thumb>
+ </thumbs>
+
+ <globals file="globals.xml.ftl" />
+ <execute file="recipe.xml.ftl" />
+
+</template>
diff --git a/templates/activities/FullscreenActivity/template_fullscreen_activity.png b/templates/activities/FullscreenActivity/template_fullscreen_activity.png
new file mode 100644
index 0000000..a8597b2
--- /dev/null
+++ b/templates/activities/FullscreenActivity/template_fullscreen_activity.png
Binary files differ
diff --git a/templates/activities/LoginActivity/globals.xml.ftl b/templates/activities/LoginActivity/globals.xml.ftl
new file mode 100644
index 0000000..cb45205
--- /dev/null
+++ b/templates/activities/LoginActivity/globals.xml.ftl
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<globals>
+ <global id="srcOut" value="src/${slashedPackageName(packageName)}" />
+ <global id="menuName" value="${layoutName}" />
+ <global id="simpleName" value="${activityToLayout(activityClass)}" />
+</globals>
diff --git a/templates/activities/LoginActivity/recipe.xml.ftl b/templates/activities/LoginActivity/recipe.xml.ftl
new file mode 100644
index 0000000..ece4285
--- /dev/null
+++ b/templates/activities/LoginActivity/recipe.xml.ftl
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<recipe>
+ <merge from="AndroidManifest.xml.ftl" />
+
+ <merge from="res/values/styles.xml" />
+ <merge from="res/values-large/styles.xml" />
+ <copy from="res/menu/activity_login.xml"
+ to="res/menu/${menuName}.xml" />
+ <instantiate from="res/layout/activity_login.xml.ftl"
+ to="res/layout/${layoutName}.xml" />
+
+ <instantiate from="res/values/strings.xml.ftl"
+ to="res/values/strings_${simpleName}.xml" />
+
+ <instantiate from="src/app_package/LoginActivity.java.ftl"
+ to="${srcOut}/${activityClass}.java" />
+
+ <open file="res/layout/${layoutName}.xml" />
+</recipe>
diff --git a/templates/activities/LoginActivity/root/AndroidManifest.xml.ftl b/templates/activities/LoginActivity/root/AndroidManifest.xml.ftl
new file mode 100644
index 0000000..3825bb4
--- /dev/null
+++ b/templates/activities/LoginActivity/root/AndroidManifest.xml.ftl
@@ -0,0 +1,15 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <application>
+ <activity android:name=".${activityClass}"
+ android:label="@string/title_${simpleName}"
+ android:windowSoftInputMode="adjustResize|stateVisible"
+ <#if buildApi gte 16 && parentActivityClass != "">android:parentActivityName="${parentActivityClass}"</#if>>
+ <#if parentActivityClass != "">
+ <meta-data android:name="android.support.PARENT_ACTIVITY"
+ android:value="${parentActivityClass}" />
+ </#if>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/templates/activities/LoginActivity/root/res/layout/activity_login.xml.ftl b/templates/activities/LoginActivity/root/res/layout/activity_login.xml.ftl
new file mode 100644
index 0000000..ceaadc8
--- /dev/null
+++ b/templates/activities/LoginActivity/root/res/layout/activity_login.xml.ftl
@@ -0,0 +1,69 @@
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:context=".${activityClass}">
+
+ <!-- Login progress -->
+ <LinearLayout android:id="@+id/login_status"
+ android:visibility="gone"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:gravity="center_horizontal"
+ android:orientation="vertical">
+ <ProgressBar style="?android:attr/progressBarStyleLarge"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="8dp"/>
+ <TextView
+ android:id="@+id/login_status_message"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:fontFamily="sans-serif-light"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="16dp"
+ android:text="@string/login_progress_signing_in" />
+ </LinearLayout>
+
+ <!-- Login form -->
+ <ScrollView
+ android:id="@+id/login_form"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout style="@style/LoginFormContainer"
+ android:orientation="vertical">
+
+ <EditText
+ android:id="@+id/email"
+ android:singleLine="true"
+ android:maxLines="2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:inputType="textEmailAddress"
+ android:hint="@string/prompt_email" />
+
+ <EditText
+ android:id="@+id/password"
+ android:singleLine="true"
+ android:maxLines="2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:hint="@string/prompt_password"
+ android:inputType="textPassword"
+ android:imeActionLabel="@string/action_sign_in_short"
+ android:imeActionId="@+id/login"
+ android:imeOptions="actionUnspecified" />
+
+ <Button android:id="@+id/sign_in_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:text="@string/action_sign_in_register"
+ android:paddingLeft="32dp"
+ android:paddingRight="32dp"
+ android:layout_gravity="right" />
+
+ </LinearLayout>
+
+ </ScrollView>
+</merge>
diff --git a/templates/activities/LoginActivity/root/res/menu/activity_login.xml b/templates/activities/LoginActivity/root/res/menu/activity_login.xml
new file mode 100644
index 0000000..1254dce
--- /dev/null
+++ b/templates/activities/LoginActivity/root/res/menu/activity_login.xml
@@ -0,0 +1,5 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/menu_forgot_password"
+ android:title="@string/menu_forgot_password"
+ android:showAsAction="never" />
+</menu>
diff --git a/templates/activities/LoginActivity/root/res/values-large/styles.xml b/templates/activities/LoginActivity/root/res/values-large/styles.xml
new file mode 100644
index 0000000..7b56acd
--- /dev/null
+++ b/templates/activities/LoginActivity/root/res/values-large/styles.xml
@@ -0,0 +1,10 @@
+<resources>
+
+ <style name="LoginFormContainer">
+ <item name="android:layout_width">400dp</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_gravity">center</item>
+ <item name="android:padding">16dp</item>
+ </style>
+
+</resources>
diff --git a/templates/activities/LoginActivity/root/res/values/strings.xml.ftl b/templates/activities/LoginActivity/root/res/values/strings.xml.ftl
new file mode 100644
index 0000000..1410671
--- /dev/null
+++ b/templates/activities/LoginActivity/root/res/values/strings.xml.ftl
@@ -0,0 +1,19 @@
+<resources>
+ <string name="title_${simpleName}">${activityTitle}</string>
+
+ <!-- Strings related to login -->
+ <string name="prompt_email">Email</string>
+ <string name="prompt_password">Password</string>
+
+ <string name="action_sign_in_register"><b>Sign in</b> or register</string>
+ <string name="action_sign_in_short">Sign in</string>
+
+ <string name="menu_forgot_password">Recover lost password</string>
+
+ <string name="login_progress_signing_in">Signing in&#8230;</string>
+
+ <string name="error_invalid_email">This email address is invalid</string>
+ <string name="error_invalid_password">This password is too short</string>
+ <string name="error_incorrect_password">This password is incorrect</string>
+ <string name="error_field_required">This field is required</string>
+</resources>
diff --git a/templates/activities/LoginActivity/root/res/values/styles.xml b/templates/activities/LoginActivity/root/res/values/styles.xml
new file mode 100644
index 0000000..eaec28d
--- /dev/null
+++ b/templates/activities/LoginActivity/root/res/values/styles.xml
@@ -0,0 +1,9 @@
+<resources>
+
+ <style name="LoginFormContainer">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:padding">16dp</item>
+ </style>
+
+</resources>
diff --git a/templates/activities/LoginActivity/root/src/app_package/LoginActivity.java.ftl b/templates/activities/LoginActivity/root/src/app_package/LoginActivity.java.ftl
new file mode 100644
index 0000000..d766051
--- /dev/null
+++ b/templates/activities/LoginActivity/root/src/app_package/LoginActivity.java.ftl
@@ -0,0 +1,278 @@
+package ${packageName};
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.View;
+import android.view.inputmethod.EditorInfo;
+import android.widget.EditText;
+import android.widget.TextView;
+<#if parentActivityClass != "">
+import android.view.MenuItem;
+import android.support.v4.app.NavUtils;
+</#if>
+
+/**
+ * Activity which displays a login screen to the user, offering registration as
+ * well.
+ */
+public class ${activityClass} extends Activity {
+ /**
+ * A dummy authentication store containing known user names and passwords.
+ * TODO: remove after connecting to a real authentication system.
+ */
+ private static final String[] DUMMY_CREDENTIALS = new String[]{
+ "foo@example.com:hello",
+ "bar@example.com:world"
+ };
+
+ /**
+ * The default email to populate the email field with.
+ */
+ public static final String EXTRA_EMAIL = "com.example.android.authenticatordemo.extra.EMAIL";
+
+ /**
+ * Keep track of the login task to ensure we can cancel it if requested.
+ */
+ private UserLoginTask mAuthTask = null;
+
+ // Values for email and password at the time of the login attempt.
+ private String mEmail;
+ private String mPassword;
+
+ // UI references.
+ private EditText mEmailView;
+ private EditText mPasswordView;
+ private View mLoginFormView;
+ private View mLoginStatusView;
+ private TextView mLoginStatusMessageView;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ setContentView(R.layout.${layoutName});
+ <#if parentActivityClass != "">
+ setupActionBar();
+ </#if>
+
+ // Set up the login form.
+ mEmail = getIntent().getStringExtra(EXTRA_EMAIL);
+ mEmailView = (EditText) findViewById(R.id.email);
+ mEmailView.setText(mEmail);
+
+ mPasswordView = (EditText) findViewById(R.id.password);
+ mPasswordView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
+ @Override
+ public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
+ if (id == R.id.login || id == EditorInfo.IME_NULL) {
+ attemptLogin();
+ return true;
+ }
+ return false;
+ }
+ });
+
+ mLoginFormView = findViewById(R.id.login_form);
+ mLoginStatusView = findViewById(R.id.login_status);
+ mLoginStatusMessageView = (TextView) findViewById(R.id.login_status_message);
+
+ findViewById(R.id.sign_in_button).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ attemptLogin();
+ }
+ });
+ }
+
+ <#if parentActivityClass != "">
+ /**
+ * Set up the {@link android.app.ActionBar}, if the API is available.
+ */
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ private void setupActionBar() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ // Show the Up button in the action bar.
+ getActionBar().setDisplayHomeAsUpEnabled(true);
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ // This ID represents the Home or Up button. In the case of this
+ // activity, the Up button is shown. Use NavUtils to allow users
+ // to navigate up one level in the application structure. For
+ // more details, see the Navigation pattern on Android Design:
+ //
+ // http://developer.android.com/design/patterns/navigation.html#up-vs-back
+ //
+ // TODO: If Settings has multiple levels, Up should navigate up
+ // that hierarchy.
+ NavUtils.navigateUpFromSameTask(this);
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+ </#if>
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ getMenuInflater().inflate(R.menu.${menuName}, menu);
+ return true;
+ }
+
+ /**
+ * Attempts to sign in or register the account specified by the login form.
+ * If there are form errors (invalid email, missing fields, etc.), the
+ * errors are presented and no actual login attempt is made.
+ */
+ public void attemptLogin() {
+ if (mAuthTask != null) {
+ return;
+ }
+
+ // Reset errors.
+ mEmailView.setError(null);
+ mPasswordView.setError(null);
+
+ // Store values at the time of the login attempt.
+ mEmail = mEmailView.getText().toString();
+ mPassword = mPasswordView.getText().toString();
+
+ boolean cancel = false;
+ View focusView = null;
+
+ // Check for a valid password.
+ if (TextUtils.isEmpty(mPassword)) {
+ mPasswordView.setError(getString(R.string.error_field_required));
+ focusView = mPasswordView;
+ cancel = true;
+ } else if (mPassword.length() < 4) {
+ mPasswordView.setError(getString(R.string.error_invalid_password));
+ focusView = mPasswordView;
+ cancel = true;
+ }
+
+ // Check for a valid email address.
+ if (TextUtils.isEmpty(mEmail)) {
+ mEmailView.setError(getString(R.string.error_field_required));
+ focusView = mEmailView;
+ cancel = true;
+ } else if (!mEmail.contains("@")) {
+ mEmailView.setError(getString(R.string.error_invalid_email));
+ focusView = mEmailView;
+ cancel = true;
+ }
+
+ if (cancel) {
+ // There was an error; don't attempt login and focus the first
+ // form field with an error.
+ focusView.requestFocus();
+ } else {
+ // Show a progress spinner, and kick off a background task to
+ // perform the user login attempt.
+ mLoginStatusMessageView.setText(R.string.login_progress_signing_in);
+ showProgress(true);
+ mAuthTask = new UserLoginTask();
+ mAuthTask.execute((Void) null);
+ }
+ }
+
+ /**
+ * Shows the progress UI and hides the login form.
+ */
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
+ private void showProgress(final boolean show) {
+ // On Honeycomb MR2 we have the ViewPropertyAnimator APIs, which allow
+ // for very easy animations. If available, use these APIs to fade-in
+ // the progress spinner.
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
+ int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime);
+
+ mLoginStatusView.setVisibility(View.VISIBLE);
+ mLoginStatusView.animate()
+ .setDuration(shortAnimTime)
+ .alpha(show ? 1 : 0)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mLoginStatusView.setVisibility(show ? View.VISIBLE : View.GONE);
+ }
+ });
+
+ mLoginFormView.setVisibility(View.VISIBLE);
+ mLoginFormView.animate()
+ .setDuration(shortAnimTime)
+ .alpha(show ? 0 : 1)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
+ }
+ });
+ } else {
+ // The ViewPropertyAnimator APIs are not available, so simply show
+ // and hide the relevant UI components.
+ mLoginStatusView.setVisibility(show ? View.VISIBLE : View.GONE);
+ mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
+ }
+ }
+
+ /**
+ * Represents an asynchronous login/registration task used to authenticate
+ * the user.
+ */
+ public class UserLoginTask extends AsyncTask<Void, Void, Boolean> {
+ @Override
+ protected Boolean doInBackground(Void... params) {
+ // TODO: attempt authentication against a network service.
+
+ try {
+ // Simulate network access.
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ return false;
+ }
+
+ for (String credential : DUMMY_CREDENTIALS) {
+ String[] pieces = credential.split(":");
+ if (pieces[0].equals(mEmail)) {
+ // Account exists, return true if the password matches.
+ return pieces[1].equals(mPassword);
+ }
+ }
+
+ // TODO: register the new account here.
+ return true;
+ }
+
+ @Override
+ protected void onPostExecute(final Boolean success) {
+ mAuthTask = null;
+ showProgress(false);
+
+ if (success) {
+ finish();
+ } else {
+ mPasswordView.setError(getString(R.string.error_incorrect_password));
+ mPasswordView.requestFocus();
+ }
+ }
+
+ @Override
+ protected void onCancelled() {
+ mAuthTask = null;
+ showProgress(false);
+ }
+ }
+}
diff --git a/templates/activities/LoginActivity/template.xml b/templates/activities/LoginActivity/template.xml
new file mode 100644
index 0000000..7df8895
--- /dev/null
+++ b/templates/activities/LoginActivity/template.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0"?>
+<template
+ format="1"
+ revision="1"
+ name="New Login Activity"
+ description="Creates a new login activity, allowing users to enter an email address and password to login or register for your service."
+ minApi="3"
+ minBuildApi="13">
+ <dependency name="android-support-v4" revision="8" />
+
+ <category value="Activities" />
+
+ <parameter
+ id="activityClass"
+ name="Activity Name"
+ type="string"
+ constraints="class|nonempty"
+ default="LoginActivity"
+ help="The name of the activity class to create" />
+
+ <parameter
+ id="layoutName"
+ name="Layout Name"
+ type="string"
+ constraints="layout|unique|nonempty"
+ suggest="${activityToLayout(activityClass)}"
+ default="activity_login"
+ help="The name of the layout to create for the activity" />
+
+ <parameter
+ id="activityTitle"
+ name="Title"
+ type="string"
+ constraints="nonempty"
+ default="Sign in"
+ help="The name of the activity." />
+
+ <parameter
+ id="parentActivityClass"
+ name="Hierarchical Parent"
+ type="string"
+ constraints="activity|exists|empty"
+ default=""
+ help="The hierarchical parent activity, used to provide a default implementation for the 'Up' button" />
+
+ <parameter
+ id="packageName"
+ name="Package name"
+ type="string"
+ constraints="package"
+ default="com.mycompany.myapp" />
+
+ <thumbs>
+ <thumb>template_login_activity.png</thumb>
+ </thumbs>
+
+ <globals file="globals.xml.ftl" />
+ <execute file="recipe.xml.ftl" />
+
+</template>
diff --git a/templates/activities/LoginActivity/template_login_activity.png b/templates/activities/LoginActivity/template_login_activity.png
new file mode 100644
index 0000000..0f9bfc0
--- /dev/null
+++ b/templates/activities/LoginActivity/template_login_activity.png
Binary files differ
diff --git a/templates/activities/MasterDetailFlow/root/AndroidManifest.xml.ftl b/templates/activities/MasterDetailFlow/root/AndroidManifest.xml.ftl
index 15ed087..395b227 100644
--- a/templates/activities/MasterDetailFlow/root/AndroidManifest.xml.ftl
+++ b/templates/activities/MasterDetailFlow/root/AndroidManifest.xml.ftl
@@ -8,7 +8,7 @@
<meta-data android:name="android.support.PARENT_ACTIVITY"
android:value="${parentActivityClass}" />
</#if>
- <#if isLauncher>
+ <#if isLauncher?string == "true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
diff --git a/uiautomatorviewer/.classpath b/uiautomatorviewer/.classpath
new file mode 100644
index 0000000..b9c01bb
--- /dev/null
+++ b/uiautomatorviewer/.classpath
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry excluding="images" kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/ddmlib"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/SdkLib"/>
+ <classpathentry kind="var" path="ANDROID_OUT_FRAMEWORK/swt.jar"/>
+ <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/eclipse/org.eclipse.core.commands_3.6.0.I20100512-1500.jar"/>
+ <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/eclipse/org.eclipse.equinox.common_3.6.0.v20100503.jar"/>
+ <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/eclipse/org.eclipse.jface_3.6.2.M20110210-1200.jar"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/uiautomatorviewer/.gitignore b/uiautomatorviewer/.gitignore
new file mode 100644
index 0000000..ba077a4
--- /dev/null
+++ b/uiautomatorviewer/.gitignore
@@ -0,0 +1 @@
+bin
diff --git a/uiautomatorviewer/.project b/uiautomatorviewer/.project
new file mode 100644
index 0000000..d5a1115
--- /dev/null
+++ b/uiautomatorviewer/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>uiautomatorviewer</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/uiautomatorviewer/Android.mk b/uiautomatorviewer/Android.mk
index a5bc768..907718b 100644
--- a/uiautomatorviewer/Android.mk
+++ b/uiautomatorviewer/Android.mk
@@ -24,6 +24,8 @@ LOCAL_MODULE_TAGS := optional
LOCAL_JAVA_LIBRARIES := \
swt \
+ sdklib \
+ ddmlib \
org.eclipse.jface_3.6.2.M20110210-1200 \
org.eclipse.core.commands_3.6.0.I20100512-1500 \
org.eclipse.equinox.common_3.6.0.v20100503
diff --git a/uiautomatorviewer/MODULE_LICENSE_APACHE2 b/uiautomatorviewer/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/uiautomatorviewer/MODULE_LICENSE_APACHE2
diff --git a/uiautomatorviewer/src/com/android/uiautomator/DebugBridge.java b/uiautomatorviewer/src/com/android/uiautomator/DebugBridge.java
new file mode 100644
index 0000000..09272bc
--- /dev/null
+++ b/uiautomatorviewer/src/com/android/uiautomator/DebugBridge.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.uiautomator;
+
+import com.android.ddmlib.AndroidDebugBridge;
+import com.android.ddmlib.IDevice;
+import com.android.sdklib.SdkConstants;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.List;
+
+public class DebugBridge {
+ private static AndroidDebugBridge sDebugBridge;
+
+ private static String getAdbLocation() {
+ String toolsDir = System.getProperty("com.android.uiautomator.bindir"); //$NON-NLS-1$
+ if (toolsDir == null) {
+ return null;
+ }
+
+ File sdk = new File(toolsDir).getParentFile();
+
+ // check if adb is present in platform-tools
+ File platformTools = new File(sdk, "platform-tools");
+ File adb = new File(platformTools, SdkConstants.FN_ADB);
+ if (adb.exists()) {
+ return adb.getAbsolutePath();
+ }
+
+ // check if adb is present in the tools directory
+ adb = new File(sdk, SdkConstants.FN_ADB);
+ if (adb.exists()) {
+ return adb.getAbsolutePath();
+ }
+
+ return null;
+ }
+
+ public static void init() {
+ String adbLocation = getAdbLocation();
+ if (adbLocation != null) {
+ AndroidDebugBridge.init(false /* debugger support */);
+ sDebugBridge = AndroidDebugBridge.createBridge(adbLocation, false);
+ }
+ }
+
+ public static void terminate() {
+ if (sDebugBridge != null) {
+ sDebugBridge = null;
+ AndroidDebugBridge.terminate();
+ }
+ }
+
+ public static boolean isInitialized() {
+ return sDebugBridge != null;
+ }
+
+ public static List<IDevice> getDevices() {
+ return Arrays.asList(sDebugBridge.getDevices());
+ }
+}
diff --git a/uiautomatorviewer/src/com/android/uiautomator/UiAutomatorViewer.java b/uiautomatorviewer/src/com/android/uiautomator/UiAutomatorViewer.java
index 9f758ae..48e01cf 100644
--- a/uiautomatorviewer/src/com/android/uiautomator/UiAutomatorViewer.java
+++ b/uiautomatorviewer/src/com/android/uiautomator/UiAutomatorViewer.java
@@ -66,7 +66,6 @@ import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Tree;
public class UiAutomatorViewer extends ApplicationWindow {
-
private static final int IMG_BORDER = 2;
private Canvas mScreenshotCanvas;
@@ -280,6 +279,8 @@ public class UiAutomatorViewer extends ApplicationWindow {
* @param args
*/
public static void main(String args[]) {
+ DebugBridge.init();
+
try {
UiAutomatorViewer window = new UiAutomatorViewer();
window.setBlockOnOpen(true);
@@ -287,6 +288,8 @@ public class UiAutomatorViewer extends ApplicationWindow {
UiAutomatorModel.getModel().cleanUp();
} catch (Exception e) {
e.printStackTrace();
+ } finally {
+ DebugBridge.terminate();
}
}
diff --git a/uiautomatorviewer/src/com/android/uiautomator/actions/ScreenshotAction.java b/uiautomatorviewer/src/com/android/uiautomator/actions/ScreenshotAction.java
index 7d1eaa3..181f655 100644
--- a/uiautomatorviewer/src/com/android/uiautomator/actions/ScreenshotAction.java
+++ b/uiautomatorviewer/src/com/android/uiautomator/actions/ScreenshotAction.java
@@ -16,6 +16,11 @@
package com.android.uiautomator.actions;
+import com.android.ddmlib.CollectingOutputReceiver;
+import com.android.ddmlib.IDevice;
+import com.android.ddmlib.RawImage;
+import com.android.ddmlib.SyncService;
+import com.android.uiautomator.DebugBridge;
import com.android.uiautomator.UiAutomatorModel;
import com.android.uiautomator.UiAutomatorViewer;
@@ -23,20 +28,39 @@ import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.Action;
+import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.ImageLoader;
+import org.eclipse.swt.graphics.PaletteData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
-import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
-import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
public class ScreenshotAction extends Action {
+ private static final String UIAUTOMATOR = "/system/bin/uiautomator"; //$NON-NLS-1$
+ private static final String UIAUTOMATOR_DUMP_COMMAND = "dump"; //$NON-NLS-1$
+ private static final String UIDUMP_DEVICE_PATH = "/sdcard/uidump.xml"; //$NON-NLS-1$
+
+ private static final int MIN_API_LEVEL = 16;
UiAutomatorViewer mViewer;
@@ -52,6 +76,18 @@ public class ScreenshotAction extends Action {
@Override
public void run() {
+ if (!DebugBridge.isInitialized()) {
+ MessageDialog.openError(mViewer.getShell(),
+ "Error obtaining Device Screenshot",
+ "Unable to connect to adb. Check if adb is installed correctly.");
+ return;
+ }
+
+ final IDevice device = pickDevice();
+ if (device == null) {
+ return;
+ }
+
ProgressMonitorDialog dialog = new ProgressMonitorDialog(mViewer.getShell());
try {
dialog.run(true, false, new IRunnableWithProgress() {
@@ -63,7 +99,7 @@ public class ScreenshotAction extends Action {
public void run() {
Status s = new Status(IStatus.ERROR, "Screenshot", msg, t);
ErrorDialog.openError(
- mViewer.getShell(), "Error", "Cannot take screenshot", s);
+ mViewer.getShell(), "Error", "Error obtaining UI hierarchy", s);
}
});
}
@@ -71,12 +107,9 @@ public class ScreenshotAction extends Action {
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException,
InterruptedException {
- ProcRunner procRunner = null;
- String serial = System.getenv("ANDROID_SERIAL");
File tmpDir = null;
File xmlDumpFile = null;
File screenshotFile = null;
- int retCode = -1;
try {
tmpDir = File.createTempFile("uiautomatorviewer_", "");
tmpDir.delete();
@@ -91,115 +124,72 @@ public class ScreenshotAction extends Action {
}
UiAutomatorModel.getModel().registerTempDirectory(tmpDir);
- // boiler plates to do a bunch of adb stuff to take XML snapshot and screenshot
- monitor.beginTask("Getting UI status dump from device...",
- IProgressMonitor.UNKNOWN);
- monitor.subTask("Detecting device...");
- procRunner = getAdbRunner(serial, "shell", "ls", "/system/bin/uiautomator");
+ String apiLevelString = device.getProperty(IDevice.PROP_BUILD_API_LEVEL);
+ int apiLevel;
try {
- retCode = procRunner.run(30000);
- } catch (IOException e) {
- e.printStackTrace();
- showError("Failed to detect device", e, monitor);
- return;
+ apiLevel = Integer.parseInt(apiLevelString);
+ } catch (NumberFormatException e) {
+ apiLevel = MIN_API_LEVEL;
}
- if (retCode != 0) {
- showError("No device or multiple devices connected. "
- + "Use ANDROID_SERIAL environment variable "
- + "if you have multiple devices", null, monitor);
- return;
- }
- if (procRunner.getOutputBlob().indexOf("No such file or directory") != -1) {
- showError("/system/bin/uiautomator not found on device", null, monitor);
+ if (apiLevel < MIN_API_LEVEL) {
+ showError("uiautomator requires a device with API Level " + MIN_API_LEVEL,
+ null, monitor);
return;
}
+
monitor.subTask("Deleting old UI XML snapshot ...");
- procRunner = getAdbRunner(serial,
- "shell", "rm", "/sdcard/uidump.xml");
+ String command = "rm " + UIDUMP_DEVICE_PATH;
try {
- retCode = procRunner.run(30000);
- if (retCode != 0) {
- throw new IOException(
- "Non-zero return code from \"rm\" xml dump command:\n"
- + procRunner.getOutputBlob());
- }
- } catch (IOException e) {
- e.printStackTrace();
- showError("Failed to execute \"rm\" xml dump command.", e, monitor);
- return;
+ CountDownLatch commandCompleteLatch = new CountDownLatch(1);
+ device.executeShellCommand(command,
+ new CollectingOutputReceiver(commandCompleteLatch));
+ commandCompleteLatch.await(5, TimeUnit.SECONDS);
+ } catch (Exception e1) {
+ // ignore exceptions while deleting stale files
}
monitor.subTask("Taking UI XML snapshot...");
- procRunner = getAdbRunner(serial,
- "shell", "/system/bin/uiautomator", "dump", "/sdcard/uidump.xml");
+ command = String.format("%s %s %s", UIAUTOMATOR,
+ UIAUTOMATOR_DUMP_COMMAND,
+ UIDUMP_DEVICE_PATH);
try {
- retCode = procRunner.run(30000);
- if (retCode != 0) {
- throw new IOException("Non-zero return code from dump command:\n"
- + procRunner.getOutputBlob());
- }
- } catch (IOException e) {
- e.printStackTrace();
- showError("Failed to execute dump command.", e, monitor);
- return;
- }
- procRunner = getAdbRunner(serial,
- "pull", "/sdcard/uidump.xml", xmlDumpFile.getAbsolutePath());
- try {
- retCode = procRunner.run(30000);
- if (retCode != 0) {
- throw new IOException("Non-zero return code from pull command:\n"
- + procRunner.getOutputBlob());
- }
- } catch (IOException e) {
- e.printStackTrace();
- showError("Failed to pull dump file.", e, monitor);
+ CountDownLatch commandCompleteLatch = new CountDownLatch(1);
+ device.executeShellCommand(command,
+ new CollectingOutputReceiver(commandCompleteLatch));
+ commandCompleteLatch.await(5, TimeUnit.SECONDS);
+ } catch (Exception e1) {
+ showError("", e1, monitor);
return;
}
- monitor.subTask("Deleting old device screenshot...");
- procRunner = getAdbRunner(serial,
- "shell", "rm", "/sdcard/screenshot.png");
+ monitor.subTask("Pull UI XML snapshot from device...");
try {
- retCode = procRunner.run(30000);
- if (retCode != 0) {
- throw new IOException(
- "Non-zero return code from \"rm\" screenshot command:\n"
- + procRunner.getOutputBlob());
- }
- } catch (IOException e) {
- e.printStackTrace();
- showError("Failed to execute \"rm\" screenshot command.", e, monitor);
+ device.getSyncService().pullFile(UIDUMP_DEVICE_PATH,
+ xmlDumpFile.getAbsolutePath(), SyncService.getNullProgressMonitor());
+ } catch (Exception e1) {
+ showError("Error copying UI XML file from device", e1, monitor);
return;
}
- monitor.subTask("Taking device screenshot...");
- procRunner = getAdbRunner(serial,
- "shell", "screencap", "-p", "/sdcard/screenshot.png");
- try {
- retCode = procRunner.run(30000);
- if (retCode != 0) {
- throw new IOException("Non-zero return code from screenshot command:\n"
- + procRunner.getOutputBlob());
- }
- } catch (IOException e) {
- e.printStackTrace();
- showError("Failed to execute screenshot command.", e, monitor);
- return;
- }
- procRunner = getAdbRunner(serial,
- "pull", "/sdcard/screenshot.png", screenshotFile.getAbsolutePath());
+ monitor.subTask("Taking screenshot...");
+ RawImage rawImage;
try {
- retCode = procRunner.run(30000);
- if (retCode != 0) {
- throw new IOException("Non-zero return code from pull command:\n"
- + procRunner.getOutputBlob());
- }
- } catch (IOException e) {
- e.printStackTrace();
- showError("Failed to pull dump file.", e, monitor);
+ rawImage = device.getScreenshot();
+ } catch (Exception e1) {
+ showError("Error taking device screenshot", e1, monitor);
return;
}
+
+ PaletteData palette = new PaletteData(
+ rawImage.getRedMask(),
+ rawImage.getGreenMask(),
+ rawImage.getBlueMask());
+ ImageData imageData = new ImageData(rawImage.width, rawImage.height,
+ rawImage.bpp, palette, 1, rawImage.data);
+ ImageLoader loader = new ImageLoader();
+ loader.data = new ImageData[] { imageData };
+ loader.save(screenshotFile.getAbsolutePath(), SWT.IMAGE_PNG);
+
final File png = screenshotFile, xml = xmlDumpFile;
if(png.length() == 0) {
showError("Screenshot file size is 0", null, monitor);
@@ -222,81 +212,68 @@ public class ScreenshotAction extends Action {
}
}
- /*
- * Convenience function to construct an 'adb' command, e.g. use 'adb' or 'adb -s NNN'
- */
- private ProcRunner getAdbRunner(String serial, String... command) {
- List<String> cmd = new ArrayList<String>();
- cmd.add("adb");
- if (serial != null) {
- cmd.add("-s");
- cmd.add(serial);
- }
- for (String s : command) {
- cmd.add(s);
+ private IDevice pickDevice() {
+ List<IDevice> devices = DebugBridge.getDevices();
+ if (devices.size() == 0) {
+ MessageDialog.openError(mViewer.getShell(),
+ "Error obtaining Device Screenshot",
+ "No Android devices were detected by adb.");
+ return null;
+ } else if (devices.size() == 1) {
+ return devices.get(0);
+ } else {
+ DevicePickerDialog dlg = new DevicePickerDialog(mViewer.getShell(), devices);
+ if (dlg.open() != Window.OK) {
+ return null;
+ }
+ return dlg.getSelectedDevice();
}
- return new ProcRunner(cmd);
}
- /**
- * Convenience class to run external process.
- *
- * Always redirects stderr into stdout, has timeout control
- *
- */
- private static class ProcRunner {
-
- ProcessBuilder mProcessBuilder;
+ private static class DevicePickerDialog extends Dialog {
+ private final List<IDevice> mDevices;
+ private final String[] mDeviceNames;
+ private static int sSelectedDeviceIndex;
- List<String> mOutput = new ArrayList<String>();
+ public DevicePickerDialog(Shell parentShell, List<IDevice> devices) {
+ super(parentShell);
- public ProcRunner(List<String> command) {
- mProcessBuilder = new ProcessBuilder(command).redirectErrorStream(true);
+ mDevices = devices;
+ mDeviceNames = new String[mDevices.size()];
+ for (int i = 0; i < devices.size(); i++) {
+ mDeviceNames[i] = devices.get(i).getName();
+ }
}
- public int run(long timeout) throws IOException {
- final Process p = mProcessBuilder.start();
- Thread t = new Thread() {
+ @Override
+ protected Control createDialogArea(Composite parentShell) {
+ Composite parent = (Composite) super.createDialogArea(parentShell);
+ Composite c = new Composite(parent, SWT.NONE);
+
+ c.setLayout(new GridLayout(2, false));
+
+ Label l = new Label(c, SWT.NONE);
+ l.setText("Select device: ");
+
+ final Combo combo = new Combo(c, SWT.BORDER | SWT.READ_ONLY);
+ combo.setItems(mDeviceNames);
+ int defaultSelection =
+ sSelectedDeviceIndex < mDevices.size() ? sSelectedDeviceIndex : 0;
+ combo.select(defaultSelection);
+ sSelectedDeviceIndex = defaultSelection;
+
+ combo.addSelectionListener(new SelectionAdapter() {
@Override
- public void run() {
- String line;
- mOutput.clear();
- try {
- BufferedReader br = new BufferedReader(new InputStreamReader(
- p.getInputStream()));
- while ((line = br.readLine()) != null) {
- mOutput.add(line);
- }
- br.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- };
- };
- t.start();
- try {
- t.join(timeout);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- if (t.isAlive()) {
- throw new IOException("external process not terminating.");
- }
- try {
- return p.waitFor();
- } catch (InterruptedException e) {
- e.printStackTrace();
- throw new IOException(e);
- }
+ public void widgetSelected(SelectionEvent arg0) {
+ sSelectedDeviceIndex = combo.getSelectionIndex();
+ }
+ });
+
+ return parent;
}
- public String getOutputBlob() {
- StringBuilder sb = new StringBuilder();
- for (String line : mOutput) {
- sb.append(line);
- sb.append(System.getProperty("line.separator"));
- }
- return sb.toString();
+ public IDevice getSelectedDevice() {
+ return mDevices.get(sSelectedDeviceIndex);
}
}
}