From 75ffc858fcff1effb785a589a0f7a659b54982b5 Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 11 Feb 2010 21:57:24 +0000 Subject: [PATCH 001/349] Future public API for interfacing with WebKit on Haiku. (What will eventually become BWebView.) Compared to the original port, the threading has been completely redesigned such that all interaction with WebKit happens in the application thread, as required by the PThread threading backend. This is counteracted by using an offscreen BBitmap/view as the top-level GraphicsContext for each Page, such that drawing is performed in various app_server threads asynchronously. WebViewWindow provides as a target for messages from within WebKit (mostly FrameLoaderClientHaiku events), which are forwarded via virtual hook methods (implemented in LauncherWindow.cpp of the HaikuLauncher). git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@6 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 68 +++++ src/apps/webpositive/DownloadWindow.h | 45 +++ src/apps/webpositive/Launcher.rdef | 254 +++++++++++++++++ src/apps/webpositive/LauncherApp.cpp | 250 +++++++++++++++++ src/apps/webpositive/LauncherApp.h | 62 +++++ src/apps/webpositive/LauncherWindow.cpp | 354 ++++++++++++++++++++++++ src/apps/webpositive/LauncherWindow.h | 91 ++++++ src/apps/webpositive/LeakTracker.h | 119 ++++++++ 8 files changed, 1243 insertions(+) create mode 100644 src/apps/webpositive/DownloadWindow.cpp create mode 100644 src/apps/webpositive/DownloadWindow.h create mode 100644 src/apps/webpositive/Launcher.rdef create mode 100644 src/apps/webpositive/LauncherApp.cpp create mode 100644 src/apps/webpositive/LauncherApp.h create mode 100644 src/apps/webpositive/LauncherWindow.cpp create mode 100644 src/apps/webpositive/LauncherWindow.h create mode 100644 src/apps/webpositive/LeakTracker.h diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp new file mode 100644 index 0000000000..b27acf86a9 --- /dev/null +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "DownloadWindow.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +DownloadWindow::DownloadWindow(BRect frame) + : BWindow(frame, "Downloads", + B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, + B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE) +{ + Minimize(true); + Show(); +} + +DownloadWindow::~DownloadWindow() +{ +} + +void DownloadWindow::MessageReceived(BMessage* message) +{ + switch (message->what) { + default: + BWindow::MessageReceived(message); + break; + } +} + +bool DownloadWindow::QuitRequested() +{ + if (!IsMinimized()) + Minimize(true); + return false; +} diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h new file mode 100644 index 0000000000..d263ddf387 --- /dev/null +++ b/src/apps/webpositive/DownloadWindow.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DownloadWindow_h +#define DownloadWindow_h + +#include + +class DownloadWindow : public BWindow { +public: + DownloadWindow(BRect frame); + virtual ~DownloadWindow(); + + virtual void MessageReceived(BMessage*); + virtual bool QuitRequested(); + +private: +}; + +#endif // DownloadWindow_h + diff --git a/src/apps/webpositive/Launcher.rdef b/src/apps/webpositive/Launcher.rdef new file mode 100644 index 0000000000..3165079460 --- /dev/null +++ b/src/apps/webpositive/Launcher.rdef @@ -0,0 +1,254 @@ +resource app_signature "application/x-vnd.RJL-HaikuLauncher"; + +resource app_version { + major = 0, + middle = 0, + minor = 1, + variety = B_APPV_ALPHA, + internal = 0, + short_info = "HaikuLauncher", + long_info = "HaikuLauncher ©2007-2010 The WebKit Haiku Project" +}; + +resource app_flags B_SINGLE_LAUNCH; + +resource file_types message { + "types" = "text/html", + "types" = "image/gif", + "types" = "image/jpeg", + "types" = "image/png", + "types" = "application/x-vnd.Be-bookmark", + "types" = "text", + "types" = "application/x-vnd.Be-doc_bookmark", + "types" = "application/x-vnd.Be.URL.file", + "types" = "application/x-vnd.Be.URL.ftp", + "types" = "application/x-vnd.Be.URL.http", + "types" = "application/x-vnd.Be.URL.https" +}; + +resource vector_icon { + $"6E636966450500020106033D0AFE000000000000BD0AFE48F10748A0783133FF" + $"FFC80066FFFF0034CC020106033D0AFE000000000000BD0AFE48F10748A07854" + $"09B4B6D8033784FF051D61020106043D950B0000000000003D950B494FBC479B" + $"EC00FFFFFF4C00FF008F00B200FF008000050002030605B812A5BE03E13DE784" + $"B8021049F79F49EDD800F1F1F136D9DDF48A9996B9B4B8BEDBFFF4F4F404EBD0" + $"020006023C92C0388F5FB854503C576348D8DF48895B004137A9FFB9B9B90401" + $"7E03FF360003FFFF0003FF9C0003FF000002010202BB36AEBA1760B80FFF392B" + $"574ACCFB48652300000001FFFF0000013205400500020004024AFFFC00FFFFBA" + $"360500020106033D0AFE000000000000BD0AFE48F10748A0783133FFFFC80066" + $"FFFF0034CC020106023D0AFE000000000000BD0AFE48F10748A0780033FFFFFF" + $"0033CC020106023D0AFE000000000000BD0AFE48F10748A0780033FFFFFF0066" + $"FF020004027AFFFC00DDFFBA360201040289FF0000A9C000000200040200FFE5" + $"CED0ECB989020004020DEFBC8CFFD4AA820200040200FFCB9CE9ECB989020004" + $"0200FFCB9CE9ECB98902000402B3FFCB9CBBD4AA820500020106033D0AFE0000" + $"00000000BD0AFE48F10748A0783133FFFFC80066FFFF0034CC020106033D0AFE" + $"000000000000BD0AFE48F10748A0785409B4B6D8033784FF051D61020106043D" + $"950B0000000000003D950B494FBC479BEC00FFFFFF4C00FF008F00B200FF0080" + $"00050002030605B812A5BE03E13DE784B8021049F79F49EDD800F1F1F136D9DD" + $"F48A9996B9B4B8BEDBFFF4F4F404EBD0020006023C92C0388F5FB854503C5763" + $"48D8DF48895B004137A9FFB9B9B904017E03FF360003FFFF000200040200FFBC" + $"34FFFF9C0003FF000002010202BB36AEBA1760B80FFF392B574ACCFB48652300" + $"000001FFFF00000132054003FFFFC9020014020026FF1C0500050002030605B8" + $"12A5BE03E13DE784B8021049F79F49EDD800F1F1F136D9DDF48A9996B9B4B8BE" + $"DBFFF4F4F404EBD0020006023C92C0388F5FB854503C576348D8DF48895B0041" + $"37A9FFB9B9B904017E03FF360003FFFF0003FF9C0003FF000002010202BB36AE" + $"BA1760B80FFF392B574ACCFB48652300000001FFFF0000013205400500030052" + $"7502001002F8006BFF003E04006C050003900000020310020000006E00650400" + $"6B05000359463503C3A414039D816035000000000204BFC2B55BBBC5B55BC3BF" + $"B55BC6FABC93C6FAB896C6FAC090BFC2C3CBC3BFC3CBBBC5C3CBB88ABC93B88A" + $"C090B88AB896026EC5DCB8B6C713BAA0C4CAB706C110B579C307B5D5C0A2B565" + $"BFC2B55BC032B55BBDBCB55BBA69B7BABBC5B63AB8F9B94FB89DBD9CB84FBB7E" + $"B8C7BE9AB924BF77B8E0BEE7B9DEC11FBCE0C332BB38C279BEC5C405C2D8C31A" + $"C0FBC3FCC2C6C2C1C22FC2B7C27AC2BEC22FC2B7C227C2B7C227C2B7C227C2B7" + $"C241C2BDC241C2BDC206C2B0C199C2DBC1D0C2CBC159C2EEC0D4C2DDC115C2E5" + $"C051C2CEBF43C313BFB0C2B4BF3DC313BF36C313BF36C313BF36C313BF20C313" + $"BF20C313BF20C313BDEDC313BE23C313BDB9C2EDBD57C2DFBD87C2E3BD54C2DC" + $"BD3EC2C3BD3EC2C3BD31C2B4BD13C2A5BD26C2ABBD13C2A5BCA4C27EBCA4C27E" + $"BCA4C27EBC31C254BC31C254BC27C251BC12C24FBC1DC250BC10C24BBC0FC242" + $"BC11C246BC0FC242BBF5C219BBF5C219BBD3C1DEBB68C195BBAEC1A4BB71C16E" + $"BB58C129BB63C14EBB4BC101BB4BC0ADBB48C0D7BB4BC0ADBB4EC087BB4EC087" + $"BB52C054BB4DBFEEBB55C021BB9EBF93BBA9BEBFBBB0BF36BBA9BEBFBBA7BE93" + $"BBA7BE93BBA7BE53BBBCBE2FBBA8BE4BBBBCBE2FBBC7BE21BBC7BE21BC00BDD5" + $"BBE3BCFCBC5BBD3DBBE3BCFCBAB7BC58BAB7BC58BAB7BC58BA8BBC44BA90BC46" + $"BA8BBC44BA8BBC42BA8BBC42BA89BBEABA23BB79BA6ABBADBA23BB79BA12BB6B" + $"BA12BB6BBA12BB6BB9F8BB49B9F8BB49B9F8BB49B9AEBAF0B9AEBAF0B97EBAC3" + $"B928BAB1B950BAB5B924BAA9B91BBA9AB920BAA1B984BA6EB9DEB997B9B5B9F9" + $"B9F6B95DBA36B8F0BA0BB91FBA5EB8C4BA78B85EBA83B89EBACCB83DBB61B7E7" + $"BB18B813BB61B7E7BB6BB7E1BB6BB7E1BB6BB7E1BBFEB787BBFEB787BC65B74A" + $"BCB6B684BC94B6F6BCF5B68ABD58B665BD2DB67BBDA8B695BE6DB651BE29B697" + $"BE6FB650BE88B64FBE7CB64FBE62B6A0BEE1B72FBE88B70EBEE4B733BEE9B73E" + $"BEE5B73ABED8B744BEC6B74ABEC6B74ABEC6B74ABE75B7A5BE75B7A5BE63B7DD" + $"BE90B849BE74B817BE91B84CBE92B852BE92B852BE94B85CBE9DB87ABE97B86B" + $"BE94B884BE8CB88DBE8CB88DBE3AB8F0BD92B98FBDB7B906BD92B98FBD8DB9A1" + $"BD8DB9A1BD64B9D8BD7EBA55BD59BA19BD7BBA5CBD77BA63BD77BA63BD56BAA0" + $"BD4DBB2CBD39BAE6BD60BB70BDCCBBCEBD98BBA2BDFFBBFABE73BC3FBE33BC27" + $"BEBEBC5CBF5EBC42BF12BC56BF5EBC42BFAC37BFAC37BFD0BC1EC01CBC0FBFF5" + $"BC0BC046BC14C083BC4EC066BC35C04DBCD9C0F4BDDAC0B6BD63C0F4BDDAC107" + $"BDF9C102BDF2C0BABE84C127BF91C0B2BF1DC127BF91C133BF9DC133BF9DC131" + $"C00FC1C5C0F9C135C0D6C259C11CC348C059C2EEC0C9C348C059C36BC02FC36B" + $"C02FC36BC02FC388C019C388C019C3A8C003C3DBBFC5C3C9BFE8C3EEBFA0C409" + $"BF52C3F0BF73C409BF52C409BF53C409BF53C40DBF9AC495BFC1C450BFCEC4EB" + $"BFB3C542BF10C51FBF56C542BF10C551BEF2C551BEF2C551BEF2C555BEEBC555" + $"BEEBC57FBEA3C568BDFCC59EBE47C53ABDBBC4A3BDDFC4E1BDAAC4A3BDCAC4A3" + $"BDB5C4A3BDB5C4A3BDB5C4A5BD31C4A5BD31C4A8BD1EC4E8BCDFC4D2BCF5C4E8" + $"BCDFC4FEBCC9C4FEBCC9C4FEBCC9C516BCB3C516BCB3C545BC8BC582BC20C571" + $"BC5EC58CBC05C588BBBCC586BBD9C588BBBCC587BBA8C587BBA8C587BBA8C588" + $"BB9DC588BB9DC58DBB614EBAFAC584BB24C58ABADAC5C2BA5DC5B0BAA2C5C4BA" + $"62C5CBBA70C5CBBA70C5D9BA8EC60FBAD4C5EDBAB3C60ABB1FC648BBAAC627BB" + $"67C669BBEBC66FBC7BC670BC33C66FBC7BC672BCC4C672BCC4C674BCEAC66EBD" + $"37C678BD11C664BD5AC649BD9CC652BD79C633BDECC62CBE92C62DBE3FC621BE" + $"D5C67FBF2CC648BF16C750BD0F0006BC12B6E4BC12B6E4BC32B6B0BC55B638BC" + $"47B674BB81B6ABBA2BB802BAC4B747BA88B7E3BB30B77EBADDB7B0BB59B765BB" + $"AAB733BB82B74DBBCBB71DBC12B6E4BBFCB707BC12B6E4001DBACDBFD1BACDBF" + $"D1BAEBBFAABB29BF5CBB13BF89BB43BF24BB34BE93BB34BED0BB34BE4DBB60BD" + $"EABB34BE25BB80BDBEBBABBD60BBA1BD98BB48BD2ABA81BCBEBAE5BCF3BA67BC" + $"B1BA20BC83BA2DBCA0BA0FBC5BBA0DBC02BA1FBC28B9FEBBE5B9BABBB6B9D0BB" + $"D0B99BBB91B95FBB44B983BB66B93DBB24B8F0BB2DB91CBB16B8C0BB48B8BEBA" + $"DFB8C3BAFFB8B1BB14B89FBB7EB8A7BB49B8C9BB7EB8C5BBB2B8C3BB8AB8C6BB" + $"DBB8C9BC2EB8C7BC05B8D0BC40B8BABC49B8CBBC49B8B4BC4BB8AABC4EB8AFBC" + $"4DB8A0BC57B893BC4BB898BC56B882BC4AB88FBD10B88EBD00B893BD49B8E1BD" + $"E7B88DBE03B90DBE04B923BE75B906BE4BB946BEA8B985BF00B973BEC1B997BF" + $"3EB9A3BFC1B998BF81B9B0C011BA17C05FB9DBC02EBA25C0B3BA75C127BA3DC0" + $"E7BA8FC144BAC0C17FBAA9C160BAD8C19FBAFCC17CBAE4C19DBADDC13ABAD7C0" + $"A6BAD3C0EFBADBC061BACDBFD1BAEAC013BACDBFD10009BD5EB5D7BD5EB5D7BD" + $"81B5EEBDB1B60EBD84B605BDD0B613BE19B601BE01B61ABE55B5C3BEF6B5C4BE" + $"B0B5EFBF2DB5A2BFA3B55EBF5BB55EBFCEB55DC00CB58CBFE9B578C03CB5A7C0" + $"90B566C064B575BF3AB541BCA7B60EBDDDB57ABCECB623BD5EB5D7BD29B601BD" + $"5EB5D70005BF35B6EABF35B6EABF55B6ECBF9AB6F5BF7BB702BFCEB6E0BF87B6" + $"7DBF9CB693BF78B66DBF3CB664BF2FB623BF45B690BF35B6EABF6BB6CCBF35B6" + $"EA0004BA07B87FBA07B87FBA0CB868B9EFB850B9FEB85FB982B8E4B8F0BA35B9" + $"2CB988B97E31BA07B87FB974B8F0BA07B87F0066C6F7BC24C6F7BC24C6DCBB0A" + $"C6002FC68BB9F2C5B9B87CC4FFB79CC563B805C4CEB768C463B709C49AB737C4" + $"52B6FBC428B6EFC440B6E2C412B6FAC407B6C1C401B6D1C316B60FC0D0B56FC1" + $"F9B59AC0FBB58BC15FB59CC131B589C170B5A2C179B5C9C19FB5BDC12DB5E2C0" + $"8AB5C9C0D7B5C4C05AB5CDC03FB60EC043B5DDC03DB629C040B676C036B65DC0" + $"4BB694C0B6B65FC0A8B66FC0CDB643C0F1B61AC0B1B608C108B64BC0D0B6B1C1" + $"3AB6D6C0B5B6A7C066B689C083B67CC064B68AC05DB6AFC05FB6ABC053B6C0C0" + $"31B6D0C044B6CBBFE6B6E5BF94B741BFB0B6EFBF87B769BF5DB791BF88B781BF" + $"3BB79DBEF7B7B2BF17B7A4BECCB7C7BEFAB81CBEEAB7FFBF06B830BF19B86CBF" + $"03B860BF59B891BFBEB7E0BFA3B802BFE1B7B3C038B7ADC008B7BDC04FB7A6C0" + $"84B777C06CB76EC0D3B795C0F8B83EC0EBB7F4C110B83FC135B810C100B802C1" + $"0DB7E5C0ECB77043B7ABC125B795C15FB7FDC14DB7BDC170B83DC1C2B820C18E" + $"B860C1CFB813C1FDB7D5C1E2B7BDC214B7EAC1F1B838C215B82FC206B84BC23A" + $"B83DC222B843C25AB834C28BB842C26CB836C2AFB850C2FAB857C2D5B854C320" + $"B859C347B898C335B87BC377B8E7C24AB8C5C259B8C6C228B8C3C1E2B8D0C202" + $"B8C2C1C9B8DAC199B8F0C1B62FC179B8E5C13FB8B6C15BB8C8C118B89CC0C5B8" + $"72C0EFB885C07FB853BFE3B84FC02FB83FBFBFB856BF7FB87CBF9CB866BF5CB8" + $"97BF11B8A4BF35B87FBEDCB8DCBE6EB942BEB6B91FBE51B950BE19B976BE2EB9" + $"5CBE04B990BDF6B9D1BE04B9B4BDE9B9EEBDE2BA1DBDCAB9FCBDF8BA3CBDEFBA" + $"76BDFEBA53BDD9BAA9BDC9BB27BD9FBAEFBDF235BE71BBBCBE3ABB94BEAFBBE9" + $"BF41BBD2BEFBBBE5BF83BBC1C009BB9CBFC5BBA1C05FBB96C0DDBC03C0A1BBCD" + $"C104BC26C0F5BC67C114BC34C0D3BC9FC103BD00C0E8BCC8C11FBD37C159BDA3" + $"C13CBD6DC166BDBAC182BDE8C177BDD0C18EBE04C16DBE2DC17BBE15C152BE5E" + $"C13FBECFC13FBE97C13FBF0EC185BF4CC15DBF24C1AABF71C1A4BFE3C1A8BFB3" + $"C1A0C025C1DBC087C1B3C053C216C08AC289C06CC253C086C2CBC04DC319BFDE" + $"C2E8C00FC347BFB0C386BF66C378BFABC396BF13C3FEBEBFC3C2BEF2C435BE90" + $"C430BE0CC42EBE4DC432BDC0C433BD22C429BD6DC43CBCDEC4ABBC78C47EBCA7" + $"C4CDBC56C512BC03C505BC34C519BBE7C513BBA8C51336C513BB93C51135C51A" + $"BB71C4F8BB29C47EBB2CC48ABB5DC476BB0EC48BBB01C477BB14C4A1BAEDC478" + $"BACDC48BBAD8C442BAADC3F1BA66C418BA9AC3CCBA36C391B9CBC3AEBA00C389" + $"B9BEC36CB93BC342B92EC39AB94AC3E2B9A3C3C4B981C419B9DFC46DBA6AC44A" + $"BA20C46EBA73C496BA8AC48FBA85C4AFBA9CC4EABAA8C4CABAABC533BAA2C55A" + $"BA20C555BA61C562B9C7C4E8B9AFC51DB9DAC4CAB997C49EB958C4B6B975C48F" + $"B946C474B90EC466B92AC493B8F9C4BDB91DC49FB90BC4E0B932C52CB951C505" + $"B944C555B95EC5B4B96CC592B952C5C9B97CC5E7B9B8C5D9B9A2C5FEB9DCC627" + $"BA26C614BA00C645BA61C694BA9FC64DBA89C667BAE8C6B6BB83C693BB3FC6DF" + $"BBD4C6E3BC7CC6E4BC23C6E2BCCEC6D0BD79C6F5BD2CC6A7BDCCC69FBE9AC69F" + $"BE3EC6A1BE95C6A5BE88C6A3BE8DC6A2BE8FC6A1BEC0C696BEBEC6B2BEC4C6D6" + $"BE02C6D2BE15C6F6BD65C6F7BC24C700BCC4C6F7BC240008C301B7D8C301B7D8" + $"C2E6B7DCC2D4B7A4C2E8B7AEC2B1B792C269B7B8C288B7A7C204B7EFC236B743" + $"C221B77BC239B73AC285B744C27AB746C2A7B740C2F3B74FC2D8B731C30CB76B" + $"C33CB7A1C31FB787C360B7C2C301B7D8C31CB7D4C301B7D80004BB53C203BB53" + $"C203BB45C20DBB26C221BB38C21DBB55C249BBBAC291BB87C26EBB92C265BB53" + $"C203BB84C227BB53C2030005C4F4BE2EC4F4BE2EC4D3BE57C48CBEA4C4A6BE76" + $"C46EBEDAC47DBF53C47DBF18C4B6BF38C4EDBEB9C4D0BEECC502BE93C4F4BE2E" + $"C531BE48C4F4BE2E0009C213C327C213C327C17FC390BFF7C345C09DC332BFD0" + $"C349BF8EC36ABFACC350BF67C38CBF20C386BF56C386BEAFC386BDCDC386BE3E" + $"C386BEC1C3CBC0C0C3BABFC4C3DDC137C3AAC221C367C1AFC38EC22AC364C262" + $"C32BC280C337C249C322C213C327C22AC331C213C32702024E284E2C542E4C32" + $"4C30482E020250304C3252344C364E344C340202C951B81858305C3254365432" + $"4E300202583456365836563C5A3854380204BCD6C1F1BACDC370BEA5C09BC4A7" + $"BFA6C361BE3CC67FC1B1C065C5ADC23AC445BE91C715B827C85DB962C9B9B682" + $"C68C0204C3CFC072C309BF46C522C2743DC65FC0DEC4E4BC10C7F7B880C76BB8" + $"DAC831B842C6E2BC70C2E3B880C5CDBE43C189061EAEE6BAEAAAAF9A0EB9E5C6" + $"DFB9CC50B985C673BA12C5CDBAE4C593BA9EC0BFBC89BE0E36B8E6B993B8DA2E" + $"B874B92DB971B7B0BCD6BA52BCEFB87ABE3BB7AEBD62B7AEBF13B7AEBF862EBF" + $"93BA78C0D2BB91C49BBB6AC51ABC10C51ABBB6C51ABC5AC49BBCB6C21DBCC3BF" + $"A0BDCEBFCCC18BC1FDC323BF00C13E46C33BC197C43B46C3DCC12BC484C02CC4" + $"94C012C3EFC092C36FBE21C2BDBF40BC50C14BBBF74EBB8451BBE8C66FBA9EC6" + $"B90611AAAAA8BA02BBF0B9ECBB4ABAB8BCC9BB9DBCE2BE4EBB71C019BC7CC0A5" + $"BE08BF73BE6144BFA0BF6DBDDBC06CBD0245BCAFC1CABC30BF40BAABBE0EBB04" + $"BF0DBB04BD83BB04BD15BAB8BCAFBA38060BBAAA2A31C653BA0CC6C5BB84C646" + $"BB2BC69FBBB6C614BBB0C5A0BBDDC309BC1DC164BCAFC0CBBB71BFE6BAD8C0CB" + $"BACBC395BAE4C5C6060AAAAB0ABE47C125BF99C131BF80454448C1FDC395C21D" + $"C362C1C4C3F1C11EC448C052C494C02CC3EFC105C389BE67470605EA02BB37BA" + $"C5BBD7BA12B9ACB887B8E0B8ADB90BB86AB887B939B920B96C0A05C16BBB91C4" + $"74BB91C4DABC36C4A7BCC3C16BBCE906078A2EBD4F2EBDB5B814BEA7BF402EBF" + $"4DBA45BE0EBB04BEA7BB2BBD8ABAE3BD29BA520607AA3A39B8EDBE012F3CB99F" + $"3EB993BEDAB920BF99B946BE34B77BBFF6B7C339B74804032EBCE932BDCEBB2B" + $"BD34BB13BECDBB51BF4DBA380208CA68BA5FCB41BD02CA3AB9D0CA0FB6BCCAF4" + $"B7AEC947B5E955B58A55B58A55B58AC844B841C8FFB76C53B953C718B814C6E6" + $"B8FBC74BB728C5A02FC601B84FC2703DC646BCB6C5ADBC1DC712BD82C89DBEE7" + $"C79E40C89DBEE7060ABFFB0FC6F2C098C626BFCCC6F2BFCC5A345C3758315A2E" + $"5A305A2C582A562E582C54305230C692B854C692B920C692B7DAC53ABAAB4FB9" + $"ACC501BB1EC46EBBF7C4AEBB9DC3FBBCB6C56DBE0EC38FBE4EC64DBDF00207C8" + $"70BE74C870BE74C7A4BDA8C78BBB44C80BBB28C71835C633BBB7C6D5BBF0C5DB" + $"BB98C501BB44C50ABB7AC4F2BAEEC3F5BC43C43FBBD2C4B4BC83C6FF38C63336" + $"C7CB3AC83DBE9AC5B3BF8DC909BD020202C6392F4DB9F9C66CBAC54DBBE34FBB" + $"17C46EBAEB0202C969B7CEC967B916CAFFB9E2543654324E3002025834563658" + $"36C877BD8FC969BB84C7ABBBF70604EAC2BD4448C111C32FC07FC362C17EC33C" + $"C0E5C37CC1E40205C5ADB861C65F31C52CB75E50204E224E20C3E2BA5FC37CB9" + $"50C455BB91C606BD02C494BCB6C723BE0DCB1BBDA8CB97BDE4C79EBBF702044E" + $"B44BC4D4284EB5174BB9B9C408B8BAC43EBAD855BD4F4BBBD057BD4FC745BB77" + $"C818BC3C51BAC502034E28C4A1B847C53AB61650BA52C593B8A0C691BBAFC4E1" + $"BAAB59BD8FC4E1B7A104032EB77BC613B63CC969B50AC7ABB778CB36BCA9C99C" + $"04032EB966B906B953B7D4B8D3B86DB9C7B749BAB82C0406BE0BB689BE67B5FD" + $"C04CB608BF7FB5F1C11CB689C1D7B65BC1A2B73BC2A3B85448B77BC33CB801C3" + $"1EB70849B609C32304032EBDA8B887BEB4B76EBE11B775BFEC2BC059B8AD0403" + $"2E28BE01B3FFC0D8B4253FB3D3C288B5BDC2FC0406FE0BC79EBB2BC8F6BBAAC8" + $"41BB48C9ECBC2FCB27BDDBCB06BD15CB41BE74CA4FC07FCA99BFCBCA0FC118C9" + $"CFC27DCA0FC1E4C998C30058C3890A04C6FFBB11C857BC50C8BDBCC3C88ABD4F" + $"040CAAFABABC70C74BC092C699C303C5CDC3DBC54DC441C4CEC44EC382C1EAC3" + $"03C237C34DC1D5C2EEC05FC402C14AC3E0BF76C423BD88C461BD48C4FABE47C5" + $"14BE2E4DBE98C58CBDBBC5870608BAAABFECC1FD4448C1FDC395C21DC362C1C4" + $"C3F1C11EC448C052C494C02CC3EFC105C389BED4C2BD0A04C369BC83C6D838C6" + $"66BD1CC35CBD350A03B46542B4BE41B4BE420605AF03B6AFC969B63DC9F2B72F" + $"C8D0BE4155B821CA8EC11CC6FAC42EC5C6C560C53ABE67C91DC1E8C7EAB86DCB" + $"270604EEBFCCBB51C1FDBBD0C13EBC43C29FBB6FC18BBAAB43BB1EC146BAF2C0" + $"9ABB4B0A0430303050505050302C0A0001021240BAB100000000000040B755C6" + $"CCDBBE997901178300040A0101020240BAB100000000000040B755C6CCDBBE99" + $"790A0201030240BAB100000000000040B755C6CCDBBE99790A030A0506070809" + $"0A0C0D040B0240BAB100000000000040B755C6CCDBBE99790A11011312408447" + $"3AE65BBB0539406A8F40BD7AC6ED3001178400040A00012712401CCA00000000" + $"00004031D6BEA7B4C5651401178100040A150112024046733A7FB6BABB054015" + $"08437714C3BB840A3B012E0A401CC92E6813AE6813401CC9C0B293C4BE831DFF" + $"0A11011412402E52374883B74883402E5243A84DC5C35901178200040A160115" + $"02402E52374883B74883402E5243A84DC5C3590A17011602402E52374883B748" + $"83402E5243A84DC5C3590A18011702402E52374883B74883402E5243A84DC5C3" + $"590A17011802402E52374883B74883402E5243A84DC5C3590A1801190240268F" + $"36C1F1B73CD33FA9DD442903C369B00A1B011A02402E52374883B74883402E52" + $"43A84DC5C3590A2C011B02402E52374883B74883402E5243A84DC5C3590A1101" + $"1C12402E52374883B74883402E5243A84DC5C35901178100040A20011D124018" + $"A13C2DD3BC6F843F776243040C3B35B701178400040A28011D024018A13C481B" + $"BC6F843FA13143AD0CC180CE0A27011E024018A13C3669BC6F843F850B43AD0C" + $"BDA6830A2603212022023F94B53C057BBC14913F373546DE4E423FFC0A2B0122" + $"02401CCA000000000000401CCAC64FB846E7CF0A2B01230241774E3E9634BD97" + $"FB40685AC6A141CA33220A0001291240075E0000000000004029CCC0DC88C59D" + $"5C01178100040A2E0124123E3A7739EBE1BA96D53D1E7BC874E948577D011784" + $"00040A360124023DE4F539818BBA43313CC9E6C7EFC848861D0A350125023DE4" + $"F539818BBA43313CC9E6C7EFC848861D0A340126023DE4F539D28CBA43313D0A" + $"55C7EFC8485E9A0A000128123FEA4E3675EFB6F2733F44E3440366C2D2660117" + $"8200040A00012A12402E52374883B74883402E5241C554C5CE0401178100040A" + $"00012B12401CCA000000000000401CCAC0623FC4B46E01178100040A00012C12" + $"403196000000000000401CCAC3AEA8C4B46E01178100040A3A012D02401CCA00" + $"0000000000401CCAC0E971C4B46E0A3C012F0A401CCA000000000000401CCAC0" + $"E971C4B46E1DFF0A3B01300A3FEC520000000000003C6A0B41051D473FEE1DFF" + $"0A3E01310240FA05000000000000417C4D3E5061C9E26E0A3F013212401CCA00" + $"0000000000401CCAC0E971C42D3C01178200040A4001330A401CCA0000000000" + $"00401CCAC0E971C4B46E1DFF0A42013402360000000000000000360000489000" + $"4AE8000A420134023600000000000000003600004870004AE8000A4301340236" + $"00000000000000003600004850004AF8000A4301340236000000000000000036" + $"00004870004AF8000A430134023600000000000000003600004890004AF8000A" + $"44013402360000000000000000360000485000466000" +}; + diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp new file mode 100644 index 0000000000..74b8d84fca --- /dev/null +++ b/src/apps/webpositive/LauncherApp.cpp @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2007 Ryan Leavengood + * Copyright (C) 2010 Stephan Aßmus + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "LauncherApp.h" + +#include "FrameView.h" +#include "GraphicsContext.h" +#include "LauncherWindow.h" +#include "WebProcess.h" +#include "WebView.h" +#include "WebViewConstants.h" + +#include +#include +#include +#include +#include +#include + +#include + +extern const char* kApplicationSignature = "application/x-vnd.RJL-HaikuLauncher"; +enum { + LOAD_AT_STARTING = 'lost' +}; + + +LauncherApp::LauncherApp() + : BApplication(kApplicationSignature) + , m_lastWindowFrame(100, 100, 700, 750) + , m_launchRefsMessage(0) + , m_initialized(false) +{ +} + +LauncherApp::~LauncherApp() +{ + delete m_launchRefsMessage; +} + +void LauncherApp::AboutRequested() +{ + BAlert* alert = new BAlert("About HaikuLauncher", + "For testing WebKit...\n\nby Ryan Leavengood", "Sweet!"); + alert->Go(); +} + +void LauncherApp::ArgvReceived(int32 argc, char** argv) +{ + for (int i = 1; i < argc; i++) { + BMessage message(LOAD_AT_STARTING); + message.AddString("url", argv[i]); + message.AddBool("new window", m_initialized || i > 1); + PostMessage(&message); + } +} + +void LauncherApp::ReadyToRun() +{ + WebProcess::initializeOnce(); + + BFile settingsFile; + BRect windowFrameFromSettings = m_lastWindowFrame; + if (openSettingsFile(settingsFile, B_READ_ONLY)) { + BMessage settingsArchive; + settingsArchive.Unflatten(&settingsFile); + settingsArchive.FindRect("window frame", &windowFrameFromSettings); + } + m_lastWindowFrame = windowFrameFromSettings; + + m_initialized = true; + + if (m_launchRefsMessage) { + RefsReceived(m_launchRefsMessage); + delete m_launchRefsMessage; + m_launchRefsMessage = 0; + } else { + LauncherWindow* window = new LauncherWindow(m_lastWindowFrame); + window->Show(); + } +} + +void LauncherApp::MessageReceived(BMessage* message) +{ + switch (message->what) { + case LOAD_AT_STARTING: { + BString url; + if (message->FindString("url", &url) != B_OK) + break; + bool newWindow; + if (message->FindBool("new window", &newWindow) != B_OK) + newWindow = false; + WebViewWindow* webWindow = NULL; + for (int i = 0; BWindow* window = WindowAt(i); i++) { + webWindow = dynamic_cast(window); + if (!webWindow) + continue; + if (!newWindow) { + // stop at the first window + break; + } + } + if (webWindow) { + // There should always be at least one window open. If not, maybe we are about + // to quit anyway... + if (newWindow) { + // open a new window with an offset to the last window + webWindow->newWindowRequested(url); + } else { + // load the URL in the first window + webWindow->webView()->loadRequest(url.String()); + } + } + break; + } + case B_SILENT_RELAUNCH: + newWindow(""); + break; + case NEW_WINDOW: { + BString url; + if (message->FindString("url", &url) != B_OK) + break; + newWindow(url); + break; + } + case WINDOW_OPENED: + m_windowCount++; + break; + case WINDOW_CLOSED: + m_windowCount--; + message->FindRect("window frame", &m_lastWindowFrame); + if (m_windowCount <= 0) + PostMessage(B_QUIT_REQUESTED); + break; + + default: + BApplication::MessageReceived(message); + break; + } +} + +void LauncherApp::RefsReceived(BMessage* message) +{ + if (!m_initialized) { + delete m_launchRefsMessage; + m_launchRefsMessage = new BMessage(*message); + return; + } + + entry_ref ref; + for (int32 i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) { + BEntry entry(&ref, true); + if (!entry.Exists()) + continue; + BPath path; + if (entry.GetPath(&path) != B_OK) + continue; + BString url; + url << path.Path(); + newWindow(url); + } +} + +bool LauncherApp::QuitRequested() +{ + for (int i = 0; BWindow* window = WindowAt(i); i++) { + WebViewWindow* webWindow = dynamic_cast(window); + if (!webWindow) + continue; + if (!webWindow->Lock()) + continue; + if (webWindow->QuitRequested()) { + m_lastWindowFrame = webWindow->Frame(); + webWindow->Quit(); + i--; + } else { + webWindow->Unlock(); + return false; + } + } + + BFile settingsFile; + if (openSettingsFile(settingsFile, B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) { + BMessage settingsArchive; + settingsArchive.AddRect("window frame", m_lastWindowFrame); + settingsArchive.Flatten(&settingsFile); + } + + return true; +} + +bool LauncherApp::openSettingsFile(BFile& file, uint32 mode) +{ + BPath path; + if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK + || path.Append("HaikuLauncher") != B_OK) { + return false; + } + return file.SetTo(path.Path(), mode) == B_OK; +} + +void LauncherApp::newWindow(const BString& url) +{ + m_lastWindowFrame.OffsetBy(20, 20); + if (!BScreen().Frame().Contains(m_lastWindowFrame)) + m_lastWindowFrame.OffsetTo(50, 50); + + LauncherWindow* window = new LauncherWindow(m_lastWindowFrame); + window->Show(); + if (url.Length()) + window->webView()->loadRequest(url.String()); +} + +// #pragma mark - + +int main(int, char**) +{ + new LauncherApp(); + be_app->Run(); + delete be_app; + + return 0; +} + diff --git a/src/apps/webpositive/LauncherApp.h b/src/apps/webpositive/LauncherApp.h new file mode 100644 index 0000000000..8afdfc4192 --- /dev/null +++ b/src/apps/webpositive/LauncherApp.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2007 Ryan Leavengood + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LauncherApp_h +#define LauncherApp_h + +#include +#include + +class BFile; +class LauncherWindow; + +class LauncherApp : public BApplication { +public: + LauncherApp(); + virtual ~LauncherApp(); + + virtual void AboutRequested(); + virtual void ArgvReceived(int32, char**); + virtual void MessageReceived(BMessage*); + virtual void RefsReceived(BMessage*); + virtual void ReadyToRun(); + virtual bool QuitRequested(); + +private: + bool openSettingsFile(BFile& file, uint32 mode); + void newWindow(const BString& url); + + int m_windowCount; + BRect m_lastWindowFrame; + BMessage* m_launchRefsMessage; + bool m_initialized; +}; + +extern const char* kApplicationSignature; + +#endif // LauncherApp_h + diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp new file mode 100644 index 0000000000..2407f34b45 --- /dev/null +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -0,0 +1,354 @@ +/* + * Copyright (C) 2007 Andrea Anzani + * Copyright (C) 2007 Ryan Leavengood + * Copyright (C) 2009 Maxime Simon + * Copyright (C) 2010 Stephan Aßmus + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "LauncherWindow.h" + +#include "WebView.h" +#include "WebViewConstants.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +enum { + GO_BACK = 'goba', + GO_FORWARD = 'gofo', + GOTO_URL = 'goul', + RELOAD = 'reld', + + TEXT_SIZE_INCREASE = 'tsin', + TEXT_SIZE_DECREASE = 'tsdc', + TEXT_SIZE_RESET = 'tsrs', + + TEXT_SHOW_FIND_GROUP = 'sfnd', + TEXT_HIDE_FIND_GROUP = 'hfnd', + TEXT_FIND_NEXT = 'fndn', + TEXT_FIND_PREVIOUS = 'fndp' +}; + +using namespace WebCore; + +static BLayoutItem* layoutItemFor(BView* view) +{ + BLayout* layout = view->Parent()->GetLayout(); + int32 index = layout->IndexOfView(view); + return layout->ItemAt(index); +} + +LauncherWindow::LauncherWindow(BRect frame, ToolbarPolicy toolbarPolicy) + : WebViewWindow(frame, "HaikuLauncher", + B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, + B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) +{ + if (toolbarPolicy == HaveToolbar) { + // Menu + m_menuBar = new BMenuBar("Main menu"); + BMenu* menu = new BMenu("Window"); + BMessage* newWindowMessage = new BMessage(NEW_WINDOW); + newWindowMessage->AddString("url", ""); + BMenuItem* newItem = new BMenuItem("New", newWindowMessage, 'N'); + menu->AddItem(newItem); + newItem->SetTarget(be_app); + menu->AddItem(new BMenuItem("Close", new BMessage(B_QUIT_REQUESTED), 'W')); + menu->AddSeparatorItem(); + BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); + menu->AddItem(quitItem); + quitItem->SetTarget(be_app); + m_menuBar->AddItem(menu); + + menu = new BMenu("Text"); + menu->AddItem(new BMenuItem("Find", new BMessage(TEXT_SHOW_FIND_GROUP), 'F')); + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("Increase size", new BMessage(TEXT_SIZE_INCREASE), '+')); + menu->AddItem(new BMenuItem("Decrease size", new BMessage(TEXT_SIZE_DECREASE), '-')); + menu->AddItem(new BMenuItem("Reset size", new BMessage(TEXT_SIZE_RESET), '0')); + m_menuBar->AddItem(menu); + + // Back & Forward + m_BackButton = new BButton("", "Back", new BMessage(GO_BACK)); + m_ForwardButton = new BButton("", "Forward", new BMessage(GO_FORWARD)); + + // URL + m_url = new BTextControl("url", "", "", new BMessage(GOTO_URL)); + m_url->SetDivider(50.0); + + // Go + BButton* button = new BButton("", "Go", new BMessage(RELOAD)); + + // Status Bar + m_statusText = new BStringView("status", ""); + m_statusText->SetAlignment(B_ALIGN_LEFT); + m_statusText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); + m_statusText->SetExplicitMinSize(BSize(150, 16)); + // Prevent the window from growing to fit a long status message... + BFont font(be_plain_font); + font.SetSize(ceilf(font.Size() * 0.8)); + m_statusText->SetFont(&font, B_FONT_SIZE); + + // Loading progress bar + m_loadingProgressBar = new BStatusBar("progress"); + m_loadingProgressBar->SetMaxValue(100); + m_loadingProgressBar->Hide(); + m_loadingProgressBar->SetBarHeight(10); + + const float kInsetSpacing = 5; + const float kElementSpacing = 7; + + m_findTextControl = new BTextControl("find", "Find:", "", + new BMessage(TEXT_FIND_NEXT)); + m_findCaseSensitiveCheckBox = new BCheckBox("Match case"); + BView* findGroup = BGroupLayoutBuilder(B_VERTICAL) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) + .Add(m_findTextControl) + .Add(new BButton("Previous", new BMessage(TEXT_FIND_PREVIOUS))) + .Add(new BButton("Next", new BMessage(TEXT_FIND_NEXT))) + .Add(m_findCaseSensitiveCheckBox) + .Add(BSpaceLayoutItem::CreateGlue()) + .Add(new BButton("Close", new BMessage(TEXT_HIDE_FIND_GROUP))) + .SetInsets(kInsetSpacing, kInsetSpacing, + kInsetSpacing, kInsetSpacing) + ) + ; + // Layout + AddChild(BGroupLayoutBuilder(B_VERTICAL) + .Add(m_menuBar) + .Add(BGridLayoutBuilder(kElementSpacing, kElementSpacing) + .Add(m_BackButton, 0, 0) + .Add(m_ForwardButton, 1, 0) + .Add(m_url, 2, 0) + .Add(button, 3, 0) + .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) + ) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(webView()) + .Add(findGroup) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) + .Add(m_statusText) + .Add(m_loadingProgressBar, 0.2) + .SetInsets(kInsetSpacing, 0, kInsetSpacing, 0) + ) + ); + + m_url->MakeFocus(true); + + m_findGroup = layoutItemFor(findGroup); + } else { + m_BackButton = 0; + m_ForwardButton = 0; + m_url = 0; + m_menuBar = 0; + m_statusText = 0; + m_loadingProgressBar = 0; + + AddChild(BGroupLayoutBuilder(B_VERTICAL, 7) + .Add(webView()) + ); + } + + m_findGroup->SetVisible(false); + + AddShortcut('G', B_COMMAND_KEY, new BMessage(TEXT_FIND_NEXT)); + AddShortcut('G', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_FIND_PREVIOUS)); + AddShortcut('F', B_COMMAND_KEY, new BMessage(TEXT_SHOW_FIND_GROUP)); + AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_HIDE_FIND_GROUP)); + + navigationCapabilitiesChanged(false, false, false); + + be_app->PostMessage(WINDOW_OPENED); +} + +LauncherWindow::~LauncherWindow() +{ +} + +void LauncherWindow::MessageReceived(BMessage* message) +{ + switch (message->what) { + case RELOAD: + webView()->loadRequest(m_url->Text()); + break; + case GOTO_URL: + if (m_loadedURL != m_url->Text()) + webView()->loadRequest(m_url->Text()); + break; + case GO_BACK: + webView()->goBack(); + break; + case GO_FORWARD: + webView()->goForward(); + break; + + case TEXT_SIZE_INCREASE: + webView()->increaseTextSize(); + break; + case TEXT_SIZE_DECREASE: + webView()->decreaseTextSize(); + break; + case TEXT_SIZE_RESET: + webView()->resetTextSize(); + break; + + case TEXT_FIND_NEXT: + webView()->findString(m_findTextControl->Text(), true, + m_findCaseSensitiveCheckBox->Value()); + break; + case TEXT_FIND_PREVIOUS: + webView()->findString(m_findTextControl->Text(), false, + m_findCaseSensitiveCheckBox->Value()); + break; + case TEXT_SHOW_FIND_GROUP: + if (!m_findGroup->IsVisible()) + m_findGroup->SetVisible(true); + m_findTextControl->MakeFocus(true); + break; + case TEXT_HIDE_FIND_GROUP: + if (m_findGroup->IsVisible()) + m_findGroup->SetVisible(false); + break; + + default: + WebViewWindow::MessageReceived(message); + break; + } +} + +bool LauncherWindow::QuitRequested() +{ + if (WebViewWindow::QuitRequested()) { + BMessage message(WINDOW_CLOSED); + message.AddRect("window frame", Frame()); + be_app->PostMessage(&message); + return true; + } + return false; +} + +// #pragma mark - Notification API + +void LauncherWindow::navigationRequested(const BString& url) +{ + m_loadedURL = url; + if (m_url) + m_url->SetText(url.String()); +} + +void LauncherWindow::newWindowRequested(const BString& url) +{ + // Always open new windows in the application thread, since + // creating a WebView will try to grab the application lock. + // But our own WebProcess may already try to lock us from within + // the application thread -> dead-lock. + BMessage message(NEW_WINDOW); + message.AddString("url", url); + be_app->PostMessage(&message); +} + +void LauncherWindow::loadNegociating(const BString& url) +{ + BString status("Requesting: "); + status << url; + statusChanged(status); +} + +void LauncherWindow::loadTransfering(const BString& url) +{ + BString status("Loading: "); + status << url; + statusChanged(status); +} + +void LauncherWindow::loadProgress(float progress) +{ + if (m_loadingProgressBar) { + if (progress < 100 && m_loadingProgressBar->IsHidden()) + m_loadingProgressBar->Show(); + m_loadingProgressBar->SetTo(progress); + } +} + +void LauncherWindow::loadFailed(const BString& url) +{ + BString status(url); + status << " failed."; + statusChanged(status); + if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) + m_loadingProgressBar->Hide(); +} + +void LauncherWindow::loadFinished(const BString& url) +{ + m_loadedURL = url; + BString status(url); + status << " finished."; + statusChanged(status); + if (m_url) + m_url->SetText(url.String()); + if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) + m_loadingProgressBar->Hide(); +} + +void LauncherWindow::titleChanged(const BString& title) +{ + BString windowTitle = title; + if (windowTitle.Length() > 0) + windowTitle << " - "; + windowTitle << "HaikuLauncher"; + SetTitle(windowTitle.String()); +} + +void LauncherWindow::statusChanged(const BString& statusText) +{ + if (m_statusText) + m_statusText->SetText(statusText.String()); +} + +void LauncherWindow::navigationCapabilitiesChanged(bool canGoBackward, + bool canGoForward, bool canStop) +{ + if (m_BackButton) + m_BackButton->SetEnabled(canGoBackward); + if (m_ForwardButton) + m_ForwardButton->SetEnabled(canGoForward); +} diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h new file mode 100644 index 0000000000..6d5dab8721 --- /dev/null +++ b/src/apps/webpositive/LauncherWindow.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2007 Ryan Leavengood + * Copyright (C) 2009 Maxime Simon + * Copyright (C) 2010 Stephan Aßmus + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LauncherWindow_h +#define LauncherWindow_h + +#include "WebViewWindow.h" +#include + +class BButton; +class BCheckBox; +class BLayoutItem; +class BMenu; +class BStatusBar; +class BStringView; +class BTextControl; +class WebView; + +enum ToolbarPolicy { + HaveToolbar, + DoNotHaveToolbar +}; + +enum { + NEW_WINDOW = 'nwnd', + WINDOW_OPENED = 'wndo', + WINDOW_CLOSED = 'wndc' +}; + +class LauncherWindow : public WebViewWindow { +public: + LauncherWindow(BRect frame, ToolbarPolicy = HaveToolbar); + virtual ~LauncherWindow(); + + virtual void MessageReceived(BMessage* message); + virtual bool QuitRequested(); + + // WebViewWindow notification API implementations + virtual void navigationRequested(const BString& url); + virtual void newWindowRequested(const BString& url); + virtual void loadNegociating(const BString& url); + virtual void loadTransfering(const BString& url); + virtual void loadProgress(float progress); + virtual void loadFailed(const BString& url); + virtual void loadFinished(const BString& url); + virtual void titleChanged(const BString& title); + virtual void statusChanged(const BString& status); + virtual void navigationCapabilitiesChanged(bool canGoBackward, + bool canGoForward, bool canStop); + +private: + BMenuBar* m_menuBar; + BButton* m_BackButton; + BButton* m_ForwardButton; + BTextControl* m_url; + BString m_loadedURL; + BStringView* m_statusText; + BStatusBar* m_loadingProgressBar; + BLayoutItem* m_findGroup; + BTextControl* m_findTextControl; + BCheckBox* m_findCaseSensitiveCheckBox; +}; + +#endif // LauncherWindow_h + diff --git a/src/apps/webpositive/LeakTracker.h b/src/apps/webpositive/LeakTracker.h new file mode 100644 index 0000000000..c00b5d1cd8 --- /dev/null +++ b/src/apps/webpositive/LeakTracker.h @@ -0,0 +1,119 @@ +#ifndef LeakTracker_h +#define LeakTracker_h + +// This code is from: +// http://www.flipcode.com/archives/How_To_Find_Memory_Leaks.shtml +// I have modified it some. + +#ifndef NDEBUG + +#if __GNUC__ > 2 + #include + using namespace std; +#endif + +#include +#include + +typedef struct { + int address; + size_t size; + char file[64]; + int line; +} ALLOC_INFO; + +typedef vector AllocList; + +AllocList *allocList; + +void AddTrack(int addr, size_t asize, const char *fname, int lnum) +{ + ALLOC_INFO *info; + + if (!allocList) + allocList = new(AllocList); + + info = new(ALLOC_INFO); + info->address = addr; + strncpy(info->file, fname, 63); + info->line = lnum; + info->size = asize; + allocList->insert(allocList->begin(), info); +}; + +void RemoveTrack(int addr) +{ + AllocList::iterator i; + + if (!allocList) + return; + + for (i = allocList->begin(); i < allocList->end(); i++) { + if ((*i)->address == addr) { + allocList->erase(i); + break; + } + } +}; + +int unfreedCount() +{ + return allocList->size(); +} + +bool nothingUnfreed() +{ + return allocList->empty(); +} + +void OutputDebugString(char *str) +{ + printf(str); +} + +void DumpUnfreed() +{ + AllocList::iterator i; + int totalSize = 0; + char buf[1024]; + + if (!allocList) + return; + + for (i = allocList->begin(); i < allocList->end(); i++) { + sprintf(buf, "%-50s:\t\tLINE %d,\t\tADDRESS %d\t%d unfreed\n", + (*i)->file, (*i)->line, (*i)->address, (int)(*i)->size); + OutputDebugString(buf); + totalSize += (*i)->size; + } + sprintf(buf, "-----------------------------------------------------------\n"); + OutputDebugString(buf); + sprintf(buf, "Total Unfreed: %d bytes\n", totalSize); + OutputDebugString(buf); +}; + +inline void *operator new(size_t size, const char *file, int line) +{ + void *ptr = (void *)malloc(size); + AddTrack((int)ptr, size, file, line); + return(ptr); +}; + +inline void operator delete(void *p) throw() +{ + RemoveTrack((int)p); + free(p); +}; + +#define DEBUG_NEW new(__FILE__, __LINE__) + +#else +#define DEBUG_NEW new +#endif + + +#define new DEBUG_NEW + + +#endif // LeakTracker_h + From d04f705dfcd06a671fb796f8e1a3a7eef9b5f75b Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 12 Feb 2010 12:29:04 +0000 Subject: [PATCH 002/349] Introduced API for setting the caching policy in WebProcess, and used it LauncherApp. The values/code come straight from the GTK port. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@47 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherApp.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 74b8d84fca..fab6e75589 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -84,6 +84,7 @@ void LauncherApp::ArgvReceived(int32 argc, char** argv) void LauncherApp::ReadyToRun() { WebProcess::initializeOnce(); + WebProcess::setCacheModel(WEBKIT_CACHE_MODEL_WEB_BROWSER); BFile settingsFile; BRect windowFrameFromSettings = m_lastWindowFrame; From c08684de2a6d9c5358fac5e93dc8a0081ce649b5 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 12 Feb 2010 17:43:55 +0000 Subject: [PATCH 003/349] Removed no longer needed and supposedly non working LeakTracker. On top of this, WebCore already has it's own LeakTracker enabled in debug builds. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@52 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LeakTracker.h | 119 ----------------------------- 1 file changed, 119 deletions(-) delete mode 100644 src/apps/webpositive/LeakTracker.h diff --git a/src/apps/webpositive/LeakTracker.h b/src/apps/webpositive/LeakTracker.h deleted file mode 100644 index c00b5d1cd8..0000000000 --- a/src/apps/webpositive/LeakTracker.h +++ /dev/null @@ -1,119 +0,0 @@ -#ifndef LeakTracker_h -#define LeakTracker_h - -// This code is from: -// http://www.flipcode.com/archives/How_To_Find_Memory_Leaks.shtml -// I have modified it some. - -#ifndef NDEBUG - -#if __GNUC__ > 2 - #include - using namespace std; -#endif - -#include -#include - -typedef struct { - int address; - size_t size; - char file[64]; - int line; -} ALLOC_INFO; - -typedef vector AllocList; - -AllocList *allocList; - -void AddTrack(int addr, size_t asize, const char *fname, int lnum) -{ - ALLOC_INFO *info; - - if (!allocList) - allocList = new(AllocList); - - info = new(ALLOC_INFO); - info->address = addr; - strncpy(info->file, fname, 63); - info->line = lnum; - info->size = asize; - allocList->insert(allocList->begin(), info); -}; - -void RemoveTrack(int addr) -{ - AllocList::iterator i; - - if (!allocList) - return; - - for (i = allocList->begin(); i < allocList->end(); i++) { - if ((*i)->address == addr) { - allocList->erase(i); - break; - } - } -}; - -int unfreedCount() -{ - return allocList->size(); -} - -bool nothingUnfreed() -{ - return allocList->empty(); -} - -void OutputDebugString(char *str) -{ - printf(str); -} - -void DumpUnfreed() -{ - AllocList::iterator i; - int totalSize = 0; - char buf[1024]; - - if (!allocList) - return; - - for (i = allocList->begin(); i < allocList->end(); i++) { - sprintf(buf, "%-50s:\t\tLINE %d,\t\tADDRESS %d\t%d unfreed\n", - (*i)->file, (*i)->line, (*i)->address, (int)(*i)->size); - OutputDebugString(buf); - totalSize += (*i)->size; - } - sprintf(buf, "-----------------------------------------------------------\n"); - OutputDebugString(buf); - sprintf(buf, "Total Unfreed: %d bytes\n", totalSize); - OutputDebugString(buf); -}; - -inline void *operator new(size_t size, const char *file, int line) -{ - void *ptr = (void *)malloc(size); - AddTrack((int)ptr, size, file, line); - return(ptr); -}; - -inline void operator delete(void *p) throw() -{ - RemoveTrack((int)p); - free(p); -}; - -#define DEBUG_NEW new(__FILE__, __LINE__) - -#else -#define DEBUG_NEW new -#endif - - -#define new DEBUG_NEW - - -#endif // LeakTracker_h - From 4b059d47cd6434ee931e315b9f7698fb532ca42a Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 12 Feb 2010 21:16:25 +0000 Subject: [PATCH 004/349] First basic GUI download progress display... git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@54 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 69 ++++++++++++++++++++++++- src/apps/webpositive/DownloadWindow.h | 5 ++ src/apps/webpositive/LauncherApp.cpp | 10 +++- src/apps/webpositive/LauncherApp.h | 3 ++ src/apps/webpositive/LauncherWindow.cpp | 6 ++- src/apps/webpositive/LauncherWindow.h | 3 +- 6 files changed, 91 insertions(+), 5 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index b27acf86a9..d6b932d6a5 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -28,6 +28,8 @@ #include "config.h" #include "DownloadWindow.h" +#include "WebDownload.h" +#include "WebProcess.h" #include #include #include @@ -35,7 +37,7 @@ #include #include #include - +#include #include DownloadWindow::DownloadWindow(BRect frame) @@ -43,6 +45,7 @@ DownloadWindow::DownloadWindow(BRect frame) B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE) { + SetLayout(new BGroupLayout(B_VERTICAL)); Minimize(true); Show(); } @@ -54,6 +57,18 @@ DownloadWindow::~DownloadWindow() void DownloadWindow::MessageReceived(BMessage* message) { switch (message->what) { + case DOWNLOAD_ADDED: { + WebDownload* download; + if (message->FindPointer("download", reinterpret_cast(&download)) == B_OK) + downloadStarted(download); + break; + } + case DOWNLOAD_REMOVED: { + WebDownload* download; + if (message->FindPointer("download", reinterpret_cast(&download)) == B_OK) + downloadFinished(download); + break; + } default: BWindow::MessageReceived(message); break; @@ -66,3 +81,55 @@ bool DownloadWindow::QuitRequested() Minimize(true); return false; } + +class DownloadProgressView : public BGroupView { +public: + DownloadProgressView(WebDownload* download) + : BGroupView(B_HORIZONTAL) + , m_download(download) + , m_expectedSize(download->expectedSize()) + { + GroupLayout()->SetInsets(5, 5, 5, 5); + m_statusBar = new BStatusBar("download progress", download->filename().String()); + m_statusBar->SetMaxValue(100); + AddChild(m_statusBar); + } + + virtual void AttachedToWindow() + { + m_download->setProgressListener(BMessenger(this)); + } + + virtual void MessageReceived(BMessage* message) + { + switch (message->what) { + case WebDownload::DOWNLOAD_PROGRESS: { + float progress; + if (message->FindFloat("progress", &progress) == B_OK) + m_statusBar->SetTo(progress); + break; + } + default: + BGroupView::MessageReceived(message); + } + } + + WebDownload* download() const + { + return m_download; + } + +private: + BStatusBar* m_statusBar; + WebDownload* m_download; + off_t m_expectedSize; +}; + +void DownloadWindow::downloadStarted(WebDownload* download) +{ + AddChild(new DownloadProgressView(download)); +} + +void DownloadWindow::downloadFinished(WebDownload* download) +{ +} diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index d263ddf387..dc652f7442 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -30,6 +30,8 @@ #include +class WebDownload; + class DownloadWindow : public BWindow { public: DownloadWindow(BRect frame); @@ -38,6 +40,9 @@ public: virtual void MessageReceived(BMessage*); virtual bool QuitRequested(); + void downloadStarted(WebDownload* download); + void downloadFinished(WebDownload* download); + private: }; diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index fab6e75589..403e750055 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -29,6 +29,7 @@ #include "config.h" #include "LauncherApp.h" +#include "DownloadWindow.h" #include "FrameView.h" #include "GraphicsContext.h" #include "LauncherWindow.h" @@ -56,6 +57,7 @@ LauncherApp::LauncherApp() , m_lastWindowFrame(100, 100, 700, 750) , m_launchRefsMessage(0) , m_initialized(false) + , m_downloadWindow(0) { } @@ -86,6 +88,8 @@ void LauncherApp::ReadyToRun() WebProcess::initializeOnce(); WebProcess::setCacheModel(WEBKIT_CACHE_MODEL_WEB_BROWSER); + m_downloadWindow = new DownloadWindow(BRect(100, 100, 300, 250)); + BFile settingsFile; BRect windowFrameFromSettings = m_lastWindowFrame; if (openSettingsFile(settingsFile, B_READ_ONLY)) { @@ -102,7 +106,8 @@ void LauncherApp::ReadyToRun() delete m_launchRefsMessage; m_launchRefsMessage = 0; } else { - LauncherWindow* window = new LauncherWindow(m_lastWindowFrame); + LauncherWindow* window = new LauncherWindow(m_lastWindowFrame, + BMessenger(m_downloadWindow)); window->Show(); } } @@ -232,7 +237,8 @@ void LauncherApp::newWindow(const BString& url) if (!BScreen().Frame().Contains(m_lastWindowFrame)) m_lastWindowFrame.OffsetTo(50, 50); - LauncherWindow* window = new LauncherWindow(m_lastWindowFrame); + LauncherWindow* window = new LauncherWindow(m_lastWindowFrame, + BMessenger(m_downloadWindow)); window->Show(); if (url.Length()) window->webView()->loadRequest(url.String()); diff --git a/src/apps/webpositive/LauncherApp.h b/src/apps/webpositive/LauncherApp.h index 8afdfc4192..f7efb72dcb 100644 --- a/src/apps/webpositive/LauncherApp.h +++ b/src/apps/webpositive/LauncherApp.h @@ -32,6 +32,7 @@ #include class BFile; +class DownloadWindow; class LauncherWindow; class LauncherApp : public BApplication { @@ -54,6 +55,8 @@ private: BRect m_lastWindowFrame; BMessage* m_launchRefsMessage; bool m_initialized; + + DownloadWindow* m_downloadWindow; }; extern const char* kApplicationSignature; diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 2407f34b45..0a171db2bd 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -31,6 +31,7 @@ #include "config.h" #include "LauncherWindow.h" +#include "WebProcess.h" #include "WebView.h" #include "WebViewConstants.h" @@ -75,7 +76,8 @@ static BLayoutItem* layoutItemFor(BView* view) return layout->ItemAt(index); } -LauncherWindow::LauncherWindow(BRect frame, ToolbarPolicy toolbarPolicy) +LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, + ToolbarPolicy toolbarPolicy) : WebViewWindow(frame, "HaikuLauncher", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) @@ -187,6 +189,8 @@ LauncherWindow::LauncherWindow(BRect frame, ToolbarPolicy toolbarPolicy) ); } + webView()->webProcess()->setDownloadListener(downloadListener); + m_findGroup->SetVisible(false); AddShortcut('G', B_COMMAND_KEY, new BMessage(TEXT_FIND_NEXT)); diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index 6d5dab8721..46fde08bac 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -55,7 +55,8 @@ enum { class LauncherWindow : public WebViewWindow { public: - LauncherWindow(BRect frame, ToolbarPolicy = HaveToolbar); + LauncherWindow(BRect frame, const BMessenger& downloadListener, + ToolbarPolicy = HaveToolbar); virtual ~LauncherWindow(); virtual void MessageReceived(BMessage* message); From 7a40c9757e509a9e04d288ca40872c0efdcc8538 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 13 Feb 2010 00:29:06 +0000 Subject: [PATCH 005/349] Make the Download Window accessible from every window. Bring it to the workspace that the window is on that send the request to show it. Remember the size and if it was showing across sessions. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@56 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 5 +++-- src/apps/webpositive/DownloadWindow.h | 2 +- src/apps/webpositive/LauncherApp.cpp | 27 +++++++++++++++++++++---- src/apps/webpositive/LauncherWindow.cpp | 7 +++++++ src/apps/webpositive/LauncherWindow.h | 3 ++- 5 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index d6b932d6a5..a90b919fd7 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -40,13 +40,14 @@ #include #include -DownloadWindow::DownloadWindow(BRect frame) +DownloadWindow::DownloadWindow(BRect frame, bool visible) : BWindow(frame, "Downloads", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE) { SetLayout(new BGroupLayout(B_VERTICAL)); - Minimize(true); + if (!visible) + Minimize(true); Show(); } diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index dc652f7442..66e88b2940 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -34,7 +34,7 @@ class WebDownload; class DownloadWindow : public BWindow { public: - DownloadWindow(BRect frame); + DownloadWindow(BRect frame, bool visible); virtual ~DownloadWindow(); virtual void MessageReceived(BMessage*); diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 403e750055..84a338ff07 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -36,14 +36,13 @@ #include "WebProcess.h" #include "WebView.h" #include "WebViewConstants.h" - #include +#include #include #include #include #include #include - #include extern const char* kApplicationSignature = "application/x-vnd.RJL-HaikuLauncher"; @@ -88,17 +87,21 @@ void LauncherApp::ReadyToRun() WebProcess::initializeOnce(); WebProcess::setCacheModel(WEBKIT_CACHE_MODEL_WEB_BROWSER); - m_downloadWindow = new DownloadWindow(BRect(100, 100, 300, 250)); - BFile settingsFile; BRect windowFrameFromSettings = m_lastWindowFrame; + BRect downloadWindowFrame(100, 100, 300, 250); + bool showDownloads = false; if (openSettingsFile(settingsFile, B_READ_ONLY)) { BMessage settingsArchive; settingsArchive.Unflatten(&settingsFile); settingsArchive.FindRect("window frame", &windowFrameFromSettings); + settingsArchive.FindRect("downloads window frame", &downloadWindowFrame); + settingsArchive.FindBool("show downloads", &showDownloads); } m_lastWindowFrame = windowFrameFromSettings; + m_downloadWindow = new DownloadWindow(downloadWindowFrame, showDownloads); + m_initialized = true; if (m_launchRefsMessage) { @@ -165,6 +168,17 @@ void LauncherApp::MessageReceived(BMessage* message) PostMessage(B_QUIT_REQUESTED); break; + case SHOW_DOWNLOAD_WINDOW: { + BAutolock _(m_downloadWindow); + uint32 workspaces; + if (message->FindUInt32("workspaces", &workspaces) == B_OK) + m_downloadWindow->SetWorkspaces(workspaces); + if (m_downloadWindow->IsMinimized()) + m_downloadWindow->Minimize(false); + else + m_downloadWindow->Activate(); + } + default: BApplication::MessageReceived(message); break; @@ -215,6 +229,11 @@ bool LauncherApp::QuitRequested() if (openSettingsFile(settingsFile, B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) { BMessage settingsArchive; settingsArchive.AddRect("window frame", m_lastWindowFrame); + if (m_downloadWindow->Lock()) { + settingsArchive.AddRect("downloads window frame", m_downloadWindow->Frame()); + settingsArchive.AddBool("show downloads", !m_downloadWindow->IsMinimized()); + m_downloadWindow->Unlock(); + } settingsArchive.Flatten(&settingsFile); } diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 0a171db2bd..bc9c3970c4 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -93,6 +93,8 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, newItem->SetTarget(be_app); menu->AddItem(new BMenuItem("Close", new BMessage(B_QUIT_REQUESTED), 'W')); menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("Show Downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'D')); + menu->AddSeparatorItem(); BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); menu->AddItem(quitItem); quitItem->SetTarget(be_app); @@ -252,6 +254,11 @@ void LauncherWindow::MessageReceived(BMessage* message) m_findGroup->SetVisible(false); break; + case SHOW_DOWNLOAD_WINDOW: + message->AddUInt32("workspaces", Workspaces()); + be_app->PostMessage(message); + break; + default: WebViewWindow::MessageReceived(message); break; diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index 46fde08bac..0760fc4280 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -50,7 +50,8 @@ enum ToolbarPolicy { enum { NEW_WINDOW = 'nwnd', WINDOW_OPENED = 'wndo', - WINDOW_CLOSED = 'wndc' + WINDOW_CLOSED = 'wndc', + SHOW_DOWNLOAD_WINDOW = 'sdwd' }; class LauncherWindow : public WebViewWindow { From dd275f312a4c3579e3f2e8a20eecf8607ea655f5 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 13 Feb 2010 01:31:54 +0000 Subject: [PATCH 006/349] More work on the download window GUI. The scroll view is broken, downloads are not persistent. Resolved TODO in WebProcess about race condition when dispatching download notifications. Just block until there is a reply. WebDownload pointers are just used for extracting information at init time, and then later only as cookie to match view and download. Although as soon as we want to cancel downloads, refcounting may become necessary again. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@57 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 72 ++++++++++++++++++++++++- src/apps/webpositive/DownloadWindow.h | 6 +++ 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index a90b919fd7..b1ad727782 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -30,22 +30,56 @@ #include "WebDownload.h" #include "WebProcess.h" +#include #include #include #include #include #include +#include #include #include #include #include +enum { + REMOVE_FINISHED_DOWNLOADS = 'rmfd' +}; + DownloadWindow::DownloadWindow(BRect frame, bool visible) : BWindow(frame, "Downloads", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE) { SetLayout(new BGroupLayout(B_VERTICAL)); + + BGroupView* downloadsGroupView = new BGroupView(B_VERTICAL); + downloadsGroupView->SetViewColor(245, 245, 245); + m_downloadViewsLayout = downloadsGroupView->GroupLayout(); + + BMenuBar* menuBar = new BMenuBar("Menu bar"); + BMenu* menu = new BMenu("Window"); + menu->AddItem(new BMenuItem("Minimize", new BMessage(B_QUIT_REQUESTED), 'M')); + menuBar->AddItem(menu); + + BScrollView* scrollView = new BScrollView("Downloads scroll view", + downloadsGroupView, 0, false, true, B_NO_BORDER); + + m_removeFinishedButton = new BButton("Remove finished", + new BMessage(REMOVE_FINISHED_DOWNLOADS)); + m_removeFinishedButton->SetEnabled(false); + + AddChild(BGroupLayoutBuilder(B_VERTICAL) + .Add(menuBar) + .Add(scrollView) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(BGroupLayoutBuilder(B_HORIZONTAL) + .AddGlue() + .Add(m_removeFinishedButton) + .SetInsets(5, 5, 5, 5) + ) + ); + if (!visible) Minimize(true); Show(); @@ -70,6 +104,9 @@ void DownloadWindow::MessageReceived(BMessage* message) downloadFinished(download); break; } + case REMOVE_FINISHED_DOWNLOADS: + removeFinishedDownloads(); + break; default: BWindow::MessageReceived(message); break; @@ -90,6 +127,7 @@ public: , m_download(download) , m_expectedSize(download->expectedSize()) { + SetViewColor(245, 245, 245); GroupLayout()->SetInsets(5, 5, 5, 5); m_statusBar = new BStatusBar("download progress", download->filename().String()); m_statusBar->SetMaxValue(100); @@ -120,6 +158,11 @@ public: return m_download; } + void downloadFinished() + { + m_download = NULL; + } + private: BStatusBar* m_statusBar; WebDownload* m_download; @@ -128,9 +171,36 @@ private: void DownloadWindow::downloadStarted(WebDownload* download) { - AddChild(new DownloadProgressView(download)); + m_downloadViewsLayout->AddView(new DownloadProgressView(download)); } void DownloadWindow::downloadFinished(WebDownload* download) { + int32 finishedCount = 0; + for (int32 i = 0; BLayoutItem* item = m_downloadViewsLayout->ItemAt(i); i++) { + DownloadProgressView* view = dynamic_cast(item->View()); + if (!view) + continue; + if (view->download() == download) { + view->downloadFinished(); + finishedCount++; + } else if (!view->download()) + finishedCount++; + } + m_removeFinishedButton->SetEnabled(finishedCount > 0); +} + +void DownloadWindow::removeFinishedDownloads() +{ + for (int32 i = m_downloadViewsLayout->CountItems() - 1; + BLayoutItem* item = m_downloadViewsLayout->ItemAt(i); i--) { + DownloadProgressView* view = dynamic_cast(item->View()); + if (!view) + continue; + if (!view->download()) { + view->RemoveSelf(); + delete view; + } + } + m_removeFinishedButton->SetEnabled(false); } diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index 66e88b2940..bd370adb17 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -30,6 +30,8 @@ #include +class BButton; +class BGroupLayout; class WebDownload; class DownloadWindow : public BWindow { @@ -40,10 +42,14 @@ public: virtual void MessageReceived(BMessage*); virtual bool QuitRequested(); +private: void downloadStarted(WebDownload* download); void downloadFinished(WebDownload* download); + void removeFinishedDownloads(); private: + BGroupLayout* m_downloadViewsLayout; + BButton* m_removeFinishedButton; }; #endif // DownloadWindow_h From a8d8342dfa61a46c9066df6a7212d641ab71c28c Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 13 Feb 2010 12:51:58 +0000 Subject: [PATCH 007/349] * DownloadWindow is now very usable. * Fixed the scroll view look and behavior. * Downloads are persistent. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@59 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 399 ++++++++++++++++++++---- src/apps/webpositive/DownloadWindow.h | 4 + 2 files changed, 348 insertions(+), 55 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index b1ad727782..0b238ff62c 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -30,12 +30,18 @@ #include "WebDownload.h" #include "WebProcess.h" +#include +#include #include +#include +#include #include #include #include #include #include +#include +#include #include #include #include @@ -43,7 +49,278 @@ #include enum { - REMOVE_FINISHED_DOWNLOADS = 'rmfd' + REMOVE_FINISHED_DOWNLOADS = 'rmfd', + OPEN_DOWNLOAD = 'opdn', + REMOVE_DOWNLOAD = 'rmdn', + SAVE_SETTINGS = 'svst' +}; + +class IconView : public BView { +public: + IconView(const BEntry& entry) + : BView("Download icon", B_WILL_DRAW) + , m_iconBitmap(BRect(0, 0, 31, 31), 0, B_RGBA32) + { + BNode node(&entry); + BNodeInfo info(&node); + info.GetTrackerIcon(&m_iconBitmap, B_LARGE_ICON); + SetDrawingMode(B_OP_OVER); + } + + IconView(BMessage* archive) + : BView("Download icon", B_WILL_DRAW) + , m_iconBitmap(archive) + { + SetDrawingMode(B_OP_OVER); + } + + status_t saveSettings(BMessage* archive) + { + return m_iconBitmap.Archive(archive); + } + + virtual void AttachedToWindow() + { + SetViewColor(Parent()->ViewColor()); + } + + virtual void Draw(BRect updateRect) + { + DrawBitmapAsync(&m_iconBitmap); + } + + virtual BSize MinSize() + { + return BSize(m_iconBitmap.Bounds().Width(), m_iconBitmap.Bounds().Height()); + } + + virtual BSize PreferredSize() + { + return MinSize(); + } + + virtual BSize MaxSize() + { + return MinSize(); + } + +private: + BBitmap m_iconBitmap; +}; + +class SmallButton : public BButton { +public: + SmallButton(const char* label, BMessage* message = NULL) + : BButton(label, message) + { + BFont font; + GetFont(&font); + float size = ceilf(font.Size() * 0.8); + font.SetSize(max_c(8, size)); + SetFont(&font, B_FONT_SIZE); + } +}; + +class DownloadProgressView : public BGridView { +public: + DownloadProgressView(WebDownload* download) + : BGridView(8, 3) + , m_download(download) + , m_path(download->path()) + , m_expectedSize(download->expectedSize()) + { + } + + DownloadProgressView(const BMessage* archive) + : BGridView(8, 3) + , m_download(NULL) + , m_path() + , m_expectedSize(0) + { + const char* path; + if (archive->FindString("path", &path) == B_OK) + m_path.SetTo(path); + } + + bool init(BMessage* archive = NULL) + { + BEntry entry(m_path.Path()); + if (!entry.Exists() && !archive) + return false; + + SetViewColor(245, 245, 245); + SetFlags(Flags() | B_FULL_UPDATE_ON_RESIZE | B_WILL_DRAW); + + BGridLayout* layout = GridLayout(); + m_statusBar = new BStatusBar("download progress", m_path.Leaf()); + m_statusBar->SetMaxValue(100); + if (archive) { + float value; + if (archive->FindFloat("value", &value) == B_OK) + m_statusBar->SetTo(value); + } + m_statusBar->SetBarHeight(12); + + if (entry.Exists()) + m_iconView = new IconView(entry); + else + m_iconView = new IconView(archive); + + m_button1 = new SmallButton("Open", new BMessage(OPEN_DOWNLOAD)); + m_button2 = new SmallButton("Remove", new BMessage(REMOVE_DOWNLOAD)); + m_button1->SetEnabled(m_download == NULL); + m_button2->SetEnabled(m_download == NULL); + + layout->SetInsets(8, 5, 5, 6); + layout->AddView(m_iconView, 0, 0, 1, 2); + layout->AddView(m_statusBar, 1, 0, 1, 2); + layout->AddView(m_button1, 2, 0); + layout->AddView(m_button2, 2, 1); + + return true; + } + + status_t saveSettings(BMessage* archive) + { + if (!archive) + return B_BAD_VALUE; + status_t ret = archive->AddString("path", m_path.Path()); + if (ret == B_OK) + ret = archive->AddFloat("value", m_statusBar->CurrentValue()); + if (ret == B_OK) + ret = m_iconView->saveSettings(archive); + return ret; + } + + virtual void AttachedToWindow() + { + if (m_download) + m_download->setProgressListener(BMessenger(this)); + m_button1->SetTarget(this); + m_button2->SetTarget(this); + } + + virtual void AllAttached() + { + SetViewColor(B_TRANSPARENT_COLOR); + SetLowColor(245, 245, 245); + SetHighColor(tint_color(LowColor(), B_DARKEN_1_TINT)); + } + + virtual void Draw(BRect updateRect) + { + BRect bounds(Bounds()); + bounds.bottom--; + FillRect(bounds, B_SOLID_LOW); + bounds.bottom++; + StrokeLine(bounds.LeftBottom(), bounds.RightBottom()); + } + + virtual void MessageReceived(BMessage* message) + { + switch (message->what) { + case WebDownload::DOWNLOAD_PROGRESS: { + float progress; + if (message->FindFloat("progress", &progress) == B_OK) + m_statusBar->SetTo(progress); + break; + } + case OPEN_DOWNLOAD: { + // TODO: In case of executable files, ask the user first! + entry_ref ref; + status_t status = get_ref_for_path(m_path.Path(), &ref); + if (status == B_OK) + status = be_roster->Launch(&ref); + if (status != B_OK && status != B_ALREADY_RUNNING) { + BAlert* alert = new BAlert("Open download error", + "The download could not be opened.", "OK"); + alert->Go(NULL); + } + break; + } + case REMOVE_DOWNLOAD: { + Window()->PostMessage(SAVE_SETTINGS); + RemoveSelf(); + delete this; + // TOAST! + return; + } + default: + BGridView::MessageReceived(message); + } + } + + WebDownload* download() const + { + return m_download; + } + + void downloadFinished() + { + m_download = NULL; + m_button1->SetEnabled(true); + m_button2->SetEnabled(true); + } + +private: + IconView* m_iconView; + BStatusBar* m_statusBar; + SmallButton* m_button1; + SmallButton* m_button2; + WebDownload* m_download; + BPath m_path; + off_t m_expectedSize; +}; + +class DownloadsContainerView : public BGroupView { +public: + DownloadsContainerView() + : BGroupView(B_VERTICAL) + { + SetViewColor(245, 245, 245); + AddChild(BSpaceLayoutItem::CreateGlue()); + } + + virtual BSize MinSize() + { + BSize minSize = BGroupView::MinSize(); + return BSize(minSize.width, 80); + } + +protected: + virtual void DoLayout() + { + BGroupView::DoLayout(); + if (BScrollBar* scrollBar = ScrollBar(B_VERTICAL)) { + BSize minSize = BGroupView::MinSize(); + float height = Bounds().Height(); + float max = minSize.height - height; + scrollBar->SetRange(0, max); + if (minSize.height > 0) + scrollBar->SetProportion(height / minSize.height); + else + scrollBar->SetProportion(1); + } + } +}; + +class DownloadContainerScrollView : public BScrollView { +public: + DownloadContainerScrollView(BView* target) + : BScrollView("Downloads scroll view", target, 0, false, true, B_NO_BORDER) + { + } + +protected: + virtual void DoLayout() + { + BScrollView::DoLayout(); + // Tweak scroll bar layout to hide part of the frame for better looks. + BScrollBar* scrollBar = ScrollBar(B_VERTICAL); + scrollBar->MoveBy(1, -1); + scrollBar->ResizeBy(0, 2); + Target()->ResizeBy(1, 0); + } }; DownloadWindow::DownloadWindow(BRect frame, bool visible) @@ -53,8 +330,7 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible) { SetLayout(new BGroupLayout(B_VERTICAL)); - BGroupView* downloadsGroupView = new BGroupView(B_VERTICAL); - downloadsGroupView->SetViewColor(245, 245, 245); + DownloadsContainerView* downloadsGroupView = new DownloadsContainerView(); m_downloadViewsLayout = downloadsGroupView->GroupLayout(); BMenuBar* menuBar = new BMenuBar("Menu bar"); @@ -62,8 +338,7 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible) menu->AddItem(new BMenuItem("Minimize", new BMessage(B_QUIT_REQUESTED), 'M')); menuBar->AddItem(menu); - BScrollView* scrollView = new BScrollView("Downloads scroll view", - downloadsGroupView, 0, false, true, B_NO_BORDER); + BScrollView* scrollView = new DownloadContainerScrollView(downloadsGroupView); m_removeFinishedButton = new BButton("Remove finished", new BMessage(REMOVE_FINISHED_DOWNLOADS)); @@ -80,6 +355,10 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible) ) ); + loadSettings(); + // Small trick to get the correct enabled status of the Remove finished button + downloadFinished(NULL); + if (!visible) Minimize(true); Show(); @@ -87,6 +366,8 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible) DownloadWindow::~DownloadWindow() { + // Only necessary to save the current progress of unfinished downloads: + saveSettings(); } void DownloadWindow::MessageReceived(BMessage* message) @@ -107,6 +388,9 @@ void DownloadWindow::MessageReceived(BMessage* message) case REMOVE_FINISHED_DOWNLOADS: removeFinishedDownloads(); break; + case SAVE_SETTINGS: + saveSettings(); + break; default: BWindow::MessageReceived(message); break; @@ -120,58 +404,13 @@ bool DownloadWindow::QuitRequested() return false; } -class DownloadProgressView : public BGroupView { -public: - DownloadProgressView(WebDownload* download) - : BGroupView(B_HORIZONTAL) - , m_download(download) - , m_expectedSize(download->expectedSize()) - { - SetViewColor(245, 245, 245); - GroupLayout()->SetInsets(5, 5, 5, 5); - m_statusBar = new BStatusBar("download progress", download->filename().String()); - m_statusBar->SetMaxValue(100); - AddChild(m_statusBar); - } - - virtual void AttachedToWindow() - { - m_download->setProgressListener(BMessenger(this)); - } - - virtual void MessageReceived(BMessage* message) - { - switch (message->what) { - case WebDownload::DOWNLOAD_PROGRESS: { - float progress; - if (message->FindFloat("progress", &progress) == B_OK) - m_statusBar->SetTo(progress); - break; - } - default: - BGroupView::MessageReceived(message); - } - } - - WebDownload* download() const - { - return m_download; - } - - void downloadFinished() - { - m_download = NULL; - } - -private: - BStatusBar* m_statusBar; - WebDownload* m_download; - off_t m_expectedSize; -}; - void DownloadWindow::downloadStarted(WebDownload* download) { - m_downloadViewsLayout->AddView(new DownloadProgressView(download)); + DownloadProgressView* view = new DownloadProgressView(download); + if (!view->init()) + return; + m_downloadViewsLayout->AddView(0, view); + saveSettings(); } void DownloadWindow::downloadFinished(WebDownload* download) @@ -188,6 +427,8 @@ void DownloadWindow::downloadFinished(WebDownload* download) finishedCount++; } m_removeFinishedButton->SetEnabled(finishedCount > 0); + if (download) + saveSettings(); } void DownloadWindow::removeFinishedDownloads() @@ -203,4 +444,52 @@ void DownloadWindow::removeFinishedDownloads() } } m_removeFinishedButton->SetEnabled(false); + saveSettings(); } + +void DownloadWindow::saveSettings() +{ + BFile file; + if (!openSettingsFile(file, B_ERASE_FILE | B_CREATE_FILE | B_WRITE_ONLY)) + return; + BMessage message; + for (int32 i = m_downloadViewsLayout->CountItems() - 1; + BLayoutItem* item = m_downloadViewsLayout->ItemAt(i); i--) { + DownloadProgressView* view = dynamic_cast(item->View()); + if (!view) + continue; + BMessage downloadArchive; + if (view->saveSettings(&downloadArchive) == B_OK) + message.AddMessage("download", &downloadArchive); + } + message.Flatten(&file); +} + +void DownloadWindow::loadSettings() +{ + BFile file; + if (!openSettingsFile(file, B_READ_ONLY)) + return; + BMessage message; + if (message.Unflatten(&file) != B_OK) + return; + BMessage downloadArchive; + for (int32 i = 0; message.FindMessage("download", i, &downloadArchive) == B_OK; i++) { + DownloadProgressView* view = new DownloadProgressView(&downloadArchive); + if (!view->init(&downloadArchive)) + continue; + m_downloadViewsLayout->AddView(0, view); + } +} + +bool DownloadWindow::openSettingsFile(BFile& file, uint32 mode) +{ + BPath path; + if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK + || path.Append("HaikuLauncher_Downloads") != B_OK) { + return false; + } + return file.SetTo(path.Path(), mode) == B_OK; +} + + diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index bd370adb17..e03fce4a3e 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -31,6 +31,7 @@ #include class BButton; +class BFile; class BGroupLayout; class WebDownload; @@ -46,6 +47,9 @@ private: void downloadStarted(WebDownload* download); void downloadFinished(WebDownload* download); void removeFinishedDownloads(); + void saveSettings(); + void loadSettings(); + bool openSettingsFile(BFile& file, uint32 mode); private: BGroupLayout* m_downloadViewsLayout; From 8260b39fbc6e19008ceea627cc87bf69a38f0045 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 13 Feb 2010 13:17:45 +0000 Subject: [PATCH 008/349] * Now stores the URL of downloads in the DownloadProgressView and in the settings, so that we can eventually restart downloads. * Checks if a downloaded file already has a previous download and replaces it. (Actually, this should take the path into account, not only URL.) * Stores the URL as "META:url" attribute, as the good old NetPositive did. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@60 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 34 ++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 0b238ff62c..0511ff194d 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -126,6 +126,7 @@ public: DownloadProgressView(WebDownload* download) : BGridView(8, 3) , m_download(download) + , m_url(download->url()) , m_path(download->path()) , m_expectedSize(download->expectedSize()) { @@ -134,12 +135,15 @@ public: DownloadProgressView(const BMessage* archive) : BGridView(8, 3) , m_download(NULL) + , m_url() , m_path() , m_expectedSize(0) { - const char* path; - if (archive->FindString("path", &path) == B_OK) - m_path.SetTo(path); + const char* string; + if (archive->FindString("path", &string) == B_OK) + m_path.SetTo(string); + if (archive->FindString("url", &string) == B_OK) + m_url = string; } bool init(BMessage* archive = NULL) @@ -185,6 +189,8 @@ public: if (!archive) return B_BAD_VALUE; status_t ret = archive->AddString("path", m_path.Path()); + if (ret == B_OK) + ret = archive->AddString("url", m_url.String()); if (ret == B_OK) ret = archive->AddFloat("value", m_statusBar->CurrentValue()); if (ret == B_OK) @@ -255,6 +261,11 @@ public: return m_download; } + const BString& url() const + { + return m_url; + } + void downloadFinished() { m_download = NULL; @@ -268,6 +279,7 @@ private: SmallButton* m_button1; SmallButton* m_button2; WebDownload* m_download; + BString m_url; BPath m_path; off_t m_expectedSize; }; @@ -406,10 +418,24 @@ bool DownloadWindow::QuitRequested() void DownloadWindow::downloadStarted(WebDownload* download) { + int32 finishedCount = 0; + int32 index = 0; + for (int32 i = m_downloadViewsLayout->CountItems() - 1; + BLayoutItem* item = m_downloadViewsLayout->ItemAt(i); i--) { + DownloadProgressView* view = dynamic_cast(item->View()); + if (!view) + continue; + if (view->url() == download->url()) { + index = i; + view->RemoveSelf(); + delete view; + } + } + m_removeFinishedButton->SetEnabled(finishedCount > 0); DownloadProgressView* view = new DownloadProgressView(download); if (!view->init()) return; - m_downloadViewsLayout->AddView(0, view); + m_downloadViewsLayout->AddView(index, view); saveSettings(); } From aab72d7ea63f8951f66a733558a1fe568255a5df Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 13 Feb 2010 13:42:52 +0000 Subject: [PATCH 009/349] * Use hiding instead of minimizing for the Download window. * Auto-show and auto-move-to-current-workspace when a download starts. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@61 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 12 ++++++++---- src/apps/webpositive/LauncherApp.cpp | 6 +++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 0511ff194d..ea0492b402 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -347,7 +347,7 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible) BMenuBar* menuBar = new BMenuBar("Menu bar"); BMenu* menu = new BMenu("Window"); - menu->AddItem(new BMenuItem("Minimize", new BMessage(B_QUIT_REQUESTED), 'M')); + menu->AddItem(new BMenuItem("Hide", new BMessage(B_QUIT_REQUESTED), 'H')); menuBar->AddItem(menu); BScrollView* scrollView = new DownloadContainerScrollView(downloadsGroupView); @@ -372,7 +372,7 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible) downloadFinished(NULL); if (!visible) - Minimize(true); + Hide(); Show(); } @@ -411,8 +411,8 @@ void DownloadWindow::MessageReceived(BMessage* message) bool DownloadWindow::QuitRequested() { - if (!IsMinimized()) - Minimize(true); + if (!IsHidden()) + Hide(); return false; } @@ -437,6 +437,10 @@ void DownloadWindow::downloadStarted(WebDownload* download) return; m_downloadViewsLayout->AddView(index, view); saveSettings(); + + SetWorkspaces(B_CURRENT_WORKSPACE); + if (IsHidden()) + Show(); } void DownloadWindow::downloadFinished(WebDownload* download) diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 84a338ff07..44baaf0210 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -173,8 +173,8 @@ void LauncherApp::MessageReceived(BMessage* message) uint32 workspaces; if (message->FindUInt32("workspaces", &workspaces) == B_OK) m_downloadWindow->SetWorkspaces(workspaces); - if (m_downloadWindow->IsMinimized()) - m_downloadWindow->Minimize(false); + if (m_downloadWindow->IsHidden()) + m_downloadWindow->Show(); else m_downloadWindow->Activate(); } @@ -231,7 +231,7 @@ bool LauncherApp::QuitRequested() settingsArchive.AddRect("window frame", m_lastWindowFrame); if (m_downloadWindow->Lock()) { settingsArchive.AddRect("downloads window frame", m_downloadWindow->Frame()); - settingsArchive.AddBool("show downloads", !m_downloadWindow->IsMinimized()); + settingsArchive.AddBool("show downloads", !m_downloadWindow->IsHidden()); m_downloadWindow->Unlock(); } settingsArchive.Flatten(&settingsFile); From 5eb61e485689dfd540b2ca4fbfe36809c4bcc6c3 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 14 Feb 2010 20:31:05 +0000 Subject: [PATCH 010/349] Added AuthenticationPanel implementation. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@70 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/AuthenticationPanel.cpp | 190 +++++++++++++++++++ src/apps/webpositive/AuthenticationPanel.h | 65 +++++++ src/apps/webpositive/LauncherApp.cpp | 2 + src/apps/webpositive/LauncherWindow.cpp | 24 ++- 4 files changed, 279 insertions(+), 2 deletions(-) create mode 100644 src/apps/webpositive/AuthenticationPanel.cpp create mode 100644 src/apps/webpositive/AuthenticationPanel.h diff --git a/src/apps/webpositive/AuthenticationPanel.cpp b/src/apps/webpositive/AuthenticationPanel.cpp new file mode 100644 index 0000000000..b6ddb3bd3f --- /dev/null +++ b/src/apps/webpositive/AuthenticationPanel.cpp @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "AuthenticationPanel.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const uint32 kMsgPanelOK = 'pnok'; +static const uint32 kMsgJitter = 'jitr'; +static const uint32 kHidePassword = 'hdpw'; + +AuthenticationPanel::AuthenticationPanel(BRect parentFrame) + : BWindow(BRect(-1000, -1000, -900, -900), "Authentication Required", + B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, + B_ASYNCHRONOUS_CONTROLS | B_NOT_RESIZABLE | B_NOT_ZOOMABLE + | B_CLOSE_ON_ESCAPE | B_AUTO_UPDATE_SIZE_LIMITS) + , m_parentWindowFrame(parentFrame) + , m_usernameTextControl(new BTextControl("user", "Username:", "", NULL)) + , m_passwordTextControl(new BTextControl("pass", "Password:", "", NULL)) + , m_hidePasswordCheckBox(new BCheckBox("hide", "Hide password text", new BMessage(kHidePassword))) + , m_remberCredentialsCheckBox(new BCheckBox("remember", "Rember this username and password", NULL)) + , m_okButton(new BButton("ok", "OK", new BMessage(kMsgPanelOK))) + , m_cancelButton(new BButton("cancel", "Cancel", new BMessage(B_QUIT_REQUESTED))) + , m_cancelled(false) + , m_exitSemaphore(create_sem(0, "Authentication Panel")) +{ +} + +AuthenticationPanel::~AuthenticationPanel() +{ + delete_sem(m_exitSemaphore); +} + +bool +AuthenticationPanel::QuitRequested() +{ + m_cancelled = true; + release_sem(m_exitSemaphore); + return false; +} + +void +AuthenticationPanel::MessageReceived(BMessage* message) +{ + switch (message->what) { + case kMsgPanelOK: + release_sem(m_exitSemaphore); + break; + case kHidePassword: { + // TODO: Toggling this is broken in BTextView. Workaround is to + // set the text and selection again. + BString text = m_passwordTextControl->Text(); + int32 selectionStart; + int32 selectionEnd; + m_passwordTextControl->TextView()->GetSelection(&selectionStart, &selectionEnd); + m_passwordTextControl->TextView()->HideTyping( + m_hidePasswordCheckBox->Value() == B_CONTROL_ON); + m_passwordTextControl->SetText(text.String()); + m_passwordTextControl->TextView()->Select(selectionStart, selectionEnd); + break; + } + case kMsgJitter: { + UpdateIfNeeded(); + BPoint leftTop = Frame().LeftTop(); + const float jitterOffsets[] = { -10, 0, 10, 0 }; + const int32 jitterOffsetCount = sizeof(jitterOffsets) / sizeof(float); + for (int32 i = 0; i < 20; i++) { + float offset = jitterOffsets[i % jitterOffsetCount]; + MoveTo(leftTop.x + offset, leftTop.y); + snooze(15000); + } + MoveTo(leftTop); + break; + } + default: + BWindow::MessageReceived(message); + } +} + +bool AuthenticationPanel::getAuthentication(const BString& realm, + const BString& method, const BString& previousUser, const BString& previousPass, + bool previousRememberCredentials, bool badPassword, + BString& user, BString& pass, bool* rememberCredentials) +{ + // Configure panel and layout controls. + BString infoText("Enter login information for: "); + infoText << realm << "\n\n"; + infoText << "Authentication method: "; + infoText << method; + + m_usernameTextControl->SetText(previousUser.String()); + m_passwordTextControl->TextView()->HideTyping(true); + // Ignore the previous password, if it didn't work. + if (!badPassword) + m_passwordTextControl->SetText(previousPass.String()); + m_hidePasswordCheckBox->SetValue(B_CONTROL_ON); + m_remberCredentialsCheckBox->SetValue(previousRememberCredentials); + + // create layout + SetLayout(new BGroupLayout(B_VERTICAL)); + float spacing = be_control_look->DefaultItemSpacing(); + AddChild(BGroupLayoutBuilder(B_VERTICAL) + // TODO: Add text view here explaining realm and method... + .Add(BGridLayoutBuilder(0, spacing) + .Add(m_usernameTextControl->CreateLabelLayoutItem(), 0, 0) + .Add(m_usernameTextControl->CreateTextViewLayoutItem(), 1, 0) + .Add(m_passwordTextControl->CreateLabelLayoutItem(), 0, 1) + .Add(m_passwordTextControl->CreateTextViewLayoutItem(), 1, 1) + .Add(BSpaceLayoutItem::CreateGlue(), 0, 2) + .Add(m_hidePasswordCheckBox, 1, 2) + .Add(m_remberCredentialsCheckBox, 0, 3, 2) + .SetInsets(spacing, spacing, spacing, spacing) + ) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(BGroupLayoutBuilder(B_HORIZONTAL, spacing) + .AddGlue() + .Add(m_cancelButton) + .Add(m_okButton) + .SetInsets(spacing, spacing, spacing, spacing) + ) + ); + + SetDefaultButton(m_okButton); + m_usernameTextControl->MakeFocus(true); + + if (m_parentWindowFrame.IsValid()) + CenterIn(m_parentWindowFrame); + else + CenterOnScreen(); + + // Start AuthenticationPanel window thread + Show(); + + // Let the window jitter, if the previous password was invalid + if (badPassword) + PostMessage(kMsgJitter); + + // Block calling thread + // TODO: When called from other window threads, this should periodically + // call UpdateIfNeeded()... + acquire_sem(m_exitSemaphore); + + // AuthenticationPanel wants to quit. + Lock(); + + user = m_usernameTextControl->Text(); + pass = m_passwordTextControl->Text(); + if (rememberCredentials) + *rememberCredentials = m_remberCredentialsCheckBox->Value() == B_CONTROL_ON; + + bool canceled = m_cancelled; + Quit(); + // AuthenticationPanel object is TOAST here. + return !canceled; +} diff --git a/src/apps/webpositive/AuthenticationPanel.h b/src/apps/webpositive/AuthenticationPanel.h new file mode 100644 index 0000000000..0f8b6ab847 --- /dev/null +++ b/src/apps/webpositive/AuthenticationPanel.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef AuthenticationPanel_h +#define AuthenticationPanel_h + +#include +#include + +class BCheckBox; +class BTextControl; + +class AuthenticationPanel : public BWindow { +public: + AuthenticationPanel(BRect parentFrame = BRect()); + virtual ~AuthenticationPanel(); + + virtual bool QuitRequested(); + + virtual void MessageReceived(BMessage *message); + + bool getAuthentication(const BString& realm, const BString& method, + const BString& previousUser, const BString& previousPass, + bool previousRememberCredentials, bool badPassword, BString& user, + BString& pass, bool* rememberCredentials); + +private: + BRect m_parentWindowFrame; + BTextControl* m_usernameTextControl; + BTextControl* m_passwordTextControl; + BCheckBox* m_hidePasswordCheckBox; + BCheckBox* m_remberCredentialsCheckBox; + BButton* m_okButton; + BButton* m_cancelButton; + + bool m_cancelled; + + sem_id m_exitSemaphore; +}; + +#endif // AuthenticationPanel_h diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 44baaf0210..67792d13d6 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -58,6 +58,8 @@ LauncherApp::LauncherApp() , m_initialized(false) , m_downloadWindow(0) { + // Since we will essentially run the GUI... + set_thread_priority(Thread(), B_DISPLAY_PRIORITY); } LauncherApp::~LauncherApp() diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index bc9c3970c4..08ebb14570 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -31,10 +31,10 @@ #include "config.h" #include "LauncherWindow.h" +#include "AuthenticationPanel.h" #include "WebProcess.h" #include "WebView.h" #include "WebViewConstants.h" - #include #include #include @@ -64,7 +64,9 @@ enum { TEXT_SHOW_FIND_GROUP = 'sfnd', TEXT_HIDE_FIND_GROUP = 'hfnd', TEXT_FIND_NEXT = 'fndn', - TEXT_FIND_PREVIOUS = 'fndp' + TEXT_FIND_PREVIOUS = 'fndp', + + TEST_AUTHENTICATION_PANEL = 'tapn' }; using namespace WebCore; @@ -199,6 +201,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, AddShortcut('G', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_FIND_PREVIOUS)); AddShortcut('F', B_COMMAND_KEY, new BMessage(TEXT_SHOW_FIND_GROUP)); AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_HIDE_FIND_GROUP)); + AddShortcut('T', B_COMMAND_KEY, new BMessage(TEST_AUTHENTICATION_PANEL)); navigationCapabilitiesChanged(false, false, false); @@ -259,6 +262,23 @@ void LauncherWindow::MessageReceived(BMessage* message) be_app->PostMessage(message); break; + case TEST_AUTHENTICATION_PANEL: { + BString realm("Realm"); + BString method("Method"); + BString previousUser; + BString previousPass; + bool rememberCredentials = false; + bool badPassword = true; + BString user; + BString pass; + AuthenticationPanel* panel = new AuthenticationPanel(Frame()); + bool success = panel->getAuthentication(realm, method, previousUser, + previousPass, rememberCredentials, badPassword, user, pass, + &rememberCredentials); + printf("success: %d\n", success); + break; + } + default: WebViewWindow::MessageReceived(message); break; From a30b7161b85848ac64412901fbbe66ed4fbb1bc2 Mon Sep 17 00:00:00 2001 From: mmlr Date: Mon, 15 Feb 2010 00:30:11 +0000 Subject: [PATCH 011/349] * Handle authentication challenges by sending them off to the WebViewWindow which then invokes the authenticationChallenge() hook. * Implemented that hook in LauncherWindow by means of the AuthenticationPanel. * Removed realm and method arguments to AuthenticationPanel::getAuthentication() and replaced them by a simple "text" that is constructed in the FrameLoaderClient based on the challenge details. It is not yet shown though. * Made a tab -> spaces replace and added myself to the copyrights in some files. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@74 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/AuthenticationPanel.cpp | 9 +- src/apps/webpositive/AuthenticationPanel.h | 8 +- src/apps/webpositive/LauncherWindow.cpp | 207 ++++++++++--------- src/apps/webpositive/LauncherWindow.h | 1 + 4 files changed, 116 insertions(+), 109 deletions(-) diff --git a/src/apps/webpositive/AuthenticationPanel.cpp b/src/apps/webpositive/AuthenticationPanel.cpp index b6ddb3bd3f..a2c70c2493 100644 --- a/src/apps/webpositive/AuthenticationPanel.cpp +++ b/src/apps/webpositive/AuthenticationPanel.cpp @@ -112,17 +112,12 @@ AuthenticationPanel::MessageReceived(BMessage* message) } } -bool AuthenticationPanel::getAuthentication(const BString& realm, - const BString& method, const BString& previousUser, const BString& previousPass, +bool AuthenticationPanel::getAuthentication(const BString& text, + const BString& previousUser, const BString& previousPass, bool previousRememberCredentials, bool badPassword, BString& user, BString& pass, bool* rememberCredentials) { // Configure panel and layout controls. - BString infoText("Enter login information for: "); - infoText << realm << "\n\n"; - infoText << "Authentication method: "; - infoText << method; - m_usernameTextControl->SetText(previousUser.String()); m_passwordTextControl->TextView()->HideTyping(true); // Ignore the previous password, if it didn't work. diff --git a/src/apps/webpositive/AuthenticationPanel.h b/src/apps/webpositive/AuthenticationPanel.h index 0f8b6ab847..568f22d1f4 100644 --- a/src/apps/webpositive/AuthenticationPanel.h +++ b/src/apps/webpositive/AuthenticationPanel.h @@ -43,10 +43,10 @@ public: virtual void MessageReceived(BMessage *message); - bool getAuthentication(const BString& realm, const BString& method, - const BString& previousUser, const BString& previousPass, - bool previousRememberCredentials, bool badPassword, BString& user, - BString& pass, bool* rememberCredentials); + bool getAuthentication(const BString& text, const BString& previousUser, + const BString& previousPass, bool previousRememberCredentials, + bool badPassword, BString& user, BString& pass, + bool* rememberCredentials); private: BRect m_parentWindowFrame; diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 08ebb14570..872da78b7f 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -3,6 +3,7 @@ * Copyright (C) 2007 Ryan Leavengood * Copyright (C) 2009 Maxime Simon * Copyright (C) 2010 Stephan Aßmus + * Copyright (C) 2010 Michael Lotz * * All rights reserved. * @@ -57,9 +58,9 @@ enum { GOTO_URL = 'goul', RELOAD = 'reld', - TEXT_SIZE_INCREASE = 'tsin', - TEXT_SIZE_DECREASE = 'tsdc', - TEXT_SIZE_RESET = 'tsrs', + TEXT_SIZE_INCREASE = 'tsin', + TEXT_SIZE_DECREASE = 'tsdc', + TEXT_SIZE_RESET = 'tsrs', TEXT_SHOW_FIND_GROUP = 'sfnd', TEXT_HIDE_FIND_GROUP = 'hfnd', @@ -73,9 +74,9 @@ using namespace WebCore; static BLayoutItem* layoutItemFor(BView* view) { - BLayout* layout = view->Parent()->GetLayout(); - int32 index = layout->IndexOfView(view); - return layout->ItemAt(index); + BLayout* layout = view->Parent()->GetLayout(); + int32 index = layout->IndexOfView(view); + return layout->ItemAt(index); } LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, @@ -85,30 +86,30 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) { if (toolbarPolicy == HaveToolbar) { - // Menu - m_menuBar = new BMenuBar("Main menu"); - BMenu* menu = new BMenu("Window"); - BMessage* newWindowMessage = new BMessage(NEW_WINDOW); - newWindowMessage->AddString("url", ""); - BMenuItem* newItem = new BMenuItem("New", newWindowMessage, 'N'); - menu->AddItem(newItem); - newItem->SetTarget(be_app); - menu->AddItem(new BMenuItem("Close", new BMessage(B_QUIT_REQUESTED), 'W')); - menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Show Downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'D')); - menu->AddSeparatorItem(); - BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); - menu->AddItem(quitItem); - quitItem->SetTarget(be_app); - m_menuBar->AddItem(menu); + // Menu + m_menuBar = new BMenuBar("Main menu"); + BMenu* menu = new BMenu("Window"); + BMessage* newWindowMessage = new BMessage(NEW_WINDOW); + newWindowMessage->AddString("url", ""); + BMenuItem* newItem = new BMenuItem("New", newWindowMessage, 'N'); + menu->AddItem(newItem); + newItem->SetTarget(be_app); + menu->AddItem(new BMenuItem("Close", new BMessage(B_QUIT_REQUESTED), 'W')); + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("Show Downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'D')); + menu->AddSeparatorItem(); + BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); + menu->AddItem(quitItem); + quitItem->SetTarget(be_app); + m_menuBar->AddItem(menu); - menu = new BMenu("Text"); - menu->AddItem(new BMenuItem("Find", new BMessage(TEXT_SHOW_FIND_GROUP), 'F')); - menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Increase size", new BMessage(TEXT_SIZE_INCREASE), '+')); - menu->AddItem(new BMenuItem("Decrease size", new BMessage(TEXT_SIZE_DECREASE), '-')); - menu->AddItem(new BMenuItem("Reset size", new BMessage(TEXT_SIZE_RESET), '0')); - m_menuBar->AddItem(menu); + menu = new BMenu("Text"); + menu->AddItem(new BMenuItem("Find", new BMessage(TEXT_SHOW_FIND_GROUP), 'F')); + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("Increase size", new BMessage(TEXT_SIZE_INCREASE), '+')); + menu->AddItem(new BMenuItem("Decrease size", new BMessage(TEXT_SIZE_DECREASE), '-')); + menu->AddItem(new BMenuItem("Reset size", new BMessage(TEXT_SIZE_RESET), '0')); + m_menuBar->AddItem(menu); // Back & Forward m_BackButton = new BButton("", "Back", new BMessage(GO_BACK)); @@ -126,16 +127,16 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_statusText->SetAlignment(B_ALIGN_LEFT); m_statusText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); m_statusText->SetExplicitMinSize(BSize(150, 16)); - // Prevent the window from growing to fit a long status message... + // Prevent the window from growing to fit a long status message... BFont font(be_plain_font); font.SetSize(ceilf(font.Size() * 0.8)); m_statusText->SetFont(&font, B_FONT_SIZE); - // Loading progress bar - m_loadingProgressBar = new BStatusBar("progress"); - m_loadingProgressBar->SetMaxValue(100); - m_loadingProgressBar->Hide(); - m_loadingProgressBar->SetBarHeight(10); + // Loading progress bar + m_loadingProgressBar = new BStatusBar("progress"); + m_loadingProgressBar->SetMaxValue(100); + m_loadingProgressBar->Hide(); + m_loadingProgressBar->SetBarHeight(10); const float kInsetSpacing = 5; const float kElementSpacing = 7; @@ -158,7 +159,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, ; // Layout AddChild(BGroupLayoutBuilder(B_VERTICAL) - .Add(m_menuBar) + .Add(m_menuBar) .Add(BGridLayoutBuilder(kElementSpacing, kElementSpacing) .Add(m_BackButton, 0, 0) .Add(m_ForwardButton, 1, 0) @@ -181,8 +182,8 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_findGroup = layoutItemFor(findGroup); } else { - m_BackButton = 0; - m_ForwardButton = 0; + m_BackButton = 0; + m_ForwardButton = 0; m_url = 0; m_menuBar = 0; m_statusText = 0; @@ -205,7 +206,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, navigationCapabilitiesChanged(false, false, false); - be_app->PostMessage(WINDOW_OPENED); + be_app->PostMessage(WINDOW_OPENED); } LauncherWindow::~LauncherWindow() @@ -262,23 +263,6 @@ void LauncherWindow::MessageReceived(BMessage* message) be_app->PostMessage(message); break; - case TEST_AUTHENTICATION_PANEL: { - BString realm("Realm"); - BString method("Method"); - BString previousUser; - BString previousPass; - bool rememberCredentials = false; - bool badPassword = true; - BString user; - BString pass; - AuthenticationPanel* panel = new AuthenticationPanel(Frame()); - bool success = panel->getAuthentication(realm, method, previousUser, - previousPass, rememberCredentials, badPassword, user, pass, - &rememberCredentials); - printf("success: %d\n", success); - break; - } - default: WebViewWindow::MessageReceived(message); break; @@ -288,8 +272,8 @@ void LauncherWindow::MessageReceived(BMessage* message) bool LauncherWindow::QuitRequested() { if (WebViewWindow::QuitRequested()) { - BMessage message(WINDOW_CLOSED); - message.AddRect("window frame", Frame()); + BMessage message(WINDOW_CLOSED); + message.AddRect("window frame", Frame()); be_app->PostMessage(&message); return true; } @@ -300,86 +284,113 @@ bool LauncherWindow::QuitRequested() void LauncherWindow::navigationRequested(const BString& url) { - m_loadedURL = url; + m_loadedURL = url; if (m_url) m_url->SetText(url.String()); } void LauncherWindow::newWindowRequested(const BString& url) { - // Always open new windows in the application thread, since - // creating a WebView will try to grab the application lock. - // But our own WebProcess may already try to lock us from within - // the application thread -> dead-lock. - BMessage message(NEW_WINDOW); - message.AddString("url", url); - be_app->PostMessage(&message); + // Always open new windows in the application thread, since + // creating a WebView will try to grab the application lock. + // But our own WebProcess may already try to lock us from within + // the application thread -> dead-lock. + BMessage message(NEW_WINDOW); + message.AddString("url", url); + be_app->PostMessage(&message); } void LauncherWindow::loadNegociating(const BString& url) { - BString status("Requesting: "); - status << url; - statusChanged(status); + BString status("Requesting: "); + status << url; + statusChanged(status); } void LauncherWindow::loadTransfering(const BString& url) { - BString status("Loading: "); - status << url; - statusChanged(status); + BString status("Loading: "); + status << url; + statusChanged(status); } void LauncherWindow::loadProgress(float progress) { - if (m_loadingProgressBar) { - if (progress < 100 && m_loadingProgressBar->IsHidden()) - m_loadingProgressBar->Show(); - m_loadingProgressBar->SetTo(progress); - } + if (m_loadingProgressBar) { + if (progress < 100 && m_loadingProgressBar->IsHidden()) + m_loadingProgressBar->Show(); + m_loadingProgressBar->SetTo(progress); + } } void LauncherWindow::loadFailed(const BString& url) { - BString status(url); - status << " failed."; - statusChanged(status); - if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) - m_loadingProgressBar->Hide(); + BString status(url); + status << " failed."; + statusChanged(status); + if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) + m_loadingProgressBar->Hide(); } void LauncherWindow::loadFinished(const BString& url) { - m_loadedURL = url; - BString status(url); - status << " finished."; - statusChanged(status); + m_loadedURL = url; + BString status(url); + status << " finished."; + statusChanged(status); if (m_url) m_url->SetText(url.String()); - if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) - m_loadingProgressBar->Hide(); + if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) + m_loadingProgressBar->Hide(); } void LauncherWindow::titleChanged(const BString& title) { - BString windowTitle = title; - if (windowTitle.Length() > 0) - windowTitle << " - "; - windowTitle << "HaikuLauncher"; - SetTitle(windowTitle.String()); + BString windowTitle = title; + if (windowTitle.Length() > 0) + windowTitle << " - "; + windowTitle << "HaikuLauncher"; + SetTitle(windowTitle.String()); } void LauncherWindow::statusChanged(const BString& statusText) { - if (m_statusText) + if (m_statusText) m_statusText->SetText(statusText.String()); } void LauncherWindow::navigationCapabilitiesChanged(bool canGoBackward, bool canGoForward, bool canStop) { - if (m_BackButton) - m_BackButton->SetEnabled(canGoBackward); - if (m_ForwardButton) - m_ForwardButton->SetEnabled(canGoForward); + if (m_BackButton) + m_BackButton->SetEnabled(canGoBackward); + if (m_ForwardButton) + m_ForwardButton->SetEnabled(canGoForward); +} + +void LauncherWindow::authenticationChallenge(BMessage* message) +{ + BString text; + bool rememberCredentials = false; + uint32 failureCount = 0; + BString user; + BString password; + + message->FindString("text", &text); + message->FindString("user", &user); + message->FindString("password", &password); + message->FindUInt32("failureCount", &failureCount); + + AuthenticationPanel* panel = new AuthenticationPanel(Frame()); + if (!panel->getAuthentication(text, user, password, rememberCredentials, + failureCount > 0, user, password, &rememberCredentials)) { + message->SendReply((uint32)0); + return; + } + + BMessage reply; + reply.AddString("user", user); + reply.AddString("password", password); + reply.AddBool("rememberCredentials", rememberCredentials); + message->SendReply(&reply); } diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index 0760fc4280..ca4b8391b5 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -75,6 +75,7 @@ public: virtual void statusChanged(const BString& status); virtual void navigationCapabilitiesChanged(bool canGoBackward, bool canGoForward, bool canStop); + virtual void authenticationChallenge(BMessage* challenge); private: BMenuBar* m_menuBar; From b067486b740ace89fe237cb802d67213120ce0bb Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 15 Feb 2010 10:24:49 +0000 Subject: [PATCH 012/349] Fix loading links from command line args. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@83 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherApp.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 67792d13d6..019f92852e 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -77,8 +77,14 @@ void LauncherApp::AboutRequested() void LauncherApp::ArgvReceived(int32 argc, char** argv) { for (int i = 1; i < argc; i++) { + BEntry entry(argv[i], true); + if (!entry.Exists()) + continue; + BPath path; + if (entry.GetPath(&path) != B_OK) + continue; BMessage message(LOAD_AT_STARTING); - message.AddString("url", argv[i]); + message.AddString("url", path.Path()); message.AddBool("new window", m_initialized || i > 1); PostMessage(&message); } From 04730674fdcf94cf4f5fa066d602b6f9a3267993 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 15 Feb 2010 10:39:24 +0000 Subject: [PATCH 013/349] Support dropping files on LauncherWindows to load them. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@85 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 28 +++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 872da78b7f..7310925007 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -39,11 +39,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -230,6 +232,32 @@ void LauncherWindow::MessageReceived(BMessage* message) webView()->goForward(); break; + case B_SIMPLE_DATA: { + // User possibly dropped files on this window. + // If there is more than one entry_ref, let the app handle it (open one + // new page per ref). If there is one ref, open it in this window. + type_code type; + int32 countFound; + if (message->GetInfo("refs", &type, &countFound) != B_OK + || type != B_REF_TYPE) { + break; + } + if (countFound > 1) { + message->what = B_REFS_RECEIVED; + be_app->PostMessage(message); + break; + } + entry_ref ref; + if (message->FindRef("refs", &ref) != B_OK) + break; + BEntry entry(&ref, true); + BPath path; + if (!entry.Exists() || entry.GetPath(&path) != B_OK) + break; + webView()->loadRequest(path.Path()); + break; + } + case TEXT_SIZE_INCREASE: webView()->increaseTextSize(); break; From 932b58673a54e9ab739f141cb63f154c45a8a1d0 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 15 Feb 2010 12:23:17 +0000 Subject: [PATCH 014/349] Removed shortcut for testing AuthenticationPanel. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@88 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 7310925007..7fb3a366ea 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -68,8 +68,6 @@ enum { TEXT_HIDE_FIND_GROUP = 'hfnd', TEXT_FIND_NEXT = 'fndn', TEXT_FIND_PREVIOUS = 'fndp', - - TEST_AUTHENTICATION_PANEL = 'tapn' }; using namespace WebCore; @@ -204,7 +202,6 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, AddShortcut('G', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_FIND_PREVIOUS)); AddShortcut('F', B_COMMAND_KEY, new BMessage(TEXT_SHOW_FIND_GROUP)); AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_HIDE_FIND_GROUP)); - AddShortcut('T', B_COMMAND_KEY, new BMessage(TEST_AUTHENTICATION_PANEL)); navigationCapabilitiesChanged(false, false, false); From 56fc5b5b334cbcb45ac2964191eb4069bc70f43c Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 15 Feb 2010 12:23:47 +0000 Subject: [PATCH 015/349] Fix regression about opening URLs from command line args. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@89 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherApp.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 019f92852e..df664c7f5a 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -77,14 +77,13 @@ void LauncherApp::AboutRequested() void LauncherApp::ArgvReceived(int32 argc, char** argv) { for (int i = 1; i < argc; i++) { + const char* url = argv[i]; BEntry entry(argv[i], true); - if (!entry.Exists()) - continue; BPath path; - if (entry.GetPath(&path) != B_OK) - continue; + if (entry.Exists() && entry.GetPath(&path) == B_OK) + url = path.Path(); BMessage message(LOAD_AT_STARTING); - message.AddString("url", path.Path()); + message.AddString("url", url); message.AddBool("new window", m_initialized || i > 1); PostMessage(&message); } From b2b53e7c19487db73002ccd219920bc07d73feb3 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 15 Feb 2010 12:25:08 +0000 Subject: [PATCH 016/349] AuthenticationPanel: * Improved wording for persistency checkbox. * Added BTextView for displaying the info text. * Focus password input on second runs with bad password. * Enabled drawing updates for blocking windows. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@90 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/AuthenticationPanel.cpp | 59 +++++++++++++++----- 1 file changed, 46 insertions(+), 13 deletions(-) diff --git a/src/apps/webpositive/AuthenticationPanel.cpp b/src/apps/webpositive/AuthenticationPanel.cpp index a2c70c2493..cebc6e2f88 100644 --- a/src/apps/webpositive/AuthenticationPanel.cpp +++ b/src/apps/webpositive/AuthenticationPanel.cpp @@ -53,7 +53,7 @@ AuthenticationPanel::AuthenticationPanel(BRect parentFrame) , m_usernameTextControl(new BTextControl("user", "Username:", "", NULL)) , m_passwordTextControl(new BTextControl("pass", "Password:", "", NULL)) , m_hidePasswordCheckBox(new BCheckBox("hide", "Hide password text", new BMessage(kHidePassword))) - , m_remberCredentialsCheckBox(new BCheckBox("remember", "Rember this username and password", NULL)) + , m_remberCredentialsCheckBox(new BCheckBox("remember", "Rember username and password for this site", NULL)) , m_okButton(new BButton("ok", "OK", new BMessage(kMsgPanelOK))) , m_cancelButton(new BButton("cancel", "Cancel", new BMessage(B_QUIT_REQUESTED))) , m_cancelled(false) @@ -118,6 +118,15 @@ bool AuthenticationPanel::getAuthentication(const BString& text, BString& user, BString& pass, bool* rememberCredentials) { // Configure panel and layout controls. + rgb_color infoColor = ui_color(B_PANEL_TEXT_COLOR); + BRect textBounds(0, 0, 250, 200); + BTextView* textView = new BTextView(textBounds, "text", textBounds, + be_plain_font, &infoColor, B_FOLLOW_NONE, B_WILL_DRAW | B_SUPPORTS_LAYOUT); + textView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + textView->SetText(text.String()); + textView->MakeEditable(false); + textView->MakeSelectable(false); + m_usernameTextControl->SetText(previousUser.String()); m_passwordTextControl->TextView()->HideTyping(true); // Ignore the previous password, if it didn't work. @@ -130,15 +139,15 @@ bool AuthenticationPanel::getAuthentication(const BString& text, SetLayout(new BGroupLayout(B_VERTICAL)); float spacing = be_control_look->DefaultItemSpacing(); AddChild(BGroupLayoutBuilder(B_VERTICAL) - // TODO: Add text view here explaining realm and method... .Add(BGridLayoutBuilder(0, spacing) - .Add(m_usernameTextControl->CreateLabelLayoutItem(), 0, 0) - .Add(m_usernameTextControl->CreateTextViewLayoutItem(), 1, 0) - .Add(m_passwordTextControl->CreateLabelLayoutItem(), 0, 1) - .Add(m_passwordTextControl->CreateTextViewLayoutItem(), 1, 1) - .Add(BSpaceLayoutItem::CreateGlue(), 0, 2) - .Add(m_hidePasswordCheckBox, 1, 2) - .Add(m_remberCredentialsCheckBox, 0, 3, 2) + .Add(textView, 0, 0, 2) + .Add(m_usernameTextControl->CreateLabelLayoutItem(), 0, 1) + .Add(m_usernameTextControl->CreateTextViewLayoutItem(), 1, 1) + .Add(m_passwordTextControl->CreateLabelLayoutItem(), 0, 2) + .Add(m_passwordTextControl->CreateTextViewLayoutItem(), 1, 2) + .Add(BSpaceLayoutItem::CreateGlue(), 0, 3) + .Add(m_hidePasswordCheckBox, 1, 3) + .Add(m_remberCredentialsCheckBox, 0, 4, 2) .SetInsets(spacing, spacing, spacing, spacing) ) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) @@ -150,8 +159,14 @@ bool AuthenticationPanel::getAuthentication(const BString& text, ) ); + float textHeight = textView->LineHeight(0) * textView->CountLines(); + textView->SetExplicitMinSize(BSize(B_SIZE_UNSET, textHeight)); + SetDefaultButton(m_okButton); - m_usernameTextControl->MakeFocus(true); + if (badPassword && previousUser.Length()) + m_passwordTextControl->MakeFocus(true); + else + m_usernameTextControl->MakeFocus(true); if (m_parentWindowFrame.IsValid()) CenterIn(m_parentWindowFrame); @@ -166,9 +181,27 @@ bool AuthenticationPanel::getAuthentication(const BString& text, PostMessage(kMsgJitter); // Block calling thread - // TODO: When called from other window threads, this should periodically - // call UpdateIfNeeded()... - acquire_sem(m_exitSemaphore); + // Get the originating window, if it exists, to let it redraw itself. + BWindow* window = dynamic_cast(BLooper::LooperForThread(find_thread(NULL))); + if (window) { + status_t err; + for (;;) { + do { + err = acquire_sem_etc(m_exitSemaphore, 1, B_RELATIVE_TIMEOUT, 10000); + // We've (probably) had our time slice taken away from us + } while (err == B_INTERRUPTED); + + if (err != B_TIMED_OUT) { + // Semaphore was finally released or nuked. + break; + } + window->UpdateIfNeeded(); + } + } else { + // No window to update, so just hang out until we're done. + while (acquire_sem(m_exitSemaphore) == B_INTERRUPTED) { + } + } // AuthenticationPanel wants to quit. Lock(); From 77d2abe296cba1de16ae16bdaf53300b44efde08 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 15 Feb 2010 14:06:28 +0000 Subject: [PATCH 017/349] First structure of BrowsingHistory. Does nothing, but can in theory save settings. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@91 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowsingHistory.cpp | 83 ++++++++++++++++++++++++ src/apps/webpositive/BrowsingHistory.h | 51 +++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 src/apps/webpositive/BrowsingHistory.cpp create mode 100644 src/apps/webpositive/BrowsingHistory.h diff --git a/src/apps/webpositive/BrowsingHistory.cpp b/src/apps/webpositive/BrowsingHistory.cpp new file mode 100644 index 0000000000..e70d3c0e03 --- /dev/null +++ b/src/apps/webpositive/BrowsingHistory.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "BrowsingHistory.h" + +#include +#include +#include +#include +#include +#include + + +BrowsingHistory BrowsingHistory::s_defaultInstance; + +BrowsingHistory::BrowsingHistory() + : BLocker("browsing history") +{ + BFile settingsFile; + if (openSettingsFile(settingsFile, B_READ_ONLY)) { + BMessage settingsArchive; + settingsArchive.Unflatten(&settingsFile); + // TODO: ... + } +} + +BrowsingHistory::~BrowsingHistory() +{ + saveSettings(); +} + +/*static*/ BrowsingHistory* BrowsingHistory::defaultInstance() +{ + return &s_defaultInstance; +} + +// #pragma mark - private + +void BrowsingHistory::saveSettings() +{ + BFile settingsFile; + if (openSettingsFile(settingsFile, B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) { + BMessage settingsArchive; + // TODO: ... + settingsArchive.Flatten(&settingsFile); + } +} + +bool BrowsingHistory::openSettingsFile(BFile& file, uint32 mode) +{ + BPath path; + if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK + || path.Append("HaikuLauncher_BrowsingHistory") != B_OK) { + return false; + } + return file.SetTo(path.Path(), mode) == B_OK; +} + diff --git a/src/apps/webpositive/BrowsingHistory.h b/src/apps/webpositive/BrowsingHistory.h new file mode 100644 index 0000000000..82ef0ba04f --- /dev/null +++ b/src/apps/webpositive/BrowsingHistory.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BrowsingHistory_h +#define BrowsingHistory_h + +#include + +class BFile; + +class BrowsingHistory : public BLocker { +public: + static BrowsingHistory* defaultInstance(); + +private: + BrowsingHistory(); + virtual ~BrowsingHistory(); + + void saveSettings(); + bool openSettingsFile(BFile& file, uint32 mode); + +private: + static BrowsingHistory s_defaultInstance; +}; + +#endif // BrowsingHistory_h + From 4e703b4b2f21ca170a7700241426abfad821bd8e Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 15 Feb 2010 15:58:35 +0000 Subject: [PATCH 018/349] Patch by Rene Gollent, which fixes some typos. Thanks! git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@92 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/AuthenticationPanel.cpp | 8 ++++---- src/apps/webpositive/AuthenticationPanel.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/apps/webpositive/AuthenticationPanel.cpp b/src/apps/webpositive/AuthenticationPanel.cpp index cebc6e2f88..8d81bbb311 100644 --- a/src/apps/webpositive/AuthenticationPanel.cpp +++ b/src/apps/webpositive/AuthenticationPanel.cpp @@ -53,7 +53,7 @@ AuthenticationPanel::AuthenticationPanel(BRect parentFrame) , m_usernameTextControl(new BTextControl("user", "Username:", "", NULL)) , m_passwordTextControl(new BTextControl("pass", "Password:", "", NULL)) , m_hidePasswordCheckBox(new BCheckBox("hide", "Hide password text", new BMessage(kHidePassword))) - , m_remberCredentialsCheckBox(new BCheckBox("remember", "Rember username and password for this site", NULL)) + , m_rememberCredentialsCheckBox(new BCheckBox("remember", "Remember username and password for this site", NULL)) , m_okButton(new BButton("ok", "OK", new BMessage(kMsgPanelOK))) , m_cancelButton(new BButton("cancel", "Cancel", new BMessage(B_QUIT_REQUESTED))) , m_cancelled(false) @@ -133,7 +133,7 @@ bool AuthenticationPanel::getAuthentication(const BString& text, if (!badPassword) m_passwordTextControl->SetText(previousPass.String()); m_hidePasswordCheckBox->SetValue(B_CONTROL_ON); - m_remberCredentialsCheckBox->SetValue(previousRememberCredentials); + m_rememberCredentialsCheckBox->SetValue(previousRememberCredentials); // create layout SetLayout(new BGroupLayout(B_VERTICAL)); @@ -147,7 +147,7 @@ bool AuthenticationPanel::getAuthentication(const BString& text, .Add(m_passwordTextControl->CreateTextViewLayoutItem(), 1, 2) .Add(BSpaceLayoutItem::CreateGlue(), 0, 3) .Add(m_hidePasswordCheckBox, 1, 3) - .Add(m_remberCredentialsCheckBox, 0, 4, 2) + .Add(m_rememberCredentialsCheckBox, 0, 4, 2) .SetInsets(spacing, spacing, spacing, spacing) ) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) @@ -209,7 +209,7 @@ bool AuthenticationPanel::getAuthentication(const BString& text, user = m_usernameTextControl->Text(); pass = m_passwordTextControl->Text(); if (rememberCredentials) - *rememberCredentials = m_remberCredentialsCheckBox->Value() == B_CONTROL_ON; + *rememberCredentials = m_rememberCredentialsCheckBox->Value() == B_CONTROL_ON; bool canceled = m_cancelled; Quit(); diff --git a/src/apps/webpositive/AuthenticationPanel.h b/src/apps/webpositive/AuthenticationPanel.h index 568f22d1f4..5af9496aad 100644 --- a/src/apps/webpositive/AuthenticationPanel.h +++ b/src/apps/webpositive/AuthenticationPanel.h @@ -53,7 +53,7 @@ private: BTextControl* m_usernameTextControl; BTextControl* m_passwordTextControl; BCheckBox* m_hidePasswordCheckBox; - BCheckBox* m_remberCredentialsCheckBox; + BCheckBox* m_rememberCredentialsCheckBox; BButton* m_okButton; BButton* m_cancelButton; From dad9d4a5a4e0f627fa2b11ff1cac30c8118bf575 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 15 Feb 2010 16:22:13 +0000 Subject: [PATCH 019/349] Added BDateTime stuff from Haiku, and addd archiving features to these classes. Needs to be put back into Haiku and made public API eventually. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@93 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DateTime.cpp | 1367 +++++++++++++++++++++++++++++ src/apps/webpositive/DateTime.h | 215 +++++ 2 files changed, 1582 insertions(+) create mode 100644 src/apps/webpositive/DateTime.cpp create mode 100644 src/apps/webpositive/DateTime.h diff --git a/src/apps/webpositive/DateTime.cpp b/src/apps/webpositive/DateTime.cpp new file mode 100644 index 0000000000..7818dc36c2 --- /dev/null +++ b/src/apps/webpositive/DateTime.cpp @@ -0,0 +1,1367 @@ +/* + * Copyright 2007-2010, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Julun + * Stephan Aßmus + */ + +#include "DateTime.h" + + +#include +#include + +#include + + +namespace BPrivate { + + +const int32 kSecondsPerMinute = 60; + +const int32 kHoursPerDay = 24; +const int32 kMinutesPerDay = 1440; +const int32 kSecondsPerDay = 86400; +const int32 kMillisecondsPerDay = 86400000; + +const bigtime_t kMicrosecondsPerSecond = 1000000LL; +const bigtime_t kMicrosecondsPerMinute = 60000000LL; +const bigtime_t kMicrosecondsPerHour = 3600000000LL; +const bigtime_t kMicrosecondsPerDay = 86400000000LL; + + +/*! + Constructs a new BTime object. Asked for its time representation, it will + return 0 for Hour(), Minute(), Second() etc. This can represent midnight, + but be aware IsValid() will return false. +*/ +BTime::BTime() + : fMicroseconds(-1) +{ +} + + +/*! + Constructs a BTime object with \c hour \c minute, \c second, \c microsecond. + + \c hour must be between 0 and 23, \c minute and \c second must be between + 0 and 59 and \c microsecond should be in the range of 0 and 999999. If the + specified time is invalid, the time is not set and IsValid() returns false. +*/ +BTime::BTime(int32 hour, int32 minute, int32 second, int32 microsecond) + : fMicroseconds(-1) +{ + _SetTime(hour, minute, second, microsecond); +} + + +/*! + Constructs a new BTime object from the provided BMessage archive. +*/ +BTime::BTime(const BMessage* archive) + : fMicroseconds(-1) +{ + if (archive == NULL) + return; + archive->FindInt64("mircoseconds", &fMicroseconds); +} + + +/*! + Empty destructor. +*/ +BTime::~BTime() +{ +} + + +/*! + Archives the BTime object into the provided BMessage object. + @returns \c B_OK if all went well. + \c B_BAD_VALUE, if the message is \c NULL. + \c other error codes, depending on failure to append + fields to the message. +*/ +status_t +BTime::Archive(BMessage* into) const +{ + if (into == NULL) + return B_BAD_VALUE; + return into->AddInt64("mircoseconds", fMicroseconds); +} + + +/*! + Returns true if the time is valid, otherwise false. A valid time can be + BTime(23, 59, 59, 999999) while BTime(24, 00, 01) would be invalid. +*/ +bool +BTime::IsValid() const +{ + return fMicroseconds > -1 && fMicroseconds < kMicrosecondsPerDay; +} + + +/*! + This is an overloaded member function, provided for convenience. +*/ +bool +BTime::IsValid(const BTime& time) const +{ + return time.fMicroseconds > -1 && time.fMicroseconds < kMicrosecondsPerDay; +} + + +/*! + This is an overloaded member function, provided for convenience. +*/ +bool +BTime::IsValid(int32 hour, int32 minute, int32 second, int32 microsecond) const +{ + return BTime(hour, minute, second, microsecond).IsValid(); +} + + +/*! + Returns the current time as reported by the system depending on the given + time_type \c type. +*/ +BTime +BTime::CurrentTime(time_type type) +{ + struct timeval tv; + if (gettimeofday(&tv, NULL) != 0) { + // gettimeofday failed? + time(&tv.tv_sec); + } + + struct tm result; + struct tm* timeinfo; + if (type == B_GMT_TIME) + timeinfo = gmtime_r(&tv.tv_sec, &result); + else + timeinfo = localtime_r(&tv.tv_sec, &result); + + int32 sec = timeinfo->tm_sec; + return BTime(timeinfo->tm_hour, timeinfo->tm_min, (sec > 59) ? 59 : sec, + tv.tv_usec); +} + + +/*! + Returns a copy of the current BTime object. +*/ +BTime +BTime::Time() const +{ + return *this; +} + + +/*! + This is an overloaded member function, provided for convenience. Set the + current BTime object to the passed BTime \c time object. +*/ +bool +BTime::SetTime(const BTime& time) +{ + fMicroseconds = time.fMicroseconds; + return IsValid(); +} + + +/*! + Set the time to \c hour \c minute, \c second and \c microsecond. + + \c hour must be between 0 and 23, \c minute and \c second must be between + 0 and 59 and \c microsecond should be in the range of 0 and 999999. Returns + true if the time is valid; otherwise false. If the specified time is + invalid, the time is not set and the function returns false. +*/ +bool +BTime::SetTime(int32 hour, int32 minute, int32 second, int32 microsecond) +{ + return _SetTime(hour, minute, second, microsecond); +} + + + +/*! + Adds \c hours to the current time. If the passed value is negativ it will + become earlier. Note: The time will wrap if it passes midnight. +*/ +void +BTime::AddHours(int32 hours) +{ + _AddMicroseconds(bigtime_t(hours % kHoursPerDay) * kMicrosecondsPerHour); +} + + +/*! + Adds \c minutes to the current time. If the passed value is negativ it will + become earlier. Note: The time will wrap if it passes midnight. +*/ +void +BTime::AddMinutes(int32 minutes) +{ + _AddMicroseconds(bigtime_t(minutes % kMinutesPerDay) * + kMicrosecondsPerMinute); +} + + +/*! + Adds \c seconds to the current time. If the passed value is negativ it will + become earlier. Note: The time will wrap if it passes midnight. +*/ +void +BTime::AddSeconds(int32 seconds) +{ + _AddMicroseconds(bigtime_t(seconds % kSecondsPerDay) * + kMicrosecondsPerSecond); +} + + +/*! + Adds \c milliseconds to the current time. If the passed value is negativ it + will become earlier. Note: The time will wrap if it passes midnight. +*/ +void +BTime::AddMilliseconds(int32 milliseconds) +{ + _AddMicroseconds(bigtime_t(milliseconds % kMillisecondsPerDay) * 1000); +} + + +/*! + Adds \c microseconds to the current time. If the passed value is negativ it + will become earlier. Note: The time will wrap if it passes midnight. +*/ +void +BTime::AddMicroseconds(int32 microseconds) +{ + _AddMicroseconds(microseconds); +} + + +/*! + Returns the hour fragment of the time. +*/ +int32 +BTime::Hour() const +{ + return int32(_Microseconds() / kMicrosecondsPerHour); +} + + +/*! + Returns the minute fragment of the time. +*/ +int32 +BTime::Minute() const +{ + return int32(((_Microseconds() % kMicrosecondsPerHour)) / kMicrosecondsPerMinute); +} + + +/*! + Returns the second fragment of the time. +*/ +int32 +BTime::Second() const +{ + return int32(_Microseconds() / kMicrosecondsPerSecond) % kSecondsPerMinute; +} + + +/*! + Returns the millisecond fragment of the time. +*/ +int32 +BTime::Millisecond() const +{ + + return Microsecond() / 1000; +} + + +/*! + Returns the microsecond fragment of the time. +*/ +int32 +BTime::Microsecond() const +{ + return int32(_Microseconds() % 1000000); +} + + +bigtime_t +BTime::_Microseconds() const +{ + return fMicroseconds == -1 ? 0 : fMicroseconds; +} + + +/*! + Returns the difference between this time and the given BTime \c time based + on the passed diff_type \c type. If \c time is earlier the return value will + be negativ. + + The return value then can be hours, minutes, seconds, milliseconds or + microseconds while its range will always be between -86400000000 and + 86400000000 depending on diff_type \c type. +*/ +bigtime_t +BTime::Difference(const BTime& time, diff_type type) const +{ + bigtime_t diff = time._Microseconds() - _Microseconds(); + switch (type) { + case B_HOURS_DIFF: { + diff /= kMicrosecondsPerHour; + } break; + case B_MINUTES_DIFF: { + diff /= kMicrosecondsPerMinute; + } break; + case B_SECONDS_DIFF: { + diff /= kMicrosecondsPerSecond; + } break; + case B_MILLISECONDS_DIFF: { + diff /= 1000; + } break; + case B_MICROSECONDS_DIFF: + default: break; + } + return diff; +} + + +/*! + Returns true if this time is different from \c time, otherwise false. +*/ +bool +BTime::operator!=(const BTime& time) const +{ + return fMicroseconds != time.fMicroseconds; +} + + +/*! + Returns true if this time is equal to \c time, otherwise false. +*/ +bool +BTime::operator==(const BTime& time) const +{ + return fMicroseconds == time.fMicroseconds; +} + + +/*! + Returns true if this time is earlier than \c time, otherwise false. +*/ +bool +BTime::operator<(const BTime& time) const +{ + return fMicroseconds < time.fMicroseconds; +} + + +/*! + Returns true if this time is earlier than or equal to \c time, otherwise false. +*/ +bool +BTime::operator<=(const BTime& time) const +{ + return fMicroseconds <= time.fMicroseconds; +} + + +/*! + Returns true if this time is later than \c time, otherwise false. +*/ +bool +BTime::operator>(const BTime& time) const +{ + return fMicroseconds > time.fMicroseconds; +} + + +/*! + Returns true if this time is later than or equal to \c time, otherwise false. +*/ +bool +BTime::operator>=(const BTime& time) const +{ + return fMicroseconds >= time.fMicroseconds; +} + + +void +BTime::_AddMicroseconds(bigtime_t microseconds) +{ + bigtime_t count = 0; + if (microseconds < 0) { + count = ((kMicrosecondsPerDay - microseconds) / kMicrosecondsPerDay) * + kMicrosecondsPerDay; + } + fMicroseconds = (_Microseconds() + microseconds + count) % kMicrosecondsPerDay; +} + + +bool +BTime::_SetTime(bigtime_t hour, bigtime_t minute, bigtime_t second, + bigtime_t microsecond) +{ + fMicroseconds = hour * kMicrosecondsPerHour + + minute * kMicrosecondsPerMinute + + second * kMicrosecondsPerSecond + + microsecond; + + bool isValid = IsValid(); + if (!isValid) + fMicroseconds = -1; + + return isValid; +} + + +// #pragma mark - BDate + + +/*! + Constructs a new BDate object. IsValid() will return false. +*/ +BDate::BDate() + : fDay(-1), + fYear(0), + fMonth(-1) +{ +} + + +/*! + Constructs a BDate object with \c year \c month and \c day. + + Please note that a date before 1.1.4713 BC, a date with year 0 and a date + between 4.10.1582 and 15.10.1582 are considered invalid. If the specified + date is invalid, the date is not set and IsValid() returns false. Also note + that every passed year will be interpreted as is. + +*/ +BDate::BDate(int32 year, int32 month, int32 day) +{ + _SetDate(year, month, day); +} + + +/*! + Constructs a new BDate object from the provided archive. +*/ +BDate::BDate(const BMessage* archive) + : fDay(-1), + fYear(0), + fMonth(-1) +{ + if (archive == NULL) + return; + archive->FindInt32("day", &fDay); + archive->FindInt32("year", &fYear); + archive->FindInt32("month", &fMonth); +} + + +/*! + Empty destructor. +*/ +BDate::~BDate() +{ +} + + +/*! + Archives the BDate object into the provided BMessage object. + @returns \c B_OK if all went well. + \c B_BAD_VALUE, if the message is \c NULL. + \c other error codes, depending on failure to append + fields to the message. +*/ +status_t +BDate::Archive(BMessage* into) const +{ + if (into == NULL) + return B_BAD_VALUE; + status_t ret = into->AddInt32("day", fDay); + if (ret == B_OK) + ret = into->AddInt32("year", fYear); + if (ret == B_OK) + ret = into->AddInt32("month", fMonth); + return ret; +} + + +/*! + Returns true if the date is valid, otherwise false. + + Please note that a date before 1.1.4713 BC, a date with year 0 and a date + between 4.10.1582 and 15.10.1582 are considered invalid. +*/ +bool +BDate::IsValid() const +{ + return IsValid(fYear, fMonth, fDay); +} + + +/*! + This is an overloaded member function, provided for convenience. +*/ +bool +BDate::IsValid(const BDate& date) const +{ + return IsValid(date.fYear, date.fMonth, date.fDay); +} + + +/*! + This is an overloaded member function, provided for convenience. +*/ +bool +BDate::IsValid(int32 year, int32 month, int32 day) const +{ + // no year 0 in Julian and nothing before 1.1.4713 BC + if (year == 0 || year < -4713) + return false; + + if (month < 1 || month > 12) + return false; + + if (day < 1 || day > _DaysInMonth(year, month)) + return false; + + // 'missing' days between switch julian - gregorian + if (year == 1582 && month == 10 && day > 4 && day < 15) + return false; + + return true; +} + + +/*! + Returns the current date as reported by the system depending on the given + time_type \c type. +*/ +BDate +BDate::CurrentDate(time_type type) +{ + time_t timer; + struct tm result; + struct tm* timeinfo; + + time(&timer); + + if (type == B_GMT_TIME) + timeinfo = gmtime_r(&timer, &result); + else + timeinfo = localtime_r(&timer, &result); + + return BDate(timeinfo->tm_year + 1900, timeinfo->tm_mon +1, timeinfo->tm_mday); +} + + +/*! + Returns a copy of the current BTime object. +*/ +BDate +BDate::Date() const +{ + return *this; +} + + +/*! + This is an overloaded member function, provided for convenience. +*/ +bool +BDate::SetDate(const BDate& date) +{ + return _SetDate(date.fYear, date.fMonth, date.fDay); +} + + +/*! + Set the date to \c year \c month and \c day. + + Returns true if the date is valid; otherwise false. If the specified date is + invalid, the date is not set and the function returns false. +*/ +bool +BDate::SetDate(int32 year, int32 month, int32 day) +{ + return _SetDate(year, month, day); +} + + +/*! + This function sets the given \c year, \c month and \c day to the + representative values of this date. The pointers can be NULL. If the date is + invalid, the values will be set to -1 for \c month and \c day, the \c year + will be set to 0. +*/ +void +BDate::GetDate(int32* year, int32* month, int32* day) +{ + if (year) + *year = fYear; + + if (month) + *month = fMonth; + + if (day) + *day = fDay; +} + + +/*! + Adds \c days to the current date. If the passed value is negativ it will + become earlier. If the current date is invalid, the \c days are not added. +*/ +void +BDate::AddDays(int32 days) +{ + if (IsValid()) + *this = JulianDayToDate(DateToJulianDay() + days); +} + + +/*! + Adds \c years to the current date. If the passed value is negativ it will + become earlier. If the current date is invalid, the \c years are not added. + The day/ month combination will be adjusted if it does not exist in the + resulting year, so this function will then return the latest valid date. +*/ +void +BDate::AddYears(int32 years) +{ + if (IsValid()) { + const int32 tmp = fYear; + fYear += years; + + if ((tmp > 0 && fYear <= 0) || (tmp < 0 && fYear >= 0)) + fYear += (years > 0) ? +1 : -1; + + fDay = min_c(fDay, _DaysInMonth(fYear, fMonth)); + } +} + + +/*! + Adds \c months to the current date. If the passed value is negativ it will + become earlier. If the current date is invalid, the \c months are not added. + The day/ month combination will be adjusted if it does not exist in the + resulting year, so this function will then return the latest valid date. +*/ +void +BDate::AddMonths(int32 months) +{ + if (IsValid()) { + const int32 tmp = fYear; + fYear += months / 12; + fMonth += months % 12; + + if (fMonth > 12) { + fYear++; + fMonth -= 12; + } else if (fMonth < 1) { + fYear--; + fMonth += 12; + } + + if ((tmp > 0 && fYear <= 0) || (tmp < 0 && fYear >= 0)) + fYear += (months > 0) ? +1 : -1; + + // 'missing' days between switch julian - gregorian + if (fYear == 1582 && fMonth == 10 && fDay > 4 && fDay < 15) + fDay = (months > 0) ? 15 : 4; + + fDay = min_c(fDay, DaysInMonth()); + } +} + + +/*! + Returns the day fragment of the date. The return value will be in the range + of 1 to 31, in case the date is invalid it will be -1. +*/ +int32 +BDate::Day() const +{ + return fDay; +} + + +/*! + Returns the year fragment of the date. If the date is invalid, the function + returns 0. +*/ +int32 +BDate::Year() const +{ + return fYear; +} + + +/*! + Returns the month fragment of the date. The return value will be in the + range of 1 to 12, in case the date is invalid it will be -1. +*/ +int32 +BDate::Month() const +{ + return fMonth; +} + + +/*! + Returns the difference in days between this date and the given BDate \c date. + If \c date is earlier the return value will be negativ. If the calculation + is done with an invalid date, the result is undefined. +*/ +int32 +BDate::Difference(const BDate& date) const +{ + return date.DateToJulianDay() - DateToJulianDay(); +} + + +/*! + Returns the week number of the date, if the date is invalid it will return + B_ERROR. Please note that this function does only work within the Gregorian + calendar, thus a date before 15.10.1582 will return B_ERROR. +*/ +int32 +BDate::WeekNumber() const +{ + /* + This algorithm is taken from: + Frequently Asked Questions about Calendars + Version 2.8 Claus Tøndering 15 December 2005 + + Note: it will work only within the Gregorian Calendar + */ + + if (!IsValid() || fYear < 1582 + || (fYear == 1582 && fMonth < 10) + || (fYear == 1582 && fMonth == 10 && fDay < 15)) + return int32(B_ERROR); + + int32 a; + int32 b; + int32 s; + int32 e; + int32 f; + + if (fMonth > 0 && fMonth < 3) { + a = fYear - 1; + b = (a / 4) - (a / 100) + (a / 400); + int32 c = ((a - 1) / 4) - ((a - 1) / 100) + ((a -1) / 400); + s = b - c; + e = 0; + f = fDay - 1 + 31 * (fMonth - 1); + } else if (fMonth >= 3 && fMonth <= 12) { + a = fYear; + b = (a / 4) - (a / 100) + (a / 400); + int32 c = ((a - 1) / 4) - ((a - 1) / 100) + ((a -1) / 400); + s = b - c; + e = s + 1; + f = fDay + ((153 * (fMonth - 3) + 2) / 5) + 58 + s; + } else + return int32(B_ERROR); + + int32 g = (a + b) % 7; + int32 d = (f + g - e) % 7; + int32 n = f + 3 - d; + + int32 weekNumber; + if (n < 0) + weekNumber = 53 - (g -s) / 5; + else if (n > 364 + s) + weekNumber = 1; + else + weekNumber = n / 7 + 1; + + return weekNumber; +} + + +/*! + Returns the day of the week in the range of 1 to 7, while 1 stands for + monday. If the date is invalid, the function will return B_ERROR. +*/ +int32 +BDate::DayOfWeek() const +{ + // http://en.wikipedia.org/wiki/Julian_day#Calculation + return IsValid() ? (DateToJulianDay() % 7) + 1 : int32(B_ERROR); +} + + +/*! + Returns the day of the year in the range of 1 to 365 (366 in leap years). If + the date is invalid, the function will return B_ERROR. +*/ +int32 +BDate::DayOfYear() const +{ + if (!IsValid()) + return int32(B_ERROR); + + return DateToJulianDay() - _DateToJulianDay(fYear, 1, 1) + 1; +} + + +/*! + Returns true if the passed \c year is a leap year, otherwise false. If the + \c year passed is before 4713 BC, the result is undefined. +*/ +bool +BDate::IsLeapYear(int32 year) const +{ + if (year < 1582) { + if (year < 0) + year++; + return (year % 4) == 0; + } + return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0); +} + + +/*! + Returns the number of days in the year of the current date. If the date is + valid it will return 365 or 366, otherwise B_ERROR; +*/ +int32 +BDate::DaysInYear() const +{ + if (!IsValid()) + return int32(B_ERROR); + + return IsLeapYear(fYear) ? 366 : 365; +} + + +/*! + Returns the number of days in the month of the current date. If the date is + valid it will return 28 up to 31, otherwise B_ERROR; +*/ +int32 +BDate::DaysInMonth() const +{ + if (!IsValid()) + return int32(B_ERROR); + + return _DaysInMonth(fYear, fMonth); +} + + +/*! + Returns the short day name in case of an valid day, otherwise an empty + string. The passed \c day must be in the range of 1 to 7 while 1 stands for + monday. +*/ +BString +BDate::ShortDayName(int32 day) const +{ + if (day < 1 || day > 7) + return BString(); + + tm tm_struct; + memset(&tm_struct, 0, sizeof(tm)); + tm_struct.tm_wday = day == 7 ? 0 : day; + + char buffer[256]; + strftime(buffer, sizeof(buffer), "%a", &tm_struct); + + return BString(buffer); +} + + +/*! + Returns the short month name in case of an valid month, otherwise an empty + string. The passed \c month must be in the range of 1 to 12. +*/ +BString +BDate::ShortMonthName(int32 month) const +{ + if (month < 1 || month > 12) + return BString(); + + tm tm_struct; + memset(&tm_struct, 0, sizeof(tm)); + tm_struct.tm_mon = month - 1; + + char buffer[256]; + strftime(buffer, sizeof(buffer), "%b", &tm_struct); + + return BString(buffer); +} + + +/*! + Returns the long day name in case of an valid day, otherwise an empty + string. The passed \c day must be in the range of 1 to 7 while 1 stands for + monday. +*/ +BString +BDate::LongDayName(int32 day) const +{ + if (day < 1 || day > 7) + return BString(); + + tm tm_struct; + memset(&tm_struct, 0, sizeof(tm)); + tm_struct.tm_wday = day == 7 ? 0 : day; + + char buffer[256]; + strftime(buffer, sizeof(buffer), "%A", &tm_struct); + + return BString(buffer); +} + + +/*! + Returns the long month name in case of an valid month, otherwise an empty + string. The passed \c month must be in the range of 1 to 12. +*/ +BString +BDate::LongMonthName(int32 month) const +{ + if (month < 1 || month > 12) + return BString(); + + tm tm_struct; + memset(&tm_struct, 0, sizeof(tm)); + tm_struct.tm_mon = month - 1; + + char buffer[256]; + strftime(buffer, sizeof(buffer), "%B", &tm_struct); + + return BString(buffer); +} + + +/*! + Converts the date to Julian day. If your date is invalid, the function will + return B_ERROR. +*/ +int32 +BDate::DateToJulianDay() const +{ + return _DateToJulianDay(fYear, fMonth, fDay); +} + + +/* + Converts the passed \c julianDay to an BDate. If the \c julianDay is negativ, + the function will return an invalid date. Because of the switch from Julian + calendar to Gregorian calendar the 4.10.1582 is followed by the 15.10.1582. +*/ +BDate +BDate::JulianDayToDate(int32 julianDay) +{ + BDate date; + const int32 kGregorianCalendarStart = 2299161; + if (julianDay >= kGregorianCalendarStart) { + // http://en.wikipedia.org/wiki/Julian_day#Gregorian_calendar_from_Julian_day_number + int32 j = julianDay + 32044; + int32 dg = j % 146097; + int32 c = (dg / 36524 + 1) * 3 / 4; + int32 dc = dg - c * 36524; + int32 db = dc % 1461; + int32 a = (db / 365 + 1) * 3 / 4; + int32 da = db - a * 365; + int32 m = (da * 5 + 308) / 153 - 2; + date.fYear = ((j / 146097) * 400 + c * 100 + (dc / 1461) * 4 + a) - 4800 + + (m + 2) / 12; + date.fMonth = (m + 2) % 12 + 1; + date.fDay = int32((da - (m + 4) * 153 / 5 + 122) + 1.5); + } else if (julianDay >= 0) { + // http://en.wikipedia.org/wiki/Julian_day#Calculation + julianDay += 32082; + int32 d = (4 * julianDay + 3) / 1461; + int32 e = julianDay - (1461 * d) / 4; + int32 m = ((5 * e) + 2) / 153; + date.fDay = e - (153 * m + 2) / 5 + 1; + date.fMonth = m + 3 - 12 * (m / 10); + int32 year = d - 4800 + (m / 10); + if (year <= 0) + year--; + date.fYear = year; + } + return date; +} + + +/*! + Returns true if this date is different from \c date, otherwise false. +*/ +bool +BDate::operator!=(const BDate& date) const +{ + return DateToJulianDay() != date.DateToJulianDay(); +} + + +/*! + Returns true if this date is equal to \c date, otherwise false. +*/ +bool +BDate::operator==(const BDate& date) const +{ + return DateToJulianDay() == date.DateToJulianDay(); +} + + +/*! + Returns true if this date is earlier than \c date, otherwise false. +*/ +bool +BDate::operator<(const BDate& date) const +{ + return DateToJulianDay() < date.DateToJulianDay(); +} + + +/*! + Returns true if this date is earlier than or equal to \c date, otherwise false. +*/ +bool +BDate::operator<=(const BDate& date) const +{ + return DateToJulianDay() <= date.DateToJulianDay(); +} + + +/*! + Returns true if this date is later than \c date, otherwise false. +*/ +bool +BDate::operator>(const BDate& date) const +{ + return DateToJulianDay() > date.DateToJulianDay(); +} + + +/*! + Returns true if this date is later than or equal to \c date, otherwise false. +*/ +bool +BDate::operator>=(const BDate& date) const +{ + return DateToJulianDay() >= date.DateToJulianDay(); +} + + +bool +BDate::_SetDate(int32 year, int32 month, int32 day) +{ + fDay = -1; + fYear = 0; + fMonth = -1; + + bool valid = IsValid(year, month, day); + if (valid) { + fDay = day; + fYear = year; + fMonth = month; + } + + return valid; +} + + +int32 +BDate::_DaysInMonth(int32 year, int32 month) const +{ + if (month == 2 && IsLeapYear(year)) + return 29; + + const int32 daysInMonth[12] = + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + return daysInMonth[month -1]; +} + + +int32 +BDate::_DateToJulianDay(int32 _year, int32 month, int32 day) const +{ + if (IsValid(_year, month, day)) { + int32 year = _year; + if (year < 0) year++; + + int32 a = (14 - month) / 12; + int32 y = year + 4800 - a; + int32 m = month + (12 * a) - 3; + + // http://en.wikipedia.org/wiki/Julian_day#Calculation + if (year > 1582 + || (year == 1582 && month > 10) + || (year == 1582 && month == 10 && day >= 15)) { + return day + (((153 * m) + 2) / 5) + (365 * y) + (y / 4) - + (y / 100) + (y / 400) - 32045; + } else if (year < 1582 + || (year == 1582 && month < 10) + || (year == 1582 && month == 10 && day <= 4)) { + return day + (((153 * m) + 2) / 5) + (365 * y) + (y / 4) - 32083; + } + } + + // http://en.wikipedia.org/wiki/Gregorian_calendar: + // The last day of the Julian calendar was Thursday October 4, 1582 + // and this was followed by the first day of the Gregorian calendar, + // Friday October 15, 1582 (the cycle of weekdays was not affected). + return int32(B_ERROR); +} + + +// #pragma mark - BDateTime + + +/*! + Constructs a new BDateTime object. IsValid() will return false. +*/ +BDateTime::BDateTime() + : fDate(), + fTime() +{ +} + + +/*! + Constructs a BDateTime object with \c date and \c time. The return value + of IsValid() depends on the validity of the passed objects. +*/ +BDateTime::BDateTime(const BDate& date, const BTime& time) + : fDate(date), + fTime(time) +{ +} + + +/*! + Constructs a new BDateTime object. IsValid() will return false. +*/ +BDateTime::BDateTime(const BMessage* archive) + : fDate(archive), + fTime(archive) +{ +} + + +/*! + Empty destructor. +*/ +BDateTime::~BDateTime() +{ +} + + +/*! + Archives the BDateTime object into the provided BMessage object. + @returns \c B_OK if all went well. + \c B_BAD_VALUE, if the message is \c NULL. + \c other error codes, depending on failure to append + fields to the message. +*/ +status_t +BDateTime::Archive(BMessage* into) const +{ + status_t ret = fDate.Archive(into); + if (ret == B_OK) + ret = fTime.Archive(into); + return ret; +} + + +/*! + Returns true if the date time is valid, otherwise false. +*/ +bool +BDateTime::IsValid() const +{ + return fDate.IsValid() && fTime.IsValid(); +} + + +/*! + Returns the current date and time as reported by the system depending on the + given time_type \c type. +*/ +BDateTime +BDateTime::CurrentDateTime(time_type type) +{ + return BDateTime(BDate::CurrentDate(type), BTime::CurrentTime(type)); +} + + +/*! + Sets the current date and time of this object to \c date and \c time. +*/ +void +BDateTime::SetDateTime(const BDate& date, const BTime& time) +{ + fDate = date; + fTime = time; +} + + +/*! + Returns the current date of this object. +*/ +BDate +BDateTime::Date() const +{ + return fDate; +} + + +/*! + Set the current date of this object to \c date. +*/ +void +BDateTime::SetDate(const BDate& date) +{ + fDate = date; +} + + +/*! + Returns the current time of this object. +*/ +BTime +BDateTime::Time() const +{ + return fTime; +} + + +/*! + Sets the current time of this object to \c time. +*/ +void +BDateTime::SetTime(const BTime& time) +{ + fTime = time; +} + + +/*! + Returns the current date and time converted to seconds since + 1.1.1970 - 00:00:00. If the current date is before 1.1.1970 the function + returns -1; +*/ +int32 +BDateTime::Time_t() const +{ + BDate date(1970, 1, 1); + if (date.Difference(fDate) < 0) + return -1; + + tm tm_struct; + + tm_struct.tm_hour = fTime.Hour(); + tm_struct.tm_min = fTime.Minute(); + tm_struct.tm_sec = fTime.Second(); + + tm_struct.tm_year = fDate.Year() - 1900; + tm_struct.tm_mon = fDate.Month() - 1; + tm_struct.tm_mday = fDate.Day(); + + // set less 0 as we wan't use it + tm_struct.tm_isdst = -1; + + // return secs_since_jan1_1970 or -1 on error + return int32(mktime(&tm_struct)); +} + + +/*! + Sets the current date and time converted from seconds since + 1.1.1970 - 00:00:00. +*/ +void +BDateTime::SetTime_t(uint32 seconds) +{ + BTime time; + time.AddSeconds(seconds % kSecondsPerDay); + fTime.SetTime(time); + + BDate date(1970, 1, 1); + date.AddDays(seconds / kSecondsPerDay); + fDate.SetDate(date); +} + + +/*! + Returns true if this datetime is different from \c dateTime, otherwise false. +*/ +bool +BDateTime::operator!=(const BDateTime& dateTime) const +{ + return fTime != dateTime.fTime && fDate != dateTime.fDate; +} + + +/*! + Returns true if this datetime is equal to \c dateTime, otherwise false. +*/ +bool +BDateTime::operator==(const BDateTime& dateTime) const +{ + return fTime == dateTime.fTime && fDate == dateTime.fDate; +} + + +/*! + Returns true if this datetime is earlier than \c dateTime, otherwise false. +*/ +bool +BDateTime::operator<(const BDateTime& dateTime) const +{ + return fTime < dateTime.fTime && fDate < dateTime.fDate; +} + + +/*! + Returns true if this datetime is earlier than or equal to \c dateTime, + otherwise false. +*/ +bool +BDateTime::operator<=(const BDateTime& dateTime) const +{ + return fTime <= dateTime.fTime && fDate <= dateTime.fDate; +} + + +/*! + Returns true if this datetime is later than \c dateTime, otherwise false. +*/ +bool +BDateTime::operator>(const BDateTime& dateTime) const +{ + return fTime > dateTime.fTime && fDate > dateTime.fDate; +} + + +/*! + Returns true if this datetime is later than or equal to \c dateTime, + otherwise false. +*/ +bool +BDateTime::operator>=(const BDateTime& dateTime) const +{ + return fTime >= dateTime.fTime && fDate >= dateTime.fDate; +} + + +} //namespace BPrivate diff --git a/src/apps/webpositive/DateTime.h b/src/apps/webpositive/DateTime.h new file mode 100644 index 0000000000..fe92d86745 --- /dev/null +++ b/src/apps/webpositive/DateTime.h @@ -0,0 +1,215 @@ +/* + * Copyright 2007-2010, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _DATE_TIME_H_ +#define _DATE_TIME_H_ + + +#include + + +class BMessage; + + +namespace BPrivate { + + +enum time_type { + B_GMT_TIME, + B_LOCAL_TIME +}; + + +enum diff_type { + B_HOURS_DIFF, + B_MINUTES_DIFF, + B_SECONDS_DIFF, + B_MILLISECONDS_DIFF, + B_MICROSECONDS_DIFF +}; + + +class BTime { +public: + BTime(); + BTime(int32 hour, int32 minute, int32 second, + int32 microsecond = 0); + BTime(const BMessage* archive); + ~BTime(); + + status_t Archive(BMessage* into) const; + + bool IsValid() const; + bool IsValid(const BTime& time) const; + bool IsValid(int32 hour, int32 minute, int32 second, + int32 microsecond = 0) const; + + static BTime CurrentTime(time_type type); + + BTime Time() const; + bool SetTime(const BTime& time); + bool SetTime(int32 hour, int32 minute, int32 second, + int32 microsecond = 0); + + void AddHours(int32 hours); + void AddMinutes(int32 minutes); + void AddSeconds(int32 seconds); + void AddMilliseconds(int32 milliseconds); + void AddMicroseconds(int32 microseconds); + + int32 Hour() const; + int32 Minute() const; + int32 Second() const; + int32 Millisecond() const; + int32 Microsecond() const; + bigtime_t Difference(const BTime& time, + diff_type type) const; + + bool operator!=(const BTime& time) const; + bool operator==(const BTime& time) const; + + bool operator<(const BTime& time) const; + bool operator<=(const BTime& time) const; + + bool operator>(const BTime& time) const; + bool operator>=(const BTime& time) const; + +private: + bigtime_t _Microseconds() const; + void _AddMicroseconds(bigtime_t microseconds); + bool _SetTime(bigtime_t hour, bigtime_t minute, + bigtime_t second, bigtime_t microsecond); + +private: + bigtime_t fMicroseconds; +}; + + +class BDate { +public: + BDate(); + BDate(int32 year, int32 month, int32 day); + BDate(const BMessage* archive); + ~BDate(); + + status_t Archive(BMessage* into) const; + + bool IsValid() const; + bool IsValid(const BDate& date) const; + bool IsValid(int32 year, int32 month, + int32 day) const; + + static BDate CurrentDate(time_type type); + + BDate Date() const; + bool SetDate(const BDate& date); + + bool SetDate(int32 year, int32 month, int32 day); + void GetDate(int32* year, int32* month, int32* day); + + void AddDays(int32 days); + void AddYears(int32 years); + void AddMonths(int32 months); + + int32 Day() const; + int32 Year() const; + int32 Month() const; + int32 Difference(const BDate& date) const; + + int32 DayOfWeek() const; + int32 DayOfYear() const; + + int32 WeekNumber() const; + bool IsLeapYear(int32 year) const; + + int32 DaysInYear() const; + int32 DaysInMonth() const; + + BString ShortDayName(int32 day) const; + BString ShortMonthName(int32 month) const; + + BString LongDayName(int32 day) const; + BString LongMonthName(int32 month) const; + + int32 DateToJulianDay() const; + static BDate JulianDayToDate(int32 julianDay); + + bool operator!=(const BDate& date) const; + bool operator==(const BDate& date) const; + + bool operator<(const BDate& date) const; + bool operator<=(const BDate& date) const; + + bool operator>(const BDate& date) const; + bool operator>=(const BDate& date) const; + +private: + int32 _DaysInMonth(int32 year, int32 month) const; + bool _SetDate(int32 year, int32 month, int32 day); + int32 _DateToJulianDay(int32 year, int32 month, + int32 day) const; + +private: + int32 fDay; + int32 fYear; + int32 fMonth; +}; + + +class BDateTime { +public: + BDateTime(); + BDateTime(const BDate &date, const BTime &time); + BDateTime(const BMessage* archive); + ~BDateTime(); + + status_t Archive(BMessage* into) const; + + bool IsValid() const; + + static BDateTime CurrentDateTime(time_type type); + void SetDateTime(const BDate &date, const BTime &time); + + BDate Date() const; + void SetDate(const BDate &date); + + BTime Time() const; + void SetTime(const BTime &time); + + int32 Time_t() const; + void SetTime_t(uint32 seconds); + + bool operator!=(const BDateTime& dateTime) const; + bool operator==(const BDateTime& dateTime) const; + + bool operator<(const BDateTime& dateTime) const; + bool operator<=(const BDateTime& dateTime) const; + + bool operator>(const BDateTime& dateTime) const; + bool operator>=(const BDateTime& dateTime) const; + +private: + BDate fDate; + BTime fTime; +}; + + +} // namespace BPrivate + + +using BPrivate::time_type; +using BPrivate::B_GMT_TIME; +using BPrivate::B_LOCAL_TIME; +using BPrivate::diff_type; +using BPrivate::B_HOURS_DIFF; +using BPrivate::B_MINUTES_DIFF; +using BPrivate::B_SECONDS_DIFF; +using BPrivate::B_MILLISECONDS_DIFF; +using BPrivate::B_MICROSECONDS_DIFF; +using BPrivate::BTime; +using BPrivate::BDate; +using BPrivate::BDateTime; + + +#endif // _DATE_TIME_H_ From d4f4c7f8084f419e2cccaf450dcd18cce809de79 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 15 Feb 2010 16:23:31 +0000 Subject: [PATCH 020/349] Added my copyright, since I've redesigned here quite a bit. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@94 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherApp.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/webpositive/LauncherApp.h b/src/apps/webpositive/LauncherApp.h index f7efb72dcb..636169c4a5 100644 --- a/src/apps/webpositive/LauncherApp.h +++ b/src/apps/webpositive/LauncherApp.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2007 Ryan Leavengood + * Copyright (C) 2010 Stephan Aßmus * * All rights reserved. * From ce277486d76d9577316368a8a24dbf7ef449524f Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 15 Feb 2010 16:24:24 +0000 Subject: [PATCH 021/349] Implemented BrowsingHistoryItem class, which uses BDateTime to track when it was invoked. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@95 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowsingHistory.cpp | 105 +++++++++++++++++++++++ src/apps/webpositive/BrowsingHistory.h | 31 +++++++ 2 files changed, 136 insertions(+) diff --git a/src/apps/webpositive/BrowsingHistory.cpp b/src/apps/webpositive/BrowsingHistory.cpp index e70d3c0e03..d58985d9e1 100644 --- a/src/apps/webpositive/BrowsingHistory.cpp +++ b/src/apps/webpositive/BrowsingHistory.cpp @@ -32,10 +32,115 @@ #include #include #include +#include #include #include +BrowsingHistoryItem::BrowsingHistoryItem(const BString& url) + : m_url(url) + , m_dateTime(BDateTime::CurrentDateTime(B_LOCAL_TIME)) + , m_invokationCount(0) +{ +} + +BrowsingHistoryItem::BrowsingHistoryItem(const BrowsingHistoryItem& other) +{ + *this = other; +} + +BrowsingHistoryItem::BrowsingHistoryItem(const BMessage* archive) +{ + if (!archive) + return; + BMessage dateTimeArchive; + if (archive->FindMessage("date time", &dateTimeArchive) == B_OK) + m_dateTime = BDateTime(&dateTimeArchive); + archive->FindString("url", &m_url); + archive->FindUInt32("invokations", &m_invokationCount); +} + +BrowsingHistoryItem::~BrowsingHistoryItem() +{ +} + +status_t BrowsingHistoryItem::archive(BMessage* archive) const +{ + if (!archive) + return B_BAD_VALUE; + BMessage dateTimeArchive; + status_t status = m_dateTime.Archive(&dateTimeArchive); + if (status == B_OK) + status = archive->AddMessage("date time", &dateTimeArchive); + if (status == B_OK) + status = archive->AddString("url", m_url.String()); + if (status == B_OK) + status = archive->AddUInt32("invokations", m_invokationCount); + return status; +} + +BrowsingHistoryItem& BrowsingHistoryItem::operator=(const BrowsingHistoryItem& other) +{ + if (this == &other) + return *this; + + m_url = other.m_url; + m_dateTime = other.m_dateTime; + m_invokationCount = other.m_invokationCount; + + return *this; +} + +bool BrowsingHistoryItem::operator==(const BrowsingHistoryItem& other) const +{ + if (this == &other) + return true; + + return m_url == other.m_url && m_dateTime == other.m_dateTime + && m_invokationCount == other.m_invokationCount; +} + +bool BrowsingHistoryItem::operator!=(const BrowsingHistoryItem& other) const +{ + return !(*this == other); +} + +bool BrowsingHistoryItem::operator<(const BrowsingHistoryItem& other) const +{ + if (this == &other) + return false; + + return m_dateTime < other.m_dateTime || m_url < other.m_url; +} + +bool BrowsingHistoryItem::operator<=(const BrowsingHistoryItem& other) const +{ + return (*this == other) || (*this < other); +} + +bool BrowsingHistoryItem::operator>(const BrowsingHistoryItem& other) const +{ + if (this == &other) + return false; + + return m_dateTime > other.m_dateTime || m_url > other.m_url; +} + +bool BrowsingHistoryItem::operator>=(const BrowsingHistoryItem& other) const +{ + return (*this == other) || (*this > other); +} + +void BrowsingHistoryItem::increaseInvokationCount() +{ + // Eventually, we may overflow... + uint32 count = m_invokationCount + 1; + if (count > m_invokationCount) + m_invokationCount = count; +} + +// #pragma mark - BrowsingHistory + BrowsingHistory BrowsingHistory::s_defaultInstance; BrowsingHistory::BrowsingHistory() diff --git a/src/apps/webpositive/BrowsingHistory.h b/src/apps/webpositive/BrowsingHistory.h index 82ef0ba04f..b660cb30fb 100644 --- a/src/apps/webpositive/BrowsingHistory.h +++ b/src/apps/webpositive/BrowsingHistory.h @@ -28,9 +28,40 @@ #ifndef BrowsingHistory_h #define BrowsingHistory_h +#include "DateTime.h" #include class BFile; +class BString; + +class BrowsingHistoryItem { +public: + BrowsingHistoryItem(const BString& url); + BrowsingHistoryItem(const BrowsingHistoryItem& other); + BrowsingHistoryItem(const BMessage* archive); + ~BrowsingHistoryItem(); + + status_t archive(BMessage* archive) const; + + BrowsingHistoryItem& operator=(const BrowsingHistoryItem& other); + + bool operator==(const BrowsingHistoryItem& other) const; + bool operator!=(const BrowsingHistoryItem& other) const; + bool operator<(const BrowsingHistoryItem& other) const; + bool operator<=(const BrowsingHistoryItem& other) const; + bool operator>(const BrowsingHistoryItem& other) const; + bool operator>=(const BrowsingHistoryItem& other) const; + + const BString& url() const { return m_url; } + const BDateTime& dateTime() const { return m_dateTime; } + uint32 invokationCount() const { return m_invokationCount; } + void increaseInvokationCount(); + +private: + BString m_url; + BDateTime m_dateTime; + uint32 m_invokationCount; +}; class BrowsingHistory : public BLocker { public: From 2bff1b82035cd2f5c983136be46b282c9dc9859c Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 15 Feb 2010 18:17:17 +0000 Subject: [PATCH 022/349] Wired and debugged everything to give us a basic "Go" menu, a.k.a browsing history... :-) git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@98 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowsingHistory.cpp | 94 ++++++++++++++++++++++-- src/apps/webpositive/BrowsingHistory.h | 13 +++- src/apps/webpositive/LauncherWindow.cpp | 60 ++++++++++++++- src/apps/webpositive/LauncherWindow.h | 3 + 4 files changed, 159 insertions(+), 11 deletions(-) diff --git a/src/apps/webpositive/BrowsingHistory.cpp b/src/apps/webpositive/BrowsingHistory.cpp index d58985d9e1..7c5246df11 100644 --- a/src/apps/webpositive/BrowsingHistory.cpp +++ b/src/apps/webpositive/BrowsingHistory.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include @@ -131,18 +132,17 @@ bool BrowsingHistoryItem::operator>=(const BrowsingHistoryItem& other) const return (*this == other) || (*this > other); } -void BrowsingHistoryItem::increaseInvokationCount() +void BrowsingHistoryItem::invoked() { // Eventually, we may overflow... uint32 count = m_invokationCount + 1; if (count > m_invokationCount) m_invokationCount = count; + m_dateTime = BDateTime::CurrentDateTime(B_LOCAL_TIME); } // #pragma mark - BrowsingHistory -BrowsingHistory BrowsingHistory::s_defaultInstance; - BrowsingHistory::BrowsingHistory() : BLocker("browsing history") { @@ -150,18 +150,91 @@ BrowsingHistory::BrowsingHistory() if (openSettingsFile(settingsFile, B_READ_ONLY)) { BMessage settingsArchive; settingsArchive.Unflatten(&settingsFile); - // TODO: ... + + BMessage historyItemArchive; + for (int32 i = 0; settingsArchive.FindMessage("history item", i, &historyItemArchive) == B_OK; i++) { + addItem(BrowsingHistoryItem(&historyItemArchive)); + historyItemArchive.MakeEmpty(); + } } } BrowsingHistory::~BrowsingHistory() { saveSettings(); + privateClear(); } /*static*/ BrowsingHistory* BrowsingHistory::defaultInstance() { - return &s_defaultInstance; + static BrowsingHistory defaultInstance; + + return &defaultInstance; +} + +bool BrowsingHistory::addItem(const BrowsingHistoryItem& item) +{ + BAutolock _(this); + + int32 count = countItems(); + int32 insertionIndex = count; + for (int32 i = 0; i < count; i++) { + BrowsingHistoryItem* existingItem = reinterpret_cast( + m_historyItems.ItemAtFast(i)); + if (item.url() == existingItem->url()) { + existingItem->invoked(); + return true; + } + if (item < *existingItem) + insertionIndex = i; + } + BrowsingHistoryItem* newItem = new(std::nothrow) BrowsingHistoryItem(item); + if (!newItem || !m_historyItems.AddItem(newItem, insertionIndex)) { + delete newItem; + return false; + } + + newItem->invoked(); + saveSettings(); + + return true; +} + +int32 BrowsingHistory::BrowsingHistory::countItems() const +{ + BAutolock _(const_cast(this)); + + return m_historyItems.CountItems(); +} + +BrowsingHistoryItem BrowsingHistory::historyItemAt(int32 index) const +{ + BAutolock _(const_cast(this)); + + BrowsingHistoryItem* existingItem = reinterpret_cast( + m_historyItems.ItemAt(index)); + if (!existingItem) + return BrowsingHistoryItem(BString()); + + return BrowsingHistoryItem(*existingItem); +} + +void BrowsingHistory::clear() +{ + BAutolock _(this); + privateClear(); + saveSettings(); +} + +void BrowsingHistory::privateClear() +{ + int32 count = countItems(); + for (int32 i = 0; i < count; i++) { + BrowsingHistoryItem* item = reinterpret_cast( + m_historyItems.ItemAtFast(i)); + delete item; + } + m_historyItems.MakeEmpty(); } // #pragma mark - private @@ -171,7 +244,16 @@ void BrowsingHistory::saveSettings() BFile settingsFile; if (openSettingsFile(settingsFile, B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) { BMessage settingsArchive; - // TODO: ... + BMessage historyItemArchive; + int32 count = countItems(); + for (int32 i = 0; i < count; i++) { + BrowsingHistoryItem item = historyItemAt(i); + if (item.archive(&historyItemArchive) != B_OK) + break; + if (settingsArchive.AddMessage("history item", &historyItemArchive) != B_OK) + break; + historyItemArchive.MakeEmpty(); + } settingsArchive.Flatten(&settingsFile); } } diff --git a/src/apps/webpositive/BrowsingHistory.h b/src/apps/webpositive/BrowsingHistory.h index b660cb30fb..00e4f3a5e7 100644 --- a/src/apps/webpositive/BrowsingHistory.h +++ b/src/apps/webpositive/BrowsingHistory.h @@ -29,6 +29,7 @@ #define BrowsingHistory_h #include "DateTime.h" +#include #include class BFile; @@ -55,7 +56,7 @@ public: const BString& url() const { return m_url; } const BDateTime& dateTime() const { return m_dateTime; } uint32 invokationCount() const { return m_invokationCount; } - void increaseInvokationCount(); + void invoked(); private: BString m_url; @@ -67,15 +68,23 @@ class BrowsingHistory : public BLocker { public: static BrowsingHistory* defaultInstance(); + bool addItem(const BrowsingHistoryItem& item); + + // Should Lock() the object when using these in some loop or so: + int32 countItems() const; + BrowsingHistoryItem historyItemAt(int32 index) const; + void clear(); + private: BrowsingHistory(); virtual ~BrowsingHistory(); + void privateClear(); void saveSettings(); bool openSettingsFile(BFile& file, uint32 mode); private: - static BrowsingHistory s_defaultInstance; + BList m_historyItems; }; #endif // BrowsingHistory_h diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 7fb3a366ea..fb654ef5ac 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -33,9 +33,11 @@ #include "LauncherWindow.h" #include "AuthenticationPanel.h" +#include "BrowsingHistory.h" #include "WebProcess.h" #include "WebView.h" #include "WebViewConstants.h" +#include #include #include #include @@ -59,6 +61,7 @@ enum { GO_FORWARD = 'gofo', GOTO_URL = 'goul', RELOAD = 'reld', + CLEAR_HISTORY = 'clhs', TEXT_SIZE_INCREASE = 'tsin', TEXT_SIZE_DECREASE = 'tsdc', @@ -111,6 +114,9 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, menu->AddItem(new BMenuItem("Reset size", new BMessage(TEXT_SIZE_RESET), '0')); m_menuBar->AddItem(menu); + m_goMenu = new BMenu("Go"); + m_menuBar->AddItem(m_goMenu); + // Back & Forward m_BackButton = new BButton("", "Back", new BMessage(GO_BACK)); m_ForwardButton = new BButton("", "Forward", new BMessage(GO_FORWARD)); @@ -218,10 +224,13 @@ void LauncherWindow::MessageReceived(BMessage* message) case RELOAD: webView()->loadRequest(m_url->Text()); break; - case GOTO_URL: - if (m_loadedURL != m_url->Text()) - webView()->loadRequest(m_url->Text()); + case GOTO_URL: { + BString url = m_url->Text(); + message->FindString("url", &url); + if (m_loadedURL != url) + webView()->loadRequest(url.String()); break; + } case GO_BACK: webView()->goBack(); break; @@ -229,6 +238,17 @@ void LauncherWindow::MessageReceived(BMessage* message) webView()->goForward(); break; + case CLEAR_HISTORY: { + BrowsingHistory* history = BrowsingHistory::defaultInstance(); + if (history->countItems() == 0) + break; + BAlert* alert = new BAlert("Confirmation", "Do you really want to clear " + "the browsing history?", "Clear", "Cancel"); + if (alert->Go() == 0) + history->clear(); + break; + } + case B_SIMPLE_DATA: { // User possibly dropped files on this window. // If there is more than one entry_ref, let the app handle it (open one @@ -305,6 +325,35 @@ bool LauncherWindow::QuitRequested() return false; } +void LauncherWindow::MenusBeginning() +{ + BMenuItem* menuItem; + while ((menuItem = m_goMenu->RemoveItem(0L))) + delete menuItem; + + BrowsingHistory* history = BrowsingHistory::defaultInstance(); + if (!history->Lock()) + return; + + int32 count = history->countItems(); + for (int32 i = 0; i < count; i++) { + BrowsingHistoryItem historyItem = history->historyItemAt(i); + BMessage* message = new BMessage(GOTO_URL); + message->AddString("url", historyItem.url().String()); + // TODO: More sophisticated menu structure... sorted by days/weeks... + menuItem = new BMenuItem(historyItem.url().String(), message); + m_goMenu->AddItem(menuItem); + } + + + if (m_goMenu->CountItems() > 3) { + m_goMenu->AddSeparatorItem(); + m_goMenu->AddItem(new BMenuItem("Clear history", new BMessage(CLEAR_HISTORY))); + } + + history->Unlock(); +} + // #pragma mark - Notification API void LauncherWindow::navigationRequested(const BString& url) @@ -393,6 +442,11 @@ void LauncherWindow::navigationCapabilitiesChanged(bool canGoBackward, m_ForwardButton->SetEnabled(canGoForward); } +void LauncherWindow::updateGlobalHistory(const BString& url) +{ + BrowsingHistory::defaultInstance()->addItem(BrowsingHistoryItem(url)); +} + void LauncherWindow::authenticationChallenge(BMessage* message) { BString text; diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index ca4b8391b5..3c814f9893 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -62,6 +62,7 @@ public: virtual void MessageReceived(BMessage* message); virtual bool QuitRequested(); + virtual void MenusBeginning(); // WebViewWindow notification API implementations virtual void navigationRequested(const BString& url); @@ -75,10 +76,12 @@ public: virtual void statusChanged(const BString& status); virtual void navigationCapabilitiesChanged(bool canGoBackward, bool canGoForward, bool canStop); + virtual void updateGlobalHistory(const BString& url); virtual void authenticationChallenge(BMessage* challenge); private: BMenuBar* m_menuBar; + BMenu* m_goMenu; BButton* m_BackButton; BButton* m_ForwardButton; BTextControl* m_url; From defb5e01c43945931205a1149b241313ce7fd983 Mon Sep 17 00:00:00 2001 From: mmlr Date: Fri, 19 Feb 2010 02:48:44 +0000 Subject: [PATCH 023/349] Fix uninitialized m_windowCount which could cause the app to close on any window close randomly (or always with libroot_debug). git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@139 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherApp.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index df664c7f5a..69713a886e 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -53,6 +53,7 @@ enum { LauncherApp::LauncherApp() : BApplication(kApplicationSignature) + , m_windowCount(0) , m_lastWindowFrame(100, 100, 700, 750) , m_launchRefsMessage(0) , m_initialized(false) From a62545c15526a03ae7a1cee64908f851edeeb118 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 19 Feb 2010 15:47:21 +0000 Subject: [PATCH 024/349] Renamed WebProcess to WebPage. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@146 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 2 +- src/apps/webpositive/LauncherApp.cpp | 6 +++--- src/apps/webpositive/LauncherWindow.cpp | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index ea0492b402..f6e94b1072 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -29,7 +29,7 @@ #include "DownloadWindow.h" #include "WebDownload.h" -#include "WebProcess.h" +#include "WebPage.h" #include #include #include diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 69713a886e..bbede28b06 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -33,7 +33,7 @@ #include "FrameView.h" #include "GraphicsContext.h" #include "LauncherWindow.h" -#include "WebProcess.h" +#include "WebPage.h" #include "WebView.h" #include "WebViewConstants.h" #include @@ -92,8 +92,8 @@ void LauncherApp::ArgvReceived(int32 argc, char** argv) void LauncherApp::ReadyToRun() { - WebProcess::initializeOnce(); - WebProcess::setCacheModel(WEBKIT_CACHE_MODEL_WEB_BROWSER); + WebPage::initializeOnce(); + WebPage::setCacheModel(WEBKIT_CACHE_MODEL_WEB_BROWSER); BFile settingsFile; BRect windowFrameFromSettings = m_lastWindowFrame; diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index fb654ef5ac..0e820b4ab3 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -34,7 +34,7 @@ #include "AuthenticationPanel.h" #include "BrowsingHistory.h" -#include "WebProcess.h" +#include "WebPage.h" #include "WebView.h" #include "WebViewConstants.h" #include @@ -200,7 +200,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, ); } - webView()->webProcess()->setDownloadListener(downloadListener); + webView()->webPage()->setDownloadListener(downloadListener); m_findGroup->SetVisible(false); @@ -367,7 +367,7 @@ void LauncherWindow::newWindowRequested(const BString& url) { // Always open new windows in the application thread, since // creating a WebView will try to grab the application lock. - // But our own WebProcess may already try to lock us from within + // But our own WebPage may already try to lock us from within // the application thread -> dead-lock. BMessage message(NEW_WINDOW); message.AddString("url", url); From a89e2a4b6c01aea49da2499ba57941526a622da0 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 19 Feb 2010 17:23:45 +0000 Subject: [PATCH 025/349] Refactoring to support multiple WebViews per WebViewWindow. There is now the notion of a current WebView. In the notification messages, carry the information which WebView it is for. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@147 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherApp.cpp | 21 ++-- src/apps/webpositive/LauncherWindow.cpp | 138 +++++++++++++++++------- src/apps/webpositive/LauncherWindow.h | 26 +++-- 3 files changed, 128 insertions(+), 57 deletions(-) diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index bbede28b06..9503f2c3e7 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -130,15 +130,14 @@ void LauncherApp::MessageReceived(BMessage* message) BString url; if (message->FindString("url", &url) != B_OK) break; - bool newWindow; - if (message->FindBool("new window", &newWindow) != B_OK) - newWindow = false; - WebViewWindow* webWindow = NULL; + bool openNewWindow = false; + message->FindBool("new window", &openNewWindow); + LauncherWindow* webWindow = NULL; for (int i = 0; BWindow* window = WindowAt(i); i++) { - webWindow = dynamic_cast(window); + webWindow = dynamic_cast(window); if (!webWindow) continue; - if (!newWindow) { + if (!openNewWindow) { // stop at the first window break; } @@ -146,12 +145,12 @@ void LauncherApp::MessageReceived(BMessage* message) if (webWindow) { // There should always be at least one window open. If not, maybe we are about // to quit anyway... - if (newWindow) { + if (openNewWindow) { // open a new window with an offset to the last window - webWindow->newWindowRequested(url); + newWindow(url); } else { // load the URL in the first window - webWindow->webView()->loadRequest(url.String()); + webWindow->currentWebView()->loadRequest(url.String()); } } break; @@ -218,7 +217,7 @@ void LauncherApp::RefsReceived(BMessage* message) bool LauncherApp::QuitRequested() { for (int i = 0; BWindow* window = WindowAt(i); i++) { - WebViewWindow* webWindow = dynamic_cast(window); + LauncherWindow* webWindow = dynamic_cast(window); if (!webWindow) continue; if (!webWindow->Lock()) @@ -268,7 +267,7 @@ void LauncherApp::newWindow(const BString& url) BMessenger(m_downloadWindow)); window->Show(); if (url.Length()) - window->webView()->loadRequest(url.String()); + window->currentWebView()->loadRequest(url.String()); } // #pragma mark - diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 0e820b4ab3..4c7b208055 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -88,6 +88,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) { + setCurrentWebView(new WebView("web_view")); if (toolbarPolicy == HaveToolbar) { // Menu m_menuBar = new BMenuBar("Main menu"); @@ -174,7 +175,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) ) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) - .Add(webView()) + .Add(currentWebView()) .Add(findGroup) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) @@ -196,11 +197,11 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_loadingProgressBar = 0; AddChild(BGroupLayoutBuilder(B_VERTICAL, 7) - .Add(webView()) + .Add(currentWebView()) ); } - webView()->webPage()->setDownloadListener(downloadListener); + currentWebView()->webPage()->setDownloadListener(downloadListener); m_findGroup->SetVisible(false); @@ -209,7 +210,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, AddShortcut('F', B_COMMAND_KEY, new BMessage(TEXT_SHOW_FIND_GROUP)); AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_HIDE_FIND_GROUP)); - navigationCapabilitiesChanged(false, false, false); + navigationCapabilitiesChanged(false, false, false, currentWebView()); be_app->PostMessage(WINDOW_OPENED); } @@ -222,20 +223,20 @@ void LauncherWindow::MessageReceived(BMessage* message) { switch (message->what) { case RELOAD: - webView()->loadRequest(m_url->Text()); + currentWebView()->loadRequest(m_url->Text()); break; case GOTO_URL: { BString url = m_url->Text(); message->FindString("url", &url); if (m_loadedURL != url) - webView()->loadRequest(url.String()); + currentWebView()->loadRequest(url.String()); break; } case GO_BACK: - webView()->goBack(); + currentWebView()->goBack(); break; case GO_FORWARD: - webView()->goForward(); + currentWebView()->goForward(); break; case CLEAR_HISTORY: { @@ -271,26 +272,26 @@ void LauncherWindow::MessageReceived(BMessage* message) BPath path; if (!entry.Exists() || entry.GetPath(&path) != B_OK) break; - webView()->loadRequest(path.Path()); + currentWebView()->loadRequest(path.Path()); break; } case TEXT_SIZE_INCREASE: - webView()->increaseTextSize(); + currentWebView()->increaseTextSize(); break; case TEXT_SIZE_DECREASE: - webView()->decreaseTextSize(); + currentWebView()->decreaseTextSize(); break; case TEXT_SIZE_RESET: - webView()->resetTextSize(); + currentWebView()->resetTextSize(); break; case TEXT_FIND_NEXT: - webView()->findString(m_findTextControl->Text(), true, + currentWebView()->findString(m_findTextControl->Text(), true, m_findCaseSensitiveCheckBox->Value()); break; case TEXT_FIND_PREVIOUS: - webView()->findString(m_findTextControl->Text(), false, + currentWebView()->findString(m_findTextControl->Text(), false, m_findCaseSensitiveCheckBox->Value()); break; case TEXT_SHOW_FIND_GROUP: @@ -309,20 +310,26 @@ void LauncherWindow::MessageReceived(BMessage* message) break; default: - WebViewWindow::MessageReceived(message); + BWindow::MessageReceived(message); break; } } bool LauncherWindow::QuitRequested() { - if (WebViewWindow::QuitRequested()) { - BMessage message(WINDOW_CLOSED); - message.AddRect("window frame", Frame()); - be_app->PostMessage(&message); - return true; - } - return false; + // TODO: Check for modified form data and ask user for confirmation, etc. + + // Do this here, so WebKit tear down happens earlier. + // TODO: Iterator over all WebViews, if there are more then one... + WebView* view = currentWebView(); + view->RemoveSelf(); + delete view; + setCurrentWebView(0); + + BMessage message(WINDOW_CLOSED); + message.AddRect("window frame", Frame()); + be_app->PostMessage(&message); + return true; } void LauncherWindow::MenusBeginning() @@ -341,7 +348,9 @@ void LauncherWindow::MenusBeginning() BMessage* message = new BMessage(GOTO_URL); message->AddString("url", historyItem.url().String()); // TODO: More sophisticated menu structure... sorted by days/weeks... - menuItem = new BMenuItem(historyItem.url().String(), message); + BString truncatedUrl(historyItem.url()); + be_plain_font->TruncateString(&truncatedUrl, B_TRUNCATE_END, 480); + menuItem = new BMenuItem(truncatedUrl, message); m_goMenu->AddItem(menuItem); } @@ -356,8 +365,9 @@ void LauncherWindow::MenusBeginning() // #pragma mark - Notification API -void LauncherWindow::navigationRequested(const BString& url) +void LauncherWindow::navigationRequested(const BString& url, WebView* view) { + // TODO: Move elsewhere, doesn't belong here. m_loadedURL = url; if (m_url) m_url->SetText(url.String()); @@ -374,22 +384,25 @@ void LauncherWindow::newWindowRequested(const BString& url) be_app->PostMessage(&message); } -void LauncherWindow::loadNegociating(const BString& url) +void LauncherWindow::loadNegociating(const BString& url, WebView* view) { BString status("Requesting: "); status << url; - statusChanged(status); + statusChanged(status, view); } -void LauncherWindow::loadTransfering(const BString& url) +void LauncherWindow::loadTransfering(const BString& url, WebView* view) { BString status("Loading: "); status << url; - statusChanged(status); + statusChanged(status, view); } -void LauncherWindow::loadProgress(float progress) +void LauncherWindow::loadProgress(float progress, WebView* view) { + if (view != currentWebView()) + return; + if (m_loadingProgressBar) { if (progress < 100 && m_loadingProgressBar->IsHidden()) m_loadingProgressBar->Show(); @@ -397,29 +410,76 @@ void LauncherWindow::loadProgress(float progress) } } -void LauncherWindow::loadFailed(const BString& url) +void LauncherWindow::loadFailed(const BString& url, WebView* view) { + if (view != currentWebView()) + return; + BString status(url); status << " failed."; - statusChanged(status); + statusChanged(status, view); if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) m_loadingProgressBar->Hide(); } -void LauncherWindow::loadFinished(const BString& url) +void LauncherWindow::loadFinished(const BString& url, WebView* view) { + if (view != currentWebView()) + return; + m_loadedURL = url; BString status(url); status << " finished."; - statusChanged(status); + statusChanged(status, view); if (m_url) m_url->SetText(url.String()); if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) m_loadingProgressBar->Hide(); } -void LauncherWindow::titleChanged(const BString& title) +void LauncherWindow::resizeRequested(float width, float height, WebView* view) { + if (view != currentWebView()) + return; + + // TODO: Ignore request when there is more than one WebView embedded! + + ResizeTo(width, height); +} + +void LauncherWindow::setToolBarsVisible(bool flag, WebView* view) +{ + // TODO + // TODO: Ignore request when there is more than one WebView embedded! +} + +void LauncherWindow::setStatusBarVisible(bool flag, WebView* view) +{ + // TODO + // TODO: Ignore request when there is more than one WebView embedded! +} + +void LauncherWindow::setMenuBarVisible(bool flag, WebView* view) +{ + // TODO + // TODO: Ignore request when there is more than one WebView embedded! +} + +void LauncherWindow::setResizable(bool flag, WebView* view) +{ + // TODO: Ignore request when there is more than one WebView embedded! + + if (flag) + SetFlags(Flags() & ~B_NOT_RESIZABLE); + else + SetFlags(Flags() | B_NOT_RESIZABLE); +} + +void LauncherWindow::titleChanged(const BString& title, WebView* view) +{ + if (view != currentWebView()) + return; + BString windowTitle = title; if (windowTitle.Length() > 0) windowTitle << " - "; @@ -427,15 +487,21 @@ void LauncherWindow::titleChanged(const BString& title) SetTitle(windowTitle.String()); } -void LauncherWindow::statusChanged(const BString& statusText) +void LauncherWindow::statusChanged(const BString& statusText, WebView* view) { + if (view != currentWebView()) + return; + if (m_statusText) m_statusText->SetText(statusText.String()); } void LauncherWindow::navigationCapabilitiesChanged(bool canGoBackward, - bool canGoForward, bool canStop) + bool canGoForward, bool canStop, WebView* view) { + if (view != currentWebView()) + return; + if (m_BackButton) m_BackButton->SetEnabled(canGoBackward); if (m_ForwardButton) diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index 3c814f9893..ac0a392657 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -64,18 +64,24 @@ public: virtual bool QuitRequested(); virtual void MenusBeginning(); - // WebViewWindow notification API implementations - virtual void navigationRequested(const BString& url); +private: + // WebPage notification API implementations + virtual void navigationRequested(const BString& url, WebView* view); virtual void newWindowRequested(const BString& url); - virtual void loadNegociating(const BString& url); - virtual void loadTransfering(const BString& url); - virtual void loadProgress(float progress); - virtual void loadFailed(const BString& url); - virtual void loadFinished(const BString& url); - virtual void titleChanged(const BString& title); - virtual void statusChanged(const BString& status); + virtual void loadNegociating(const BString& url, WebView* view); + virtual void loadTransfering(const BString& url, WebView* view); + virtual void loadProgress(float progress, WebView* view); + virtual void loadFailed(const BString& url, WebView* view); + virtual void loadFinished(const BString& url, WebView* view); + virtual void titleChanged(const BString& title, WebView* view); + virtual void resizeRequested(float width, float height, WebView* view); + virtual void setToolBarsVisible(bool flag, WebView* view); + virtual void setStatusBarVisible(bool flag, WebView* view); + virtual void setMenuBarVisible(bool flag, WebView* view); + virtual void setResizable(bool flag, WebView* view); + virtual void statusChanged(const BString& status, WebView* view); virtual void navigationCapabilitiesChanged(bool canGoBackward, - bool canGoForward, bool canStop); + bool canGoForward, bool canStop, WebView* view); virtual void updateGlobalHistory(const BString& url); virtual void authenticationChallenge(BMessage* challenge); From c9219daa51601fd635ca7c83a19eb8fbcc9a366d Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 19 Feb 2010 18:29:13 +0000 Subject: [PATCH 026/349] Fixed left-over bug from refactoring. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@148 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 4c7b208055..3a4171c277 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -310,7 +310,7 @@ void LauncherWindow::MessageReceived(BMessage* message) break; default: - BWindow::MessageReceived(message); + WebViewWindow::MessageReceived(message); break; } } From 82912660d55e139b15faeb4efaa5743faf7762ee Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 20 Feb 2010 11:13:44 +0000 Subject: [PATCH 027/349] * Began renaming some public API with the B* prefix and using the Haiku coding style. (WebPage -> BWebPage). Documented what needs to go where in WebPage.h. * Moved misplaced functionality from WebFrame to BWebPage (navigation). * EditorClientHaiku takes a BWebPage pointer now, which brings a slight cleanup. * Exposed WebFrame::isEditable() to EditorClientHaiku, so isEditable() can be implemented. * Added some asserts in FrameLoaderClientHaiku according to the Gtk port and placed some debug output. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@150 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 4 ++-- src/apps/webpositive/LauncherApp.cpp | 4 ++-- src/apps/webpositive/LauncherWindow.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index f6e94b1072..335b526a20 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -385,13 +385,13 @@ DownloadWindow::~DownloadWindow() void DownloadWindow::MessageReceived(BMessage* message) { switch (message->what) { - case DOWNLOAD_ADDED: { + case B_DOWNLOAD_ADDED: { WebDownload* download; if (message->FindPointer("download", reinterpret_cast(&download)) == B_OK) downloadStarted(download); break; } - case DOWNLOAD_REMOVED: { + case B_DOWNLOAD_REMOVED: { WebDownload* download; if (message->FindPointer("download", reinterpret_cast(&download)) == B_OK) downloadFinished(download); diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 9503f2c3e7..4f01619717 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -92,8 +92,8 @@ void LauncherApp::ArgvReceived(int32 argc, char** argv) void LauncherApp::ReadyToRun() { - WebPage::initializeOnce(); - WebPage::setCacheModel(WEBKIT_CACHE_MODEL_WEB_BROWSER); + BWebPage::InitializeOnce(); + BWebPage::SetCacheModel(B_WEBKIT_CACHE_MODEL_WEB_BROWSER); BFile settingsFile; BRect windowFrameFromSettings = m_lastWindowFrame; diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 3a4171c277..b8f07ad021 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -201,7 +201,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, ); } - currentWebView()->webPage()->setDownloadListener(downloadListener); + currentWebView()->webPage()->SetDownloadListener(downloadListener); m_findGroup->SetVisible(false); From c14fa6263858745ec3148398b7f0cc1eac3a96ce Mon Sep 17 00:00:00 2001 From: anevilyak Date: Sat, 20 Feb 2010 15:28:30 +0000 Subject: [PATCH 028/349] Typo/spelling corrections. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@151 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 2 +- src/apps/webpositive/LauncherWindow.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index b8f07ad021..adbeea2a15 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -384,7 +384,7 @@ void LauncherWindow::newWindowRequested(const BString& url) be_app->PostMessage(&message); } -void LauncherWindow::loadNegociating(const BString& url, WebView* view) +void LauncherWindow::loadNegotiating(const BString& url, WebView* view) { BString status("Requesting: "); status << url; diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index ac0a392657..ff537a6be5 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -68,7 +68,7 @@ private: // WebPage notification API implementations virtual void navigationRequested(const BString& url, WebView* view); virtual void newWindowRequested(const BString& url); - virtual void loadNegociating(const BString& url, WebView* view); + virtual void loadNegotiating(const BString& url, WebView* view); virtual void loadTransfering(const BString& url, WebView* view); virtual void loadProgress(float progress, WebView* view); virtual void loadFailed(const BString& url, WebView* view); From 95b246f2a7e410b0c9924a64ae1cf06cd2754410 Mon Sep 17 00:00:00 2001 From: anevilyak Date: Sat, 20 Feb 2010 16:22:31 +0000 Subject: [PATCH 029/349] Add basic tabbed browsing support. Does not yet properly handle maintaining/switching the current URL or status bar text per-tab. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@152 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 134 ++++++++++++++++-------- src/apps/webpositive/LauncherWindow.h | 10 +- src/apps/webpositive/WebTabView.cpp | 57 ++++++++++ src/apps/webpositive/WebTabView.h | 52 +++++++++ 4 files changed, 204 insertions(+), 49 deletions(-) create mode 100644 src/apps/webpositive/WebTabView.cpp create mode 100644 src/apps/webpositive/WebTabView.h diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index adbeea2a15..9e2e3f5e72 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -35,6 +35,7 @@ #include "AuthenticationPanel.h" #include "BrowsingHistory.h" #include "WebPage.h" +#include "WebTabView.h" #include "WebView.h" #include "WebViewConstants.h" #include @@ -88,16 +89,26 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) { - setCurrentWebView(new WebView("web_view")); + m_tabView = new WebTabView("tabview", BMessenger(this)); + WebView *webView = new WebView("web_view"); + m_tabView->AddTab(webView); + m_tabView->TabAt(0L)->SetLabel("New Tab"); + setCurrentWebView(webView); + if (toolbarPolicy == HaveToolbar) { // Menu m_menuBar = new BMenuBar("Main menu"); BMenu* menu = new BMenu("Window"); BMessage* newWindowMessage = new BMessage(NEW_WINDOW); newWindowMessage->AddString("url", ""); - BMenuItem* newItem = new BMenuItem("New", newWindowMessage, 'N'); - menu->AddItem(newItem); + BMenu *newMenu = new BMenu("New"); + BMenuItem* newItem = new BMenuItem("Window", newWindowMessage, 'N'); + newMenu->AddItem(newItem); newItem->SetTarget(be_app); + newItem = new BMenuItem("Tab", new BMessage(NEW_TAB), 'T'); + newMenu->AddItem(newItem); + newItem->SetTarget(this); + menu->AddItem(newMenu); menu->AddItem(new BMenuItem("Close", new BMessage(B_QUIT_REQUESTED), 'W')); menu->AddSeparatorItem(); menu->AddItem(new BMenuItem("Show Downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'D')); @@ -175,7 +186,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) ) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) - .Add(currentWebView()) + .Add(m_tabView) .Add(findGroup) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) @@ -240,20 +251,20 @@ void LauncherWindow::MessageReceived(BMessage* message) break; case CLEAR_HISTORY: { - BrowsingHistory* history = BrowsingHistory::defaultInstance(); - if (history->countItems() == 0) - break; - BAlert* alert = new BAlert("Confirmation", "Do you really want to clear " - "the browsing history?", "Clear", "Cancel"); - if (alert->Go() == 0) - history->clear(); + BrowsingHistory* history = BrowsingHistory::defaultInstance(); + if (history->countItems() == 0) + break; + BAlert* alert = new BAlert("Confirmation", "Do you really want to clear " + "the browsing history?", "Clear", "Cancel"); + if (alert->Go() == 0) + history->clear(); break; } case B_SIMPLE_DATA: { - // User possibly dropped files on this window. - // If there is more than one entry_ref, let the app handle it (open one - // new page per ref). If there is one ref, open it in this window. + // User possibly dropped files on this window. + // If there is more than one entry_ref, let the app handle it (open one + // new page per ref). If there is one ref, open it in this window. type_code type; int32 countFound; if (message->GetInfo("refs", &type, &countFound) != B_OK @@ -309,6 +320,24 @@ void LauncherWindow::MessageReceived(BMessage* message) be_app->PostMessage(message); break; + case NEW_TAB: + { + m_tabView->AddTab(new WebView("web_view")); + m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New Tab"); + m_tabView->DrawTabs(); + m_tabView->Select(m_tabView->CountTabs() - 1); + break; + } + + case TAB_CHANGED: + { + int32 index = message->FindInt32("index"); + setCurrentWebView(dynamic_cast( + m_tabView->ViewForTab(index))); + updateTitle(m_tabView->TabAt(index)->Label()); + break; + } + default: WebViewWindow::MessageReceived(message); break; @@ -334,9 +363,9 @@ bool LauncherWindow::QuitRequested() void LauncherWindow::MenusBeginning() { - BMenuItem* menuItem; - while ((menuItem = m_goMenu->RemoveItem(0L))) - delete menuItem; + BMenuItem* menuItem; + while ((menuItem = m_goMenu->RemoveItem(0L))) + delete menuItem; BrowsingHistory* history = BrowsingHistory::defaultInstance(); if (!history->Lock()) @@ -344,14 +373,14 @@ void LauncherWindow::MenusBeginning() int32 count = history->countItems(); for (int32 i = 0; i < count; i++) { - BrowsingHistoryItem historyItem = history->historyItemAt(i); - BMessage* message = new BMessage(GOTO_URL); - message->AddString("url", historyItem.url().String()); - // TODO: More sophisticated menu structure... sorted by days/weeks... + BrowsingHistoryItem historyItem = history->historyItemAt(i); + BMessage* message = new BMessage(GOTO_URL); + message->AddString("url", historyItem.url().String()); + // TODO: More sophisticated menu structure... sorted by days/weeks... BString truncatedUrl(historyItem.url()); be_plain_font->TruncateString(&truncatedUrl, B_TRUNCATE_END, 480); menuItem = new BMenuItem(truncatedUrl, message); - m_goMenu->AddItem(menuItem); + m_goMenu->AddItem(menuItem); } @@ -367,7 +396,7 @@ void LauncherWindow::MenusBeginning() void LauncherWindow::navigationRequested(const BString& url, WebView* view) { - // TODO: Move elsewhere, doesn't belong here. + // TODO: Move elsewhere, doesn't belong here. m_loadedURL = url; if (m_url) m_url->SetText(url.String()); @@ -400,8 +429,8 @@ void LauncherWindow::loadTransfering(const BString& url, WebView* view) void LauncherWindow::loadProgress(float progress, WebView* view) { - if (view != currentWebView()) - return; + if (view != currentWebView()) + return; if (m_loadingProgressBar) { if (progress < 100 && m_loadingProgressBar->IsHidden()) @@ -412,8 +441,8 @@ void LauncherWindow::loadProgress(float progress, WebView* view) void LauncherWindow::loadFailed(const BString& url, WebView* view) { - if (view != currentWebView()) - return; + if (view != currentWebView()) + return; BString status(url); status << " failed."; @@ -424,8 +453,8 @@ void LauncherWindow::loadFailed(const BString& url, WebView* view) void LauncherWindow::loadFinished(const BString& url, WebView* view) { - if (view != currentWebView()) - return; + if (view != currentWebView()) + return; m_loadedURL = url; BString status(url); @@ -439,8 +468,8 @@ void LauncherWindow::loadFinished(const BString& url, WebView* view) void LauncherWindow::resizeRequested(float width, float height, WebView* view) { - if (view != currentWebView()) - return; + if (view != currentWebView()) + return; // TODO: Ignore request when there is more than one WebView embedded! @@ -449,19 +478,19 @@ void LauncherWindow::resizeRequested(float width, float height, WebView* view) void LauncherWindow::setToolBarsVisible(bool flag, WebView* view) { - // TODO + // TODO // TODO: Ignore request when there is more than one WebView embedded! } void LauncherWindow::setStatusBarVisible(bool flag, WebView* view) { - // TODO + // TODO // TODO: Ignore request when there is more than one WebView embedded! } void LauncherWindow::setMenuBarVisible(bool flag, WebView* view) { - // TODO + // TODO // TODO: Ignore request when there is more than one WebView embedded! } @@ -477,20 +506,24 @@ void LauncherWindow::setResizable(bool flag, WebView* view) void LauncherWindow::titleChanged(const BString& title, WebView* view) { - if (view != currentWebView()) - return; + for (int32 i = 0; i < m_tabView->CountTabs(); i++) + { + if (m_tabView->ViewForTab(i) == view) { + m_tabView->TabAt(i)->SetLabel(title); + m_tabView->DrawTabs(); + break; + } + } + if (view != currentWebView()) + return; - BString windowTitle = title; - if (windowTitle.Length() > 0) - windowTitle << " - "; - windowTitle << "HaikuLauncher"; - SetTitle(windowTitle.String()); + updateTitle(title); } void LauncherWindow::statusChanged(const BString& statusText, WebView* view) { - if (view != currentWebView()) - return; + if (view != currentWebView()) + return; if (m_statusText) m_statusText->SetText(statusText.String()); @@ -499,8 +532,8 @@ void LauncherWindow::statusChanged(const BString& statusText, WebView* view) void LauncherWindow::navigationCapabilitiesChanged(bool canGoBackward, bool canGoForward, bool canStop, WebView* view) { - if (view != currentWebView()) - return; + if (view != currentWebView()) + return; if (m_BackButton) m_BackButton->SetEnabled(canGoBackward); @@ -510,7 +543,7 @@ void LauncherWindow::navigationCapabilitiesChanged(bool canGoBackward, void LauncherWindow::updateGlobalHistory(const BString& url) { - BrowsingHistory::defaultInstance()->addItem(BrowsingHistoryItem(url)); + BrowsingHistory::defaultInstance()->addItem(BrowsingHistoryItem(url)); } void LauncherWindow::authenticationChallenge(BMessage* message) @@ -539,3 +572,12 @@ void LauncherWindow::authenticationChallenge(BMessage* message) reply.AddBool("rememberCredentials", rememberCredentials); message->SendReply(&reply); } + +void LauncherWindow::updateTitle(const BString& title) +{ + BString windowTitle = title; + if (windowTitle.Length() > 0) + windowTitle << " - "; + windowTitle << "HaikuLauncher"; + SetTitle(windowTitle.String()); +} diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index ff537a6be5..ca325b4bc5 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -39,6 +39,7 @@ class BLayoutItem; class BMenu; class BStatusBar; class BStringView; +class BTabView; class BTextControl; class WebView; @@ -48,9 +49,10 @@ enum ToolbarPolicy { }; enum { - NEW_WINDOW = 'nwnd', - WINDOW_OPENED = 'wndo', - WINDOW_CLOSED = 'wndc', + NEW_WINDOW = 'nwnd', + NEW_TAB = 'ntab', + WINDOW_OPENED = 'wndo', + WINDOW_CLOSED = 'wndc', SHOW_DOWNLOAD_WINDOW = 'sdwd' }; @@ -84,6 +86,7 @@ private: bool canGoForward, bool canStop, WebView* view); virtual void updateGlobalHistory(const BString& url); virtual void authenticationChallenge(BMessage* challenge); + void updateTitle(const BString &title); private: BMenuBar* m_menuBar; @@ -97,6 +100,7 @@ private: BLayoutItem* m_findGroup; BTextControl* m_findTextControl; BCheckBox* m_findCaseSensitiveCheckBox; + BTabView* m_tabView; }; #endif // LauncherWindow_h diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp new file mode 100644 index 0000000000..fc454953c7 --- /dev/null +++ b/src/apps/webpositive/WebTabView.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2010 Rene Gollent + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "WebTabView.h" + +WebTabView::WebTabView(const char *name, const BMessenger& target) + : BTabView(name) + , m_target(target) +{ +} + +WebTabView::~WebTabView(void) +{ +} + +void +WebTabView::Select(int32 tab) +{ + BTabView::Select(tab); + BMessage message(TAB_CHANGED); + message.AddInt32("index", tab); + m_target.SendMessage(&message); +} + +const BMessenger& WebTabView::Target(void) const +{ + return m_target; +} + +void WebTabView::SetTarget(const BMessenger& target) +{ + m_target = target; +} diff --git a/src/apps/webpositive/WebTabView.h b/src/apps/webpositive/WebTabView.h new file mode 100644 index 0000000000..7cd7964afb --- /dev/null +++ b/src/apps/webpositive/WebTabView.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2010 Rene Gollent + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WebTabView_h +#define WebTabView_h + +#include +#include + +enum { + TAB_CHANGED = 'tcha' +}; + +class WebTabView : public BTabView { +public: + WebTabView(const char *name, const BMessenger& target); + virtual ~WebTabView(void); + virtual void Select(int32 tab); + + const BMessenger& Target(void) const; + void SetTarget(const BMessenger& target); + +private: + BMessenger m_target; +}; + +#define WebTabView_h +#endif // WebTabView_h From 5eba20dc102e37cf1d2675d6cd05c40d6d6868cd Mon Sep 17 00:00:00 2001 From: anevilyak Date: Sat, 20 Feb 2010 18:46:53 +0000 Subject: [PATCH 030/349] Add close tab support via cmd+shift+w. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@153 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 18 ++++++++++++++++-- src/apps/webpositive/LauncherWindow.h | 1 - 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 9e2e3f5e72..e1ff5e2ba4 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -4,6 +4,7 @@ * Copyright (C) 2009 Maxime Simon * Copyright (C) 2010 Stephan Aßmus * Copyright (C) 2010 Michael Lotz + * Copyright (C) 2010 Rene Gollent * * All rights reserved. * @@ -72,6 +73,9 @@ enum { TEXT_HIDE_FIND_GROUP = 'hfnd', TEXT_FIND_NEXT = 'fndn', TEXT_FIND_PREVIOUS = 'fndp', + + NEW_TAB = 'ntab', + CLOSE_TAB = 'ctab' }; using namespace WebCore; @@ -109,7 +113,10 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, newMenu->AddItem(newItem); newItem->SetTarget(this); menu->AddItem(newMenu); - menu->AddItem(new BMenuItem("Close", new BMessage(B_QUIT_REQUESTED), 'W')); + BMenu *closeMenu = new BMenu("Close"); + closeMenu->AddItem(new BMenuItem("Window", new BMessage(B_QUIT_REQUESTED), 'W')); + closeMenu->AddItem(new BMenuItem("Tab", new BMessage(CLOSE_TAB), 'W', B_SHIFT_KEY)); + menu->AddItem(closeMenu); menu->AddSeparatorItem(); menu->AddItem(new BMenuItem("Show Downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'D')); menu->AddSeparatorItem(); @@ -324,11 +331,18 @@ void LauncherWindow::MessageReceived(BMessage* message) { m_tabView->AddTab(new WebView("web_view")); m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New Tab"); - m_tabView->DrawTabs(); m_tabView->Select(m_tabView->CountTabs() - 1); break; } + case CLOSE_TAB: + { + if (m_tabView->CountTabs() > 0) { + delete m_tabView->RemoveTab(m_tabView->FocusTab()); + } + break; + } + case TAB_CHANGED: { int32 index = message->FindInt32("index"); diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index ca325b4bc5..803b7f2517 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -50,7 +50,6 @@ enum ToolbarPolicy { enum { NEW_WINDOW = 'nwnd', - NEW_TAB = 'ntab', WINDOW_OPENED = 'wndo', WINDOW_CLOSED = 'wndc', SHOW_DOWNLOAD_WINDOW = 'sdwd' From d311e279f536e28f24e65d9c1edc52e772e9d76c Mon Sep 17 00:00:00 2001 From: anevilyak Date: Sat, 20 Feb 2010 18:59:51 +0000 Subject: [PATCH 031/349] Clean up tabs properly on quit. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@154 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index e1ff5e2ba4..92ec37d911 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -349,6 +349,7 @@ void LauncherWindow::MessageReceived(BMessage* message) setCurrentWebView(dynamic_cast( m_tabView->ViewForTab(index))); updateTitle(m_tabView->TabAt(index)->Label()); + m_url->TextView()->SetText(currentWebView()->mainFrameURL()); break; } @@ -364,9 +365,9 @@ bool LauncherWindow::QuitRequested() // Do this here, so WebKit tear down happens earlier. // TODO: Iterator over all WebViews, if there are more then one... - WebView* view = currentWebView(); - view->RemoveSelf(); - delete view; + while (m_tabView->CountTabs() > 0) { + delete m_tabView->RemoveTab(0L); + } setCurrentWebView(0); BMessage message(WINDOW_CLOSED); From 75845de732ffa2ca970d6b9d4e1197769616ee7e Mon Sep 17 00:00:00 2001 From: anevilyak Date: Sat, 20 Feb 2010 19:52:10 +0000 Subject: [PATCH 032/349] Add mechanism for asking LauncherApp to create a web view to ensure new view creation always happens in the main thread. Fixes assert failure when creating a new tab with debug builds. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@155 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherApp.cpp | 6 ++++++ src/apps/webpositive/LauncherApp.h | 4 ++++ src/apps/webpositive/LauncherWindow.cpp | 13 ++++++++++++- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 4f01619717..367894b11a 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -165,6 +165,12 @@ void LauncherApp::MessageReceived(BMessage* message) newWindow(url); break; } + case CREATE_WEBVIEW: { + BMessage reply; + reply.AddPointer("view", new WebView("web_view")); + message->SendReply(&reply); + break; + } case WINDOW_OPENED: m_windowCount++; break; diff --git a/src/apps/webpositive/LauncherApp.h b/src/apps/webpositive/LauncherApp.h index 636169c4a5..8be0c4ebb1 100644 --- a/src/apps/webpositive/LauncherApp.h +++ b/src/apps/webpositive/LauncherApp.h @@ -36,6 +36,10 @@ class BFile; class DownloadWindow; class LauncherWindow; +enum { + CREATE_WEBVIEW = 'crwb' +}; + class LauncherApp : public BApplication { public: LauncherApp(); diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 92ec37d911..12c5c460e9 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -35,6 +35,7 @@ #include "AuthenticationPanel.h" #include "BrowsingHistory.h" +#include "LauncherApp.h" #include "WebPage.h" #include "WebTabView.h" #include "WebView.h" @@ -329,9 +330,14 @@ void LauncherWindow::MessageReceived(BMessage* message) case NEW_TAB: { - m_tabView->AddTab(new WebView("web_view")); + BMessage reply; + be_app_messenger.SendMessage(CREATE_WEBVIEW, &reply); + WebView *view = NULL; + reply.FindPointer("view", reinterpret_cast(&view)); + m_tabView->AddTab(view); m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New Tab"); m_tabView->Select(m_tabView->CountTabs() - 1); + navigationCapabilitiesChanged(false, false, false, currentWebView()); break; } @@ -350,6 +356,11 @@ void LauncherWindow::MessageReceived(BMessage* message) m_tabView->ViewForTab(index))); updateTitle(m_tabView->TabAt(index)->Label()); m_url->TextView()->SetText(currentWebView()->mainFrameURL()); + BWebPage *page = currentWebView()->webPage(); +// bool canGoForward = page->CanGoInDirection(1); +// bool canGoBackward = page->CanGoInDirection(-1); +// navigationCapabilitiesChanged(canGoForward, canGoBackward, false, +// currentWebView()); break; } From 14ad7bdb25ce28b1be7d4bdff21f2013df2407c1 Mon Sep 17 00:00:00 2001 From: anevilyak Date: Sat, 20 Feb 2010 19:59:29 +0000 Subject: [PATCH 033/349] Focus address bar when creating a new tab. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@156 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 12c5c460e9..97a0fbd30a 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -338,6 +338,7 @@ void LauncherWindow::MessageReceived(BMessage* message) m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New Tab"); m_tabView->Select(m_tabView->CountTabs() - 1); navigationCapabilitiesChanged(false, false, false, currentWebView()); + m_url->MakeFocus(true); break; } From 5478dd2992636f251b24de249a421a2c82554396 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 20 Feb 2010 20:03:11 +0000 Subject: [PATCH 034/349] * Asthetical improvements with the new tab view. * Actually set the target on the tab view, so that we change urls when switching tabs. * Move all New/Close items to the top-level, since I find it slightly too awkward to reach them otherwise. * Misc coding style fixes. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@157 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 50 +++++++++++-------------- src/apps/webpositive/LauncherWindow.h | 4 +- src/apps/webpositive/WebTabView.cpp | 11 ++++-- src/apps/webpositive/WebTabView.h | 4 +- 4 files changed, 32 insertions(+), 37 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 97a0fbd30a..e6adae4285 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -95,9 +95,10 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) { m_tabView = new WebTabView("tabview", BMessenger(this)); - WebView *webView = new WebView("web_view"); + WebView* webView = new WebView("web_view"); m_tabView->AddTab(webView); m_tabView->TabAt(0L)->SetLabel("New Tab"); + m_tabView->setTarget(BMessenger(this)); setCurrentWebView(webView); if (toolbarPolicy == HaveToolbar) { @@ -106,20 +107,17 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, BMenu* menu = new BMenu("Window"); BMessage* newWindowMessage = new BMessage(NEW_WINDOW); newWindowMessage->AddString("url", ""); - BMenu *newMenu = new BMenu("New"); - BMenuItem* newItem = new BMenuItem("Window", newWindowMessage, 'N'); - newMenu->AddItem(newItem); + BMenuItem* newItem = new BMenuItem("New window", newWindowMessage, 'N'); + menu->AddItem(newItem); newItem->SetTarget(be_app); - newItem = new BMenuItem("Tab", new BMessage(NEW_TAB), 'T'); - newMenu->AddItem(newItem); + newItem = new BMenuItem("New tab", new BMessage(NEW_TAB), 'T'); + menu->AddItem(newItem); newItem->SetTarget(this); - menu->AddItem(newMenu); - BMenu *closeMenu = new BMenu("Close"); - closeMenu->AddItem(new BMenuItem("Window", new BMessage(B_QUIT_REQUESTED), 'W')); - closeMenu->AddItem(new BMenuItem("Tab", new BMessage(CLOSE_TAB), 'W', B_SHIFT_KEY)); - menu->AddItem(closeMenu); menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Show Downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'D')); + menu->AddItem(new BMenuItem("Close window", new BMessage(B_QUIT_REQUESTED), 'W')); + menu->AddItem(new BMenuItem("Close tab", new BMessage(CLOSE_TAB), 'W', B_SHIFT_KEY)); + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("Show downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'D')); menu->AddSeparatorItem(); BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); menu->AddItem(quitItem); @@ -152,7 +150,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_statusText = new BStringView("status", ""); m_statusText->SetAlignment(B_ALIGN_LEFT); m_statusText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); - m_statusText->SetExplicitMinSize(BSize(150, 16)); + m_statusText->SetExplicitMinSize(BSize(150, 15)); // Prevent the window from growing to fit a long status message... BFont font(be_plain_font); font.SetSize(ceilf(font.Size() * 0.8)); @@ -171,7 +169,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, new BMessage(TEXT_FIND_NEXT)); m_findCaseSensitiveCheckBox = new BCheckBox("Match case"); BView* findGroup = BGroupLayoutBuilder(B_VERTICAL) - .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) +// .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) .Add(m_findTextControl) .Add(new BButton("Previous", new BMessage(TEXT_FIND_PREVIOUS))) @@ -193,10 +191,10 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, .Add(button, 3, 0) .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) ) - .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) +// .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(m_tabView) .Add(findGroup) - .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) +// .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) .Add(m_statusText) .Add(m_loadingProgressBar, 0.2) @@ -328,30 +326,26 @@ void LauncherWindow::MessageReceived(BMessage* message) be_app->PostMessage(message); break; - case NEW_TAB: - { + case NEW_TAB: { BMessage reply; be_app_messenger.SendMessage(CREATE_WEBVIEW, &reply); WebView *view = NULL; reply.FindPointer("view", reinterpret_cast(&view)); m_tabView->AddTab(view); - m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New Tab"); + m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New tab"); m_tabView->Select(m_tabView->CountTabs() - 1); navigationCapabilitiesChanged(false, false, false, currentWebView()); m_url->MakeFocus(true); break; } - case CLOSE_TAB: - { - if (m_tabView->CountTabs() > 0) { + case CLOSE_TAB: { + if (m_tabView->CountTabs() > 0) delete m_tabView->RemoveTab(m_tabView->FocusTab()); - } break; } - case TAB_CHANGED: - { + case TAB_CHANGED: { int32 index = message->FindInt32("index"); setCurrentWebView(dynamic_cast( m_tabView->ViewForTab(index))); @@ -377,9 +371,8 @@ bool LauncherWindow::QuitRequested() // Do this here, so WebKit tear down happens earlier. // TODO: Iterator over all WebViews, if there are more then one... - while (m_tabView->CountTabs() > 0) { + while (m_tabView->CountTabs() > 0) delete m_tabView->RemoveTab(0L); - } setCurrentWebView(0); BMessage message(WINDOW_CLOSED); @@ -533,8 +526,7 @@ void LauncherWindow::setResizable(bool flag, WebView* view) void LauncherWindow::titleChanged(const BString& title, WebView* view) { - for (int32 i = 0; i < m_tabView->CountTabs(); i++) - { + for (int32 i = 0; i < m_tabView->CountTabs(); i++) { if (m_tabView->ViewForTab(i) == view) { m_tabView->TabAt(i)->SetLabel(title); m_tabView->DrawTabs(); diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index 803b7f2517..43e00b4700 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -39,8 +39,8 @@ class BLayoutItem; class BMenu; class BStatusBar; class BStringView; -class BTabView; class BTextControl; +class WebTabView; class WebView; enum ToolbarPolicy { @@ -99,7 +99,7 @@ private: BLayoutItem* m_findGroup; BTextControl* m_findTextControl; BCheckBox* m_findCaseSensitiveCheckBox; - BTabView* m_tabView; + WebTabView* m_tabView; }; #endif // LauncherWindow_h diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index fc454953c7..a45ccc38c2 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -27,18 +27,21 @@ #include "WebTabView.h" +#include + WebTabView::WebTabView(const char *name, const BMessenger& target) : BTabView(name) , m_target(target) { + if (BGroupLayout* layout = dynamic_cast(GetLayout())) + layout->SetInsets(2, 2 + TabHeight() - 1, 2, 2); } WebTabView::~WebTabView(void) { } -void -WebTabView::Select(int32 tab) +void WebTabView::Select(int32 tab) { BTabView::Select(tab); BMessage message(TAB_CHANGED); @@ -46,12 +49,12 @@ WebTabView::Select(int32 tab) m_target.SendMessage(&message); } -const BMessenger& WebTabView::Target(void) const +const BMessenger& WebTabView::target() const { return m_target; } -void WebTabView::SetTarget(const BMessenger& target) +void WebTabView::setTarget(const BMessenger& target) { m_target = target; } diff --git a/src/apps/webpositive/WebTabView.h b/src/apps/webpositive/WebTabView.h index 7cd7964afb..ac85a460c1 100644 --- a/src/apps/webpositive/WebTabView.h +++ b/src/apps/webpositive/WebTabView.h @@ -41,8 +41,8 @@ public: virtual ~WebTabView(void); virtual void Select(int32 tab); - const BMessenger& Target(void) const; - void SetTarget(const BMessenger& target); + const BMessenger& target() const; + void setTarget(const BMessenger& target); private: BMessenger m_target; From 14c76a65466a543522170992ed253a7b399b07e2 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 21 Feb 2010 12:49:11 +0000 Subject: [PATCH 035/349] Use arrow icons for th enavigation buttons. The IconButton class is a slightly extended version of the LaunchBox version (added TrimIcon() method). Will go away when/if the browser is moved into the Haiku source tree. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@159 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/IconButton.cpp | 924 ++++++++++++++++++++++++ src/apps/webpositive/IconButton.h | 134 ++++ src/apps/webpositive/IconUtils.h | 80 ++ src/apps/webpositive/Launcher.rdef | 36 + src/apps/webpositive/LauncherWindow.cpp | 18 +- src/apps/webpositive/LauncherWindow.h | 5 +- 6 files changed, 1188 insertions(+), 9 deletions(-) create mode 100644 src/apps/webpositive/IconButton.cpp create mode 100644 src/apps/webpositive/IconButton.h create mode 100644 src/apps/webpositive/IconUtils.h diff --git a/src/apps/webpositive/IconButton.cpp b/src/apps/webpositive/IconButton.cpp new file mode 100644 index 0000000000..317754aecd --- /dev/null +++ b/src/apps/webpositive/IconButton.cpp @@ -0,0 +1,924 @@ +/* + * Copyright 2006-2010, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +// NOTE: this file is a duplicate of the version in Icon-O-Matic/generic +// it should be placed into a common folder for generic useful stuff + +#include "IconButton.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "IconUtils.h" + +using std::nothrow; + +// constructor +IconButton::IconButton(const char* name, uint32 id, const char* label, + BMessage* message, BHandler* target) + : BView(name, B_WILL_DRAW), + BInvoker(message, target), + fButtonState(STATE_ENABLED), + fID(id), + fNormalBitmap(NULL), + fDisabledBitmap(NULL), + fClickedBitmap(NULL), + fDisabledClickedBitmap(NULL), + fLabel(label), + fTargetCache(target) +{ + SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + SetViewColor(B_TRANSPARENT_32_BIT); +} + +// destructor +IconButton::~IconButton() +{ + _DeleteBitmaps(); +} + +// MessageReceived +void +IconButton::MessageReceived(BMessage* message) +{ + switch (message->what) { + default: + BView::MessageReceived(message); + break; + } +} + +// AttachedToWindow +void +IconButton::AttachedToWindow() +{ + rgb_color background = B_TRANSPARENT_COLOR; + if (BView* parent = Parent()) { + background = parent->ViewColor(); + if (background == B_TRANSPARENT_COLOR) + background = parent->LowColor(); + } + if (background == B_TRANSPARENT_COLOR) + background = ui_color(B_PANEL_BACKGROUND_COLOR); + SetLowColor(background); + + SetTarget(fTargetCache); + if (!Target()) + SetTarget(Window()); +} + +// Draw +void +IconButton::Draw(BRect area) +{ + rgb_color background = LowColor(); + + BRect r(Bounds()); + + if (be_control_look != NULL) { + uint32 flags = 0; + BBitmap* bitmap = fNormalBitmap; + if (!IsEnabled()) { + flags |= BControlLook::B_DISABLED; + bitmap = fDisabledBitmap; + } + if (_HasFlags(STATE_PRESSED) || _HasFlags(STATE_FORCE_PRESSED)) + flags |= BControlLook::B_ACTIVATED; + + if (DrawBorder()) { + be_control_look->DrawButtonFrame(this, r, area, background, + background, flags); + be_control_look->DrawButtonBackground(this, r, area, background, + flags); + } else { + SetHighColor(background); + FillRect(r); + } + + if (bitmap && bitmap->IsValid()) { + float x = r.left + floorf((r.Width() + - bitmap->Bounds().Width()) / 2.0 + 0.5); + float y = r.top + floorf((r.Height() + - bitmap->Bounds().Height()) / 2.0 + 0.5); + BPoint point(x, y); + if (_HasFlags(STATE_PRESSED) || _HasFlags(STATE_FORCE_PRESSED)) + point += BPoint(1.0, 1.0); + if (bitmap->ColorSpace() == B_RGBA32 + || bitmap->ColorSpace() == B_RGBA32_BIG) { + SetDrawingMode(B_OP_ALPHA); + SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); + } + DrawBitmap(bitmap, point); + } + return; + } + + rgb_color lightShadow, shadow, darkShadow, light; + BBitmap* bitmap = fNormalBitmap; + // adjust colors and bitmap according to flags + if (IsEnabled()) { + lightShadow = tint_color(background, B_DARKEN_1_TINT); + shadow = tint_color(background, B_DARKEN_2_TINT); + darkShadow = tint_color(background, B_DARKEN_4_TINT); + light = tint_color(background, B_LIGHTEN_MAX_TINT); + SetHighColor(0, 0, 0, 255); + } else { + lightShadow = tint_color(background, 1.11); + shadow = tint_color(background, B_DARKEN_1_TINT); + darkShadow = tint_color(background, B_DARKEN_2_TINT); + light = tint_color(background, B_LIGHTEN_2_TINT); + bitmap = fDisabledBitmap; + SetHighColor(tint_color(background, B_DISABLED_LABEL_TINT)); + } + if (_HasFlags(STATE_PRESSED) || _HasFlags(STATE_FORCE_PRESSED)) { + if (IsEnabled()) { +// background = tint_color(background, B_DARKEN_2_TINT); +// background = tint_color(background, B_LIGHTEN_1_TINT); + background = tint_color(background, B_DARKEN_1_TINT); + bitmap = fClickedBitmap; + } else { +// background = tint_color(background, B_DARKEN_1_TINT); +// background = tint_color(background, (B_NO_TINT + B_LIGHTEN_1_TINT) / 2.0); + background = tint_color(background, (B_NO_TINT + B_DARKEN_1_TINT) / 2.0); + bitmap = fDisabledClickedBitmap; + } + // background + SetLowColor(background); + r.InsetBy(2.0, 2.0); + StrokeLine(r.LeftBottom(), r.LeftTop(), B_SOLID_LOW); + StrokeLine(r.LeftTop(), r.RightTop(), B_SOLID_LOW); + r.InsetBy(-2.0, -2.0); + } + // draw frame only if tracking + if (DrawBorder()) { + if (_HasFlags(STATE_PRESSED) || _HasFlags(STATE_FORCE_PRESSED)) + DrawPressedBorder(r, background, shadow, darkShadow, lightShadow, light); + else + DrawNormalBorder(r, background, shadow, darkShadow, lightShadow, light); + r.InsetBy(2.0, 2.0); + } else + _DrawFrame(r, background, background, background, background); + float width = Bounds().Width(); + float height = Bounds().Height(); + // bitmap + BRegion originalClippingRegion; + if (bitmap && bitmap->IsValid()) { + float x = floorf((width - bitmap->Bounds().Width()) / 2.0 + 0.5); + float y = floorf((height - bitmap->Bounds().Height()) / 2.0 + 0.5); + BPoint point(x, y); + if (_HasFlags(STATE_PRESSED) || _HasFlags(STATE_FORCE_PRESSED)) + point += BPoint(1.0, 1.0); + if (bitmap->ColorSpace() == B_RGBA32 || bitmap->ColorSpace() == B_RGBA32_BIG) { + FillRect(r, B_SOLID_LOW); + SetDrawingMode(B_OP_ALPHA); + SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); + } + DrawBitmap(bitmap, point); + // constrain clipping region + BRegion region= originalClippingRegion; + GetClippingRegion(®ion); + region.Exclude(bitmap->Bounds().OffsetByCopy(point)); + ConstrainClippingRegion(®ion); + } + // background + SetDrawingMode(B_OP_COPY); + FillRect(r, B_SOLID_LOW); + ConstrainClippingRegion(NULL); + // label + if (fLabel.CountChars() > 0) { + SetDrawingMode(B_OP_COPY); + font_height fh; + GetFontHeight(&fh); + float y = Bounds().bottom - 4.0; + y -= fh.descent; + float x = (width - StringWidth(fLabel.String())) / 2.0; + DrawString(fLabel.String(), BPoint(x, y)); + } +} + +// MouseDown +void +IconButton::MouseDown(BPoint where) +{ + if (!IsValid()) + return; + + if (_HasFlags(STATE_ENABLED)/* && !_HasFlags(STATE_FORCE_PRESSED)*/) { + if (Bounds().Contains(where)) { + SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); + _AddFlags(STATE_PRESSED | STATE_TRACKING); + } else { + _ClearFlags(STATE_PRESSED | STATE_TRACKING); + } + } +} + +// MouseUp +void +IconButton::MouseUp(BPoint where) +{ + if (!IsValid()) + return; + +// if (!_HasFlags(STATE_FORCE_PRESSED)) { + if (_HasFlags(STATE_ENABLED) && _HasFlags(STATE_PRESSED) && Bounds().Contains(where)) + Invoke(); + else if (Bounds().Contains(where)) + _AddFlags(STATE_INSIDE); + _ClearFlags(STATE_PRESSED | STATE_TRACKING); +// } +} + +// MouseMoved +void +IconButton::MouseMoved(BPoint where, uint32 transit, const BMessage* message) +{ + if (!IsValid()) + return; + + uint32 buttons = 0; + Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons); + // catch a mouse up event that we might have missed + if (!buttons && _HasFlags(STATE_PRESSED)) { + MouseUp(where); + return; + } + if (buttons && !_HasFlags(STATE_TRACKING)) + return; + if ((transit == B_INSIDE_VIEW || transit == B_ENTERED_VIEW) + && _HasFlags(STATE_ENABLED)) + _AddFlags(STATE_INSIDE); + else + _ClearFlags(STATE_INSIDE); + if (_HasFlags(STATE_TRACKING)) { + if (Bounds().Contains(where)) + _AddFlags(STATE_PRESSED); + else + _ClearFlags(STATE_PRESSED); + } +} + +#define MIN_SPACE 15.0 + +// GetPreferredSize +void +IconButton::GetPreferredSize(float* width, float* height) +{ + float minWidth = 0.0; + float minHeight = 0.0; + if (IsValid()) { + minWidth += fNormalBitmap->Bounds().IntegerWidth() + 1.0; + minHeight += fNormalBitmap->Bounds().IntegerHeight() + 1.0; + } + if (minWidth < MIN_SPACE) + minWidth = MIN_SPACE; + if (minHeight < MIN_SPACE) + minHeight = MIN_SPACE; + + float hPadding = max_c(6.0, ceilf(minHeight / 4.0)); + float vPadding = max_c(6.0, ceilf(minWidth / 4.0)); + + if (fLabel.CountChars() > 0) { + font_height fh; + GetFontHeight(&fh); + minHeight += ceilf(fh.ascent + fh.descent) + vPadding; + minWidth += StringWidth(fLabel.String()) + vPadding; + } + + if (width) + *width = minWidth + hPadding; + if (height) + *height = minHeight + vPadding; +} + +// MinSize +BSize +IconButton::MinSize() +{ + BSize size; + GetPreferredSize(&size.width, &size.height); + return size; +} + +// MaxSize +BSize +IconButton::MaxSize() +{ + return MinSize(); +} + +// Invoke +status_t +IconButton::Invoke(BMessage* message) +{ + if (!message) + message = Message(); + if (message) { + BMessage clone(*message); + clone.AddInt64("be:when", system_time()); + clone.AddPointer("be:source", (BView*)this); + clone.AddInt32("be:value", Value()); + clone.AddInt32("id", ID()); + return BInvoker::Invoke(&clone); + } + return BInvoker::Invoke(message); +} + +// SetPressed +void +IconButton::SetPressed(bool pressed) +{ + if (pressed) + _AddFlags(STATE_FORCE_PRESSED); + else + _ClearFlags(STATE_FORCE_PRESSED); +} + +// IsPressed +bool +IconButton::IsPressed() const +{ + return _HasFlags(STATE_FORCE_PRESSED); +} + +status_t +IconButton::SetIcon(int32 resourceID) +{ + app_info info; + status_t status = be_app->GetAppInfo(&info); + if (status != B_OK) + return status; + + BResources resources(&info.ref); + status = resources.InitCheck(); + if (status != B_OK) + return status; + +printf("check\n"); + size_t size; + const void* data = resources.LoadResource(B_VECTOR_ICON_TYPE, resourceID, + &size); + if (data != NULL) { +printf("found resource\n"); + BBitmap bitmap(BRect(0, 0, 31, 31), B_BITMAP_NO_SERVER_LINK, B_RGBA32); + status = bitmap.InitCheck(); + if (status != B_OK) + return status; + status = BIconUtils::GetVectorIcon(reinterpret_cast(data), + size, &bitmap); + if (status != B_OK) + return status; + return SetIcon(&bitmap); + } +// const void* data = resources.LoadResource(B_BITMAP_TYPE, resourceID, &size); + return B_ERROR; +} + +// SetIcon +status_t +IconButton::SetIcon(const char* pathToBitmap) +{ + if (pathToBitmap == NULL) + return B_BAD_VALUE; + + status_t status = B_BAD_VALUE; + BBitmap* fileBitmap = NULL; + // try to load bitmap from either relative or absolute path + BEntry entry(pathToBitmap, true); + if (!entry.Exists()) { + app_info info; + status = be_app->GetAppInfo(&info); + if (status == B_OK) { + BEntry app_entry(&info.ref, true); + BPath path; + app_entry.GetPath(&path); + status = path.InitCheck(); + if (status == B_OK) { + status = path.GetParent(&path); + if (status == B_OK) { + status = path.Append(pathToBitmap, true); + if (status == B_OK) + fileBitmap = BTranslationUtils::GetBitmap(path.Path()); + else + printf("IconButton::SetIcon() - path.Append() failed: %s\n", strerror(status)); + } else + printf("IconButton::SetIcon() - path.GetParent() failed: %s\n", strerror(status)); + } else + printf("IconButton::SetIcon() - path.InitCheck() failed: %s\n", strerror(status)); + } else + printf("IconButton::SetIcon() - be_app->GetAppInfo() failed: %s\n", strerror(status)); + } else + fileBitmap = BTranslationUtils::GetBitmap(pathToBitmap); + if (fileBitmap) { + status = _MakeBitmaps(fileBitmap); + delete fileBitmap; + } else + status = B_ERROR; + return status; +} + +// SetIcon +status_t +IconButton::SetIcon(const BBitmap* bitmap) +{ + if (bitmap && bitmap->ColorSpace() == B_CMAP8) { + status_t status = bitmap->InitCheck(); + if (status >= B_OK) { + if (BBitmap* rgb32Bitmap = _ConvertToRGB32(bitmap)) { + status = _MakeBitmaps(rgb32Bitmap); + delete rgb32Bitmap; + } else + status = B_NO_MEMORY; + } + return status; + } else + return _MakeBitmaps(bitmap); +} + +// SetIcon +status_t +IconButton::SetIcon(const BMimeType* fileType, bool small) +{ + status_t status = fileType ? fileType->InitCheck() : B_BAD_VALUE; + if (status >= B_OK) { + BBitmap* mimeBitmap = new(nothrow) BBitmap(BRect(0.0, 0.0, 15.0, 15.0), B_CMAP8); + if (mimeBitmap && mimeBitmap->IsValid()) { + status = fileType->GetIcon(mimeBitmap, small ? B_MINI_ICON : B_LARGE_ICON); + if (status >= B_OK) { + if (BBitmap* bitmap = _ConvertToRGB32(mimeBitmap)) { + status = _MakeBitmaps(bitmap); + delete bitmap; + } else + printf("IconButton::SetIcon() - B_RGB32 bitmap is not valid\n"); + } else + printf("IconButton::SetIcon() - fileType->GetIcon() failed: %s\n", strerror(status)); + } else + printf("IconButton::SetIcon() - B_CMAP8 bitmap is not valid\n"); + delete mimeBitmap; + } else + printf("IconButton::SetIcon() - fileType is not valid: %s\n", strerror(status)); + return status; +} + +// SetIcon +status_t +IconButton::SetIcon(const unsigned char* bitsFromQuickRes, + uint32 width, uint32 height, color_space format, bool convertToBW) +{ + status_t status = B_BAD_VALUE; + if (bitsFromQuickRes && width > 0 && height > 0) { + BBitmap* quickResBitmap = new(nothrow) BBitmap(BRect(0.0, 0.0, width - 1.0, height - 1.0), format); + status = quickResBitmap ? quickResBitmap->InitCheck() : B_ERROR; + if (status >= B_OK) { + // It doesn't look right to copy BitsLength() bytes, but bitmaps + // exported from QuickRes still contain their padding, so it is alright. + memcpy(quickResBitmap->Bits(), bitsFromQuickRes, quickResBitmap->BitsLength()); + if (format != B_RGB32 && format != B_RGBA32 && format != B_RGB32_BIG && format != B_RGBA32_BIG) { + // colorspace needs conversion + BBitmap* bitmap = new(nothrow) BBitmap(quickResBitmap->Bounds(), B_RGB32, true); + if (bitmap && bitmap->IsValid()) { + BView* helper = new BView(bitmap->Bounds(), "helper", + B_FOLLOW_NONE, B_WILL_DRAW); + if (bitmap->Lock()) { + bitmap->AddChild(helper); + helper->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + helper->FillRect(helper->Bounds()); + helper->SetDrawingMode(B_OP_OVER); + helper->DrawBitmap(quickResBitmap, BPoint(0.0, 0.0)); + helper->Sync(); + bitmap->Unlock(); + } + status = _MakeBitmaps(bitmap); + } else + printf("IconButton::SetIcon() - B_RGB32 bitmap is not valid\n"); + delete bitmap; + } else { + // native colorspace (32 bits) + if (convertToBW) { + // convert to gray scale icon + uint8* bits = (uint8*)quickResBitmap->Bits(); + uint32 bpr = quickResBitmap->BytesPerRow(); + for (uint32 y = 0; y < height; y++) { + uint8* handle = bits; + uint8 gray; + for (uint32 x = 0; x < width; x++) { + gray = uint8((116 * handle[0] + 600 * handle[1] + 308 * handle[2]) / 1024); + handle[0] = gray; + handle[1] = gray; + handle[2] = gray; + handle += 4; + } + bits += bpr; + } + } + status = _MakeBitmaps(quickResBitmap); + } + } else + printf("IconButton::SetIcon() - error allocating bitmap: %s\n", strerror(status)); + delete quickResBitmap; + } + return status; +} + +// ClearIcon +void +IconButton::ClearIcon() +{ + _DeleteBitmaps(); + _Update(); +} + +void +IconButton::TrimIcon(bool keepAspect) +{ + if (fNormalBitmap == NULL) + return; + + uint8* bits = (uint8*)fNormalBitmap->Bits(); + uint32 bpr = fNormalBitmap->BytesPerRow(); + uint32 width = fNormalBitmap->Bounds().IntegerWidth() + 1; + uint32 height = fNormalBitmap->Bounds().IntegerHeight() + 1; + BRect trimmed(LONG_MAX, LONG_MAX, LONG_MIN, LONG_MIN); + for (uint32 y = 0; y < height; y++) { + uint8* b = bits + 3; + bool rowHasAlpha = false; + for (uint32 x = 0; x < width; x++) { + if (*b) { + rowHasAlpha = true; + if (x < trimmed.left) + trimmed.left = x; + if (x > trimmed.right) + trimmed.right = x; + } + b += 4; + } + if (rowHasAlpha) { + if (y < trimmed.top) + trimmed.top = y; + if (y > trimmed.bottom) + trimmed.bottom = y; + } + bits += bpr; + } + if (!trimmed.IsValid()) + return; + if (keepAspect) { + float minInset = trimmed.left; + minInset = min_c(minInset, trimmed.top); + minInset = min_c(minInset, fNormalBitmap->Bounds().right - trimmed.right); + minInset = min_c(minInset, fNormalBitmap->Bounds().bottom - trimmed.bottom); + trimmed = fNormalBitmap->Bounds().InsetByCopy(minInset, minInset); + } + trimmed = trimmed & fNormalBitmap->Bounds(); + BBitmap trimmedBitmap(trimmed.OffsetToCopy(B_ORIGIN), + B_BITMAP_NO_SERVER_LINK, B_RGBA32); + bits = (uint8*)fNormalBitmap->Bits(); + bits += 4 * (int32)trimmed.left + bpr * (int32)trimmed.top; + uint8* dst = (uint8*)trimmedBitmap.Bits(); + uint32 trimmedWidth = trimmedBitmap.Bounds().IntegerWidth() + 1; + uint32 trimmedHeight = trimmedBitmap.Bounds().IntegerHeight() + 1; + uint32 trimmedBPR = trimmedBitmap.BytesPerRow(); + for (uint32 y = 0; y < trimmedHeight; y++) { + memcpy(dst, bits, trimmedWidth * 4); + dst += trimmedBPR; + bits += bpr; + } + SetIcon(&trimmedBitmap); +} + +// Bitmap +BBitmap* +IconButton::Bitmap() const +{ + BBitmap* bitmap = NULL; + if (fNormalBitmap && fNormalBitmap->IsValid()) { + bitmap = new(nothrow) BBitmap(fNormalBitmap); + if (bitmap->IsValid()) { + // TODO: remove this functionality when we use real transparent bitmaps + uint8* bits = (uint8*)bitmap->Bits(); + uint32 bpr = bitmap->BytesPerRow(); + uint32 width = bitmap->Bounds().IntegerWidth() + 1; + uint32 height = bitmap->Bounds().IntegerHeight() + 1; + color_space format = bitmap->ColorSpace(); + if (format == B_CMAP8) { + // replace gray with magic transparent index + } else if (format == B_RGB32) { + for (uint32 y = 0; y < height; y++) { + uint8* bitsHandle = bits; + for (uint32 x = 0; x < width; x++) { + if (bitsHandle[0] == 216 + && bitsHandle[1] == 216 + && bitsHandle[2] == 216) { + bitsHandle[3] = 0; // make this pixel completely transparent + } + bitsHandle += 4; + } + bits += bpr; + } + } + } else { + delete bitmap; + bitmap = NULL; + } + } + return bitmap; +} + +// DrawBorder +bool +IconButton::DrawBorder() const +{ + return ((IsEnabled() && (_HasFlags(STATE_INSIDE) + || _HasFlags(STATE_TRACKING))) || _HasFlags(STATE_FORCE_PRESSED)); +} + +// DrawNormalBorder +void +IconButton::DrawNormalBorder(BRect r, rgb_color background, + rgb_color shadow, rgb_color darkShadow, + rgb_color lightShadow, rgb_color light) +{ + _DrawFrame(r, shadow, darkShadow, light, lightShadow); +} + +// DrawPressedBorder +void +IconButton::DrawPressedBorder(BRect r, rgb_color background, + rgb_color shadow, rgb_color darkShadow, + rgb_color lightShadow, rgb_color light) +{ + _DrawFrame(r, shadow, light, darkShadow, background); +} + +// IsValid +bool +IconButton::IsValid() const +{ + return (fNormalBitmap && fDisabledBitmap && fClickedBitmap + && fDisabledClickedBitmap + && fNormalBitmap->IsValid() + && fDisabledBitmap->IsValid() + && fClickedBitmap->IsValid() + && fDisabledClickedBitmap->IsValid()); +} + +// Value +int32 +IconButton::Value() const +{ + return _HasFlags(STATE_PRESSED) ? B_CONTROL_ON : B_CONTROL_OFF; +} + +// SetValue +void +IconButton::SetValue(int32 value) +{ + if (value) + _AddFlags(STATE_PRESSED); + else + _ClearFlags(STATE_PRESSED); +} + +// IsEnabled +bool +IconButton::IsEnabled() const +{ + return _HasFlags(STATE_ENABLED) ? B_CONTROL_ON : B_CONTROL_OFF; +} + +// SetEnabled +void +IconButton::SetEnabled(bool enabled) +{ + if (enabled) + _AddFlags(STATE_ENABLED); + else + _ClearFlags(STATE_ENABLED | STATE_TRACKING | STATE_INSIDE); +} + +// _ConvertToRGB32 +BBitmap* +IconButton::_ConvertToRGB32(const BBitmap* bitmap) const +{ + BBitmap* convertedBitmap = new(nothrow) BBitmap(bitmap->Bounds(), + B_BITMAP_ACCEPTS_VIEWS, B_RGBA32); + if (convertedBitmap && convertedBitmap->IsValid()) { + memset(convertedBitmap->Bits(), 0, convertedBitmap->BitsLength()); + BView* helper = new BView(bitmap->Bounds(), "helper", + B_FOLLOW_NONE, B_WILL_DRAW); + if (convertedBitmap->Lock()) { + convertedBitmap->AddChild(helper); + helper->SetDrawingMode(B_OP_OVER); + helper->DrawBitmap(bitmap, BPoint(0.0, 0.0)); + helper->Sync(); + convertedBitmap->Unlock(); + } + } else { + delete convertedBitmap; + convertedBitmap = NULL; + } + return convertedBitmap; +} + +// _MakeBitmaps +status_t +IconButton::_MakeBitmaps(const BBitmap* bitmap) +{ + status_t status = bitmap ? bitmap->InitCheck() : B_BAD_VALUE; + if (status >= B_OK) { + // make our own versions of the bitmap + BRect b(bitmap->Bounds()); + _DeleteBitmaps(); + color_space format = bitmap->ColorSpace(); + fNormalBitmap = new(nothrow) BBitmap(b, format); + fDisabledBitmap = new(nothrow) BBitmap(b, format); + fClickedBitmap = new(nothrow) BBitmap(b, format); + fDisabledClickedBitmap = new(nothrow) BBitmap(b, format); + if (IsValid()) { + // copy bitmaps from file bitmap + uint8* nBits = (uint8*)fNormalBitmap->Bits(); + uint8* dBits = (uint8*)fDisabledBitmap->Bits(); + uint8* cBits = (uint8*)fClickedBitmap->Bits(); + uint8* dcBits = (uint8*)fDisabledClickedBitmap->Bits(); + uint8* fBits = (uint8*)bitmap->Bits(); + int32 nbpr = fNormalBitmap->BytesPerRow(); + int32 fbpr = bitmap->BytesPerRow(); + int32 pixels = b.IntegerWidth() + 1; + int32 lines = b.IntegerHeight() + 1; + // nontransparent version: + if (format == B_RGB32 || format == B_RGB32_BIG) { + // iterate over color components + for (int32 y = 0; y < lines; y++) { + for (int32 x = 0; x < pixels; x++) { + int32 nOffset = 4 * x; + int32 fOffset = 4 * x; + nBits[nOffset + 0] = fBits[fOffset + 0]; + nBits[nOffset + 1] = fBits[fOffset + 1]; + nBits[nOffset + 2] = fBits[fOffset + 2]; + nBits[nOffset + 3] = 255; + // clicked bits are darker (lame method...) + cBits[nOffset + 0] = (uint8)((float)nBits[nOffset + 0] * 0.8); + cBits[nOffset + 1] = (uint8)((float)nBits[nOffset + 1] * 0.8); + cBits[nOffset + 2] = (uint8)((float)nBits[nOffset + 2] * 0.8); + cBits[nOffset + 3] = 255; + // disabled bits have less contrast (lame method...) + uint8 grey = 216; + float dist = (nBits[nOffset + 0] - grey) * 0.4; + dBits[nOffset + 0] = (uint8)(grey + dist); + dist = (nBits[nOffset + 1] - grey) * 0.4; + dBits[nOffset + 1] = (uint8)(grey + dist); + dist = (nBits[nOffset + 2] - grey) * 0.4; + dBits[nOffset + 2] = (uint8)(grey + dist); + dBits[nOffset + 3] = 255; + // disabled bits have less contrast (lame method...) + grey = 188; + dist = (nBits[nOffset + 0] - grey) * 0.4; + dcBits[nOffset + 0] = (uint8)(grey + dist); + dist = (nBits[nOffset + 1] - grey) * 0.4; + dcBits[nOffset + 1] = (uint8)(grey + dist); + dist = (nBits[nOffset + 2] - grey) * 0.4; + dcBits[nOffset + 2] = (uint8)(grey + dist); + dcBits[nOffset + 3] = 255; + } + nBits += nbpr; + dBits += nbpr; + cBits += nbpr; + dcBits += nbpr; + fBits += fbpr; + } + // transparent version: + } else if (format == B_RGBA32 || format == B_RGBA32_BIG) { + // iterate over color components + for (int32 y = 0; y < lines; y++) { + for (int32 x = 0; x < pixels; x++) { + int32 nOffset = 4 * x; + int32 fOffset = 4 * x; + nBits[nOffset + 0] = fBits[fOffset + 0]; + nBits[nOffset + 1] = fBits[fOffset + 1]; + nBits[nOffset + 2] = fBits[fOffset + 2]; + nBits[nOffset + 3] = fBits[fOffset + 3]; + // clicked bits are darker (lame method...) + cBits[nOffset + 0] = (uint8)(nBits[nOffset + 0] * 0.8); + cBits[nOffset + 1] = (uint8)(nBits[nOffset + 1] * 0.8); + cBits[nOffset + 2] = (uint8)(nBits[nOffset + 2] * 0.8); + cBits[nOffset + 3] = fBits[fOffset + 3]; + // disabled bits have less opacity + dBits[nOffset + 0] = fBits[fOffset + 0]; + dBits[nOffset + 1] = fBits[fOffset + 1]; + dBits[nOffset + 2] = fBits[fOffset + 2]; + dBits[nOffset + 3] = (uint8)(fBits[fOffset + 3] * 0.5); + // disabled bits have less contrast (lame method...) + dcBits[nOffset + 0] = (uint8)(nBits[nOffset + 0] * 0.8); + dcBits[nOffset + 1] = (uint8)(nBits[nOffset + 1] * 0.8); + dcBits[nOffset + 2] = (uint8)(nBits[nOffset + 2] * 0.8); + dcBits[nOffset + 3] = (uint8)(fBits[fOffset + 3] * 0.5); + } + nBits += nbpr; + dBits += nbpr; + cBits += nbpr; + dcBits += nbpr; + fBits += fbpr; + } + // unsupported format + } else { + printf("IconButton::_MakeBitmaps() - bitmap has unsupported colorspace\n"); + status = B_MISMATCHED_VALUES; + _DeleteBitmaps(); + } + } else { + printf("IconButton::_MakeBitmaps() - error allocating local bitmaps\n"); + status = B_NO_MEMORY; + _DeleteBitmaps(); + } + } else + printf("IconButton::_MakeBitmaps() - bitmap is not valid\n"); + return status; +} + +// _DeleteBitmaps +void +IconButton::_DeleteBitmaps() +{ + delete fNormalBitmap; + fNormalBitmap = NULL; + delete fDisabledBitmap; + fDisabledBitmap = NULL; + delete fClickedBitmap; + fClickedBitmap = NULL; + delete fDisabledClickedBitmap; + fDisabledClickedBitmap = NULL; +} + +// _Update +void +IconButton::_Update() +{ + if (LockLooper()) { + Invalidate(); + UnlockLooper(); + } +} + +// _AddFlags +void +IconButton::_AddFlags(uint32 flags) +{ + if (!(fButtonState & flags)) { + fButtonState |= flags; + _Update(); + } +} + +// _ClearFlags +void +IconButton::_ClearFlags(uint32 flags) +{ + if (fButtonState & flags) { + fButtonState &= ~flags; + _Update(); + } +} + +// _HasFlags +bool +IconButton::_HasFlags(uint32 flags) const +{ + return (fButtonState & flags); +} + +// _DrawFrame +void +IconButton::_DrawFrame(BRect r, rgb_color col1, rgb_color col2, + rgb_color col3, rgb_color col4) +{ + BeginLineArray(8); + AddLine(BPoint(r.left, r.bottom), BPoint(r.left, r.top), col1); + AddLine(BPoint(r.left + 1.0, r.top), BPoint(r.right, r.top), col1); + AddLine(BPoint(r.right, r.top + 1.0), BPoint(r.right, r.bottom), col2); + AddLine(BPoint(r.right - 1.0, r.bottom), BPoint(r.left + 1.0, r.bottom), col2); + r.InsetBy(1.0, 1.0); + AddLine(BPoint(r.left, r.bottom), BPoint(r.left, r.top), col3); + AddLine(BPoint(r.left + 1.0, r.top), BPoint(r.right, r.top), col3); + AddLine(BPoint(r.right, r.top + 1.0), BPoint(r.right, r.bottom), col4); + AddLine(BPoint(r.right - 1.0, r.bottom), BPoint(r.left + 1.0, r.bottom), col4); + EndLineArray(); +} diff --git a/src/apps/webpositive/IconButton.h b/src/apps/webpositive/IconButton.h new file mode 100644 index 0000000000..2876dd8cfd --- /dev/null +++ b/src/apps/webpositive/IconButton.h @@ -0,0 +1,134 @@ +/* + * Copyright 2006-2010, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + */ + +/** gui class that loads an image from disk and shows it + as clickable button */ + +// TODO: inherit from BControl? + +// NOTE: this file is a duplicate of the version in Icon-O-Matic/generic +// it should be placed into a common folder for generic useful stuff + +#ifndef ICON_BUTTON_H +#define ICON_BUTTON_H + +#include +#include +#include + +class BBitmap; +class BMimeType; + +class IconButton : public BView, public BInvoker { +public: + IconButton(const char* name, + uint32 id, + const char* label = NULL, + BMessage* message = NULL, + BHandler* target = NULL); + virtual ~IconButton(); + + // BView interface + virtual void MessageReceived(BMessage* message); + virtual void AttachedToWindow(); + virtual void Draw(BRect updateRect); + virtual void MouseDown(BPoint where); + virtual void MouseUp(BPoint where); + virtual void MouseMoved(BPoint where, uint32 transit, + const BMessage* message); + virtual void GetPreferredSize(float* width, + float* height); + virtual BSize MinSize(); + virtual BSize MaxSize(); + + + // BInvoker interface + virtual status_t Invoke(BMessage* message = NULL); + + // IconButton + bool IsValid() const; + + virtual int32 Value() const; + virtual void SetValue(int32 value); + + bool IsEnabled() const; + void SetEnabled(bool enable); + + void SetPressed(bool pressed); + bool IsPressed() const; + uint32 ID() const + { return fID; } + + status_t SetIcon(int32 resourceID); + status_t SetIcon(const char* pathToBitmap); + status_t SetIcon(const BBitmap* bitmap); + status_t SetIcon(const BMimeType* fileType, + bool small = true); + status_t SetIcon(const unsigned char* bitsFromQuickRes, + uint32 width, uint32 height, + color_space format, + bool convertToBW = false); + void ClearIcon(); + void TrimIcon(bool keepAspect = true); + + BBitmap* Bitmap() const; + // caller has to delete the returned bitmap + + virtual bool DrawBorder() const; + virtual void DrawNormalBorder(BRect r, + rgb_color background, + rgb_color shadow, + rgb_color darkShadow, + rgb_color lightShadow, + rgb_color light); + virtual void DrawPressedBorder(BRect r, + rgb_color background, + rgb_color shadow, + rgb_color darkShadow, + rgb_color lightShadow, + rgb_color light); + +protected: + enum { + STATE_NONE = 0x0000, + STATE_TRACKING = 0x0001, + STATE_PRESSED = 0x0002, + STATE_ENABLED = 0x0004, + STATE_INSIDE = 0x0008, + STATE_FORCE_PRESSED = 0x0010, + }; + + void _AddFlags(uint32 flags); + void _ClearFlags(uint32 flags); + bool _HasFlags(uint32 flags) const; + + void _DrawFrame(BRect frame, + rgb_color col1, + rgb_color col2, + rgb_color col3, + rgb_color col4); + +// private: + BBitmap* _ConvertToRGB32(const BBitmap* bitmap) const; + status_t _MakeBitmaps(const BBitmap* bitmap); + void _DeleteBitmaps(); + void _SendMessage() const; + void _Update(); + + uint32 fButtonState; + int32 fID; + BBitmap* fNormalBitmap; + BBitmap* fDisabledBitmap; + BBitmap* fClickedBitmap; + BBitmap* fDisabledClickedBitmap; + BString fLabel; + + BHandler* fTargetCache; +}; + +#endif // ICON_BUTTON_H diff --git a/src/apps/webpositive/IconUtils.h b/src/apps/webpositive/IconUtils.h new file mode 100644 index 0000000000..fdcfbd946f --- /dev/null +++ b/src/apps/webpositive/IconUtils.h @@ -0,0 +1,80 @@ +/* + * Copyright 2006-2008, Haiku. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _ICON_UTILS_H +#define _ICON_UTILS_H + + +#include + +class BBitmap; +class BNode; + + +// This class is a little different from many other classes. +// You don't create an instance of it; you just call its various +// static member functions for utility-like operations. +class BIconUtils { + BIconUtils(); + ~BIconUtils(); + BIconUtils(const BIconUtils&); + BIconUtils& operator=(const BIconUtils&); + +public: + + // Utility function to import an icon from the node that + // has either of the provided attribute names. Which icon type + // is preferred (vector, small or large B_CMAP8 icon) depends + // on the colorspace of the provided bitmap. If the colorspace + // is B_CMAP8, B_CMAP8 icons are preferred. In that case, the + // bitmap size must also match the provided icon_size "size"! + static status_t GetIcon(BNode* node, + const char* vectorIconAttrName, + const char* smallIconAttrName, + const char* largeIconAttrName, + icon_size size, BBitmap* result); + + // Utility functions to import a vector icon in "flat icon" + // format from a BNode attribute or from a flat buffer in + // memory into the preallocated BBitmap "result". + // The colorspace of result needs to be B_RGBA32 or at + // least B_RGB32 (though that makes less sense). The icon + // will be scaled from it's "native" size of 64x64 to the + // size of the bitmap, the scale is derived from the bitmap + // width, the bitmap should have square dimension, or the + // icon will be cut off at the bottom (or have room left). + static status_t GetVectorIcon(BNode* node, + const char* attrName, BBitmap* result); + + static status_t GetVectorIcon(const uint8* buffer, + size_t size, BBitmap* result); + + // Utility function to import an "old" BeOS icon in B_CMAP8 + // colorspace from either the small icon attribute or the + // large icon attribute as given in "smallIconAttrName" and + // "largeIconAttrName". Which icon is loaded depends on + // the given "size". + static status_t GetCMAP8Icon(BNode* node, + const char* smallIconAttrName, + const char* largeIconAttrName, + icon_size size, BBitmap* icon); + + // Utility functions to convert from old icon colorspace + // into colorspace of BBitmap "result" (should be B_RGBA32 + // to make any sense). + static status_t ConvertFromCMAP8(BBitmap* source, + BBitmap* result); + static status_t ConvertToCMAP8(BBitmap* source, + BBitmap* result); + + static status_t ConvertFromCMAP8(const uint8* data, + uint32 width, uint32 height, + uint32 bytesPerRow, BBitmap* result); + + static status_t ConvertToCMAP8(const uint8* data, + uint32 width, uint32 height, + uint32 bytesPerRow, BBitmap* result); +}; + +#endif // _ICON_UTILS_H diff --git a/src/apps/webpositive/Launcher.rdef b/src/apps/webpositive/Launcher.rdef index 3165079460..fd1410f0e3 100644 --- a/src/apps/webpositive/Launcher.rdef +++ b/src/apps/webpositive/Launcher.rdef @@ -252,3 +252,39 @@ resource vector_icon { $"44013402360000000000000000360000485000466000" }; +resource(201) #'VICN' array { + $"6E636966070500020006023B2FA63AC896BCCBD33D335A4A6980490D0B00ACE2" + $"FFFF6ECDFF0200060236D841374D6EBD38553CC6154AA9DF4607770026A8EBFF" + $"0694DE020006023729EA388C8FBC29073AAE614A51AF4A729A00035E8CFF0585" + $"C70200060238E8A83647FBBA8E2D3D42294AF6F7496CE200047BB8FF0694DE02" + $"0006023957BB3923F0BC39AC3C5E604AA873475AB1000592DAFD67CBFF04FF49" + $"080A092E3C3A53424C484F5047503A4435442B3A300A072E3C3A533A48484F48" + $"403A3A3A300A043A303A3A4435442B0A033A483A53424C0A044840484F504750" + $"3A0A043A3A4435503A48400803C125B7D43AB99FB8D3BE0E08023A3A4840070A" + $"0001001001178400040A010101000A020102000A030103000A040104000A0501" + $"05000A06020607100117812004" +}; + +resource(202) #'VICN' array { + $"6E636966050500020006023B2FA63AC896BCCBD33D335A4A6980490D0B00ACE2" + $"FFFF6ECDFF0200060239AF2C39E19BBC89D83C68DC4AFA1247CFA20006A5F7FF" + $"069EEC02000602B8EEBEB986C33C7FB4BC13FB46FA0C49FBDD000592DAFD3EBD" + $"FF04FF49050A0A2E423A483A524847503F432A3A2F3A3136302E350A0748473A" + $"2F3A392E352E423A483A520A043A2F4847503F432A0A042E3536303A313A3908" + $"0536B9932FBB773B3A3BB939C0E5B755050A0001001001178400040A01010100" + $"0A020102000A030103000A040104100117812004" +}; + +resource(203) #'VICN' array { + $"6E63696607050002000602396DF23A056B3B94FCBB09F547CD484AAB5F0090D9" + $"FFFF6ECDFF02000602B5E5793878A83E023B3B2AC34893F147CC490060C8FFFF" + $"44BEFD02000602B6F90538542D3C2FCA3ACA9249A8634A929A00034F77FF0468" + $"9C020006023AC62E392AB63B6BA0BCFF0B49DAAA4AAE4500046FA7FF2BA5E502" + $"0006023A1CB834EBA6383E33BD3E8D499DE44A647800ACE2FFFD6DCCFF04FF49" + $"080A09523A48533F503C532E4C2E3E3A363A2B482E0A07523A485348473C533C" + $"43483A482E0A04482E483A3A363A2B0A03484748533F500A043C433C532E4C2E" + $"3E0A04483A3A362E3E3C430802BD8FB795C2BDB8E008023C43B8C7BF0D070A00" + $"01001001178400040A040101000A020102000A030103000A010104000A050105" + $"000A06020607100117812004" +}; + diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index e6adae4285..1a453aaf27 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -35,6 +35,7 @@ #include "AuthenticationPanel.h" #include "BrowsingHistory.h" +#include "IconButton.h" #include "LauncherApp.h" #include "WebPage.h" #include "WebTabView.h" @@ -42,6 +43,7 @@ #include "WebViewConstants.h" #include #include +#include #include #include #include @@ -136,8 +138,13 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_menuBar->AddItem(m_goMenu); // Back & Forward - m_BackButton = new BButton("", "Back", new BMessage(GO_BACK)); - m_ForwardButton = new BButton("", "Forward", new BMessage(GO_FORWARD)); + m_BackButton = new IconButton("Back", 0, NULL, new BMessage(GO_BACK)); + m_BackButton->SetIcon(201); + m_BackButton->TrimIcon(); + + m_ForwardButton = new IconButton("Forward", 0, NULL, new BMessage(GO_FORWARD)); + m_ForwardButton->SetIcon(202); + m_ForwardButton->TrimIcon(); // URL m_url = new BTextControl("url", "", "", new BMessage(GOTO_URL)); @@ -347,11 +354,10 @@ void LauncherWindow::MessageReceived(BMessage* message) case TAB_CHANGED: { int32 index = message->FindInt32("index"); - setCurrentWebView(dynamic_cast( - m_tabView->ViewForTab(index))); + setCurrentWebView(dynamic_cast(m_tabView->ViewForTab(index))); updateTitle(m_tabView->TabAt(index)->Label()); m_url->TextView()->SetText(currentWebView()->mainFrameURL()); - BWebPage *page = currentWebView()->webPage(); +// BWebPage* page = currentWebView()->webPage(); // bool canGoForward = page->CanGoInDirection(1); // bool canGoBackward = page->CanGoInDirection(-1); // navigationCapabilitiesChanged(canGoForward, canGoBackward, false, @@ -480,8 +486,6 @@ void LauncherWindow::loadFinished(const BString& url, WebView* view) BString status(url); status << " finished."; statusChanged(status, view); - if (m_url) - m_url->SetText(url.String()); if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) m_loadingProgressBar->Hide(); } diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index 43e00b4700..64d0a18045 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -40,6 +40,7 @@ class BMenu; class BStatusBar; class BStringView; class BTextControl; +class IconButton; class WebTabView; class WebView; @@ -90,8 +91,8 @@ private: private: BMenuBar* m_menuBar; BMenu* m_goMenu; - BButton* m_BackButton; - BButton* m_ForwardButton; + IconButton* m_BackButton; + IconButton* m_ForwardButton; BTextControl* m_url; BString m_loadedURL; BStringView* m_statusText; From 56bdbcc74ec1eb329ec771bea4c10425e5eacfd3 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 21 Feb 2010 13:13:03 +0000 Subject: [PATCH 036/349] Fixed deadlocks when adding a new tab. The WebView needs to be created int the app thread indeed, but the app thread may already be blocking on the window lock, we we cannot wait for a synchronous reply from the app in the window thread. Refactored the tab creation and reused it in the LauncherWindow constructor. Added the ability to load a URL in the new tab right away. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@160 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherApp.cpp | 22 +++++++++--- src/apps/webpositive/LauncherApp.h | 5 +-- src/apps/webpositive/LauncherWindow.cpp | 47 +++++++++++++------------ src/apps/webpositive/LauncherWindow.h | 3 ++ 4 files changed, 46 insertions(+), 31 deletions(-) diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 367894b11a..22c8eb05f6 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -165,10 +165,13 @@ void LauncherApp::MessageReceived(BMessage* message) newWindow(url); break; } - case CREATE_WEBVIEW: { - BMessage reply; - reply.AddPointer("view", new WebView("web_view")); - message->SendReply(&reply); + case NEW_TAB: { + LauncherWindow* window; + if (message->FindPointer("window", reinterpret_cast(&window)) != B_OK) + break; + BString url; + message->FindString("url", &url); + newTab(window, url); break; } case WINDOW_OPENED: @@ -276,6 +279,17 @@ void LauncherApp::newWindow(const BString& url) window->currentWebView()->loadRequest(url.String()); } +void LauncherApp::newTab(LauncherWindow* window, const BString& url) +{ + if (!window->Lock()) + return; + window->newTab(); + window->Unlock(); + + if (url.Length()) + window->currentWebView()->loadRequest(url.String()); +} + // #pragma mark - int main(int, char**) diff --git a/src/apps/webpositive/LauncherApp.h b/src/apps/webpositive/LauncherApp.h index 8be0c4ebb1..69b60bcc78 100644 --- a/src/apps/webpositive/LauncherApp.h +++ b/src/apps/webpositive/LauncherApp.h @@ -36,10 +36,6 @@ class BFile; class DownloadWindow; class LauncherWindow; -enum { - CREATE_WEBVIEW = 'crwb' -}; - class LauncherApp : public BApplication { public: LauncherApp(); @@ -55,6 +51,7 @@ public: private: bool openSettingsFile(BFile& file, uint32 mode); void newWindow(const BString& url); + void newTab(LauncherWindow* window, const BString& url); int m_windowCount; BRect m_lastWindowFrame; diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 1a453aaf27..d434b7934a 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -77,7 +77,6 @@ enum { TEXT_FIND_NEXT = 'fndn', TEXT_FIND_PREVIOUS = 'fndp', - NEW_TAB = 'ntab', CLOSE_TAB = 'ctab' }; @@ -97,11 +96,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) { m_tabView = new WebTabView("tabview", BMessenger(this)); - WebView* webView = new WebView("web_view"); - m_tabView->AddTab(webView); - m_tabView->TabAt(0L)->SetLabel("New Tab"); m_tabView->setTarget(BMessenger(this)); - setCurrentWebView(webView); if (toolbarPolicy == HaveToolbar) { // Menu @@ -112,9 +107,12 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, BMenuItem* newItem = new BMenuItem("New window", newWindowMessage, 'N'); menu->AddItem(newItem); newItem->SetTarget(be_app); - newItem = new BMenuItem("New tab", new BMessage(NEW_TAB), 'T'); + BMessage* newTabMessage = new BMessage(NEW_TAB); + newTabMessage->AddString("url", ""); + newTabMessage->AddPointer("window", this); + newItem = new BMenuItem("New tab", newTabMessage, 'T'); menu->AddItem(newItem); - newItem->SetTarget(this); + newItem->SetTarget(be_app); menu->AddSeparatorItem(); menu->AddItem(new BMenuItem("Close window", new BMessage(B_QUIT_REQUESTED), 'W')); menu->AddItem(new BMenuItem("Close tab", new BMessage(CLOSE_TAB), 'W', B_SHIFT_KEY)); @@ -220,11 +218,15 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_statusText = 0; m_loadingProgressBar = 0; + WebView* webView = new WebView("web_view"); + setCurrentWebView(webView); + AddChild(BGroupLayoutBuilder(B_VERTICAL, 7) .Add(currentWebView()) ); } + newTab(); currentWebView()->webPage()->SetDownloadListener(downloadListener); m_findGroup->SetVisible(false); @@ -234,8 +236,6 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, AddShortcut('F', B_COMMAND_KEY, new BMessage(TEXT_SHOW_FIND_GROUP)); AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_HIDE_FIND_GROUP)); - navigationCapabilitiesChanged(false, false, false, currentWebView()); - be_app->PostMessage(WINDOW_OPENED); } @@ -333,21 +333,9 @@ void LauncherWindow::MessageReceived(BMessage* message) be_app->PostMessage(message); break; - case NEW_TAB: { - BMessage reply; - be_app_messenger.SendMessage(CREATE_WEBVIEW, &reply); - WebView *view = NULL; - reply.FindPointer("view", reinterpret_cast(&view)); - m_tabView->AddTab(view); - m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New tab"); - m_tabView->Select(m_tabView->CountTabs() - 1); - navigationCapabilitiesChanged(false, false, false, currentWebView()); - m_url->MakeFocus(true); - break; - } - case CLOSE_TAB: { - if (m_tabView->CountTabs() > 0) + printf("CLOSE_TAB\n"); + if (m_tabView->CountTabs() > 1) delete m_tabView->RemoveTab(m_tabView->FocusTab()); break; } @@ -418,6 +406,19 @@ void LauncherWindow::MenusBeginning() history->Unlock(); } +void LauncherWindow::newTab() +{ + // Executed in app thread (new BWebPage needs to be created in app thread). + WebView* webView = new WebView("web_view"); + m_tabView->AddTab(webView); + m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New tab"); + m_tabView->Select(m_tabView->CountTabs() - 1); + setCurrentWebView(webView); + navigationCapabilitiesChanged(false, false, false, webView); + if (m_url) + m_url->MakeFocus(true); +} + // #pragma mark - Notification API void LauncherWindow::navigationRequested(const BString& url, WebView* view) diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index 64d0a18045..b113541683 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -51,6 +51,7 @@ enum ToolbarPolicy { enum { NEW_WINDOW = 'nwnd', + NEW_TAB = 'ntab', WINDOW_OPENED = 'wndo', WINDOW_CLOSED = 'wndc', SHOW_DOWNLOAD_WINDOW = 'sdwd' @@ -66,6 +67,8 @@ public: virtual bool QuitRequested(); virtual void MenusBeginning(); + void newTab(); + private: // WebPage notification API implementations virtual void navigationRequested(const BString& url, WebView* view); From 63d76ab872832ad7a57f1bd166d54aac425381cf Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 21 Feb 2010 13:20:57 +0000 Subject: [PATCH 037/349] Middle clicking links will open new tabs, but will not select them. Matches Firefox behavior. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@161 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherApp.cpp | 11 +++++----- src/apps/webpositive/LauncherApp.h | 2 +- src/apps/webpositive/LauncherWindow.cpp | 27 ++++++++++++++++--------- src/apps/webpositive/LauncherWindow.h | 2 +- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 22c8eb05f6..5b60e09a66 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -171,7 +171,9 @@ void LauncherApp::MessageReceived(BMessage* message) break; BString url; message->FindString("url", &url); - newTab(window, url); + bool select = false; + message->FindBool("select", &select); + newTab(window, url, select); break; } case WINDOW_OPENED: @@ -279,15 +281,12 @@ void LauncherApp::newWindow(const BString& url) window->currentWebView()->loadRequest(url.String()); } -void LauncherApp::newTab(LauncherWindow* window, const BString& url) +void LauncherApp::newTab(LauncherWindow* window, const BString& url, bool select) { if (!window->Lock()) return; - window->newTab(); + window->newTab(url, select); window->Unlock(); - - if (url.Length()) - window->currentWebView()->loadRequest(url.String()); } // #pragma mark - diff --git a/src/apps/webpositive/LauncherApp.h b/src/apps/webpositive/LauncherApp.h index 69b60bcc78..15dabba6a2 100644 --- a/src/apps/webpositive/LauncherApp.h +++ b/src/apps/webpositive/LauncherApp.h @@ -51,7 +51,7 @@ public: private: bool openSettingsFile(BFile& file, uint32 mode); void newWindow(const BString& url); - void newTab(LauncherWindow* window, const BString& url); + void newTab(LauncherWindow* window, const BString& url, bool select); int m_windowCount; BRect m_lastWindowFrame; diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index d434b7934a..d1ef7f15eb 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -226,7 +226,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, ); } - newTab(); + newTab("", true); currentWebView()->webPage()->SetDownloadListener(downloadListener); m_findGroup->SetVisible(false); @@ -406,17 +406,23 @@ void LauncherWindow::MenusBeginning() history->Unlock(); } -void LauncherWindow::newTab() +void LauncherWindow::newTab(const BString& url, bool select) { // Executed in app thread (new BWebPage needs to be created in app thread). WebView* webView = new WebView("web_view"); m_tabView->AddTab(webView); m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New tab"); - m_tabView->Select(m_tabView->CountTabs() - 1); - setCurrentWebView(webView); - navigationCapabilitiesChanged(false, false, false, webView); - if (m_url) - m_url->MakeFocus(true); + + if (url.Length()) + webView->loadRequest(url.String()); + + if (select) { + m_tabView->Select(m_tabView->CountTabs() - 1); + setCurrentWebView(webView); + navigationCapabilitiesChanged(false, false, false, webView); + if (m_url) + m_url->MakeFocus(true); + } } // #pragma mark - Notification API @@ -434,9 +440,12 @@ void LauncherWindow::newWindowRequested(const BString& url) // Always open new windows in the application thread, since // creating a WebView will try to grab the application lock. // But our own WebPage may already try to lock us from within - // the application thread -> dead-lock. - BMessage message(NEW_WINDOW); + // the application thread -> dead-lock. Thus we can't wait for + // a reply here. + BMessage message(NEW_TAB); + message.AddPointer("window", this); message.AddString("url", url); + message.AddBool("select", false); be_app->PostMessage(&message); } diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index b113541683..e660d8d1df 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -67,7 +67,7 @@ public: virtual bool QuitRequested(); virtual void MenusBeginning(); - void newTab(); + void newTab(const BString& url, bool select); private: // WebPage notification API implementations From fafcdf7cd1897e868b9fcecf0114fcf68bb4fe52 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 21 Feb 2010 13:34:54 +0000 Subject: [PATCH 038/349] Introduced BWebPage::ResendNotifications(). This is a simple way for the window to update itself to the properties of a page when switching pages. Resolves deadlock problem with BWebPage::CanGoInDirection(), which I've removed. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@162 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index d1ef7f15eb..6c5100a246 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -345,11 +345,9 @@ void LauncherWindow::MessageReceived(BMessage* message) setCurrentWebView(dynamic_cast(m_tabView->ViewForTab(index))); updateTitle(m_tabView->TabAt(index)->Label()); m_url->TextView()->SetText(currentWebView()->mainFrameURL()); -// BWebPage* page = currentWebView()->webPage(); -// bool canGoForward = page->CanGoInDirection(1); -// bool canGoBackward = page->CanGoInDirection(-1); -// navigationCapabilitiesChanged(canGoForward, canGoBackward, false, -// currentWebView()); + // Trigger update of the interface to the new page, by requesting + // to resend all notifications. + currentWebView()->webPage()->ResendNotifications(); break; } From 714edff6e1c1219ac19df3d4dda33e5d695db570 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 21 Feb 2010 13:43:27 +0000 Subject: [PATCH 039/349] Select the new tab when creating it via the menu. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@163 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 6c5100a246..b1ba5135b0 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -110,6 +110,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, BMessage* newTabMessage = new BMessage(NEW_TAB); newTabMessage->AddString("url", ""); newTabMessage->AddPointer("window", this); + newTabMessage->AddBool("select", true); newItem = new BMenuItem("New tab", newTabMessage, 'T'); menu->AddItem(newItem); newItem->SetTarget(be_app); From d3d066c32244cd5587fe792e7bf869cf26b9e3f8 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 21 Feb 2010 13:48:07 +0000 Subject: [PATCH 040/349] BTabView doesn't properly trigger a relayout when adding a new tab. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@164 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index b1ba5135b0..09b484f0fc 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -411,6 +411,8 @@ void LauncherWindow::newTab(const BString& url, bool select) WebView* webView = new WebView("web_view"); m_tabView->AddTab(webView); m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New tab"); + // TODO: Remove when BTabView is fixed... + m_tabView->InvalidateLayout(); if (url.Length()) webView->loadRequest(url.String()); From df621688c56c7c0c2ae2578de9b21136fc404435 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 21 Feb 2010 15:30:49 +0000 Subject: [PATCH 041/349] Fix closing tabs. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@165 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 09b484f0fc..db0c838c66 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -337,7 +337,7 @@ void LauncherWindow::MessageReceived(BMessage* message) case CLOSE_TAB: { printf("CLOSE_TAB\n"); if (m_tabView->CountTabs() > 1) - delete m_tabView->RemoveTab(m_tabView->FocusTab()); + delete m_tabView->RemoveTab(m_tabView->Selection()); break; } From b6ffb2048f4681bbfcc6493c4cd5f25c1197570f Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 21 Feb 2010 15:31:11 +0000 Subject: [PATCH 042/349] Removed stray debug output. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@166 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index db0c838c66..068e5c76f4 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -335,7 +335,6 @@ void LauncherWindow::MessageReceived(BMessage* message) break; case CLOSE_TAB: { - printf("CLOSE_TAB\n"); if (m_tabView->CountTabs() > 1) delete m_tabView->RemoveTab(m_tabView->Selection()); break; From d05b8e1a31a94bf2fdc5784adb5c5663a55b8d1b Mon Sep 17 00:00:00 2001 From: anevilyak Date: Sun, 21 Feb 2010 16:16:46 +0000 Subject: [PATCH 043/349] Change window/tab management shortcuts: - cmd+w now closes the active tab. If the tab is the only one remaining, the window is closed. - cmd+shift+w closes the window, regardless of tab count. Whitespace cleanups. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@167 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 068e5c76f4..8255555a73 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -115,8 +115,8 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, menu->AddItem(newItem); newItem->SetTarget(be_app); menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Close window", new BMessage(B_QUIT_REQUESTED), 'W')); - menu->AddItem(new BMenuItem("Close tab", new BMessage(CLOSE_TAB), 'W', B_SHIFT_KEY)); + menu->AddItem(new BMenuItem("Close window", new BMessage(B_QUIT_REQUESTED), 'W', B_SHIFT_KEY)); + menu->AddItem(new BMenuItem("Close tab", new BMessage(CLOSE_TAB), 'W')); menu->AddSeparatorItem(); menu->AddItem(new BMenuItem("Show downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'D')); menu->AddSeparatorItem(); @@ -337,6 +337,8 @@ void LauncherWindow::MessageReceived(BMessage* message) case CLOSE_TAB: { if (m_tabView->CountTabs() > 1) delete m_tabView->RemoveTab(m_tabView->Selection()); + else + PostMessage(B_QUIT_REQUESTED); break; } @@ -406,19 +408,19 @@ void LauncherWindow::MenusBeginning() void LauncherWindow::newTab(const BString& url, bool select) { - // Executed in app thread (new BWebPage needs to be created in app thread). + // Executed in app thread (new BWebPage needs to be created in app thread). WebView* webView = new WebView("web_view"); m_tabView->AddTab(webView); m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New tab"); // TODO: Remove when BTabView is fixed... m_tabView->InvalidateLayout(); - if (url.Length()) - webView->loadRequest(url.String()); + if (url.Length()) + webView->loadRequest(url.String()); if (select) { - m_tabView->Select(m_tabView->CountTabs() - 1); - setCurrentWebView(webView); + m_tabView->Select(m_tabView->CountTabs() - 1); + setCurrentWebView(webView); navigationCapabilitiesChanged(false, false, false, webView); if (m_url) m_url->MakeFocus(true); @@ -543,7 +545,7 @@ void LauncherWindow::titleChanged(const BString& title, WebView* view) for (int32 i = 0; i < m_tabView->CountTabs(); i++) { if (m_tabView->ViewForTab(i) == view) { m_tabView->TabAt(i)->SetLabel(title); - m_tabView->DrawTabs(); + m_tabView->DrawTabs(); break; } } From 7a9d9c2cf8af614e84de04e78093f3acb96bad74 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 22 Feb 2010 13:23:55 +0000 Subject: [PATCH 044/349] Set the "no border" look to avoid the double frame around the WebView. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@169 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/WebTabView.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index a45ccc38c2..ff59b0f1ca 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -33,8 +33,7 @@ WebTabView::WebTabView(const char *name, const BMessenger& target) : BTabView(name) , m_target(target) { - if (BGroupLayout* layout = dynamic_cast(GetLayout())) - layout->SetInsets(2, 2 + TabHeight() - 1, 2, 2); + SetBorder(B_NO_BORDER); } WebTabView::~WebTabView(void) From 0bcb05f98d1429abbb764249195863e408b93047 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 22 Feb 2010 13:30:54 +0000 Subject: [PATCH 045/349] Forgot to commit this. Polishes no-border BTabView look. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@173 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 8255555a73..1f979bfe63 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -156,7 +156,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_statusText = new BStringView("status", ""); m_statusText->SetAlignment(B_ALIGN_LEFT); m_statusText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); - m_statusText->SetExplicitMinSize(BSize(150, 15)); + m_statusText->SetExplicitMinSize(BSize(150, 16)); // Prevent the window from growing to fit a long status message... BFont font(be_plain_font); font.SetSize(ceilf(font.Size() * 0.8)); @@ -175,7 +175,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, new BMessage(TEXT_FIND_NEXT)); m_findCaseSensitiveCheckBox = new BCheckBox("Match case"); BView* findGroup = BGroupLayoutBuilder(B_VERTICAL) -// .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) .Add(m_findTextControl) .Add(new BButton("Previous", new BMessage(TEXT_FIND_PREVIOUS))) @@ -200,7 +200,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, // .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(m_tabView) .Add(findGroup) -// .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) .Add(m_statusText) .Add(m_loadingProgressBar, 0.2) From e7bd43d9ca7bef43777c1670353f04c6d9762a2f Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 22 Feb 2010 13:36:46 +0000 Subject: [PATCH 046/349] Place the thread priority tweak somewhere where it actually works. This makes HaikuLauncher totally usable under heavy system load. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@174 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherApp.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 5b60e09a66..04d0b5650b 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -59,8 +59,6 @@ LauncherApp::LauncherApp() , m_initialized(false) , m_downloadWindow(0) { - // Since we will essentially run the GUI... - set_thread_priority(Thread(), B_DISPLAY_PRIORITY); } LauncherApp::~LauncherApp() @@ -92,6 +90,9 @@ void LauncherApp::ArgvReceived(int32 argc, char** argv) void LauncherApp::ReadyToRun() { + // Since we will essentially run the GUI... + set_thread_priority(Thread(), B_DISPLAY_PRIORITY); + BWebPage::InitializeOnce(); BWebPage::SetCacheModel(B_WEBKIT_CACHE_MODEL_WEB_BROWSER); From 58a9dd9dfe861e69bc05fccb868a4180ed276a88 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 23 Feb 2010 15:52:17 +0000 Subject: [PATCH 047/349] * Moved exposed classes from WebCore out of WebFrame.h, reintroduced WebFramePrivate to hide WebCore internals from the public API. FrameLoadClientHaiku: * Don't send load requested in policy decision method dispatchDecidePolicyForNavigationAction(). Calling the policy function with PolicyUse will already trigger the load correctly. Ignore the request when we want to load it into a new window/frame instead. * Subframes returned false in canHandleRequest(). This was what stopped stuff being loaded into sub frames! Finally frames and iframes are working. Praise Ingo's Debugger once more! * Renamed LOAD_TRANSFERING to LOAD_COMMITED, since WebCore means that the loader and policy stuff have come to the conclusion to finally load the URL. So that's also the event which needs to update the URL text control. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@182 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/IconButton.cpp | 2 -- src/apps/webpositive/LauncherWindow.cpp | 10 +++++----- src/apps/webpositive/LauncherWindow.h | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/apps/webpositive/IconButton.cpp b/src/apps/webpositive/IconButton.cpp index 317754aecd..36cc142bac 100644 --- a/src/apps/webpositive/IconButton.cpp +++ b/src/apps/webpositive/IconButton.cpp @@ -373,12 +373,10 @@ IconButton::SetIcon(int32 resourceID) if (status != B_OK) return status; -printf("check\n"); size_t size; const void* data = resources.LoadResource(B_VECTOR_ICON_TYPE, resourceID, &size); if (data != NULL) { -printf("found resource\n"); BBitmap bitmap(BRect(0, 0, 31, 31), B_BITMAP_NO_SERVER_LINK, B_RGBA32); status = bitmap.InitCheck(); if (status != B_OK) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 1f979bfe63..3c74d2422c 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -431,10 +431,6 @@ void LauncherWindow::newTab(const BString& url, bool select) void LauncherWindow::navigationRequested(const BString& url, WebView* view) { - // TODO: Move elsewhere, doesn't belong here. - m_loadedURL = url; - if (m_url) - m_url->SetText(url.String()); } void LauncherWindow::newWindowRequested(const BString& url) @@ -458,8 +454,12 @@ void LauncherWindow::loadNegotiating(const BString& url, WebView* view) statusChanged(status, view); } -void LauncherWindow::loadTransfering(const BString& url, WebView* view) +void LauncherWindow::loadCommited(const BString& url, WebView* view) { + // This hook is invoked when the load is commited. + if (m_url) + m_url->SetText(url.String()); + BString status("Loading: "); status << url; statusChanged(status, view); diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index e660d8d1df..745cf70189 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -74,7 +74,7 @@ private: virtual void navigationRequested(const BString& url, WebView* view); virtual void newWindowRequested(const BString& url); virtual void loadNegotiating(const BString& url, WebView* view); - virtual void loadTransfering(const BString& url, WebView* view); + virtual void loadCommited(const BString& url, WebView* view); virtual void loadProgress(float progress, WebView* view); virtual void loadFailed(const BString& url, WebView* view); virtual void loadFinished(const BString& url, WebView* view); From 57b6a0fc1b3532a58a3677288af8dbf6328e3c69 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Feb 2010 10:20:33 +0000 Subject: [PATCH 048/349] * The next round of API cleanup. WebView was renamed to BWebView. Some API needed be ChromeClientHaiku has been moved to BWebPage. WebView.h is now clean and would be ready for the Haiku tree. * BWebPage no longer invalidates the BWebView when a resize happens, WebCore already takes care of that. * BWebView draws a white area in Draw() when the offscreen view is not clean. since no unnecessary invalidation happens, this doesn't result in any flicker and basically only speeds up perceived loading speed, since the web page is immediately white upon program launch. * Since WebTabView does not draw a frame, it removes B_FULL_UPDATE_ON_RESIZE and thereby completely avoids flickering upon window resize. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@190 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherApp.cpp | 4 +- src/apps/webpositive/LauncherWindow.cpp | 79 +++++++++++++------------ src/apps/webpositive/LauncherWindow.h | 30 +++++----- src/apps/webpositive/WebTabView.cpp | 1 + 4 files changed, 60 insertions(+), 54 deletions(-) diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 04d0b5650b..112b528b4b 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -151,7 +151,7 @@ void LauncherApp::MessageReceived(BMessage* message) newWindow(url); } else { // load the URL in the first window - webWindow->currentWebView()->loadRequest(url.String()); + webWindow->currentWebView()->LoadURL(url.String()); } } break; @@ -279,7 +279,7 @@ void LauncherApp::newWindow(const BString& url) BMessenger(m_downloadWindow)); window->Show(); if (url.Length()) - window->currentWebView()->loadRequest(url.String()); + window->currentWebView()->LoadURL(url.String()); } void LauncherApp::newTab(LauncherWindow* window, const BString& url, bool select) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 3c74d2422c..b721e8d313 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -219,7 +219,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_statusText = 0; m_loadingProgressBar = 0; - WebView* webView = new WebView("web_view"); + BWebView* webView = new BWebView("web_view"); setCurrentWebView(webView); AddChild(BGroupLayoutBuilder(B_VERTICAL, 7) @@ -228,7 +228,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, } newTab("", true); - currentWebView()->webPage()->SetDownloadListener(downloadListener); + currentWebView()->WebPage()->SetDownloadListener(downloadListener); m_findGroup->SetVisible(false); @@ -248,20 +248,20 @@ void LauncherWindow::MessageReceived(BMessage* message) { switch (message->what) { case RELOAD: - currentWebView()->loadRequest(m_url->Text()); + currentWebView()->LoadURL(m_url->Text()); break; case GOTO_URL: { BString url = m_url->Text(); message->FindString("url", &url); if (m_loadedURL != url) - currentWebView()->loadRequest(url.String()); + currentWebView()->LoadURL(url.String()); break; } case GO_BACK: - currentWebView()->goBack(); + currentWebView()->GoBack(); break; case GO_FORWARD: - currentWebView()->goForward(); + currentWebView()->GoForward(); break; case CLEAR_HISTORY: { @@ -297,26 +297,26 @@ void LauncherWindow::MessageReceived(BMessage* message) BPath path; if (!entry.Exists() || entry.GetPath(&path) != B_OK) break; - currentWebView()->loadRequest(path.Path()); + currentWebView()->LoadURL(path.Path()); break; } case TEXT_SIZE_INCREASE: - currentWebView()->increaseTextSize(); + currentWebView()->IncreaseTextSize(); break; case TEXT_SIZE_DECREASE: - currentWebView()->decreaseTextSize(); + currentWebView()->DecreaseTextSize(); break; case TEXT_SIZE_RESET: - currentWebView()->resetTextSize(); + currentWebView()->ResetTextSize(); break; case TEXT_FIND_NEXT: - currentWebView()->findString(m_findTextControl->Text(), true, + currentWebView()->FindString(m_findTextControl->Text(), true, m_findCaseSensitiveCheckBox->Value()); break; case TEXT_FIND_PREVIOUS: - currentWebView()->findString(m_findTextControl->Text(), false, + currentWebView()->FindString(m_findTextControl->Text(), false, m_findCaseSensitiveCheckBox->Value()); break; case TEXT_SHOW_FIND_GROUP: @@ -344,12 +344,12 @@ void LauncherWindow::MessageReceived(BMessage* message) case TAB_CHANGED: { int32 index = message->FindInt32("index"); - setCurrentWebView(dynamic_cast(m_tabView->ViewForTab(index))); + setCurrentWebView(dynamic_cast(m_tabView->ViewForTab(index))); updateTitle(m_tabView->TabAt(index)->Label()); - m_url->TextView()->SetText(currentWebView()->mainFrameURL()); + m_url->SetText(currentWebView()->MainFrameURL()); // Trigger update of the interface to the new page, by requesting // to resend all notifications. - currentWebView()->webPage()->ResendNotifications(); + currentWebView()->WebPage()->ResendNotifications(); break; } @@ -409,14 +409,14 @@ void LauncherWindow::MenusBeginning() void LauncherWindow::newTab(const BString& url, bool select) { // Executed in app thread (new BWebPage needs to be created in app thread). - WebView* webView = new WebView("web_view"); + BWebView* webView = new BWebView("web_view"); m_tabView->AddTab(webView); m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New tab"); // TODO: Remove when BTabView is fixed... m_tabView->InvalidateLayout(); if (url.Length()) - webView->loadRequest(url.String()); + webView->LoadURL(url.String()); if (select) { m_tabView->Select(m_tabView->CountTabs() - 1); @@ -429,14 +429,14 @@ void LauncherWindow::newTab(const BString& url, bool select) // #pragma mark - Notification API -void LauncherWindow::navigationRequested(const BString& url, WebView* view) +void LauncherWindow::navigationRequested(const BString& url, BWebView* view) { } void LauncherWindow::newWindowRequested(const BString& url) { // Always open new windows in the application thread, since - // creating a WebView will try to grab the application lock. + // creating a BWebView will try to grab the application lock. // But our own WebPage may already try to lock us from within // the application thread -> dead-lock. Thus we can't wait for // a reply here. @@ -447,15 +447,20 @@ void LauncherWindow::newWindowRequested(const BString& url) be_app->PostMessage(&message); } -void LauncherWindow::loadNegotiating(const BString& url, WebView* view) +void LauncherWindow::loadNegotiating(const BString& url, BWebView* view) { BString status("Requesting: "); status << url; statusChanged(status, view); } -void LauncherWindow::loadCommited(const BString& url, WebView* view) +void LauncherWindow::loadCommited(const BString& url, BWebView* view) { + if (view != currentWebView()) + return; + + m_loadedURL = url; + // This hook is invoked when the load is commited. if (m_url) m_url->SetText(url.String()); @@ -465,7 +470,7 @@ void LauncherWindow::loadCommited(const BString& url, WebView* view) statusChanged(status, view); } -void LauncherWindow::loadProgress(float progress, WebView* view) +void LauncherWindow::loadProgress(float progress, BWebView* view) { if (view != currentWebView()) return; @@ -477,7 +482,7 @@ void LauncherWindow::loadProgress(float progress, WebView* view) } } -void LauncherWindow::loadFailed(const BString& url, WebView* view) +void LauncherWindow::loadFailed(const BString& url, BWebView* view) { if (view != currentWebView()) return; @@ -489,7 +494,7 @@ void LauncherWindow::loadFailed(const BString& url, WebView* view) m_loadingProgressBar->Hide(); } -void LauncherWindow::loadFinished(const BString& url, WebView* view) +void LauncherWindow::loadFinished(const BString& url, BWebView* view) { if (view != currentWebView()) return; @@ -502,37 +507,37 @@ void LauncherWindow::loadFinished(const BString& url, WebView* view) m_loadingProgressBar->Hide(); } -void LauncherWindow::resizeRequested(float width, float height, WebView* view) +void LauncherWindow::resizeRequested(float width, float height, BWebView* view) { if (view != currentWebView()) return; - // TODO: Ignore request when there is more than one WebView embedded! + // TODO: Ignore request when there is more than one BWebView embedded! ResizeTo(width, height); } -void LauncherWindow::setToolBarsVisible(bool flag, WebView* view) +void LauncherWindow::setToolBarsVisible(bool flag, BWebView* view) { // TODO - // TODO: Ignore request when there is more than one WebView embedded! + // TODO: Ignore request when there is more than one BWebView embedded! } -void LauncherWindow::setStatusBarVisible(bool flag, WebView* view) +void LauncherWindow::setStatusBarVisible(bool flag, BWebView* view) { // TODO - // TODO: Ignore request when there is more than one WebView embedded! + // TODO: Ignore request when there is more than one BWebView embedded! } -void LauncherWindow::setMenuBarVisible(bool flag, WebView* view) +void LauncherWindow::setMenuBarVisible(bool flag, BWebView* view) { // TODO - // TODO: Ignore request when there is more than one WebView embedded! + // TODO: Ignore request when there is more than one BWebView embedded! } -void LauncherWindow::setResizable(bool flag, WebView* view) +void LauncherWindow::setResizable(bool flag, BWebView* view) { - // TODO: Ignore request when there is more than one WebView embedded! + // TODO: Ignore request when there is more than one BWebView embedded! if (flag) SetFlags(Flags() & ~B_NOT_RESIZABLE); @@ -540,7 +545,7 @@ void LauncherWindow::setResizable(bool flag, WebView* view) SetFlags(Flags() | B_NOT_RESIZABLE); } -void LauncherWindow::titleChanged(const BString& title, WebView* view) +void LauncherWindow::titleChanged(const BString& title, BWebView* view) { for (int32 i = 0; i < m_tabView->CountTabs(); i++) { if (m_tabView->ViewForTab(i) == view) { @@ -555,7 +560,7 @@ void LauncherWindow::titleChanged(const BString& title, WebView* view) updateTitle(title); } -void LauncherWindow::statusChanged(const BString& statusText, WebView* view) +void LauncherWindow::statusChanged(const BString& statusText, BWebView* view) { if (view != currentWebView()) return; @@ -565,7 +570,7 @@ void LauncherWindow::statusChanged(const BString& statusText, WebView* view) } void LauncherWindow::navigationCapabilitiesChanged(bool canGoBackward, - bool canGoForward, bool canStop, WebView* view) + bool canGoForward, bool canStop, BWebView* view) { if (view != currentWebView()) return; diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index 745cf70189..f1879290fa 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -42,7 +42,7 @@ class BStringView; class BTextControl; class IconButton; class WebTabView; -class WebView; +class BWebView; enum ToolbarPolicy { HaveToolbar, @@ -71,22 +71,22 @@ public: private: // WebPage notification API implementations - virtual void navigationRequested(const BString& url, WebView* view); + virtual void navigationRequested(const BString& url, BWebView* view); virtual void newWindowRequested(const BString& url); - virtual void loadNegotiating(const BString& url, WebView* view); - virtual void loadCommited(const BString& url, WebView* view); - virtual void loadProgress(float progress, WebView* view); - virtual void loadFailed(const BString& url, WebView* view); - virtual void loadFinished(const BString& url, WebView* view); - virtual void titleChanged(const BString& title, WebView* view); - virtual void resizeRequested(float width, float height, WebView* view); - virtual void setToolBarsVisible(bool flag, WebView* view); - virtual void setStatusBarVisible(bool flag, WebView* view); - virtual void setMenuBarVisible(bool flag, WebView* view); - virtual void setResizable(bool flag, WebView* view); - virtual void statusChanged(const BString& status, WebView* view); + virtual void loadNegotiating(const BString& url, BWebView* view); + virtual void loadCommited(const BString& url, BWebView* view); + virtual void loadProgress(float progress, BWebView* view); + virtual void loadFailed(const BString& url, BWebView* view); + virtual void loadFinished(const BString& url, BWebView* view); + virtual void titleChanged(const BString& title, BWebView* view); + virtual void resizeRequested(float width, float height, BWebView* view); + virtual void setToolBarsVisible(bool flag, BWebView* view); + virtual void setStatusBarVisible(bool flag, BWebView* view); + virtual void setMenuBarVisible(bool flag, BWebView* view); + virtual void setResizable(bool flag, BWebView* view); + virtual void statusChanged(const BString& status, BWebView* view); virtual void navigationCapabilitiesChanged(bool canGoBackward, - bool canGoForward, bool canStop, WebView* view); + bool canGoForward, bool canStop, BWebView* view); virtual void updateGlobalHistory(const BString& url); virtual void authenticationChallenge(BMessage* challenge); void updateTitle(const BString &title); diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index ff59b0f1ca..b4ead81c6c 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -34,6 +34,7 @@ WebTabView::WebTabView(const char *name, const BMessenger& target) , m_target(target) { SetBorder(B_NO_BORDER); + SetFlags(Flags() & ~B_FULL_UPDATE_ON_RESIZE); } WebTabView::~WebTabView(void) From d54c477ad18cac663d4c135007985c051f571679 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Feb 2010 10:34:53 +0000 Subject: [PATCH 049/349] Properly set the download listener on new tabs. This fixes the Downloads window not popping up for subsequent tabs. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@192 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 4 +++- src/apps/webpositive/LauncherWindow.h | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index b721e8d313..5fc38abc75 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -94,6 +94,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, : WebViewWindow(frame, "HaikuLauncher", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) + , m_downloadListener(downloadListener) { m_tabView = new WebTabView("tabview", BMessenger(this)); m_tabView->setTarget(BMessenger(this)); @@ -228,7 +229,6 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, } newTab("", true); - currentWebView()->WebPage()->SetDownloadListener(downloadListener); m_findGroup->SetVisible(false); @@ -410,6 +410,8 @@ void LauncherWindow::newTab(const BString& url, bool select) { // Executed in app thread (new BWebPage needs to be created in app thread). BWebView* webView = new BWebView("web_view"); + webView->WebPage()->SetDownloadListener(m_downloadListener); + m_tabView->AddTab(webView); m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New tab"); // TODO: Remove when BTabView is fixed... diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index f1879290fa..d0f8fe0a2c 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -31,6 +31,7 @@ #define LauncherWindow_h #include "WebViewWindow.h" +#include #include class BButton; @@ -92,6 +93,7 @@ private: void updateTitle(const BString &title); private: + BMessenger m_downloadListener; BMenuBar* m_menuBar; BMenu* m_goMenu; IconButton* m_BackButton; From feba54b70cafab7c24a621053b83cc51bbacb2d4 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Feb 2010 10:39:17 +0000 Subject: [PATCH 050/349] Invalidate the BTabView when new tabs are added. Works around new tabs not showing immediately after they have been created, some pages don't set the title either, so then the tab still would't show. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@193 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 5fc38abc75..fe5f9b2c8a 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -415,7 +415,7 @@ void LauncherWindow::newTab(const BString& url, bool select) m_tabView->AddTab(webView); m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New tab"); // TODO: Remove when BTabView is fixed... - m_tabView->InvalidateLayout(); + m_tabView->Invalidate(); if (url.Length()) webView->LoadURL(url.String()); From 054c42b1b9c907fca81f251cbf779c024cf4c64c Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Feb 2010 18:33:22 +0000 Subject: [PATCH 051/349] Renamed WebViewWindow to BWebWindow and converted the API to Haiku coding guide lines. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@195 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherApp.cpp | 4 +- src/apps/webpositive/LauncherWindow.cpp | 98 ++++++++++++------------- src/apps/webpositive/LauncherWindow.h | 39 +++++----- 3 files changed, 71 insertions(+), 70 deletions(-) diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/LauncherApp.cpp index 112b528b4b..5ebef34120 100644 --- a/src/apps/webpositive/LauncherApp.cpp +++ b/src/apps/webpositive/LauncherApp.cpp @@ -151,7 +151,7 @@ void LauncherApp::MessageReceived(BMessage* message) newWindow(url); } else { // load the URL in the first window - webWindow->currentWebView()->LoadURL(url.String()); + webWindow->CurrentWebView()->LoadURL(url.String()); } } break; @@ -279,7 +279,7 @@ void LauncherApp::newWindow(const BString& url) BMessenger(m_downloadWindow)); window->Show(); if (url.Length()) - window->currentWebView()->LoadURL(url.String()); + window->CurrentWebView()->LoadURL(url.String()); } void LauncherApp::newTab(LauncherWindow* window, const BString& url, bool select) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index fe5f9b2c8a..f89037dc13 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -91,7 +91,7 @@ static BLayoutItem* layoutItemFor(BView* view) LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, ToolbarPolicy toolbarPolicy) - : WebViewWindow(frame, "HaikuLauncher", + : BWebWindow(frame, "HaikuLauncher", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) , m_downloadListener(downloadListener) @@ -221,10 +221,10 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_loadingProgressBar = 0; BWebView* webView = new BWebView("web_view"); - setCurrentWebView(webView); + SetCurrentWebView(webView); AddChild(BGroupLayoutBuilder(B_VERTICAL, 7) - .Add(currentWebView()) + .Add(CurrentWebView()) ); } @@ -248,20 +248,20 @@ void LauncherWindow::MessageReceived(BMessage* message) { switch (message->what) { case RELOAD: - currentWebView()->LoadURL(m_url->Text()); + CurrentWebView()->LoadURL(m_url->Text()); break; case GOTO_URL: { BString url = m_url->Text(); message->FindString("url", &url); if (m_loadedURL != url) - currentWebView()->LoadURL(url.String()); + CurrentWebView()->LoadURL(url.String()); break; } case GO_BACK: - currentWebView()->GoBack(); + CurrentWebView()->GoBack(); break; case GO_FORWARD: - currentWebView()->GoForward(); + CurrentWebView()->GoForward(); break; case CLEAR_HISTORY: { @@ -297,26 +297,26 @@ void LauncherWindow::MessageReceived(BMessage* message) BPath path; if (!entry.Exists() || entry.GetPath(&path) != B_OK) break; - currentWebView()->LoadURL(path.Path()); + CurrentWebView()->LoadURL(path.Path()); break; } case TEXT_SIZE_INCREASE: - currentWebView()->IncreaseTextSize(); + CurrentWebView()->IncreaseTextSize(); break; case TEXT_SIZE_DECREASE: - currentWebView()->DecreaseTextSize(); + CurrentWebView()->DecreaseTextSize(); break; case TEXT_SIZE_RESET: - currentWebView()->ResetTextSize(); + CurrentWebView()->ResetTextSize(); break; case TEXT_FIND_NEXT: - currentWebView()->FindString(m_findTextControl->Text(), true, + CurrentWebView()->FindString(m_findTextControl->Text(), true, m_findCaseSensitiveCheckBox->Value()); break; case TEXT_FIND_PREVIOUS: - currentWebView()->FindString(m_findTextControl->Text(), false, + CurrentWebView()->FindString(m_findTextControl->Text(), false, m_findCaseSensitiveCheckBox->Value()); break; case TEXT_SHOW_FIND_GROUP: @@ -344,17 +344,17 @@ void LauncherWindow::MessageReceived(BMessage* message) case TAB_CHANGED: { int32 index = message->FindInt32("index"); - setCurrentWebView(dynamic_cast(m_tabView->ViewForTab(index))); + SetCurrentWebView(dynamic_cast(m_tabView->ViewForTab(index))); updateTitle(m_tabView->TabAt(index)->Label()); - m_url->SetText(currentWebView()->MainFrameURL()); + m_url->SetText(CurrentWebView()->MainFrameURL()); // Trigger update of the interface to the new page, by requesting // to resend all notifications. - currentWebView()->WebPage()->ResendNotifications(); + CurrentWebView()->WebPage()->ResendNotifications(); break; } default: - WebViewWindow::MessageReceived(message); + BWebWindow::MessageReceived(message); break; } } @@ -367,7 +367,7 @@ bool LauncherWindow::QuitRequested() // TODO: Iterator over all WebViews, if there are more then one... while (m_tabView->CountTabs() > 0) delete m_tabView->RemoveTab(0L); - setCurrentWebView(0); + SetCurrentWebView(0); BMessage message(WINDOW_CLOSED); message.AddRect("window frame", Frame()); @@ -422,8 +422,8 @@ void LauncherWindow::newTab(const BString& url, bool select) if (select) { m_tabView->Select(m_tabView->CountTabs() - 1); - setCurrentWebView(webView); - navigationCapabilitiesChanged(false, false, false, webView); + SetCurrentWebView(webView); + NavigationCapabilitiesChanged(false, false, false, webView); if (m_url) m_url->MakeFocus(true); } @@ -431,11 +431,11 @@ void LauncherWindow::newTab(const BString& url, bool select) // #pragma mark - Notification API -void LauncherWindow::navigationRequested(const BString& url, BWebView* view) +void LauncherWindow::NavigationRequested(const BString& url, BWebView* view) { } -void LauncherWindow::newWindowRequested(const BString& url) +void LauncherWindow::NewWindowRequested(const BString& url) { // Always open new windows in the application thread, since // creating a BWebView will try to grab the application lock. @@ -449,16 +449,16 @@ void LauncherWindow::newWindowRequested(const BString& url) be_app->PostMessage(&message); } -void LauncherWindow::loadNegotiating(const BString& url, BWebView* view) +void LauncherWindow::LoadNegotiating(const BString& url, BWebView* view) { BString status("Requesting: "); status << url; - statusChanged(status, view); + StatusChanged(status, view); } -void LauncherWindow::loadCommited(const BString& url, BWebView* view) +void LauncherWindow::LoadCommited(const BString& url, BWebView* view) { - if (view != currentWebView()) + if (view != CurrentWebView()) return; m_loadedURL = url; @@ -469,12 +469,12 @@ void LauncherWindow::loadCommited(const BString& url, BWebView* view) BString status("Loading: "); status << url; - statusChanged(status, view); + StatusChanged(status, view); } -void LauncherWindow::loadProgress(float progress, BWebView* view) +void LauncherWindow::LoadProgress(float progress, BWebView* view) { - if (view != currentWebView()) + if (view != CurrentWebView()) return; if (m_loadingProgressBar) { @@ -484,34 +484,34 @@ void LauncherWindow::loadProgress(float progress, BWebView* view) } } -void LauncherWindow::loadFailed(const BString& url, BWebView* view) +void LauncherWindow::LoadFailed(const BString& url, BWebView* view) { - if (view != currentWebView()) + if (view != CurrentWebView()) return; BString status(url); status << " failed."; - statusChanged(status, view); + StatusChanged(status, view); if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) m_loadingProgressBar->Hide(); } -void LauncherWindow::loadFinished(const BString& url, BWebView* view) +void LauncherWindow::LoadFinished(const BString& url, BWebView* view) { - if (view != currentWebView()) + if (view != CurrentWebView()) return; m_loadedURL = url; BString status(url); status << " finished."; - statusChanged(status, view); + StatusChanged(status, view); if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) m_loadingProgressBar->Hide(); } -void LauncherWindow::resizeRequested(float width, float height, BWebView* view) +void LauncherWindow::ResizeRequested(float width, float height, BWebView* view) { - if (view != currentWebView()) + if (view != CurrentWebView()) return; // TODO: Ignore request when there is more than one BWebView embedded! @@ -519,25 +519,25 @@ void LauncherWindow::resizeRequested(float width, float height, BWebView* view) ResizeTo(width, height); } -void LauncherWindow::setToolBarsVisible(bool flag, BWebView* view) +void LauncherWindow::SetToolBarsVisible(bool flag, BWebView* view) { // TODO // TODO: Ignore request when there is more than one BWebView embedded! } -void LauncherWindow::setStatusBarVisible(bool flag, BWebView* view) +void LauncherWindow::SetStatusBarVisible(bool flag, BWebView* view) { // TODO // TODO: Ignore request when there is more than one BWebView embedded! } -void LauncherWindow::setMenuBarVisible(bool flag, BWebView* view) +void LauncherWindow::SetMenuBarVisible(bool flag, BWebView* view) { // TODO // TODO: Ignore request when there is more than one BWebView embedded! } -void LauncherWindow::setResizable(bool flag, BWebView* view) +void LauncherWindow::SetResizable(bool flag, BWebView* view) { // TODO: Ignore request when there is more than one BWebView embedded! @@ -547,7 +547,7 @@ void LauncherWindow::setResizable(bool flag, BWebView* view) SetFlags(Flags() | B_NOT_RESIZABLE); } -void LauncherWindow::titleChanged(const BString& title, BWebView* view) +void LauncherWindow::TitleChanged(const BString& title, BWebView* view) { for (int32 i = 0; i < m_tabView->CountTabs(); i++) { if (m_tabView->ViewForTab(i) == view) { @@ -556,25 +556,25 @@ void LauncherWindow::titleChanged(const BString& title, BWebView* view) break; } } - if (view != currentWebView()) + if (view != CurrentWebView()) return; updateTitle(title); } -void LauncherWindow::statusChanged(const BString& statusText, BWebView* view) +void LauncherWindow::StatusChanged(const BString& statusText, BWebView* view) { - if (view != currentWebView()) + if (view != CurrentWebView()) return; if (m_statusText) m_statusText->SetText(statusText.String()); } -void LauncherWindow::navigationCapabilitiesChanged(bool canGoBackward, +void LauncherWindow::NavigationCapabilitiesChanged(bool canGoBackward, bool canGoForward, bool canStop, BWebView* view) { - if (view != currentWebView()) + if (view != CurrentWebView()) return; if (m_BackButton) @@ -583,12 +583,12 @@ void LauncherWindow::navigationCapabilitiesChanged(bool canGoBackward, m_ForwardButton->SetEnabled(canGoForward); } -void LauncherWindow::updateGlobalHistory(const BString& url) +void LauncherWindow::UpdateGlobalHistory(const BString& url) { BrowsingHistory::defaultInstance()->addItem(BrowsingHistoryItem(url)); } -void LauncherWindow::authenticationChallenge(BMessage* message) +void LauncherWindow::AuthenticationChallenge(BMessage* message) { BString text; bool rememberCredentials = false; diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index d0f8fe0a2c..c85530ec49 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -30,7 +30,7 @@ #ifndef LauncherWindow_h #define LauncherWindow_h -#include "WebViewWindow.h" +#include "WebWindow.h" #include #include @@ -58,7 +58,7 @@ enum { SHOW_DOWNLOAD_WINDOW = 'sdwd' }; -class LauncherWindow : public WebViewWindow { +class LauncherWindow : public BWebWindow { public: LauncherWindow(BRect frame, const BMessenger& downloadListener, ToolbarPolicy = HaveToolbar); @@ -72,24 +72,25 @@ public: private: // WebPage notification API implementations - virtual void navigationRequested(const BString& url, BWebView* view); - virtual void newWindowRequested(const BString& url); - virtual void loadNegotiating(const BString& url, BWebView* view); - virtual void loadCommited(const BString& url, BWebView* view); - virtual void loadProgress(float progress, BWebView* view); - virtual void loadFailed(const BString& url, BWebView* view); - virtual void loadFinished(const BString& url, BWebView* view); - virtual void titleChanged(const BString& title, BWebView* view); - virtual void resizeRequested(float width, float height, BWebView* view); - virtual void setToolBarsVisible(bool flag, BWebView* view); - virtual void setStatusBarVisible(bool flag, BWebView* view); - virtual void setMenuBarVisible(bool flag, BWebView* view); - virtual void setResizable(bool flag, BWebView* view); - virtual void statusChanged(const BString& status, BWebView* view); - virtual void navigationCapabilitiesChanged(bool canGoBackward, + virtual void NavigationRequested(const BString& url, BWebView* view); + virtual void NewWindowRequested(const BString& url); + virtual void LoadNegotiating(const BString& url, BWebView* view); + virtual void LoadCommited(const BString& url, BWebView* view); + virtual void LoadProgress(float progress, BWebView* view); + virtual void LoadFailed(const BString& url, BWebView* view); + virtual void LoadFinished(const BString& url, BWebView* view); + virtual void TitleChanged(const BString& title, BWebView* view); + virtual void ResizeRequested(float width, float height, BWebView* view); + virtual void SetToolBarsVisible(bool flag, BWebView* view); + virtual void SetStatusBarVisible(bool flag, BWebView* view); + virtual void SetMenuBarVisible(bool flag, BWebView* view); + virtual void SetResizable(bool flag, BWebView* view); + virtual void StatusChanged(const BString& status, BWebView* view); + virtual void NavigationCapabilitiesChanged(bool canGoBackward, bool canGoForward, bool canStop, BWebView* view); - virtual void updateGlobalHistory(const BString& url); - virtual void authenticationChallenge(BMessage* challenge); + virtual void UpdateGlobalHistory(const BString& url); + virtual void AuthenticationChallenge(BMessage* challenge); + void updateTitle(const BString &title); private: From c516096e8eb664f0b44242354cc2f8ae179745a9 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Feb 2010 19:48:35 +0000 Subject: [PATCH 052/349] * Refactored WebDownload into BWebDownload and BPrivate::WebDownloadPrivate. * Fixed a bug where the "Remove Finished" button in the downloads window would be wrongly disabled whenever a new download started. * Implemented cancelling downloads. * Prepared restarting downloads as far as the GUI goes. Need to research this first how a download can be triggered independently from anything else in WebCore... git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@196 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 70 ++++++++++++++++++------- src/apps/webpositive/DownloadWindow.h | 6 +-- 2 files changed, 55 insertions(+), 21 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 335b526a20..248e3bde44 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +52,8 @@ enum { REMOVE_FINISHED_DOWNLOADS = 'rmfd', OPEN_DOWNLOAD = 'opdn', + RESTART_DOWNLOAD = 'rsdn', + CANCEL_DOWNLOAD = 'cndn', REMOVE_DOWNLOAD = 'rmdn', SAVE_SETTINGS = 'svst' }; @@ -123,12 +126,12 @@ public: class DownloadProgressView : public BGridView { public: - DownloadProgressView(WebDownload* download) + DownloadProgressView(BWebDownload* download) : BGridView(8, 3) , m_download(download) - , m_url(download->url()) - , m_path(download->path()) - , m_expectedSize(download->expectedSize()) + , m_url(download->URL()) + , m_path(download->Path()) + , m_expectedSize(download->ExpectedSize()) { } @@ -170,10 +173,18 @@ public: else m_iconView = new IconView(archive); - m_button1 = new SmallButton("Open", new BMessage(OPEN_DOWNLOAD)); - m_button2 = new SmallButton("Remove", new BMessage(REMOVE_DOWNLOAD)); - m_button1->SetEnabled(m_download == NULL); - m_button2->SetEnabled(m_download == NULL); + if (!m_download && m_statusBar->CurrentValue() < 100) + m_button1 = new SmallButton("Restart", new BMessage(RESTART_DOWNLOAD)); + else { + m_button1 = new SmallButton("Open", new BMessage(OPEN_DOWNLOAD)); + m_button1->SetEnabled(m_download == NULL); + } + if (m_download) + m_button2 = new SmallButton("Cancel", new BMessage(CANCEL_DOWNLOAD)); + else { + m_button2 = new SmallButton("Remove", new BMessage(REMOVE_DOWNLOAD)); + m_button2->SetEnabled(m_download == NULL); + } layout->SetInsets(8, 5, 5, 6); layout->AddView(m_iconView, 0, 0, 1, 2); @@ -201,7 +212,7 @@ public: virtual void AttachedToWindow() { if (m_download) - m_download->setProgressListener(BMessenger(this)); + m_download->SetProgressListener(BMessenger(this)); m_button1->SetTarget(this); m_button2->SetTarget(this); } @@ -225,7 +236,7 @@ public: virtual void MessageReceived(BMessage* message) { switch (message->what) { - case WebDownload::DOWNLOAD_PROGRESS: { + case B_DOWNLOAD_PROGRESS: { float progress; if (message->FindFloat("progress", &progress) == B_OK) m_statusBar->SetTo(progress); @@ -244,6 +255,15 @@ public: } break; } + case RESTART_DOWNLOAD: + // TODO: + break; + + case CANCEL_DOWNLOAD: + m_download->Cancel(); + downloadCanceled(); + break; + case REMOVE_DOWNLOAD: { Window()->PostMessage(SAVE_SETTINGS); RemoveSelf(); @@ -256,7 +276,7 @@ public: } } - WebDownload* download() const + BWebDownload* download() const { return m_download; } @@ -270,6 +290,19 @@ public: { m_download = NULL; m_button1->SetEnabled(true); + m_button2->SetLabel("Remove"); + m_button2->SetMessage(new BMessage(REMOVE_DOWNLOAD)); + m_button2->SetEnabled(true); + } + + void downloadCanceled() + { + m_download = NULL; + m_button1->SetLabel("Restart"); + m_button1->SetMessage(new BMessage(RESTART_DOWNLOAD)); + m_button1->SetEnabled(true); + m_button2->SetLabel("Remove"); + m_button2->SetMessage(new BMessage(REMOVE_DOWNLOAD)); m_button2->SetEnabled(true); } @@ -278,7 +311,7 @@ private: BStatusBar* m_statusBar; SmallButton* m_button1; SmallButton* m_button2; - WebDownload* m_download; + BWebDownload* m_download; BString m_url; BPath m_path; off_t m_expectedSize; @@ -386,13 +419,13 @@ void DownloadWindow::MessageReceived(BMessage* message) { switch (message->what) { case B_DOWNLOAD_ADDED: { - WebDownload* download; + BWebDownload* download; if (message->FindPointer("download", reinterpret_cast(&download)) == B_OK) downloadStarted(download); break; } case B_DOWNLOAD_REMOVED: { - WebDownload* download; + BWebDownload* download; if (message->FindPointer("download", reinterpret_cast(&download)) == B_OK) downloadFinished(download); break; @@ -416,7 +449,7 @@ bool DownloadWindow::QuitRequested() return false; } -void DownloadWindow::downloadStarted(WebDownload* download) +void DownloadWindow::downloadStarted(BWebDownload* download) { int32 finishedCount = 0; int32 index = 0; @@ -425,11 +458,12 @@ void DownloadWindow::downloadStarted(WebDownload* download) DownloadProgressView* view = dynamic_cast(item->View()); if (!view) continue; - if (view->url() == download->url()) { + if (view->url() == download->URL()) { index = i; view->RemoveSelf(); delete view; - } + } else if (!view->download()) + finishedCount++; } m_removeFinishedButton->SetEnabled(finishedCount > 0); DownloadProgressView* view = new DownloadProgressView(download); @@ -443,7 +477,7 @@ void DownloadWindow::downloadStarted(WebDownload* download) Show(); } -void DownloadWindow::downloadFinished(WebDownload* download) +void DownloadWindow::downloadFinished(BWebDownload* download) { int32 finishedCount = 0; for (int32 i = 0; BLayoutItem* item = m_downloadViewsLayout->ItemAt(i); i++) { diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index e03fce4a3e..c7819ffdec 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -33,7 +33,7 @@ class BButton; class BFile; class BGroupLayout; -class WebDownload; +class BWebDownload; class DownloadWindow : public BWindow { public: @@ -44,8 +44,8 @@ public: virtual bool QuitRequested(); private: - void downloadStarted(WebDownload* download); - void downloadFinished(WebDownload* download); + void downloadStarted(BWebDownload* download); + void downloadFinished(BWebDownload* download); void removeFinishedDownloads(); void saveSettings(); void loadSettings(); From ce869c629ba44e90bfe808d136625c32226ba91f Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Feb 2010 21:00:55 +0000 Subject: [PATCH 053/349] Selecting or not selecting the newly opened tab never worked, since the "select" field was added to the NEW_WINDOW_REQUESTED message, and not passed on to the internal NEW_TAB message. Fixed this, and also added a check for the tertiary mouse button for regular navigation actions. This means clicking links with the middle mouse button opens in a background tab regard less if it would have opened a new page when clicked with the primary button. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@199 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 5 +++-- src/apps/webpositive/LauncherWindow.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index f89037dc13..61522109f1 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -408,6 +408,7 @@ void LauncherWindow::MenusBeginning() void LauncherWindow::newTab(const BString& url, bool select) { +printf("newTab(%s, %d)\n", url.String(), select); // Executed in app thread (new BWebPage needs to be created in app thread). BWebView* webView = new BWebView("web_view"); webView->WebPage()->SetDownloadListener(m_downloadListener); @@ -435,7 +436,7 @@ void LauncherWindow::NavigationRequested(const BString& url, BWebView* view) { } -void LauncherWindow::NewWindowRequested(const BString& url) +void LauncherWindow::NewWindowRequested(const BString& url, bool primaryAction) { // Always open new windows in the application thread, since // creating a BWebView will try to grab the application lock. @@ -445,7 +446,7 @@ void LauncherWindow::NewWindowRequested(const BString& url) BMessage message(NEW_TAB); message.AddPointer("window", this); message.AddString("url", url); - message.AddBool("select", false); + message.AddBool("select", primaryAction); be_app->PostMessage(&message); } diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index c85530ec49..d2ad03c5cd 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -73,7 +73,7 @@ public: private: // WebPage notification API implementations virtual void NavigationRequested(const BString& url, BWebView* view); - virtual void NewWindowRequested(const BString& url); + virtual void NewWindowRequested(const BString& url, bool primaryAction); virtual void LoadNegotiating(const BString& url, BWebView* view); virtual void LoadCommited(const BString& url, BWebView* view); virtual void LoadProgress(float progress, BWebView* view); From 16ccf622ab727d14fd5b98e774977a9f1393a6c9 Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 25 Feb 2010 09:20:53 +0000 Subject: [PATCH 054/349] Removed forgotten debug output. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@207 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 61522109f1..3452583c51 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -408,7 +408,6 @@ void LauncherWindow::MenusBeginning() void LauncherWindow::newTab(const BString& url, bool select) { -printf("newTab(%s, %d)\n", url.String(), select); // Executed in app thread (new BWebPage needs to be created in app thread). BWebView* webView = new BWebView("web_view"); webView->WebPage()->SetDownloadListener(m_downloadListener); From 1da75c0bed505b0000a8fccc3d9a7beab60363db Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 25 Feb 2010 12:30:39 +0000 Subject: [PATCH 055/349] Implemented "Stop Loading" feature, designed icon, added button and necessary wiring to arrive at BWebFrame::StopLoading(). git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@211 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/Launcher.rdef | 13 +++++++++++++ src/apps/webpositive/LauncherWindow.cpp | 20 +++++++++++++++++--- src/apps/webpositive/LauncherWindow.h | 1 + 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/Launcher.rdef b/src/apps/webpositive/Launcher.rdef index fd1410f0e3..fee9516509 100644 --- a/src/apps/webpositive/Launcher.rdef +++ b/src/apps/webpositive/Launcher.rdef @@ -288,3 +288,16 @@ resource(203) #'VICN' array { $"000A06020607100117812004" }; +resource(204) #'VICN' array { + $"6E63696606050102000602393D323BB602BEA28F3C4CC64B601449439F00FF3E" + $"3EFFF70606020006033B27153C10C7BDF9893D088A4B2F634882C500C805057D" + $"9D0404FFB4040403750303020006023B06EB3B5469BC08EB3BB31F4AB15D4478" + $"7700FF9090FFFF757504FF440A0A0C2E4C364E3C4742524A5440434A3842353C" + $"BE1B36312E2E38400A0636313C3C40434A54504E402E0A03364E3E483C470A04" + $"483FC712BADE4A3840430A042E2E3631402E382C0A0442354A38C712BADE4AB9" + $"EC0A0E2E4C364EBEB6C37042524A54504E483FC712BADE4AB9EC4335402E382C" + $"2E2E384008022FB8A0BCC3B80708033C3C42364ABA120802BCA9BFF3B8D3C47B" + $"060A0001061001178400040A020101000A03020302000A010100000A04020504" + $"000A0503070809100117810004" +}; + diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 3452583c51..f3cfbbfc6c 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -64,6 +64,7 @@ enum { GO_BACK = 'goba', GO_FORWARD = 'gofo', + STOP = 'stop', GOTO_URL = 'goul', RELOAD = 'reld', CLEAR_HISTORY = 'clhs', @@ -137,7 +138,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_goMenu = new BMenu("Go"); m_menuBar->AddItem(m_goMenu); - // Back & Forward + // Back, Forward & Stop m_BackButton = new IconButton("Back", 0, NULL, new BMessage(GO_BACK)); m_BackButton->SetIcon(201); m_BackButton->TrimIcon(); @@ -146,6 +147,10 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_ForwardButton->SetIcon(202); m_ForwardButton->TrimIcon(); + m_StopButton = new IconButton("Stop", 0, NULL, new BMessage(STOP)); + m_StopButton->SetIcon(204); + m_StopButton->TrimIcon(); + // URL m_url = new BTextControl("url", "", "", new BMessage(GOTO_URL)); m_url->SetDivider(50.0); @@ -194,8 +199,9 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, .Add(BGridLayoutBuilder(kElementSpacing, kElementSpacing) .Add(m_BackButton, 0, 0) .Add(m_ForwardButton, 1, 0) - .Add(m_url, 2, 0) - .Add(button, 3, 0) + .Add(m_StopButton, 2, 0) + .Add(m_url, 3, 0) + .Add(button, 4, 0) .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) ) // .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) @@ -263,6 +269,9 @@ void LauncherWindow::MessageReceived(BMessage* message) case GO_FORWARD: CurrentWebView()->GoForward(); break; + case STOP: + CurrentWebView()->StopLoading(); + break; case CLEAR_HISTORY: { BrowsingHistory* history = BrowsingHistory::defaultInstance(); @@ -507,6 +516,9 @@ void LauncherWindow::LoadFinished(const BString& url, BWebView* view) StatusChanged(status, view); if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) m_loadingProgressBar->Hide(); + + NavigationCapabilitiesChanged(m_BackButton->IsEnabled(), + m_ForwardButton->IsEnabled(), false, view); } void LauncherWindow::ResizeRequested(float width, float height, BWebView* view) @@ -581,6 +593,8 @@ void LauncherWindow::NavigationCapabilitiesChanged(bool canGoBackward, m_BackButton->SetEnabled(canGoBackward); if (m_ForwardButton) m_ForwardButton->SetEnabled(canGoForward); + if (m_StopButton) + m_StopButton->SetEnabled(canStop); } void LauncherWindow::UpdateGlobalHistory(const BString& url) diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index d2ad03c5cd..b9ff488050 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -99,6 +99,7 @@ private: BMenu* m_goMenu; IconButton* m_BackButton; IconButton* m_ForwardButton; + IconButton* m_StopButton; BTextControl* m_url; BString m_loadedURL; BStringView* m_statusText; From 9db22c336b87369f3ec99eab664e5a134e17d807 Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 25 Feb 2010 12:46:28 +0000 Subject: [PATCH 056/349] Make it much more obvious when icon buttons are disabled. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@212 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/IconButton.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/apps/webpositive/IconButton.cpp b/src/apps/webpositive/IconButton.cpp index 36cc142bac..3ccf1c13b3 100644 --- a/src/apps/webpositive/IconButton.cpp +++ b/src/apps/webpositive/IconButton.cpp @@ -820,15 +820,21 @@ IconButton::_MakeBitmaps(const BBitmap* bitmap) cBits[nOffset + 2] = (uint8)(nBits[nOffset + 2] * 0.8); cBits[nOffset + 3] = fBits[fOffset + 3]; // disabled bits have less opacity - dBits[nOffset + 0] = fBits[fOffset + 0]; - dBits[nOffset + 1] = fBits[fOffset + 1]; - dBits[nOffset + 2] = fBits[fOffset + 2]; - dBits[nOffset + 3] = (uint8)(fBits[fOffset + 3] * 0.5); + + uint8 grey = ((uint16)nBits[nOffset + 0] + nBits[nOffset + 1] + + nBits[nOffset + 2]) / 3; + float dist = (nBits[nOffset + 0] - grey) * 0.3; + dBits[nOffset + 0] = (uint8)(grey + dist); + dist = (nBits[nOffset + 1] - grey) * 0.3; + dBits[nOffset + 1] = (uint8)(grey + dist); + dist = (nBits[nOffset + 2] - grey) * 0.3; + dBits[nOffset + 2] = (uint8)(grey + dist); + dBits[nOffset + 3] = (uint8)(fBits[fOffset + 3] * 0.3); // disabled bits have less contrast (lame method...) - dcBits[nOffset + 0] = (uint8)(nBits[nOffset + 0] * 0.8); - dcBits[nOffset + 1] = (uint8)(nBits[nOffset + 1] * 0.8); - dcBits[nOffset + 2] = (uint8)(nBits[nOffset + 2] * 0.8); - dcBits[nOffset + 3] = (uint8)(fBits[fOffset + 3] * 0.5); + dcBits[nOffset + 0] = (uint8)(dBits[nOffset + 0] * 0.8); + dcBits[nOffset + 1] = (uint8)(dBits[nOffset + 1] * 0.8); + dcBits[nOffset + 2] = (uint8)(dBits[nOffset + 2] * 0.8); + dcBits[nOffset + 3] = (uint8)(fBits[fOffset + 3] * 0.3); } nBits += nbpr; dBits += nbpr; From f16ed908beb203e13d7a9ac785c03e698f755ad4 Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 25 Feb 2010 12:49:38 +0000 Subject: [PATCH 057/349] What the heck... use the correct weighting for calculating the average grey. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@213 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/IconButton.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/IconButton.cpp b/src/apps/webpositive/IconButton.cpp index 3ccf1c13b3..5cd2ede604 100644 --- a/src/apps/webpositive/IconButton.cpp +++ b/src/apps/webpositive/IconButton.cpp @@ -821,8 +821,9 @@ IconButton::_MakeBitmaps(const BBitmap* bitmap) cBits[nOffset + 3] = fBits[fOffset + 3]; // disabled bits have less opacity - uint8 grey = ((uint16)nBits[nOffset + 0] + nBits[nOffset + 1] - + nBits[nOffset + 2]) / 3; + uint8 grey = ((uint16)nBits[nOffset + 0] * 10 + + nBits[nOffset + 1] * 60 + + nBits[nOffset + 2] * 30) / 100; float dist = (nBits[nOffset + 0] - grey) * 0.3; dBits[nOffset + 0] = (uint8)(grey + dist); dist = (nBits[nOffset + 1] - grey) * 0.3; From 9397a29aafc3929d472484e7a782657e7154b3e2 Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 25 Feb 2010 14:16:06 +0000 Subject: [PATCH 058/349] Use the document look for the LauncherWindow and adjust the layout accordinly. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@214 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index f3cfbbfc6c..5ab6a965fc 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -93,7 +93,7 @@ static BLayoutItem* layoutItemFor(BView* view) LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, ToolbarPolicy toolbarPolicy) : BWebWindow(frame, "HaikuLauncher", - B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, + B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) , m_downloadListener(downloadListener) { @@ -162,7 +162,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_statusText = new BStringView("status", ""); m_statusText->SetAlignment(B_ALIGN_LEFT); m_statusText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); - m_statusText->SetExplicitMinSize(BSize(150, 16)); + m_statusText->SetExplicitMinSize(BSize(150, 12)); // Prevent the window from growing to fit a long status message... BFont font(be_plain_font); font.SetSize(ceilf(font.Size() * 0.8)); @@ -172,7 +172,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_loadingProgressBar = new BStatusBar("progress"); m_loadingProgressBar->SetMaxValue(100); m_loadingProgressBar->Hide(); - m_loadingProgressBar->SetBarHeight(10); + m_loadingProgressBar->SetBarHeight(12); const float kInsetSpacing = 5; const float kElementSpacing = 7; @@ -211,6 +211,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) .Add(m_statusText) .Add(m_loadingProgressBar, 0.2) + .AddStrut(12 - kElementSpacing) .SetInsets(kInsetSpacing, 0, kInsetSpacing, 0) ) ); From 5afb1a0f0c1b9a8d935eb6c1de96ef12a087364d Mon Sep 17 00:00:00 2001 From: anevilyak Date: Thu, 25 Feb 2010 15:33:01 +0000 Subject: [PATCH 059/349] Spelling fix. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@216 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 2 +- src/apps/webpositive/LauncherWindow.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 5ab6a965fc..7752ac0eb3 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -466,7 +466,7 @@ void LauncherWindow::LoadNegotiating(const BString& url, BWebView* view) StatusChanged(status, view); } -void LauncherWindow::LoadCommited(const BString& url, BWebView* view) +void LauncherWindow::LoadCommitted(const BString& url, BWebView* view) { if (view != CurrentWebView()) return; diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index b9ff488050..ba7b611bc2 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -75,7 +75,7 @@ private: virtual void NavigationRequested(const BString& url, BWebView* view); virtual void NewWindowRequested(const BString& url, bool primaryAction); virtual void LoadNegotiating(const BString& url, BWebView* view); - virtual void LoadCommited(const BString& url, BWebView* view); + virtual void LoadCommitted(const BString& url, BWebView* view); virtual void LoadProgress(float progress, BWebView* view); virtual void LoadFailed(const BString& url, BWebView* view); virtual void LoadFinished(const BString& url, BWebView* view); From 4978460d4c30ef99888faa5b5ccff23aae316d4d Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 25 Feb 2010 18:50:51 +0000 Subject: [PATCH 060/349] Implement creating new pages properly. This fixes content submission on haiku-os.org and probably a few other things. Basically, we were creating the new pages ourselves in dispatchDecidePolicyForNewWindowAction(), but we were meant to implement dispatchCreatePage() instead. Now, what we do is similar for the Qt port, only better (found a bug in Arora): When the user clicked with the tertiary mouse button, we create the window ourselves, as before, and otherwise always have WebCore create the page instead. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@218 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 10 ++++++++-- src/apps/webpositive/LauncherWindow.h | 3 ++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 7752ac0eb3..4f0dcc143a 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -416,10 +416,11 @@ void LauncherWindow::MenusBeginning() history->Unlock(); } -void LauncherWindow::newTab(const BString& url, bool select) +void LauncherWindow::newTab(const BString& url, bool select, BWebView* webView) { // Executed in app thread (new BWebPage needs to be created in app thread). - BWebView* webView = new BWebView("web_view"); + if (!webView) + webView = new BWebView("web view"); webView->WebPage()->SetDownloadListener(m_downloadListener); m_tabView->AddTab(webView); @@ -459,6 +460,11 @@ void LauncherWindow::NewWindowRequested(const BString& url, bool primaryAction) be_app->PostMessage(&message); } +void LauncherWindow::NewPageCreated(BWebView* view) +{ + newTab(BString(), true, view); +} + void LauncherWindow::LoadNegotiating(const BString& url, BWebView* view) { BString status("Requesting: "); diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index ba7b611bc2..97b28f1123 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -68,12 +68,13 @@ public: virtual bool QuitRequested(); virtual void MenusBeginning(); - void newTab(const BString& url, bool select); + void newTab(const BString& url, bool select, BWebView* webView = 0); private: // WebPage notification API implementations virtual void NavigationRequested(const BString& url, BWebView* view); virtual void NewWindowRequested(const BString& url, bool primaryAction); + virtual void NewPageCreated(BWebView* view); virtual void LoadNegotiating(const BString& url, BWebView* view); virtual void LoadCommitted(const BString& url, BWebView* view); virtual void LoadProgress(float progress, BWebView* view); From 64f8c067354e3e23a3a0d4dcdc9de8345bc2fd36 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 26 Feb 2010 08:53:10 +0000 Subject: [PATCH 061/349] Fix crash on program exit. Always good to use defensive programming techniques... git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@225 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 4f0dcc143a..4a014a62ef 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -353,13 +353,22 @@ void LauncherWindow::MessageReceived(BMessage* message) } case TAB_CHANGED: { - int32 index = message->FindInt32("index"); - SetCurrentWebView(dynamic_cast(m_tabView->ViewForTab(index))); - updateTitle(m_tabView->TabAt(index)->Label()); - m_url->SetText(CurrentWebView()->MainFrameURL()); - // Trigger update of the interface to the new page, by requesting - // to resend all notifications. - CurrentWebView()->WebPage()->ResendNotifications(); + // This message may be received also when the last tab closed, i.e. with index == -1. + int32 index = -1; + message->FindInt32("index", &index); + BWebView* webView = dynamic_cast(m_tabView->ViewForTab(index)); + SetCurrentWebView(webView); + BTab* tab = m_tabView->TabAt(index); + if (tab) + updateTitle(tab->Label()); + else + updateTitle(""); + if (webView) { + m_url->SetText(webView->MainFrameURL()); + // Trigger update of the interface to the new page, by requesting + // to resend all notifications. + webView->WebPage()->ResendNotifications(); + } break; } From 1c3a676322a4891d01cc8928594a0c3a96a0d8af Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 26 Feb 2010 08:55:29 +0000 Subject: [PATCH 062/349] Fixed comment, the TODO was already resolved. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@226 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 4a014a62ef..af877d99ca 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -382,8 +382,8 @@ bool LauncherWindow::QuitRequested() { // TODO: Check for modified form data and ask user for confirmation, etc. + // Iterate over all tabs to delete all BWebViews. // Do this here, so WebKit tear down happens earlier. - // TODO: Iterator over all WebViews, if there are more then one... while (m_tabView->CountTabs() > 0) delete m_tabView->RemoveTab(0L); SetCurrentWebView(0); From 72664707fa7568f6e44b493717bef1791e3453ae Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 26 Feb 2010 19:02:24 +0000 Subject: [PATCH 063/349] Implemented a completely new tab view framework: * Tabs are only visible when there are more than one. * Tabs have close buttons. * Much more flexible, adding scrolling and left/right buttons when there are more tabs than room will be easy. Also drag&drop of tabs. I've tested this quite a bit, hopefully there are no regressions. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@228 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 70 +- src/apps/webpositive/LauncherWindow.h | 6 +- src/apps/webpositive/WebTabView.cpp | 987 +++++++++++++++++++++++- src/apps/webpositive/WebTabView.h | 52 +- 4 files changed, 1055 insertions(+), 60 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index af877d99ca..908c4a1582 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -77,8 +77,6 @@ enum { TEXT_HIDE_FIND_GROUP = 'hfnd', TEXT_FIND_NEXT = 'fndn', TEXT_FIND_PREVIOUS = 'fndp', - - CLOSE_TAB = 'ctab' }; using namespace WebCore; @@ -97,8 +95,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) , m_downloadListener(downloadListener) { - m_tabView = new WebTabView("tabview", BMessenger(this)); - m_tabView->setTarget(BMessenger(this)); + m_tabManager = new TabManager(BMessenger(this)); if (toolbarPolicy == HaveToolbar) { // Menu @@ -196,6 +193,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, // Layout AddChild(BGroupLayoutBuilder(B_VERTICAL) .Add(m_menuBar) + .Add(m_tabManager->TabGroup()) .Add(BGridLayoutBuilder(kElementSpacing, kElementSpacing) .Add(m_BackButton, 0, 0) .Add(m_ForwardButton, 1, 0) @@ -204,8 +202,8 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, .Add(button, 4, 0) .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) ) -// .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) - .Add(m_tabView) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(m_tabManager->ContainerView()) .Add(findGroup) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) @@ -219,6 +217,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_url->MakeFocus(true); m_findGroup = layoutItemFor(findGroup); + m_tabGroup = layoutItemFor(m_tabManager->TabGroup()); } else { m_BackButton = 0; m_ForwardButton = 0; @@ -344,23 +343,28 @@ void LauncherWindow::MessageReceived(BMessage* message) be_app->PostMessage(message); break; - case CLOSE_TAB: { - if (m_tabView->CountTabs() > 1) - delete m_tabView->RemoveTab(m_tabView->Selection()); - else + case CLOSE_TAB: + if (m_tabManager->CountTabs() > 1) { + int32 index; + if (message->FindInt32("tab index", &index) != B_OK) + index = m_tabManager->SelectedTabIndex(); + delete m_tabManager->RemoveTab(index); + updateTabGroupVisibility(); + } else PostMessage(B_QUIT_REQUESTED); break; - } case TAB_CHANGED: { // This message may be received also when the last tab closed, i.e. with index == -1. - int32 index = -1; - message->FindInt32("index", &index); - BWebView* webView = dynamic_cast(m_tabView->ViewForTab(index)); + int32 index; + if (message->FindInt32("tab index", &index) != B_OK) + index = -1; + BWebView* webView = dynamic_cast(m_tabManager->ViewForTab(index)); + if (webView == CurrentWebView()) + break; SetCurrentWebView(webView); - BTab* tab = m_tabView->TabAt(index); - if (tab) - updateTitle(tab->Label()); + if (webView) + updateTitle(webView->MainFrameTitle()); else updateTitle(""); if (webView) { @@ -384,8 +388,8 @@ bool LauncherWindow::QuitRequested() // Iterate over all tabs to delete all BWebViews. // Do this here, so WebKit tear down happens earlier. - while (m_tabView->CountTabs() > 0) - delete m_tabView->RemoveTab(0L); + while (m_tabManager->CountTabs() > 0) + delete m_tabManager->RemoveTab(0L); SetCurrentWebView(0); BMessage message(WINDOW_CLOSED); @@ -432,21 +436,22 @@ void LauncherWindow::newTab(const BString& url, bool select, BWebView* webView) webView = new BWebView("web view"); webView->WebPage()->SetDownloadListener(m_downloadListener); - m_tabView->AddTab(webView); - m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New tab"); - // TODO: Remove when BTabView is fixed... - m_tabView->Invalidate(); + m_tabManager->AddTab(webView, "New tab"); if (url.Length()) webView->LoadURL(url.String()); if (select) { - m_tabView->Select(m_tabView->CountTabs() - 1); + m_tabManager->SelectTab(m_tabManager->CountTabs() - 1); SetCurrentWebView(webView); NavigationCapabilitiesChanged(false, false, false, webView); - if (m_url) + if (m_url) { + m_url->SetText(url.String()); m_url->MakeFocus(true); + } } + + updateTabGroupVisibility(); } // #pragma mark - Notification API @@ -577,10 +582,9 @@ void LauncherWindow::SetResizable(bool flag, BWebView* view) void LauncherWindow::TitleChanged(const BString& title, BWebView* view) { - for (int32 i = 0; i < m_tabView->CountTabs(); i++) { - if (m_tabView->ViewForTab(i) == view) { - m_tabView->TabAt(i)->SetLabel(title); - m_tabView->DrawTabs(); + for (int32 i = 0; i < m_tabManager->CountTabs(); i++) { + if (m_tabManager->ViewForTab(i) == view) { + m_tabManager->SetTabLabel(i, title); break; } } @@ -653,3 +657,11 @@ void LauncherWindow::updateTitle(const BString& title) windowTitle << "HaikuLauncher"; SetTitle(windowTitle.String()); } + +void LauncherWindow::updateTabGroupVisibility() +{ + if (Lock()) { + m_tabGroup->SetVisible(m_tabManager->CountTabs() > 1); + Unlock(); + } +} diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index 97b28f1123..e06837b48f 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -42,7 +42,7 @@ class BStatusBar; class BStringView; class BTextControl; class IconButton; -class WebTabView; +class TabManager; class BWebView; enum ToolbarPolicy { @@ -93,6 +93,7 @@ private: virtual void AuthenticationChallenge(BMessage* challenge); void updateTitle(const BString &title); + void updateTabGroupVisibility(); private: BMessenger m_downloadListener; @@ -106,9 +107,10 @@ private: BStringView* m_statusText; BStatusBar* m_loadingProgressBar; BLayoutItem* m_findGroup; + BLayoutItem* m_tabGroup; BTextControl* m_findTextControl; BCheckBox* m_findCaseSensitiveCheckBox; - WebTabView* m_tabView; + TabManager* m_tabManager; }; #endif // LauncherWindow_h diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index b4ead81c6c..cb93ada686 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Rene Gollent + * Copyright (C) 2010 Stephan Aßmus * * All rights reserved. * @@ -27,34 +28,990 @@ #include "WebTabView.h" -#include +#include "WebView.h" +#include +#include +#include +#include +#include +#include +#include -WebTabView::WebTabView(const char *name, const BMessenger& target) - : BTabView(name) - , m_target(target) + +class TabView; +class TabContainerView; + + +class TabLayoutItem : public BAbstractLayoutItem { +public: + TabLayoutItem(TabView* parent); + + virtual bool IsVisible(); + virtual void SetVisible(bool visible); + + virtual BRect Frame(); + virtual void SetFrame(BRect frame); + + virtual BView* View(); + + virtual BSize BaseMinSize(); + virtual BSize BaseMaxSize(); + virtual BSize BasePreferredSize(); + virtual BAlignment BaseAlignment(); + + TabView* Parent() const; + +private: + TabView* fParent; + BRect fFrame; +}; + + +class TabView { +public: + TabView(); + virtual ~TabView(); + + virtual BSize MinSize(); + virtual BSize PreferredSize(); + virtual BSize MaxSize(); + + void Draw(BRect updateRect); + virtual void DrawBackground(BView* owner, BRect frame, + const BRect& updateRect, bool isFirst, bool isLast, bool isFront); + virtual void DrawContents(BView* owner, BRect frame, + const BRect& updateRect, bool isFirst, bool isLast, bool isFront); + + virtual void MouseDown(BPoint where); + virtual void MouseUp(BPoint where); + virtual void MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMessage); + + void SetIsFront(bool isFront); + bool IsFront() const; + void SetIsLast(bool isLast); + virtual void Update(bool isFirst, bool isLast, bool isFront); + + BLayoutItem* LayoutItem() const; + void SetContainerView(TabContainerView* containerView); + TabContainerView* ContainerView() const; + + void SetLabel(const char* label); + const BString& Label() const; + + BRect Frame() const; + +private: + float _LabelHeight() const; + +private: + TabContainerView* fContainerView; + TabLayoutItem* fLayoutItem; + + BString fLabel; + + bool fIsFirst; + bool fIsLast; + bool fIsFront; +}; + + +class TabContainerView : public BGroupView { +public: + class Controller { + public: + virtual void TabSelected(int32 tabIndex) = 0; + virtual bool HasFrames() = 0; + virtual TabView* CreateTabView() = 0; + }; + +public: + TabContainerView(Controller* controller); + virtual ~TabContainerView(); + + virtual BSize MinSize(); + + virtual void MessageReceived(BMessage*); + + virtual void Draw(BRect updateRect); + + virtual void MouseDown(BPoint where); + virtual void MouseUp(BPoint where); + virtual void MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMessage); + + void AddTab(const char* label, int32 index = -1); + void AddTab(TabView* tab, int32 index = -1); + TabView* RemoveTab(int32 index); + + int32 IndexOf(TabView* tab) const; + + void SelectTab(int32 tabIndex); + void SelectTab(TabView* tab); + + void SetTabLabel(int32 tabIndex, const char* label); + +private: + TabView* _TabAt(const BPoint& where) const; + +private: + TabView* fLastMouseEventTab; + bool fMouseDown; + TabView* fSelectedTab; + Controller* fController; +}; + + +// #pragma mark - TabContainerView + + +static const float kLeftTabInset = 4; + + +TabContainerView::TabContainerView(Controller* controller) + : + BGroupView(B_HORIZONTAL), + fLastMouseEventTab(NULL), + fMouseDown(false), + fSelectedTab(NULL), + fController(controller) { - SetBorder(B_NO_BORDER); - SetFlags(Flags() & ~B_FULL_UPDATE_ON_RESIZE); + SetFlags(Flags() | B_WILL_DRAW); + SetViewColor(B_TRANSPARENT_COLOR); + GroupLayout()->SetInsets(kLeftTabInset, 0, 0, 1); + GroupLayout()->AddItem(BSpaceLayoutItem::CreateGlue(), 0.0f); } -WebTabView::~WebTabView(void) + +TabContainerView::~TabContainerView() +{ + // TODO: Not so nice, that we take ownership of the controller. + delete fController; +} + + +BSize +TabContainerView::MinSize() +{ + // Eventually, we want to be scrolling if the tabs don't fit. + BSize size(BGroupView::MinSize()); + size.width = 300; + return size; +} + + +void +TabContainerView::MessageReceived(BMessage* message) +{ + switch (message->what) { + default: + BGroupView::MessageReceived(message); + } +} + + +void +TabContainerView::Draw(BRect updateRect) +{ + // Stroke separator line at bottom. + rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); + BRect frame(Bounds()); + SetHighColor(tint_color(base, B_DARKEN_2_TINT)); + StrokeLine(frame.LeftBottom(), frame.RightBottom()); + frame.bottom--; + + // Draw empty area before first tab. + uint32 borders = BControlLook::B_TOP_BORDER | BControlLook::B_BOTTOM_BORDER; + BRect leftFrame(frame.left, frame.top, kLeftTabInset, frame.bottom); + be_control_look->DrawInactiveTab(this, leftFrame, updateRect, base, 0, + borders); + + // Draw all tabs, keeping track of where they end. + BGroupLayout* layout = GroupLayout(); + int32 count = layout->CountItems() - 1; + for (int32 i = 0; i < count; i++) { + TabLayoutItem* item = dynamic_cast( + layout->ItemAt(i)); + if (!item) + continue; + item->Parent()->Draw(updateRect); + frame.left = item->Frame().right + 1; + } + + // Draw empty area after last tab. + be_control_look->DrawInactiveTab(this, frame, updateRect, base, 0, borders); +} + + +void +TabContainerView::MouseDown(BPoint where) +{ + fMouseDown = true; + SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); + if (fLastMouseEventTab) + fLastMouseEventTab->MouseDown(where); +} + + +void +TabContainerView::MouseUp(BPoint where) +{ + fMouseDown = false; + if (fLastMouseEventTab) + fLastMouseEventTab->MouseUp(where); +} + + +void +TabContainerView::MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMessage) +{ + TabView* tab = _TabAt(where); + if (fMouseDown) { + uint32 transit = tab == fLastMouseEventTab + ? B_INSIDE_VIEW : B_OUTSIDE_VIEW; + if (fLastMouseEventTab) + fLastMouseEventTab->MouseMoved(where, transit, dragMessage); + return; + } + + if (fLastMouseEventTab && fLastMouseEventTab == tab) + fLastMouseEventTab->MouseMoved(where, B_INSIDE_VIEW, dragMessage); + else { + if (fLastMouseEventTab) + fLastMouseEventTab->MouseMoved(where, B_EXITED_VIEW, dragMessage); + fLastMouseEventTab = tab; + if (fLastMouseEventTab) + fLastMouseEventTab->MouseMoved(where, B_ENTERED_VIEW, dragMessage); + } +} + + +void +TabContainerView::AddTab(const char* label, int32 index) +{ + TabView* tab; + if (fController) + tab = fController->CreateTabView(); + else + tab = new TabView(); + tab->SetLabel(label); + AddTab(tab, index); +} + + +void +TabContainerView::AddTab(TabView* tab, int32 index) +{ + tab->SetContainerView(this); + + if (index == -1) + index = GroupLayout()->CountItems() - 1; + + bool hasFrames = fController != NULL && fController->HasFrames(); + bool isFirst = index == 0 && hasFrames; + bool isLast = index == GroupLayout()->CountItems() - 1 && hasFrames; + bool isFront = fSelectedTab == NULL; + tab->Update(isFirst, isLast, isFront); + + GroupLayout()->AddItem(index, tab->LayoutItem()); + + if (isFront) + SelectTab(tab); + if (isLast) { + TabLayoutItem* item + = dynamic_cast(GroupLayout()->ItemAt(index - 1)); + if (item) + item->Parent()->SetIsLast(false); + } +} + +TabView* +TabContainerView::RemoveTab(int32 index) +{ + TabLayoutItem* item + = dynamic_cast(GroupLayout()->RemoveItem(index)); + + if (!item) + return NULL; + + BRect dirty(Bounds()); + dirty.left = item->Frame().left; + TabView* removedTab = item->Parent(); + removedTab->SetContainerView(NULL); + + if (removedTab == fLastMouseEventTab) + fLastMouseEventTab = NULL; + + // Update tabs after or before the removed tab. + bool hasFrames = fController != NULL && fController->HasFrames(); + item = dynamic_cast(GroupLayout()->ItemAt(index)); + if (item) { + // This tab is behind the removed tab. + TabView* tab = item->Parent(); + tab->Update(index == 0 && hasFrames, + index == GroupLayout()->CountItems() - 2 && hasFrames, + tab == fSelectedTab); + if (removedTab == fSelectedTab) { + fSelectedTab = NULL; + SelectTab(tab); + } else if (fController && tab == fSelectedTab) + fController->TabSelected(index); + } else { + // The removed tab was the last tab. + item = dynamic_cast(GroupLayout()->ItemAt(index - 1)); + if (item) { + TabView* tab = item->Parent(); + tab->Update(index == 0 && hasFrames, + index == GroupLayout()->CountItems() - 2 && hasFrames, + tab == fSelectedTab); + if (removedTab == fSelectedTab) { + fSelectedTab = NULL; + SelectTab(tab); + } + } + } + + Invalidate(dirty); + + return removedTab; +} + + +int32 +TabContainerView::IndexOf(TabView* tab) const +{ + return GroupLayout()->IndexOfItem(tab->LayoutItem()); +} + + +void +TabContainerView::SelectTab(int32 index) +{ + TabView* tab = NULL; + TabLayoutItem* item = dynamic_cast( + GroupLayout()->ItemAt(index)); + if (item) + tab = item->Parent(); + + SelectTab(tab); +} + + +void +TabContainerView::SelectTab(TabView* tab) +{ + if (tab == fSelectedTab) + return; + + if (fSelectedTab) + fSelectedTab->SetIsFront(false); + + fSelectedTab = tab; + + if (fSelectedTab) + fSelectedTab->SetIsFront(true); + + if (fController != NULL) { + int32 index = -1; + if (fSelectedTab != NULL) + index = GroupLayout()->IndexOfItem(tab->LayoutItem()); + + fController->TabSelected(index); + } +} + + +void +TabContainerView::SetTabLabel(int32 tabIndex, const char* label) +{ + TabLayoutItem* item = dynamic_cast( + GroupLayout()->ItemAt(tabIndex)); + if (item == NULL) + return; + + item->Parent()->SetLabel(label); +} + + +TabView* +TabContainerView::_TabAt(const BPoint& where) const +{ + BGroupLayout* layout = GroupLayout(); + int32 count = layout->CountItems() - 1; + for (int32 i = 0; i < count; i++) { + TabLayoutItem* item = dynamic_cast( + layout->ItemAt(i)); + if (item && item->Frame().Contains(where)) + return item->Parent(); + } + return NULL; +} + + +// #pragma mark - TabView + + +TabView::TabView() + : fContainerView(NULL) + , fLayoutItem(new TabLayoutItem(this)) + , fLabel() { } -void WebTabView::Select(int32 tab) +TabView::~TabView() { - BTabView::Select(tab); + // The layout item is deleted for us by the layout which contains it. + if (!fContainerView) + delete fLayoutItem; +} + +BSize TabView::MinSize() +{ + BSize size(MaxSize()); + size.width = 100.0f; + return size; +} + +BSize TabView::PreferredSize() +{ + return MaxSize(); +} + +BSize TabView::MaxSize() +{ + float extra = be_control_look->DefaultLabelSpacing(); + float labelWidth = fContainerView->StringWidth(fLabel.String()) + 2 * extra; + labelWidth = min_c(300.0f, labelWidth); + return BSize(labelWidth, _LabelHeight() + extra); +} + +void TabView::Draw(BRect updateRect) +{ + BRect frame(fLayoutItem->Frame()); + if (fIsFront) { + // Extend the front tab outward left/right in order to merge + // the frames of adjacent tabs. + if (!fIsFirst) + frame.left--; + if (!fIsLast) + frame.right++; + + frame.bottom++; + } + DrawBackground(fContainerView, frame, updateRect, fIsFirst, fIsLast, + fIsFront); + if (fIsFront) { + frame.top += 3.0f; + if (!fIsFirst) + frame.left++; + if (!fIsLast) + frame.right--; + } else + frame.top += 6.0f; + float spacing = be_control_look->DefaultLabelSpacing(); + frame.InsetBy(spacing, spacing / 2); + DrawContents(fContainerView, frame, updateRect, fIsFirst, fIsLast, + fIsFront); +} + +void TabView::DrawBackground(BView* owner, BRect frame, const BRect& updateRect, + bool isFirst, bool isLast, bool isFront) +{ + rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); + uint32 borders = BControlLook::B_TOP_BORDER + | BControlLook::B_BOTTOM_BORDER; + if (isFirst) + borders |= BControlLook::B_LEFT_BORDER; + if (isLast) + borders |= BControlLook::B_RIGHT_BORDER; + if (isFront) { + be_control_look->DrawActiveTab(owner, frame, updateRect, base, + 0, borders); + } else { + be_control_look->DrawInactiveTab(owner, frame, updateRect, base, + 0, borders); + } +} + +void TabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect, + bool isFirst, bool isLast, bool isFront) +{ + rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); + be_control_look->DrawLabel(owner, fLabel.String(), frame, updateRect, + base, 0, BAlignment(B_ALIGN_LEFT, B_ALIGN_MIDDLE)); +} + +void TabView::MouseDown(BPoint where) +{ + fContainerView->SelectTab(this); +} + +void TabView::MouseUp(BPoint where) +{ +} + +void TabView::MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMessage) +{ +} + +void TabView::SetIsFront(bool isFront) +{ + Update(fIsFirst, fIsLast, isFront); +} + +bool TabView::IsFront() const +{ + return fIsFront; +} + +void TabView::SetIsLast(bool isLast) +{ + Update(fIsFirst, isLast, fIsFront); +} + +void TabView::Update(bool isFirst, bool isLast, bool isFront) +{ + if (fIsFirst == isFirst && fIsLast == isLast && fIsFront == isFront) + return; + fIsFirst = isFirst; + fIsLast = isLast; + fIsFront = isFront; + BRect frame = fLayoutItem->Frame(); + frame.bottom++; + fContainerView->Invalidate(frame); +} + +void TabView::SetContainerView(TabContainerView* containerView) +{ + fContainerView = containerView; +} + +TabContainerView* TabView::ContainerView() const +{ + return fContainerView; +} + +BLayoutItem* TabView::LayoutItem() const +{ + return fLayoutItem; +} + +void TabView::SetLabel(const char* label) +{ + if (fLabel == label) + return; + fLabel = label; + fLayoutItem->InvalidateLayout(); +} + +const BString& TabView::Label() const +{ + return fLabel; +} + + +BRect +TabView::Frame() const +{ + return fLayoutItem->Frame(); +} + + +float TabView::_LabelHeight() const +{ + font_height fontHeight; + fContainerView->GetFontHeight(&fontHeight); + return ceilf(fontHeight.ascent) + ceilf(fontHeight.descent); +} + +// #pragma mark - TabLayoutItem + +TabLayoutItem::TabLayoutItem(TabView* parent) + : fParent(parent) +{ +} + +bool TabLayoutItem::IsVisible() +{ + return !fParent->ContainerView()->IsHidden(fParent->ContainerView()); +} + +void TabLayoutItem::SetVisible(bool visible) +{ + // not allowed +} + +BRect TabLayoutItem::Frame() +{ + return fFrame; +} + +void TabLayoutItem::SetFrame(BRect frame) +{ + BRect dirty = fFrame; + fFrame = frame; + dirty = dirty | fFrame; + // Invalidate more than necessary, to help the TabContainerView + // redraw the parts outside any tabs... + dirty.bottom++; + dirty.right++; + fParent->ContainerView()->Invalidate(dirty); +} + +BView* TabLayoutItem::View() +{ + return NULL; +} + +BSize TabLayoutItem::BaseMinSize() +{ + return fParent->MinSize(); +} + +BSize TabLayoutItem::BaseMaxSize() +{ + return fParent->MaxSize(); +} + +BSize TabLayoutItem::BasePreferredSize() +{ + return fParent->PreferredSize(); +} + +BAlignment TabLayoutItem::BaseAlignment() +{ + return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); +} + +TabView* TabLayoutItem::Parent() const +{ + return fParent; +} + + +// #pragma mark - TabManagerController + + +class TabManagerController : public TabContainerView::Controller { +public: + TabManagerController(TabManager* manager); + + virtual void TabSelected(int32 index) + { + fManager->SelectTab(index); + } + + virtual bool HasFrames() + { + return false; + } + + virtual TabView* CreateTabView(); + + void CloseTab(int32 index); + +private: + TabManager* fManager; +}; + + +// #pragma mark - WebTabView + + +class WebTabView : public TabView { +public: + WebTabView(TabManagerController* controller); + + virtual BSize MaxSize(); + + virtual void DrawContents(BView* owner, BRect frame, const BRect& updateRect, + bool isFirst, bool isLast, bool isFront); + + virtual void MouseDown(BPoint where); + virtual void MouseUp(BPoint where); + virtual void MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMessage); + +private: + BRect _CloseRectFrame(BRect frame) const; + +private: + TabManagerController* fController; + bool fOverCloseRect; + bool fClicked; +}; + + +WebTabView::WebTabView(TabManagerController* controller) + : + TabView(), + fController(controller), + fOverCloseRect(false), + fClicked(false) +{ +} + + +BSize +WebTabView::MaxSize() +{ + // Account for close button. + BSize size(TabView::MaxSize()); + size.width += size.height; + return size; +} + + +void +WebTabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect, + bool isFirst, bool isLast, bool isFront) +{ + BRect closeRect = _CloseRectFrame(frame); + frame.right = closeRect.left - be_control_look->DefaultLabelSpacing(); + + closeRect.left = (closeRect.left + closeRect.right) / 2 - 3; + closeRect.right = closeRect.left + 6; + closeRect.top = (closeRect.top + closeRect.bottom) / 2 - 3; + closeRect.bottom = closeRect.top + 6; + + rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); + float tint = B_DARKEN_1_TINT; + if (!IsFront()) + tint *= 1.02; + + base = tint_color(base, tint); + + if (fOverCloseRect) + tint *= 1.2; + + if (fClicked && fOverCloseRect) { + BRect buttonRect(closeRect.InsetByCopy(-4, -4)); + be_control_look->DrawButtonFrame(owner, buttonRect, updateRect, + base, base, + BControlLook::B_ACTIVATED | BControlLook::B_BLEND_FRAME); + be_control_look->DrawButtonBackground(owner, buttonRect, updateRect, + base, BControlLook::B_ACTIVATED); + tint *= 1.2; + closeRect.OffsetBy(1, 1); + } + + base = tint_color(base, tint); + owner->SetHighColor(base); + owner->SetPenSize(2); + owner->StrokeLine(closeRect.LeftTop(), closeRect.RightBottom()); + owner->StrokeLine(closeRect.LeftBottom(), closeRect.RightTop()); + owner->SetPenSize(1); + + TabView::DrawContents(owner, frame, updateRect, isFirst, isLast, isFront); +} + + +void +WebTabView::MouseDown(BPoint where) +{ + BRect closeRect = _CloseRectFrame(Frame()); + if (!closeRect.Contains(where)) { + TabView::MouseDown(where); + return; + } + + fClicked = true; + ContainerView()->Invalidate(closeRect); +} + + +void +WebTabView::MouseUp(BPoint where) +{ + if (!fClicked) { + TabView::MouseUp(where); + return; + } + + fClicked = false; + + if (_CloseRectFrame(Frame()).Contains(where)) + fController->CloseTab(ContainerView()->IndexOf(this)); +} + + +void +WebTabView::MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMessage) +{ + BRect closeRect = _CloseRectFrame(Frame()); + bool overCloseRect = closeRect.Contains(where); + if (overCloseRect != fOverCloseRect) { + fOverCloseRect = overCloseRect; + ContainerView()->Invalidate(closeRect); + } + + TabView::MouseMoved(where, transit, dragMessage); +} + + +BRect +WebTabView::_CloseRectFrame(BRect frame) const +{ + frame.left = frame.right - frame.Height(); + return frame; +} + + +// #pragma mark - TabManagerController + + +TabManagerController::TabManagerController(TabManager* manager) + : + fManager(manager) +{ +} + + +TabView* +TabManagerController::CreateTabView() +{ + return new WebTabView(this); +} + + +void +TabManagerController::CloseTab(int32 index) +{ + fManager->CloseTab(index); +} + + +// #pragma mark - TabManager + + + +TabManager::TabManager(const BMessenger& target) + : + fTarget(target) +{ + fContainerView = new BView("web view container", 0); + fCardLayout = new BCardLayout(); + fContainerView->SetLayout(fCardLayout); + + fTabContainerView = new TabContainerView(new TabManagerController(this)); + fTabContainerGroup = new BGroupView(B_HORIZONTAL); + fTabContainerGroup->GroupLayout()->SetInsets(0, 5, 0, 0); + fTabContainerGroup->GroupLayout()->AddView(fTabContainerView); +} + + +TabManager::~TabManager() +{ +} + + +void +TabManager::SetTarget(const BMessenger& target) +{ + fTarget = target; +} + + +const BMessenger& +TabManager::Target() const +{ + return fTarget; +} + + +BView* +TabManager::TabGroup() const +{ + return fTabContainerGroup; +} + + +BView* +TabManager::ContainerView() const +{ + return fContainerView; +} + + +BView* +TabManager::ViewForTab(int32 tabIndex) const +{ + BLayoutItem* item = fCardLayout->ItemAt(tabIndex); + if (item != NULL) + return item->View(); + return NULL; +} + + +void +TabManager::SelectTab(int32 tabIndex) +{ + fCardLayout->SetVisibleItem(tabIndex); + fTabContainerView->SelectTab(tabIndex); + BMessage message(TAB_CHANGED); - message.AddInt32("index", tab); - m_target.SendMessage(&message); + message.AddInt32("tab index", tabIndex); + fTarget.SendMessage(&message); } -const BMessenger& WebTabView::target() const + +int32 +TabManager::SelectedTabIndex() const { - return m_target; + return fCardLayout->VisibleIndex(); } -void WebTabView::setTarget(const BMessenger& target) + +void +TabManager::CloseTab(int32 tabIndex) { - m_target = target; + BMessage message(CLOSE_TAB); + message.AddInt32("tab index", tabIndex); + fTarget.SendMessage(&message); } + + +void +TabManager::AddTab(BView* view, const char* label, int32 index) +{ + fTabContainerView->AddTab(label, index); + fCardLayout->AddView(index, view); +} + + +BView* +TabManager::RemoveTab(int32 index) +{ + // It's important to remove the view first, since + // removing the tab will preliminary mess with the selected tab + // and then item count of card layout and tab container will not + // match yet. + BLayoutItem* item = fCardLayout->RemoveItem(index); + if (item == NULL) + return NULL; + + TabView* tab = fTabContainerView->RemoveTab(index); + delete tab; + + BView* view = item->View(); + delete item; + return view; +} + + +int32 +TabManager::CountTabs() const +{ + return fCardLayout->CountItems(); +} + + +void +TabManager::SetTabLabel(int32 tabIndex, const char* label) +{ + fTabContainerView->SetTabLabel(tabIndex, label); +} + diff --git a/src/apps/webpositive/WebTabView.h b/src/apps/webpositive/WebTabView.h index ac85a460c1..c97c899c7b 100644 --- a/src/apps/webpositive/WebTabView.h +++ b/src/apps/webpositive/WebTabView.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Rene Gollent + * Copyright (C) 2010 Stephan Aßmus * * All rights reserved. * @@ -25,28 +25,52 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebTabView_h -#define WebTabView_h +#ifndef TAB_MANAGER_H +#define TAB_MANAGER_H #include #include enum { - TAB_CHANGED = 'tcha' + TAB_CHANGED = 'tcha', + CLOSE_TAB = 'cltb' }; -class WebTabView : public BTabView { -public: - WebTabView(const char *name, const BMessenger& target); - virtual ~WebTabView(void); - virtual void Select(int32 tab); +class BCardLayout; +class BGroupView; +class TabContainerView; - const BMessenger& target() const; - void setTarget(const BMessenger& target); +class TabManager { +public: + TabManager(const BMessenger& target); + virtual ~TabManager(); + + void SetTarget(const BMessenger& target); + const BMessenger& Target() const; + + BView* TabGroup() const; + BView* ContainerView() const; + + BView* ViewForTab(int32 tabIndex) const; + + void SelectTab(int32 tabIndex); + int32 SelectedTabIndex() const; + void CloseTab(int32 tabIndex); + + void AddTab(BView* view, const char* label, + int32 index = -1); + BView* RemoveTab(int32 index); + int32 CountTabs() const; + + void SetTabLabel(int32 tabIndex, const char* label); private: - BMessenger m_target; + BGroupView* fTabContainerGroup; + TabContainerView* fTabContainerView; + BView* fContainerView; + BCardLayout* fCardLayout; + + BMessenger fTarget; }; -#define WebTabView_h -#endif // WebTabView_h +#endif // TAB_MANAGER_H From 84c9928e4052b1cc0ee20d1b4dde9b2252422da6 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 26 Feb 2010 23:17:51 +0000 Subject: [PATCH 064/349] * Added small symbol buttons to tab container view. Currently only "New tab" is added and works. * Added "Open location" shortcut Cmd-L as in Firefox. * Moved "Show downloads" shortcut to Cmd-J, again as in Firefox. It uses Cmd-D for "Bookmark this page". Though I have no idea why we simply shouldn't use Cmd-D for Downloads and Cmd-B for Bookmark this page. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@229 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 24 ++-- src/apps/webpositive/WebTabView.cpp | 148 +++++++++++++++++++++++- src/apps/webpositive/WebTabView.h | 3 +- 3 files changed, 166 insertions(+), 9 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 908c4a1582..4dac5a84b5 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -62,6 +62,7 @@ #include enum { + OPEN_LOCATION = 'open', GO_BACK = 'goba', GO_FORWARD = 'gofo', STOP = 'stop', @@ -95,7 +96,11 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) , m_downloadListener(downloadListener) { - m_tabManager = new TabManager(BMessenger(this)); + BMessage* newTabMessage = new BMessage(NEW_TAB); + newTabMessage->AddString("url", ""); + newTabMessage->AddPointer("window", this); + newTabMessage->AddBool("select", true); + m_tabManager = new TabManager(BMessenger(this), newTabMessage); if (toolbarPolicy == HaveToolbar) { // Menu @@ -106,18 +111,15 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, BMenuItem* newItem = new BMenuItem("New window", newWindowMessage, 'N'); menu->AddItem(newItem); newItem->SetTarget(be_app); - BMessage* newTabMessage = new BMessage(NEW_TAB); - newTabMessage->AddString("url", ""); - newTabMessage->AddPointer("window", this); - newTabMessage->AddBool("select", true); - newItem = new BMenuItem("New tab", newTabMessage, 'T'); + newItem = new BMenuItem("New tab", new BMessage(*newTabMessage), 'T'); menu->AddItem(newItem); newItem->SetTarget(be_app); + menu->AddItem(new BMenuItem("Open location", new BMessage(OPEN_LOCATION), 'L')); menu->AddSeparatorItem(); menu->AddItem(new BMenuItem("Close window", new BMessage(B_QUIT_REQUESTED), 'W', B_SHIFT_KEY)); menu->AddItem(new BMenuItem("Close tab", new BMessage(CLOSE_TAB), 'W')); menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Show downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'D')); + menu->AddItem(new BMenuItem("Show downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'J')); menu->AddSeparatorItem(); BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); menu->AddItem(quitItem); @@ -253,6 +255,14 @@ LauncherWindow::~LauncherWindow() void LauncherWindow::MessageReceived(BMessage* message) { switch (message->what) { + case OPEN_LOCATION: + if (m_url) { + if (m_url->TextView()->IsFocus()) + m_url->TextView()->SelectAll(); + else + m_url->MakeFocus(true); + } + break; case RELOAD: CurrentWebView()->LoadURL(m_url->Text()); break; diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index cb93ada686..5882c98de3 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -29,7 +29,9 @@ #include "WebTabView.h" #include "WebView.h" +#include #include +#include #include #include #include @@ -884,11 +886,149 @@ TabManagerController::CloseTab(int32 index) } +// #pragma mark - TabButton + + +class TabButton : public BButton { +public: + TabButton(BMessage* message) + : BButton("", message) + { + } + + virtual BSize MinSize() + { + return BSize(12, 12); + } + + virtual BSize MaxSize() + { + return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED); + } + + virtual BSize PreferredSize() + { + return MinSize(); + } + + virtual void Draw(BRect updateRect) + { + BRect bounds(Bounds()); + rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); + SetHighColor(tint_color(base, B_DARKEN_2_TINT)); + StrokeLine(bounds.LeftBottom(), bounds.RightBottom()); + bounds.bottom--; + uint32 flags = be_control_look->Flags(this); + uint32 borders = BControlLook::B_TOP_BORDER + | BControlLook::B_BOTTOM_BORDER; + be_control_look->DrawInactiveTab(this, bounds, updateRect, base, + flags, borders); + if (IsEnabled()) { + rgb_color button = tint_color(base, 1.07); + be_control_look->DrawButtonBackground(this, bounds, updateRect, + button, flags, 0); + } + + bounds.left = (bounds.left + bounds.right) / 2 - 6; + bounds.top = (bounds.top + bounds.bottom) / 2 - 6; + bounds.right = bounds.left + 12; + bounds.bottom = bounds.top + 12; + DrawSymbol(bounds, updateRect, base); + } + + virtual void DrawSymbol(BRect frame, const BRect& updateRect, + const rgb_color& base) + { + } +}; + + +class ScrollLeftTabButton : public TabButton { +public: + ScrollLeftTabButton(BMessage* message) + : TabButton(message) + { + } + + virtual void DrawSymbol(BRect frame, const BRect& updateRect, + const rgb_color& base) + { + be_control_look->DrawArrowShape(this, frame, updateRect, + base, BControlLook::B_LEFT_ARROW, 0, B_DARKEN_4_TINT); + } +}; + + +class ScrollRightTabButton : public TabButton { +public: + ScrollRightTabButton(BMessage* message) + : TabButton(message) + { + } + + virtual void DrawSymbol(BRect frame, const BRect& updateRect, + const rgb_color& base) + { + be_control_look->DrawArrowShape(this, frame, updateRect, + base, BControlLook::B_RIGHT_ARROW, 0, B_DARKEN_4_TINT); + } +}; + + +class NewTabButton : public TabButton { +public: + NewTabButton(BMessage* message) + : TabButton(message) + { + } + + virtual BSize MinSize() + { + return BSize(18, 12); + } + + virtual void DrawSymbol(BRect frame, const BRect& updateRect, + const rgb_color& base) + { + SetHighColor(tint_color(base, B_DARKEN_4_TINT)); + float inset = 3; + frame.InsetBy(2, 2); + frame.top++; + frame.left++; + FillRoundRect(BRect(frame.left, frame.top + inset, + frame.right, frame.bottom - inset), 1, 1); + FillRoundRect(BRect(frame.left + inset, frame.top, + frame.right - inset, frame.bottom), 1, 1); + } +}; + + +class TabMenuTabButton : public TabButton { +public: + TabMenuTabButton(BMessage* message) + : TabButton(message) + { + } + + virtual BSize MinSize() + { + return BSize(18, 12); + } + + virtual void DrawSymbol(BRect frame, const BRect& updateRect, + const rgb_color& base) + { + be_control_look->DrawArrowShape(this, frame, updateRect, + base, BControlLook::B_DOWN_ARROW, 0, B_DARKEN_4_TINT); + } +}; + + // #pragma mark - TabManager -TabManager::TabManager(const BMessenger& target) +TabManager::TabManager(const BMessenger& target, BMessage* newTabMessage) : fTarget(target) { @@ -900,6 +1040,12 @@ TabManager::TabManager(const BMessenger& target) fTabContainerGroup = new BGroupView(B_HORIZONTAL); fTabContainerGroup->GroupLayout()->SetInsets(0, 5, 0, 0); fTabContainerGroup->GroupLayout()->AddView(fTabContainerView); +// fTabContainerGroup->GroupLayout()->AddView(new ScrollLeftTabButton(NULL), 0.0f); +// fTabContainerGroup->GroupLayout()->AddView(new ScrollRightTabButton(NULL), 0.0f); + NewTabButton* newTabButton = new NewTabButton(newTabMessage); + newTabButton->SetTarget(be_app); + fTabContainerGroup->GroupLayout()->AddView(newTabButton, 0.0f); +// fTabContainerGroup->GroupLayout()->AddView(new TabMenuTabButton(NULL), 0.0f); } diff --git a/src/apps/webpositive/WebTabView.h b/src/apps/webpositive/WebTabView.h index c97c899c7b..9df5f501c4 100644 --- a/src/apps/webpositive/WebTabView.h +++ b/src/apps/webpositive/WebTabView.h @@ -42,7 +42,8 @@ class TabContainerView; class TabManager { public: - TabManager(const BMessenger& target); + TabManager(const BMessenger& target, + BMessage* newTabMessage); virtual ~TabManager(); void SetTarget(const BMessenger& target); From f44756cf46a6c87ed142cf2a1c1d59981773ce13 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 27 Feb 2010 00:05:33 +0000 Subject: [PATCH 065/349] Middle click anywhere into a tab closes that page. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@230 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/WebTabView.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index 5882c98de3..355290e6e0 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -84,7 +84,7 @@ public: virtual void DrawContents(BView* owner, BRect frame, const BRect& updateRect, bool isFirst, bool isLast, bool isFront); - virtual void MouseDown(BPoint where); + virtual void MouseDown(BPoint where, uint32 buttons); virtual void MouseUp(BPoint where); virtual void MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage); @@ -248,10 +248,13 @@ TabContainerView::Draw(BRect updateRect) void TabContainerView::MouseDown(BPoint where) { + uint32 buttons; + if (Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons) != B_OK) + buttons = B_PRIMARY_MOUSE_BUTTON; fMouseDown = true; SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); if (fLastMouseEventTab) - fLastMouseEventTab->MouseDown(where); + fLastMouseEventTab->MouseDown(where, buttons); } @@ -544,7 +547,7 @@ void TabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect, base, 0, BAlignment(B_ALIGN_LEFT, B_ALIGN_MIDDLE)); } -void TabView::MouseDown(BPoint where) +void TabView::MouseDown(BPoint where, uint32 buttons) { fContainerView->SelectTab(this); } @@ -731,7 +734,7 @@ public: virtual void DrawContents(BView* owner, BRect frame, const BRect& updateRect, bool isFirst, bool isLast, bool isFront); - virtual void MouseDown(BPoint where); + virtual void MouseDown(BPoint where, uint32 buttons); virtual void MouseUp(BPoint where); virtual void MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage); @@ -811,11 +814,16 @@ WebTabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect, void -WebTabView::MouseDown(BPoint where) +WebTabView::MouseDown(BPoint where, uint32 buttons) { + if (buttons & B_TERTIARY_MOUSE_BUTTON) { + fController->CloseTab(ContainerView()->IndexOf(this)); + return; + } + BRect closeRect = _CloseRectFrame(Frame()); if (!closeRect.Contains(where)) { - TabView::MouseDown(where); + TabView::MouseDown(where, buttons); return; } From 507875ecb1aabbbaf57bd52681637647253151f8 Mon Sep 17 00:00:00 2001 From: anevilyak Date: Sat, 27 Feb 2010 01:48:18 +0000 Subject: [PATCH 066/349] Add Cmd+R as a shortcut for reload page. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@231 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 4dac5a84b5..d3589820c3 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -244,7 +244,8 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, AddShortcut('G', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_FIND_PREVIOUS)); AddShortcut('F', B_COMMAND_KEY, new BMessage(TEXT_SHOW_FIND_GROUP)); AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_HIDE_FIND_GROUP)); - + AddShortcut('R', B_COMMAND_KEY, new BMessage(RELOAD)); + be_app->PostMessage(WINDOW_OPENED); } From 1cba0fd63a2a0442a6e41d15e2c2a24aa49c3e17 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 27 Feb 2010 11:01:36 +0000 Subject: [PATCH 067/349] * Use the proper channels for reloading. (Added BWebView/BWebPage::Reload().) * Catch B_RETURN key down messages, when the target is the URL text view. Don't let the text view send a message, but react on B_RETURN only, in the window, also letting the Go button flash for a bonus. This fixes unprovoked (re-)loading of pages when the text control went out of focus and thought the text had changed, sending GOTO_URL. This could happen when just grabbing the scrollbar so that the text control looses focus. Also makes the m_loadedURL string superfluous, which I added for the same purpose. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@232 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 42 ++++++++++++++++++------- src/apps/webpositive/LauncherWindow.h | 3 +- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index d3589820c3..d2c77647ae 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -151,11 +151,11 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, m_StopButton->TrimIcon(); // URL - m_url = new BTextControl("url", "", "", new BMessage(GOTO_URL)); + m_url = new BTextControl("url", "", "", NULL); m_url->SetDivider(50.0); // Go - BButton* button = new BButton("", "Go", new BMessage(RELOAD)); + m_goButton = new BButton("", "Go", new BMessage(GOTO_URL)); // Status Bar m_statusText = new BStringView("status", ""); @@ -201,7 +201,7 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, .Add(m_ForwardButton, 1, 0) .Add(m_StopButton, 2, 0) .Add(m_url, 3, 0) - .Add(button, 4, 0) + .Add(m_goButton, 4, 0) .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) ) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) @@ -223,6 +223,8 @@ LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, } else { m_BackButton = 0; m_ForwardButton = 0; + m_StopButton = 0; + m_goButton = 0; m_url = 0; m_menuBar = 0; m_statusText = 0; @@ -253,6 +255,27 @@ LauncherWindow::~LauncherWindow() { } +void LauncherWindow::DispatchMessage(BMessage* message, BHandler* target) +{ + if (m_url && message->what == B_KEY_DOWN && target == m_url->TextView()) { + // Handle B_RETURN in the URL text control. This is the easiest + // way to react *only* when the user presses the return key in the + // address bar, as opposed to trying to load whatever is in there when + // the text control just goes out of focus. + const char* bytes; + if (message->FindString("bytes", &bytes) == B_OK + && bytes[0] == B_RETURN) { + // Do it in such a way that the user sees the Go-button go down. + m_goButton->SetValue(B_CONTROL_ON); + UpdateIfNeeded(); + m_goButton->Invoke(); + snooze(1000); + m_goButton->SetValue(B_CONTROL_OFF); + } + } + BWebWindow::DispatchMessage(message, target); +} + void LauncherWindow::MessageReceived(BMessage* message) { switch (message->what) { @@ -265,13 +288,13 @@ void LauncherWindow::MessageReceived(BMessage* message) } break; case RELOAD: - CurrentWebView()->LoadURL(m_url->Text()); + CurrentWebView()->Reload(); break; case GOTO_URL: { - BString url = m_url->Text(); - message->FindString("url", &url); - if (m_loadedURL != url) - CurrentWebView()->LoadURL(url.String()); + BString url; + if (message->FindString("url", &url) != B_OK) + url = m_url->Text(); + CurrentWebView()->LoadURL(url.String()); break; } case GO_BACK: @@ -502,8 +525,6 @@ void LauncherWindow::LoadCommitted(const BString& url, BWebView* view) if (view != CurrentWebView()) return; - m_loadedURL = url; - // This hook is invoked when the load is commited. if (m_url) m_url->SetText(url.String()); @@ -542,7 +563,6 @@ void LauncherWindow::LoadFinished(const BString& url, BWebView* view) if (view != CurrentWebView()) return; - m_loadedURL = url; BString status(url); status << " finished."; StatusChanged(status, view); diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index e06837b48f..192d42786a 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -64,6 +64,7 @@ public: ToolbarPolicy = HaveToolbar); virtual ~LauncherWindow(); + virtual void DispatchMessage(BMessage* message, BHandler* target); virtual void MessageReceived(BMessage* message); virtual bool QuitRequested(); virtual void MenusBeginning(); @@ -102,8 +103,8 @@ private: IconButton* m_BackButton; IconButton* m_ForwardButton; IconButton* m_StopButton; + BButton* m_goButton; BTextControl* m_url; - BString m_loadedURL; BStringView* m_statusText; BStatusBar* m_loadingProgressBar; BLayoutItem* m_findGroup; From bf0181bd0014d91717a12af6af7b9da78c21db73 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 27 Feb 2010 12:26:17 +0000 Subject: [PATCH 068/349] Instead of hiding the tab view when there is only one tab, make the tab close buttons only available when there is more than one tab. This gives a more consistent interface and doesn't hide features, most importantly the "Add tab" button. For users that wish the most minimalistic UI, this behavior could later be configurable (along with opening new windows versus new tabs). git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@233 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 3 +- src/apps/webpositive/WebTabView.cpp | 160 ++++++++++++++---------- src/apps/webpositive/WebTabView.h | 3 + 3 files changed, 102 insertions(+), 64 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index d2c77647ae..4bd0ac61a6 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -692,7 +692,8 @@ void LauncherWindow::updateTitle(const BString& title) void LauncherWindow::updateTabGroupVisibility() { if (Lock()) { - m_tabGroup->SetVisible(m_tabManager->CountTabs() > 1); + //m_tabGroup->SetVisible(m_tabManager->CountTabs() > 1); + m_tabManager->SetCloseButtonsAvailable(m_tabManager->CountTabs() > 1); Unlock(); } } diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index 355290e6e0..483f5b2811 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -187,8 +187,6 @@ TabContainerView::TabContainerView(Controller* controller) TabContainerView::~TabContainerView() { - // TODO: Not so nice, that we take ownership of the controller. - delete fController; } @@ -717,8 +715,19 @@ public: void CloseTab(int32 index); + void SetCloseButtonsAvailable(bool available) + { + fCloseButtonsAvailable = available; + } + + bool CloseButtonsAvailable() const + { + return fCloseButtonsAvailable; + } + private: TabManager* fManager; + bool fCloseButtonsAvailable; }; @@ -740,6 +749,8 @@ public: const BMessage* dragMessage); private: + void _DrawCloseButton(BView* owner, BRect& frame, const BRect& updateRect, + bool isFirst, bool isLast, bool isFront); BRect _CloseRectFrame(BRect frame) const; private: @@ -772,6 +783,75 @@ WebTabView::MaxSize() void WebTabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect, bool isFirst, bool isLast, bool isFront) +{ + if (fController->CloseButtonsAvailable()) + _DrawCloseButton(owner, frame, updateRect, isFirst, isLast, isFront); + + TabView::DrawContents(owner, frame, updateRect, isFirst, isLast, isFront); +} + + +void +WebTabView::MouseDown(BPoint where, uint32 buttons) +{ + if (buttons & B_TERTIARY_MOUSE_BUTTON) { + fController->CloseTab(ContainerView()->IndexOf(this)); + return; + } + + BRect closeRect = _CloseRectFrame(Frame()); + if (!fController->CloseButtonsAvailable() || !closeRect.Contains(where)) { + TabView::MouseDown(where, buttons); + return; + } + + fClicked = true; + ContainerView()->Invalidate(closeRect); +} + + +void +WebTabView::MouseUp(BPoint where) +{ + if (!fClicked) { + TabView::MouseUp(where); + return; + } + + fClicked = false; + + if (_CloseRectFrame(Frame()).Contains(where)) + fController->CloseTab(ContainerView()->IndexOf(this)); +} + + +void +WebTabView::MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMessage) +{ + if (fController->CloseButtonsAvailable()) { + BRect closeRect = _CloseRectFrame(Frame()); + bool overCloseRect = closeRect.Contains(where); + if (overCloseRect != fOverCloseRect) { + fOverCloseRect = overCloseRect; + ContainerView()->Invalidate(closeRect); + } + } + + TabView::MouseMoved(where, transit, dragMessage); +} + + +BRect +WebTabView::_CloseRectFrame(BRect frame) const +{ + frame.left = frame.right - frame.Height(); + return frame; +} + + +void WebTabView::_DrawCloseButton(BView* owner, BRect& frame, + const BRect& updateRect, bool isFirst, bool isLast, bool isFront) { BRect closeRect = _CloseRectFrame(frame); frame.right = closeRect.left - be_control_look->DefaultLabelSpacing(); @@ -808,65 +888,6 @@ WebTabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect, owner->StrokeLine(closeRect.LeftTop(), closeRect.RightBottom()); owner->StrokeLine(closeRect.LeftBottom(), closeRect.RightTop()); owner->SetPenSize(1); - - TabView::DrawContents(owner, frame, updateRect, isFirst, isLast, isFront); -} - - -void -WebTabView::MouseDown(BPoint where, uint32 buttons) -{ - if (buttons & B_TERTIARY_MOUSE_BUTTON) { - fController->CloseTab(ContainerView()->IndexOf(this)); - return; - } - - BRect closeRect = _CloseRectFrame(Frame()); - if (!closeRect.Contains(where)) { - TabView::MouseDown(where, buttons); - return; - } - - fClicked = true; - ContainerView()->Invalidate(closeRect); -} - - -void -WebTabView::MouseUp(BPoint where) -{ - if (!fClicked) { - TabView::MouseUp(where); - return; - } - - fClicked = false; - - if (_CloseRectFrame(Frame()).Contains(where)) - fController->CloseTab(ContainerView()->IndexOf(this)); -} - - -void -WebTabView::MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage) -{ - BRect closeRect = _CloseRectFrame(Frame()); - bool overCloseRect = closeRect.Contains(where); - if (overCloseRect != fOverCloseRect) { - fOverCloseRect = overCloseRect; - ContainerView()->Invalidate(closeRect); - } - - TabView::MouseMoved(where, transit, dragMessage); -} - - -BRect -WebTabView::_CloseRectFrame(BRect frame) const -{ - frame.left = frame.right - frame.Height(); - return frame; } @@ -875,7 +896,8 @@ WebTabView::_CloseRectFrame(BRect frame) const TabManagerController::TabManagerController(TabManager* manager) : - fManager(manager) + fManager(manager), + fCloseButtonsAvailable(false) { } @@ -1038,13 +1060,14 @@ public: TabManager::TabManager(const BMessenger& target, BMessage* newTabMessage) : + fController(new TabManagerController(this)), fTarget(target) { fContainerView = new BView("web view container", 0); fCardLayout = new BCardLayout(); fContainerView->SetLayout(fCardLayout); - fTabContainerView = new TabContainerView(new TabManagerController(this)); + fTabContainerView = new TabContainerView(fController); fTabContainerGroup = new BGroupView(B_HORIZONTAL); fTabContainerGroup->GroupLayout()->SetInsets(0, 5, 0, 0); fTabContainerGroup->GroupLayout()->AddView(fTabContainerView); @@ -1059,6 +1082,7 @@ TabManager::TabManager(const BMessenger& target, BMessage* newTabMessage) TabManager::~TabManager() { + delete fController; } @@ -1169,3 +1193,13 @@ TabManager::SetTabLabel(int32 tabIndex, const char* label) fTabContainerView->SetTabLabel(tabIndex, label); } + +void +TabManager::SetCloseButtonsAvailable(bool available) +{ + if (available == fController->CloseButtonsAvailable()) + return; + fController->SetCloseButtonsAvailable(available); + fTabContainerView->Invalidate(); +} + diff --git a/src/apps/webpositive/WebTabView.h b/src/apps/webpositive/WebTabView.h index 9df5f501c4..9965e62a9a 100644 --- a/src/apps/webpositive/WebTabView.h +++ b/src/apps/webpositive/WebTabView.h @@ -39,6 +39,7 @@ enum { class BCardLayout; class BGroupView; class TabContainerView; +class TabManagerController; class TabManager { public: @@ -64,12 +65,14 @@ public: int32 CountTabs() const; void SetTabLabel(int32 tabIndex, const char* label); + void SetCloseButtonsAvailable(bool available); private: BGroupView* fTabContainerGroup; TabContainerView* fTabContainerView; BView* fContainerView; BCardLayout* fCardLayout; + TabManagerController* fController; BMessenger fTarget; }; From b3a723711e7a9145ea9cd4e9ba6916a510bb1eac Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 27 Feb 2010 13:09:57 +0000 Subject: [PATCH 069/349] Added tool tip to Add tab button... git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@234 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/WebTabView.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index 483f5b2811..e635c03cc8 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -1010,6 +1010,7 @@ public: NewTabButton(BMessage* message) : TabButton(message) { + SetToolTip("New tab (Cmd-T)"); } virtual BSize MinSize() From ce1641f62c58ef2dd82e37b96f3b35071cef2468 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 27 Feb 2010 13:20:24 +0000 Subject: [PATCH 070/349] Hide the implementation details of BWebWindow::AuthenticationChallenge() from clients. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@235 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 29 +++++-------------------- src/apps/webpositive/LauncherWindow.h | 4 +++- 2 files changed, 9 insertions(+), 24 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 4bd0ac61a6..e44836cec8 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -653,31 +653,14 @@ void LauncherWindow::UpdateGlobalHistory(const BString& url) BrowsingHistory::defaultInstance()->addItem(BrowsingHistoryItem(url)); } -void LauncherWindow::AuthenticationChallenge(BMessage* message) +bool LauncherWindow::AuthenticationChallenge(BString message, BString& inOutUser, + BString& inOutPassword, bool& inOutRememberCredentials, uint32 failureCount) { - BString text; - bool rememberCredentials = false; - uint32 failureCount = 0; - BString user; - BString password; - - message->FindString("text", &text); - message->FindString("user", &user); - message->FindString("password", &password); - message->FindUInt32("failureCount", &failureCount); - AuthenticationPanel* panel = new AuthenticationPanel(Frame()); - if (!panel->getAuthentication(text, user, password, rememberCredentials, - failureCount > 0, user, password, &rememberCredentials)) { - message->SendReply((uint32)0); - return; - } - - BMessage reply; - reply.AddString("user", user); - reply.AddString("password", password); - reply.AddBool("rememberCredentials", rememberCredentials); - message->SendReply(&reply); + // Panel auto-destructs. + return panel->getAuthentication(message, inOutUser, inOutPassword, + inOutRememberCredentials, failureCount > 0, inOutUser, inOutPassword, + &inOutRememberCredentials); } void LauncherWindow::updateTitle(const BString& title) diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index 192d42786a..e502360f49 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -91,7 +91,9 @@ private: virtual void NavigationCapabilitiesChanged(bool canGoBackward, bool canGoForward, bool canStop, BWebView* view); virtual void UpdateGlobalHistory(const BString& url); - virtual void AuthenticationChallenge(BMessage* challenge); + virtual bool AuthenticationChallenge(BString message, BString& inOutUser, + BString& inOutPassword, bool& inOutRememberCredentials, + uint32 failureCount); void updateTitle(const BString &title); void updateTabGroupVisibility(); From 3d6558b6ca6f25e225951fec74e144001e911678 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 27 Feb 2010 13:20:50 +0000 Subject: [PATCH 071/349] Coding style fix. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@236 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index e44836cec8..63ace8ba70 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -659,8 +659,8 @@ bool LauncherWindow::AuthenticationChallenge(BString message, BString& inOutUser AuthenticationPanel* panel = new AuthenticationPanel(Frame()); // Panel auto-destructs. return panel->getAuthentication(message, inOutUser, inOutPassword, - inOutRememberCredentials, failureCount > 0, inOutUser, inOutPassword, - &inOutRememberCredentials); + inOutRememberCredentials, failureCount > 0, inOutUser, inOutPassword, + &inOutRememberCredentials); } void LauncherWindow::updateTitle(const BString& title) From 50c04c441db77a54512b0eff6f6e3323fe403f46 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 27 Feb 2010 13:31:29 +0000 Subject: [PATCH 072/349] Actually, the authentication challenge needs to know for which page it is, otherwise we may display the login panel above an unrelated page. Tested by clicking Login on dev.haiku-os.org and Cmd-T to open a new tab before the login panel shows. Works. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@237 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/LauncherWindow.cpp | 8 +++++++- src/apps/webpositive/LauncherWindow.h | 2 +- src/apps/webpositive/WebTabView.cpp | 14 ++++++++++++++ src/apps/webpositive/WebTabView.h | 1 + 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/LauncherWindow.cpp index 63ace8ba70..37ff504ae6 100644 --- a/src/apps/webpositive/LauncherWindow.cpp +++ b/src/apps/webpositive/LauncherWindow.cpp @@ -654,8 +654,14 @@ void LauncherWindow::UpdateGlobalHistory(const BString& url) } bool LauncherWindow::AuthenticationChallenge(BString message, BString& inOutUser, - BString& inOutPassword, bool& inOutRememberCredentials, uint32 failureCount) + BString& inOutPassword, bool& inOutRememberCredentials, uint32 failureCount, + BWebView* view) { + // Switch to the page for which this authentication is required. + if (view != CurrentWebView()) { + m_tabManager->SelectTab(view); + UpdateIfNeeded(); + } AuthenticationPanel* panel = new AuthenticationPanel(Frame()); // Panel auto-destructs. return panel->getAuthentication(message, inOutUser, inOutPassword, diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/LauncherWindow.h index e502360f49..018ac29a16 100644 --- a/src/apps/webpositive/LauncherWindow.h +++ b/src/apps/webpositive/LauncherWindow.h @@ -93,7 +93,7 @@ private: virtual void UpdateGlobalHistory(const BString& url); virtual bool AuthenticationChallenge(BString message, BString& inOutUser, BString& inOutPassword, bool& inOutRememberCredentials, - uint32 failureCount); + uint32 failureCount, BWebView* view); void updateTitle(const BString &title); void updateTabGroupVisibility(); diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index e635c03cc8..1b491385c0 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -1137,6 +1137,20 @@ TabManager::SelectTab(int32 tabIndex) } +void +TabManager::SelectTab(BView* containedView) +{ + int32 count = fCardLayout->CountItems(); + for (int32 i = 0; i < count; i++) { + BLayoutItem* item = fCardLayout->ItemAt(i); + if (item->View() == containedView) { + SelectTab(i); + break; + } + } +} + + int32 TabManager::SelectedTabIndex() const { diff --git a/src/apps/webpositive/WebTabView.h b/src/apps/webpositive/WebTabView.h index 9965e62a9a..3f9f086755 100644 --- a/src/apps/webpositive/WebTabView.h +++ b/src/apps/webpositive/WebTabView.h @@ -56,6 +56,7 @@ public: BView* ViewForTab(int32 tabIndex) const; void SelectTab(int32 tabIndex); + void SelectTab(BView* containedView); int32 SelectedTabIndex() const; void CloseTab(int32 tabIndex); From 90f510906d5cda45f8580a5cfbcb8b8dc19fd47c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sun, 17 Jun 2012 12:19:54 +0200 Subject: [PATCH 073/349] When the value hint mode is active, keep it active. * Ie. when a different value is pressed, the hint is now being shown for the new value instead of turning of the value hints. --- src/apps/sudoku/SudokuView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/sudoku/SudokuView.cpp b/src/apps/sudoku/SudokuView.cpp index 849c5e51ac..8d5d1114cf 100644 --- a/src/apps/sudoku/SudokuView.cpp +++ b/src/apps/sudoku/SudokuView.cpp @@ -890,7 +890,7 @@ SudokuView::MouseDown(BPoint where) } if (value + 1 != fValueHintValue) - _SetValueHintValue(~0UL); + _SetValueHintValue(value + 1); if (wasCompleted != fField->IsValueCompleted(value + 1)) _InvalidateValue(value + 1, false, x, y); From d6e44a2a3a7baf72872eb2cb9bddf0a293fba3c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Mon, 18 Jun 2012 21:51:08 +0200 Subject: [PATCH 074/349] Fixed BootLoaderTest build and debug build. --- src/tests/system/boot/loader/Jamfile | 24 ++++--- .../loader/file_systems/amiga_ffs/Jamfile | 5 +- .../boot/loader/file_systems/bfs/Jamfile | 3 +- .../boot/loader/file_systems/tarfs/Jamfile | 6 +- .../system/boot/loader/platform_console.cpp | 65 +++++++++++++++++++ .../system/boot/loader/platform_debug.cpp | 12 +++- .../system/boot/loader/platform_menu.cpp | 18 ++++- .../system/boot/loader/platform_start.cpp | 3 +- 8 files changed, 114 insertions(+), 22 deletions(-) create mode 100644 src/tests/system/boot/loader/platform_console.cpp diff --git a/src/tests/system/boot/loader/Jamfile b/src/tests/system/boot/loader/Jamfile index f68a9411c3..3378873b0d 100644 --- a/src/tests/system/boot/loader/Jamfile +++ b/src/tests/system/boot/loader/Jamfile @@ -2,11 +2,11 @@ SubDir HAIKU_TOP src tests system boot loader ; SetSubDirSupportedPlatformsBeOSCompatible ; -UsePrivateHeaders [ FDirName kernel ] ; UsePrivateHeaders [ FDirName kernel disk_device_manager ] ; -UsePrivateHeaders [ FDirName storage ] ; -UsePrivateHeaders [ FDirName shared ] ; +UsePrivateHeaders [ FDirName kernel util ] ; +UsePrivateHeaders kernel shared storage system ; SubDirSysHdrs $(HAIKU_TOP) headers private kernel arch $(TARGET_ARCH) ; +SubDirSysHdrs $(HAIKU_TOP) headers private system arch $(TARGET_ARCH) ; SubDirSysHdrs $(HAIKU_TOP) src tests system boot loader ; SubDirHdrs $(HAIKU_TOP) src system boot loader ; SubDirHdrs $(HAIKU_TOP) src add-ons kernel partitioning_systems amiga ; @@ -34,6 +34,7 @@ ObjectDefines loader.cpp kernel_args.cpp load_driver_settings.cpp + pager.cpp # other platform_menu.cpp @@ -79,6 +80,7 @@ ObjectDefines SimpleTest BootLoaderTest : # userland bindings platform_start.cpp + platform_console.cpp platform_debug.cpp platform_devices.cpp platform_heap.cpp @@ -97,6 +99,7 @@ SimpleTest BootLoaderTest : loader.cpp kernel_args.cpp load_driver_settings.cpp + pager.cpp # partitioning systems amiga_rdb.cpp @@ -106,19 +109,20 @@ SimpleTest BootLoaderTest : PartitionMap.cpp PartitionMapParser.cpp - # utility functions - Dano has a strlcpy() function in libroot.so, while R5 has not + # utility functions list.cpp - strlcat.c - strlcpy.c driver_settings.cpp + ring_buffer.cpp KMessage.cpp - : boottest_bfs.a boottest_amiga_ffs.a boottest_tarfs.a libz.a - ; + : + boottest_bfs.a boottest_amiga_ffs.a boottest_tarfs.a libz.a + kernelland_emu +; # Tell Jam where to find the utility sources -SEARCH on [ FGristFiles list.cpp ] +SEARCH on [ FGristFiles list.cpp ring_buffer.cpp ] = [ FDirName $(HAIKU_TOP) src system kernel util ] ; SEARCH on [ FGristFiles KMessage.cpp ] @@ -134,7 +138,7 @@ SEARCH on [ FGristFiles main.cpp vfs.cpp partitions.cpp heap.cpp RootFileSystem.cpp elf.cpp menu.cpp loader.cpp - kernel_args.cpp load_driver_settings.cpp + kernel_args.cpp load_driver_settings.cpp pager.cpp ] = [ FDirName $(HAIKU_TOP) src system boot loader ] ; # partitioning system modules diff --git a/src/tests/system/boot/loader/file_systems/amiga_ffs/Jamfile b/src/tests/system/boot/loader/file_systems/amiga_ffs/Jamfile index 84fc846197..afee6b72ec 100644 --- a/src/tests/system/boot/loader/file_systems/amiga_ffs/Jamfile +++ b/src/tests/system/boot/loader/file_systems/amiga_ffs/Jamfile @@ -2,7 +2,8 @@ SubDir HAIKU_TOP src tests system boot loader file_systems amiga_ffs ; SetSubDirSupportedPlatformsBeOSCompatible ; -UsePrivateHeaders [ FDirName kernel ] ; +UsePrivateKernelHeaders ; +UsePrivateSystemHeaders ; UsePrivateHeaders [ FDirName kernel disk_device_manager ] ; UsePrivateHeaders [ FDirName storage ] ; SubDirSysHdrs $(HAIKU_TOP) src tests system boot loader ; @@ -13,7 +14,7 @@ if $(TARGET_PLATFORM) != haiku { UsePublicHeaders storage ; # DiskDeviceDefs.h } -ObjectDefines +ObjectDefines amiga_ffs.cpp Volume.cpp Directory.cpp diff --git a/src/tests/system/boot/loader/file_systems/bfs/Jamfile b/src/tests/system/boot/loader/file_systems/bfs/Jamfile index 1ed8911c4a..9adcf06ba9 100644 --- a/src/tests/system/boot/loader/file_systems/bfs/Jamfile +++ b/src/tests/system/boot/loader/file_systems/bfs/Jamfile @@ -2,7 +2,8 @@ SubDir HAIKU_TOP src tests system boot loader file_systems bfs ; SetSubDirSupportedPlatformsBeOSCompatible ; -UsePrivateHeaders [ FDirName kernel ] ; +UsePrivateKernelHeaders ; +UsePrivateSystemHeaders ; UsePrivateHeaders [ FDirName kernel disk_device_manager ] ; UsePrivateHeaders [ FDirName storage ] ; SubDirSysHdrs $(HAIKU_TOP) src tests system boot loader ; diff --git a/src/tests/system/boot/loader/file_systems/tarfs/Jamfile b/src/tests/system/boot/loader/file_systems/tarfs/Jamfile index 874d75b5bc..bc94520bd3 100644 --- a/src/tests/system/boot/loader/file_systems/tarfs/Jamfile +++ b/src/tests/system/boot/loader/file_systems/tarfs/Jamfile @@ -2,8 +2,10 @@ SubDir HAIKU_TOP src tests system boot loader file_systems tarfs ; SetSubDirSupportedPlatformsBeOSCompatible ; +UsePrivateKernelHeaders ; +UsePrivateSystemHeaders ; UsePrivateHeaders [ FDirName kernel disk_device_manager ] ; -UsePrivateHeaders kernel shared storage ; +UsePrivateHeaders shared storage ; SubDirSysHdrs $(HAIKU_TOP) src tests system boot loader ; SubDirSysHdrs $(HAIKU_TOP) headers libs zlib ; SubDirHdrs $(HAIKU_TOP) src system boot loader file_systems tarfs ; @@ -15,7 +17,7 @@ if $(TARGET_PLATFORM) != haiku { ObjectDefines tarfs.cpp : B_BUFFER_OVERFLOW=B_BAD_VALUE ; } -ObjectDefines +ObjectDefines tarfs.cpp : read_pos=boot_read_pos fstat=boot_fstat open=boot_open close=boot_close _BOOT_MODE diff --git a/src/tests/system/boot/loader/platform_console.cpp b/src/tests/system/boot/loader/platform_console.cpp new file mode 100644 index 0000000000..50512ae85f --- /dev/null +++ b/src/tests/system/boot/loader/platform_console.cpp @@ -0,0 +1,65 @@ +/* + * Copyright 2012, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + + +#include + + +void +console_clear_screen(void) +{ +} + + +int32 +console_width(void) +{ + return 80; +} + + +int32 +console_height(void) +{ + return 25; +} + + +void +console_set_cursor(int32 x, int32 y) +{ +} + + +void +console_show_cursor(void) +{ +} + + +void +console_hide_cursor(void) +{ +} + + +void +console_set_color(int32 foreground, int32 background) +{ +} + + +int +console_wait_for_key(void) +{ + return 0; +} + + +status_t +console_init(void) +{ + return B_OK; +} diff --git a/src/tests/system/boot/loader/platform_debug.cpp b/src/tests/system/boot/loader/platform_debug.cpp index 500293ca76..a5a8696474 100644 --- a/src/tests/system/boot/loader/platform_debug.cpp +++ b/src/tests/system/boot/loader/platform_debug.cpp @@ -1,7 +1,7 @@ /* -** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. -** Distributed under the terms of the OpenBeOS License. -*/ + * Copyright 2003-2012, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ #include @@ -32,3 +32,9 @@ dprintf(const char *format, ...) va_end(args); } + +char* +platform_debug_get_log_buffer(size_t* _size) +{ + return NULL; +} diff --git a/src/tests/system/boot/loader/platform_menu.cpp b/src/tests/system/boot/loader/platform_menu.cpp index a028d653d1..b6ef143da6 100644 --- a/src/tests/system/boot/loader/platform_menu.cpp +++ b/src/tests/system/boot/loader/platform_menu.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Copyright 2004-2012, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. */ @@ -40,7 +40,7 @@ print_item_at(int32 line, MenuItem *item, bool clearHelp = true) printf(" "); printf(item->Label()); - + if (item->Submenu() && item->Submenu()->Type() == CHOICE_MENU) { // show the current choice (if any) Menu *subMenu = item->Submenu(); @@ -165,11 +165,16 @@ platform_run_menu(Menu *menu) char buffer[32]; if (fgets(buffer, sizeof(buffer), stdin) == NULL) return; - + if (buffer[0] != '\n') selected = atoi(buffer); item = menu->ItemAt(selected); + if (item == NULL) { + printf("Invalid choice."); + continue; + } + item->Select(true); // leave the menu @@ -194,3 +199,10 @@ platform_run_menu(Menu *menu) } } + +size_t +platform_get_user_input_text(Menu* menu, MenuItem* item, char* buffer, + size_t bufferSize) +{ + return 0; +} diff --git a/src/tests/system/boot/loader/platform_start.cpp b/src/tests/system/boot/loader/platform_start.cpp index 27c9ddb19d..cc379b5b4c 100644 --- a/src/tests/system/boot/loader/platform_start.cpp +++ b/src/tests/system/boot/loader/platform_start.cpp @@ -35,7 +35,8 @@ main(int argc, char **argv) { // The command arguments are evaluated in platform_devices.cpp! - boot_main(NULL); + stage2_args args; + boot_main(&args); return 0; } From 24df347e9c97f484f208f35142f8e7da36efe2b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Wed, 20 Jun 2012 19:53:32 +0200 Subject: [PATCH 075/349] Patch by X512 for Icon-O-Matic. * support HVIF icons and SVG images in rdef Signed-off-by: Stephan Assmus --- src/apps/icon-o-matic/Icon-O-Matic.rdef | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/apps/icon-o-matic/Icon-O-Matic.rdef b/src/apps/icon-o-matic/Icon-O-Matic.rdef index c0b28b6101..b349c8de07 100644 --- a/src/apps/icon-o-matic/Icon-O-Matic.rdef +++ b/src/apps/icon-o-matic/Icon-O-Matic.rdef @@ -20,6 +20,11 @@ resource app_version { resource app_flags B_SINGLE_LAUNCH; +resource file_types message { + "types" = "application/x-vnd.Haiku-icon", + "types" = "image/svg+xml" +}; + resource vector_icon { $"6E6369660E050102000603399E0F3D9C0ABF82B23B84A94B88504910C900A5B1" $"FFBCEAF1FFFFB3B8FF020106023E49240000000000003CAAAA4940004A8000FF" From 55713eef96817a78bbfed8df3717bcd779e268f2 Mon Sep 17 00:00:00 2001 From: Matt Madia Date: Wed, 20 Jun 2012 22:11:33 -0400 Subject: [PATCH 076/349] Updated URL's for WifiFirmwareScriptData. Fixes #8645. --- build/jam/OptionalPackages | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/build/jam/OptionalPackages b/build/jam/OptionalPackages index d612b8ed9e..533fd73bcb 100644 --- a/build/jam/OptionalPackages +++ b/build/jam/OptionalPackages @@ -1869,7 +1869,7 @@ if [ IsOptionalHaikuImagePackageAdded WifiFirmwareScriptData ] { # firmware cutter local broadcomFWCutterArchive = b43-fwcutter-012.tar.bz2 ; local broadcomFWCutterURL = - http://bu3sch.de/b43/fwcutter/$(broadcomFWCutterArchive) ; + http://www.haiku-files.org/files/wifi-firmwares/b43/fwcutter/$(broadcomFWCutterArchive) ; local broadcomFWCutterFile = [ DownloadFile $(broadcomFWCutterArchive) : $(broadcomFWCutterURL) ] ; AddFilesToHaikuImage system data firmware broadcom43xx b43-fwcutter @@ -1889,16 +1889,16 @@ if [ IsOptionalHaikuImagePackageAdded WifiFirmwareScriptData ] { # file containing firmware local broadcom43xxFile ; broadcom43xxFile = [ DownloadFile wl_apsta-3.130.20.0.o - : http://downloads.openwrt.org/sources/wl_apsta-3.130.20.0.o ] ; + : http://www.haiku-files.org/files/wifi-firmwares/b43/wl_apsta-3.130.20.0.o ] ; AddFilesToHaikuImage system data firmware broadcom43xx : $(broadcom43xxFile) ; # marvell88w8335 - local marvelArchive = malo-firmware-1.4.tgz ; - local marvelURL = http://www.nazgul.ch/malo/$(marvelArchive) ; - local marvelFile = [ DownloadFile $(marvelArchive) : $(marvelURL) ] ; + local marvellArchive = malo-firmware-1.4.tgz ; + local marvellURL = http://www.haiku-files.org/files/wifi-firmwares/marvell/$(marvellArchive) ; + local marvellFile = [ DownloadFile $(marvellArchive) : $(marvellURL) ] ; AddFilesToHaikuImage system data firmware marvell88w8335 - : $(marvelFile) ; + : $(marvellFile) ; } } From ccae01d421db5f197e39ab834adf8e5c141629f5 Mon Sep 17 00:00:00 2001 From: Humdinger Date: Sat, 23 Jun 2012 20:16:58 +0200 Subject: [PATCH 077/349] Fixed issue when auto-showing toolbar in fullscreen mode. If you've zoomed in fullscreen mode and moved the mouse to the top of the screen, the toolbar didn't appear. You had to scroll up to the top of zoomed image first. Using the screen coords instead of the view coords fixes this. --- src/apps/showimage/ShowImageView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/showimage/ShowImageView.cpp b/src/apps/showimage/ShowImageView.cpp index 4551cf1f42..22e14a4c52 100644 --- a/src/apps/showimage/ShowImageView.cpp +++ b/src/apps/showimage/ShowImageView.cpp @@ -1172,7 +1172,7 @@ ShowImageView::MouseMoved(BPoint point, uint32 state, const BMessage* message) fHideCursorCountDown = HIDE_CURSOR_DELAY_TIME; if (fHideCursor) { // Show toolbar when mouse hits top 15 pixels, hide otherwise - _ShowToolBarIfEnabled(point.y <= 15); + _ShowToolBarIfEnabled(ConvertToScreen(point).y <= 15); } if (fCreatingSelection) _UpdateSelectionRect(point, false); From 6f55e249dfd6e86460037055c524d65fd6e406bd Mon Sep 17 00:00:00 2001 From: Humdinger Date: Sat, 23 Jun 2012 20:53:42 +0200 Subject: [PATCH 078/349] Fixed redrawing bug when coming out of fullscreen mode. After coming back from fullscreen mode, horizontally scrolling a zoomed image would draw vertical lines from the right border. Seems like an off-by-one issue. This fixes it in my tests... hope it's properly done. --- src/apps/showimage/ShowImageWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/showimage/ShowImageWindow.cpp b/src/apps/showimage/ShowImageWindow.cpp index ac52492589..1fad14f560 100644 --- a/src/apps/showimage/ShowImageWindow.cpp +++ b/src/apps/showimage/ShowImageWindow.cpp @@ -1272,7 +1272,7 @@ ShowImageWindow::_ToggleFullScreen() fWindowFrame = Frame(); frame = screen.Frame(); frame.top -= fBar->Bounds().Height()+1; - frame.right += B_V_SCROLL_BAR_WIDTH; + frame.right += B_V_SCROLL_BAR_WIDTH-1; frame.bottom += B_H_SCROLL_BAR_HEIGHT; frame.InsetBy(-1, -1); // PEN_SIZE in ShowImageView From 91102c544efd6df8a835eca0b3cdf6db728b2a33 Mon Sep 17 00:00:00 2001 From: Fredrik Holmqvist Date: Sat, 11 Feb 2012 10:34:48 +0100 Subject: [PATCH 079/349] Logging calculations was done outside the #def TRACE_VM_PAGE, but never printed. Now done inside #def as well as this triggered unused variables warnings. --- src/system/kernel/vm/vm_page.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/system/kernel/vm/vm_page.cpp b/src/system/kernel/vm/vm_page.cpp index e7740ddeb6..9e4c591779 100644 --- a/src/system/kernel/vm/vm_page.cpp +++ b/src/system/kernel/vm/vm_page.cpp @@ -714,7 +714,7 @@ public: private: bool fPrintStackTrace; page_num_t fPageFilter; - team_id fTeamFilter; + team_id fTeamFilter; thread_id fThreadFilter; }; @@ -1530,7 +1530,7 @@ free_page(vm_page* page, bool clear) TA(FreePage(page->physical_page_number)); #if VM_PAGE_ALLOCATION_TRACKING_AVAILABLE - page->allocation_tracking_info.Clear(); + page->allocation_tracking_info.Clear(); #endif ReadLocker locker(sFreePageQueuesLock); @@ -2295,12 +2295,12 @@ status_t page_writer(void* /*unused*/) { const uint32 kNumPages = 256; - uint32 writtenPages = 0; #ifdef TRACE_VM_PAGE + uint32 writtenPages = 0; bigtime_t lastWrittenTime = 0; -#endif bigtime_t pageCollectionTime = 0; bigtime_t pageWritingTime = 0; +#endif PageWriterRun run; if (run.Init(kNumPages) != B_OK) { @@ -2356,7 +2356,9 @@ page_writer(void* /*unused*/) // enough to do). // collect pages to be written +#ifdef TRACE_VM_PAGE pageCollectionTime -= system_time(); +#endif page_num_t maxPagesToSee = modifiedPages; @@ -2429,31 +2431,35 @@ page_writer(void* /*unused*/) numPages++; } +#ifdef TRACE_VM_PAGE pageCollectionTime += system_time(); - +#endif if (numPages == 0) continue; // write pages to disk and do all the cleanup +#ifdef TRACE_VM_PAGE pageWritingTime -= system_time(); +#endif uint32 failedPages = run.Go(); +#ifdef TRACE_VM_PAGE pageWritingTime += system_time(); // debug output only... writtenPages += numPages; if (writtenPages >= 1024) { -#ifdef TRACE_VM_PAGE bigtime_t now = system_time(); TRACE(("page writer: wrote 1024 pages (total: %llu ms, " "collect: %llu ms, write: %llu ms)\n", (now - lastWrittenTime) / 1000, pageCollectionTime / 1000, pageWritingTime / 1000)); lastWrittenTime = now; -#endif + writtenPages -= 1024; pageCollectionTime = 0; pageWritingTime = 0; } +#endif if (failedPages == numPages) pagesSinceLastSuccessfulWrite += modifiedPages - maxPagesToSee; From 9c7d5593e68f9f5026e314d098f87a0b873b21ed Mon Sep 17 00:00:00 2001 From: Ryan Leavengood Date: Sun, 24 Jun 2012 00:12:34 -0400 Subject: [PATCH 080/349] Update DejaVu fonts to version 2.33. --- .../data/fonts/ttfonts/DejaVuSans-Bold.ttf | Bin 573136 -> 672300 bytes .../fonts/ttfonts/DejaVuSans-BoldOblique.ttf | Bin 524056 -> 611212 bytes .../fonts/ttfonts/DejaVuSans-ExtraLight.ttf | Bin 329412 -> 345208 bytes .../data/fonts/ttfonts/DejaVuSans-Oblique.ttf | Bin 523804 -> 611556 bytes data/system/data/fonts/ttfonts/DejaVuSans.ttf | Bin 622280 -> 720012 bytes .../ttfonts/DejaVuSansCondensed-Bold.ttf | Bin 534464 -> 631992 bytes .../DejaVuSansCondensed-BoldOblique.ttf | Bin 493196 -> 580168 bytes .../ttfonts/DejaVuSansCondensed-Oblique.ttf | Bin 488440 -> 576004 bytes .../fonts/ttfonts/DejaVuSansCondensed.ttf | Bin 544636 -> 643852 bytes .../fonts/ttfonts/DejaVuSansMono-Bold.ttf | Bin 301928 -> 313856 bytes .../ttfonts/DejaVuSansMono-BoldOblique.ttf | Bin 223408 -> 235848 bytes .../fonts/ttfonts/DejaVuSansMono-Oblique.ttf | Bin 229284 -> 241972 bytes .../data/fonts/ttfonts/DejaVuSansMono.ttf | Bin 321524 -> 333636 bytes .../data/fonts/ttfonts/DejaVuSerif-Bold.ttf | Bin 306532 -> 341072 bytes .../fonts/ttfonts/DejaVuSerif-BoldItalic.ttf | Bin 294244 -> 332036 bytes .../data/fonts/ttfonts/DejaVuSerif-Italic.ttf | Bin 301828 -> 338776 bytes .../system/data/fonts/ttfonts/DejaVuSerif.ttf | Bin 328908 -> 363200 bytes .../ttfonts/DejaVuSerifCondensed-Bold.ttf | Bin 282092 -> 316440 bytes .../DejaVuSerifCondensed-BoldItalic.ttf | Bin 293472 -> 331128 bytes .../ttfonts/DejaVuSerifCondensed-Italic.ttf | Bin 301244 -> 338140 bytes .../fonts/ttfonts/DejaVuSerifCondensed.ttf | Bin 295840 -> 330012 bytes 21 files changed, 0 insertions(+), 0 deletions(-) diff --git a/data/system/data/fonts/ttfonts/DejaVuSans-Bold.ttf b/data/system/data/fonts/ttfonts/DejaVuSans-Bold.ttf index ec1a2ebaf247e5d2a547a5ec406f6831dabe26bd..0f4d5e9d484c3b42f473956a1d5726c96357fc9a 100644 GIT binary patch delta 190761 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 JcG=Fa(;IC_HXQ%} delta 93631 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

@`BH|@4| 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%0A;7hYX^|q2J+Gi+g-{`m1 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 delta 81070 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

IzTgwhy4cFFbl?g*SlMY1vW7Mcy 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
y=uvUU>&s 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 z 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 NbDAIhO55tT{|Wib_6Ps~ diff --git a/data/system/data/fonts/ttfonts/DejaVuSans-Oblique.ttf b/data/system/data/fonts/ttfonts/DejaVuSans-Oblique.ttf index becc54992732780a54a3843eea37884768d36c97..44856388daebcdafb106684d4708702c03798932 100644 GIT binary patch delta 168248 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 delta 81368 zcmagH2YggT_dh&y>+WW=+1*q^LN*;jNCJU`-g^s8YJh|$ga8o&(qs`36cmI7mL^T4 zH$g~1MMOX)$b(V@#D=sWD$P6!$<6znxtp-j=l6f*Gv&^mnN#PSGcz~q%^k7pN+XiuNhGCx`##-z|Ikq;gf>NMSckUl+UF0-n~vxHNS8bG$mm^W?AnJAF@=y$c^!Jc z(7H5#Zvr7*HxlBfW%N$2x9Z}<&V*#*ne-h#E<5k=e8){Z|3!#x=kO`{j(0Zfk0WIK z7R;ABD(^+-xH~xyPZE-6#ehXGW>3l^D*lnYb$B+vm^*FMn3uHg@VuSKx7UpxnLXm+ zg__5R(yuMvr;SE~c}K|mc%F&pn9<|%r*>OrO~LaZcfqDkowB$N21VBafw=3B_|)LYfWBn=mOq|M1gG zL~XsFkb)t36G!GPTPj2m^(hdR%oxM?M^29{IK#`2I)+!4?2QE-&aoCEkj_LD_7f_+ zFPuW{v~U`A*DG|k(?qE3Bl{3RHp{-KTjU@j%E597>eb}xsE5g6sE5npsMnCAP>+_Q zQICwTJ|k2uHBcfN1QX^lg`2{OV5(t?N4=&g z!HI|3rpb7iVw!^b%ci-g&oeC~qG^$75nA3fEkVoMrlqJaGwncqr)d}JyG?F z`e_?<$u`@D{#zS{O4+PB)aqQ1>`6!i~nMW~;(oh7wI+gG-) z@Nmv{4g>yUUrDIlZQn#h`)2zY)QjvzsGqezJQyOrD)cObu2PURLN86d^wQ^dlwh|x zQ!gzNfhH5`m%yK8>-B(;faw9hN0mSpXm6CIm+jMB_vAMI!@#;x@{96lc`VvF^IR>J zK^eJ#CCFps9Nyc6kyb*>O4tl#zpA!(#3X-ztk?xYVHNV3Q% zl1nC%sbm(J=X#{XS3g^J4WqAVfyggw5y-#SAnda1TA-`F8t2-m#=17BJ84r_XT#St z>0p@Am%74DW>*7Kk4PrTNG_guaLG-Q?5pjoNwR${IF`bA<=SdWuf}>s@LsW;mx-K< z>7=1+q5li6EaY9!beG{(`?2X7lP%@9t z$!rXzD|xO%VT1`ph9PJL3%kVTCdoCh*w&GF+XgJT+I+Fq!vtnn6+hW3+hn`!F9*nh zauBmEauJcmIB_=khRe5tWLk=d2{~u172^(axsdx{D;;>J%H7n zq?p1g2S?B%e(x{K`-f#_+dO_}lk*-i7DKdHV>SuYaDyfU{AxSWY@{ zg0*5Y~_yws&mniNkgn77s=nRwWcUAqs%#yy}ldM`0n%aC%k}M8eRoCP^aT za%cHNSOSZ{2B>ICo^0}rPYJGm@H3`UzVrJ(++mG4W+f%qNCz}xQdB#J9!YM8H~w- z<$0KZks>m~DCZu$Y;R44@-kOwKnF@)i);39iZz5EFgOmB4J3zQBTtYo$T@P6Tq8e` z+vGm^KeUTBrY&iE+LiXA{pk=og67aXI)%=pbLi`IFUFLTjO;&|T;w41~oSCFBYdg{i_U zVVsQuuq`vjM^=p!5{nq*|X=v+X>qi>d2HRdF&1^Zg$)uxgx@{KeWB=CvEg8VX z0*`mjwLYX;^|tU5lyn7uWF$KYAvG{J6&*@|>xYm~*8CZ{M1G@ww2mvNT09-?YF;g) z*0;9twh6XZ?C)YQ6|NxX>QuI!$;v$5RDygvG1I}WA%Tq#-mNxUaGei}b3F)CD$>CR zVLhptkb`#iW?DB9HN}HF=7E zZKyBxC2eUR+K05G*)*H9r@1tjbbx@SkdAZ)ok2R$68abEEXabHbQ3JXIP!wnUTjYe ziCx96OQ}*SIVR1NULl{TSxz;Ze5#I9 z$CJ<0JasZTrA}36lOlDV`Z~F&zNs!HS50r3-XcGmR+!x6C(|0!I`WHYgJ}b~ZQ5+w zM(&vQn)Z_4Ob1K{$nU1ZrULSZ>4@n=^3e3L>0|Q5^oi*+@~7#v=}Yp|`ib=uqFFz+ zo*?Dclh%urS}$9BUZHj-P#S0(U>iuQ*)nY}(&|jCG@gl-rrK-Uo6&~$7wj+4F7|%* zezdFoP5TPk&Hk=^3+-qB(Ebq}U_WI)MF%kjpqU4Q{Dpt46aV!#=z;%DVisbg&QcGl zuaqeblSWJ9rF?0+G+UZ4y(uk|R!QrnEz(YDzjRpoNID^XA)S*hO4p>Hq}$Sc>5=r8 zq{)(Of`Jc0uoxxRl#^hk8p|!^_HtLbm)u_-B9FjQ&BF?x2`liryjWf?uaTV_<*o8= z`G8y~ACphYXXNwpW%;^%L%u8jEw3cmD9>uM(V*I$q6Jr>nEo`H=N8b(Oka-Jud{E_K|=?l|2 z(?!!Y(@&<`ru(KxroT*@kK|+WvHAr0g!x4I)bvU6sqfR+r=?GOpRPW=eERzg@fqQh z6^9G};H7W+7t`>gTV=(E*lx6c8eLZ4$kCw;9KHbY7s03i^URP3AH#Zah60&JxfDNb4y!GXG;%DUrVNCm}RtO zyd~c<-7?!U-}0u#xy-W4vfi@AveUBPa@g{b<%H!6%Q?$M%QeeSmfM#5mPeMqESjI> zXY#Z91^I>fMfuhAOY*Dl*VwP6Uwgl$b=7)Bqo!||6(7vP#T=`(qiw>njNq_D)2GCJ-6d6dz z&>S)dJ|vF}rulR#8OD9ci*WC|$!K_zzsVTxNyc$cGFfaVb|#m^u1>KR`A+O3_8~XK zzT#l=i#S3YNq!Z_h-1ia;#hGk`CXhKP9T4XFN-ge2jV<&9(l-J&m(aaT+d^1i@2MV zh^Au zq(jmn`l6bpX4BDdaFb~cT-&R35_4_z6?Kuil+ICCs4M6j%)!xx%)!w`%)!yc%)vS7 zQs&|4GUnmvD(2znYUbhS8s_2XI_BZ%2Ik@DM&{w@d+=~q=nh-FEs=g^OR^==FKsEd z6ne&1&(@F@*_zmz&~I$bY|ZEe?(!~jmv@D`yldR$-R3Uu5qEjb{>yxxU}8Q`@L@hr zFk`R2MF?U(PpD@9#Qup;-G0LUnGnYOpHRd8x&4d~!Mval?b_TdIgss7Yw`VQGT)!3 zvHj`6+sztLS9P<`!GsoX_(VT8J|@)o%=nB{H&up=Si*zc|-(!tA} zzoMyg40A}7VV+?g^7)4O$R8OVk!U_N##m}BC9!;HjEP_aA8UKnHpg|j>kOaA=uu`Y zH&OdqS7x_3!G6^>uUoxD`$HC7A@-N-SMA>uV*kYNxqc7lVRoA6@xIC^d3i=BB&sW?dnz@! zj%QSJeU)K$eb(JUeV1hfsv;JfOsvZ?s>uq_wDBJ48KJ%dyZ7$qAnki)ARp)&k`bJ2 zBtAT5WOJ%)|3~x|3*yLsw)qje>+OtAPXFxe+Z}NOO&)1E} z9rGgD%JbbkKQNlL6!QESs@dcuj?!|;8J?f#`Q=G${_8xy!E=5}0A9g{5ML)RfF2$g zr8r{ol#D4jQRL7300*S8UPhj?0~bmRJon+b%5$0L3eSz zFC4w(lbOUh54*YLWF6Upqm2)+A2~_RVmES~+{9kw2`R-s*GvPj%S8;%r@)~hYLrSS zF(vK6OOtd$4wWa$XOt*qy7G}Ksa@6OkS}_wAL%2FZ9Qd2E_Z6|%HHGf#JJMau+>xE z^OR5Z(u8wB_RqB5Q*PELGHvygCq3m2&M|8GOYi5Cptt)ZdCDwLxzbaz`M`hbKPk9XDun>t}qu*gC^*vf8>Y$M{hQ{KJ9eWc8{xLDN=DeXYVpd+$PaoKUrGVpv zYRIeOz*6AHlY*Sa`(ZYm;E+bHw#SPm@XV#*K3U6Og1DF zYA7<`Y!ELO;9L=}Fi3<71d%u$x@Vd|{)AOpn4{F00+C8_HE~nL%V;phoC*#^;zE_|7!nw zSIu=FW7xjA>Rh3&A^n40gZlX}dvo2D)2}+M?mE{m*!507ACvuim>>Zr=;z88Q6~Eh zSR?@!>2_sfu&Yjg^u7ZlCBR7i>UlAwf0SguZ~ucmI@u}AFcOT@h3+JaMs#$qYp4~5T;Umk0PhyDOR_!RZA&bFP*_J6KM$ZZYBZx z(U5H(#L@lwprEc${bf zlpKS+HKsEInTG5gzlu=g-`*HiH814)4 zbR!Q19~@H+6&E1>yl-HJQMY=EwJs*7!Zu+Sw{?n@0rP%t@{i}1|9Ec4pCk1N1c+0% zKdkuY)s?tz4oanxDqG9ziYYh~sH z<7?rcgnwCMZH>QOmcfzX@s1IWmmG^7%N>UtUpu~aTzC8&X^iX?*(I`j*5MsQwO(@CnUa{_=@Z3;K;y?ZF9H1xvjk9)HCH-@Uy1Rnm=pxtgY+8;AHA> z)fh4kVAh78tU+q5cP$?h-6Fw}%s`K;vAlH(=EN(xH~ zN)DGCD*2$~K*{?h`%Ctg>?zq@va@9SliN?OKfLnr+lQAQUV3=(;f04^KRo~Ni-(^- zJpJ(Fhesane>msi?1y0wO74xjmwPYg-k5u%?`7T_c(3QZruQ1&6Yi1Xr^SC2mlQv7 z7C$O}Sp1;)kK*5p?-&1Ce6RR!@txvZ#W#z8DgL?mdhxa5tHtMvKPcW`yr+0a@uK2| z#cvcZD4tt9wRmE2Uh(+i+~T<6sA5NPaIsIZeE0U<3wOV{yYlY9J16gadS}|5sduK_ znS3Yz&ZIkecP8Ayee9hvcZT2Te5c)=R(G1*X>>=vJ@n-58MjB>?ti<_?Jl<)-MWA4 z$6K3jt-H1AR?f|#H;3FDeB-klM{gYXEHdZ&oU1wC=3L4t%GsZ@GpAur{hXwngq)b1 zs4ZxIB>xQ4T=D0k`x6%50is6Zvx_+ziR*k?tYIAU!~Og46=Hww@%nCB$iY6%BLnq8-Y4dXhV!1R%@nXzz#; zfLM|{qkKzGau<}#k=$tSigGp52Go0?+=TQl>itl@rzd$J%58dLN9~rKNV^cY$(g9^ zK{|o~Lr{K*^fBsVQ65J+iTZeypo}FP^b^Y$NVuAl^HG9I%T?5;qr8rUEsYF9tQ(O| zp*|la`dD$7CGRFA01G@oMIB=Tj80_L@$eH$h$5f?>bN`$fJg#BtpfH2fVzNQs6#{n zeUN~h5|0wd1>8e@Da!k}fXAfDM<}gG%~8LCvLzBYqT*d3<_OF|Jp?5X4}1-ECuAMC z5DC{_Y8#Xrk@lgEL4lAtOKKL%pY?=8V-nOJsRP=Fp#*1wrl3B8;LZan0QGSwgOH+8 zhiJp&kdjb;8)XU-*snrd;e#RnaE1}s6#g>ORMan^oS`T65=vmnl6o2CTBJ`<{}v_0 z68e`?>KGp}8|eeob5R~f0)j>;Vgz(10z?`2 zqXZEV-=TgC<@ZQ`K>kK_jCh3f1a(jrQG%qQevJ?yN*s{2@fVZ{NMN(c2PL@XcnNig z!U0)27Ng!B<=aThQ6GbHBhn$%AtJ|lq_0t*hZ0CQ0LL^Rr4!gVuH)f#l#nq?_%wk; z0&pbui17O`{79WpUx5-FV99h5B>=Kyf|w$EBVlqACXWOX(KbSS3@E|&=xW%YV9w|; zBus366J-oiO~~K843*kQiFn~gISFYp>QInqEGd@E>rjHtEScXyxj;{5$T%9*vSi+X zaxKzc)IoXlIV4=JnLj`Y?y+P(jPjPA%mw(OB?|J7ftH#J@sNcCwwaF-5)10%0MvXE zB_@l*drLMU@f1ly9Z1D1NZ^oV7D_V`#Ka6)d@Uq!$O7czp%*M!K1G>fwHfj zETk=NLY$~(CYa2k&dArit-c^l*$k6i~mVa_zHu>-$wcs z?ciqo143$+qh6PgT0pdx3Io&%r3uLg^)@J5B014$ZHLNSB*@R&0VROff=sQQP+~%s ztUXaaMS6xhr~o{Y0K}|)P=fjd$ky5qWwM^EqftU!2^-N4t|mY%3E-^tEtFWE37E^e z2J)|siE4-90qm|Ffds{{LN>LbP_;3+^<%_HSx6I5{{-brNH3%QAC%LO0K^KVOA67G z6$+gcg#;N|ucJ)Tll3P;x*bOXSFAr1vb8Nz2gu(RiAq-_$jOF5TYDgZS{vlK6$oqv zRW`_U>oBD8sMkRWZQcq>Y>iPuTwAd+Y|RPT294hqgnCPq)saAuEdym75-7D{zHKQ; zEl?kbvb_^o7d+&k?2d%awmg)xksuP=M3iqJy@~o1lwkihP+*%*ND1_SC43n~&`h2| z&NhsD=8qJN`T~^UNKH}4_-8gze3xMmW%`jS{tv13N-_zzE8mkB$;&>|ectd{AolTj7pGJ+#b#tX zIZ9q7!^wD`Wwejaai3Xa9C^iLB*VxY@)~jDfGQBTNB_l##*rCNE7cV1YI!lZR;<{7J&}C&4u^=5 z<-e#q}#Z}baHulxeKw?eRZro4!bgpx38+wKCZHTtylX4 zbx39VYOnVDYWK=^_raLU%Y;zC*~s9KbOaeD4hJTL!Ev3x5)^7*TjezyuD^CKyNb7K z#3mJkMJpei=oy^CUa$3f9mQemuidV!t0kfK)sn_X_bUHIe#%GJ zYeuR5daY|Cd%e2KYlfNr+I{f+wKW1`;8Q;QWz7BopS_`nf!^(GTD^U3mHuo#z1{6; ze-#WG&F8_|VGKHW_Im~2JgjnEEUqcwI9n@DYG~gecc7E)3OhFgQ-_rQB6U`*)_7qp z6p^4EO9}0LfzuL|!A3vKwazu-UQ(!io%AC|8N-ytN&sHN^5XT%gS+p2LE&Gk*mGE1AHZ<$Enqfe%3m*zojiIfz zzS1cVdW&3Je#4-(?jK@t9c5p8Q20Gm5bUd6H69FM!)HAhA=o##Zaz54UhaH2g+fB& zn{*05CiB?RZoKBENS^~!^59?u6kt6WikV$yX7U;i@% zpw_!K|2IjnZ#?+Te-Gesm23V}_SSX(Dacsm3VMc@YhCT1@y6ZHhA@6PIlo{O#jh2{ zPS|C}FIPr3!+^an07oPGjUcTq98Ac)M z?Kt>UAcD!zki%+Y7>oXVp6%|uFbeJ7LrOVQ_4h3+-|um6dH;O;4)^&md|_yR z&;1vNvyJ@D=jj7DE0l-87e*H>+E&mqoF0Y{*17+x!4O&}i=3B`qI8R^CR`6wO?S%( zn#cMbh@guhh=SG*s$k$6cjri2KheHQnM|jE5>e!GXCAKMU#fvchhB@ ze{3ahQhtFPdU3YwCJVLwm_fH)8JI!0J{#nCnvZtYe*vGF^;d+olepgK{S8ej`)@0l znLuBzULP(sou*P%2@YyP)##}Bxb$2aRH)qx4-X3;Q#Ydhq2?`W&6bxx&0W5_Zpyl> zEQB`&5$)*@btrLbljwhwBcL!Gh9=0h$P}fcRTb8hj`p;@BeyMQRzellmLh1u;LOR? zD%s1+%X(@Hw07ma*{f$kf43=^KaIXD8ToYZUJ(V#EEBWMyvvit}lA0DAgpYpGrP!Eg$KQMR9RF?v zwS7<3-88E(gVGrZ%mkauS zO&8i2A~$Z}IvbR^Ti>DG(coUjOSk*R9kvAAZu?!mY<(A~Xo!&#R?iDZYiDoAZN^&oCo5f(##HR4)1DTH#Y%cAKRkKo#jVP1~@g^ z-=3Zp=?D%IRUJ%}s`$~!dcl=&Ba4d;HQKY6R;R&JCO7seQULkHXMkKo=)a;{_X@aW z+r=$32B4Q|R~tDVjLFFv^WdF9gFH~7s{*bdi84}tgu@BM-_)7<97t^{M*Byy)tBbM zhWay_fec%ksj^=OFHjx&7xmW?zMR>&cHP~Fs6VX^j%ZKQJRFG%k88b6m{WW*mMIK3OtGW1hI~x76474+IA&`i2 zgR~U~fRUsQwkolaG3kK7&0ZQwWm+ImFHHPX?G6YeKF+}q!L_j;4H(%lqW6rSMvqCV zL)+h=hQZ@rnV{YB!mL57qC3=jG9sc`Gws2!VG$Agem);>OL~35ueWK?>3iA^?LXRo z8H!G5Bffs^dUW%q!9#`&-n5xvNJ*n|13tjL#7?kctEeHCM%Cvy`r3+a8BtvC>+~$! zPos)D>ME&osYluNeHCJmFKLS^>N=b>CjbqD+#Og2|6>uT-ZDu$)M)P>tN{NR`4ubR z)R=Kei#;+i2F54#^r-)0?UJtkxxbagR4h8idMrC-3Evw4!CW-Gmew;YT}5fp|z2)3^dZH)E<8P1_Xp|KL0g0ARl&Q*xWuCq5lNHhEML)S-!U#0to&OFgza zUwl;dm`w=f6OUp-gayW`Mvw||<>X%qCtrGctpYO)!+(^-z^vE9Lv=ieg10f}3#~eh z1YW74==^+adbOyjvzw+?f30X?!t1%;obHj?zPom|pa`1WNy;kwR=d@_U%xI3g#Bgd zmtGk*EDv9ixk@vbE;Et*h^_2-Xis@3d`u>y~y}JGI=^w%zY9uISz!CWfoCwEww$dX(+`dF|%(wCrKDaO0-5w4np# zxSzEx+J0YNH>m;;d%2q7NptLtKJ4p^@oED%GHA z`1;i0Wg|+zj}q@|`@z7yrHRf8RQHL;@rfS(6N#hzg0u|gF&?Y533JQ3X@qX4{mW2d z^#(z`*&>dOW2=*Zt(C?yScsY4cXyk?Aq~DbFlEiAh7rAH{xo`Y9goo*KP&%^Gp=?< z@|vKP zDxU5s8JgA+;sy_{Fr(NiQSwu{L5b6iTV#bN_3~mq@N~{f4=>(e(Zq>UV{((36XTXH zG=EYfR|nm$2Qcea)r-NEmic&FxB2Balxh%#h5PpBE{u85$msOc^yV}*QjKJWfe8w0 z)0xf{z+VuUFFWz+xUne_EPyF9ABZ|2M%`E;Mn{#Id$wvApd0lSMZO2W*6vK6)ClHb zmA+~>!H4V%*mZbc-Gs3aXBlljV#RWN$^#C-#j5^52sQ%C@PC9?PH%;g*SeUE`ge3i z?Ow}3jw|!wcIhASRfQ&TrDR)^*TH(6EmG(Mi>;WBs6nihpz`UdP!>nJlPgPfWO^jC zk{%~ZrLeu5XfO?U^^LG10sXa=IYX;SyOw12@1M0~_MicdsNuu+{dsp%e#z$U-MV$(yscZe4Xs+`52%}x zQoA!#bV`nw|Ke0yf<1@dV3$fz;SnV}!`ji%ex^MKDF=ILG74KQ?bJyOZaU*`()auP+$BwPr zwEhJhxF_;u{vy@i>G88ZG`eDisA3I|0}ZVVvUzN`-{Tyi_NAHnQeZBVQ?#1E@3Oz&r zv$x*=9VA9LY2f)qA;T@^1U*oUoW1D!^_`2U^p7}^hl%feb|UfPZ;!QPf#S~mSx_Vv zPW}Ic?JzPG!PNf<+nt_ZqcUjvpK-faWQ53_?PvMHrhEwpE!gn_kq0ofHL;Q$xNY;- zO3|YBO3;eKzS+F|n zkd6M+Zs}%=8S-c*ai|27yT{5^iTtn{q}2b@f;n$YidDZd)E>EdMtZ|)VSC>dYU)N$ z+x)yuw1nT`XMmpD`rhP89vFGBjl2;)oTKZtP?1N2nm* zX7U#i$76+zfFjlbw`#M90ozst#LU5ADZ++wXIHU%`P?X>xedW-@ zBg419`|FblQ^UfyuX$3^D1kol@;;gw`(DR$mn;-6%o%RAcj>Y4_1xh$TbEw=LqEfc zNqKqG-(E32uXkl&%67mWS1nwpt(x~4+^jXFZJo^q^=;mUQN$0^xI*Eq22qd^3YLv1 z$Uyu_UC<;lIfH#{PtN2Hlp}PtfLn#1h))Lz!TugiNUf&|+ec37H8v!uVY>FHi@9Ng zhLK_Zbsc{vUF+K~CSlul?M}|bNiREVj-Sw~W$vNQy&@BalCs)rgKM}tp`@csmiJKwNiG_)ZVm@YS2D?R)1AU_B2)f>Z{CJ(!&eAsiRce zNe$E2zbVjzI18pE8c41Jk_skFVY^^8nuhHBN|+rkJrwF|!`Nq(8_I90`14u!&i1rU ztxL*26E$peZxscprdxuGPiZXT} zr>~ycS(*W`La$SsbC&nWqy~z!cE-4lKw!di!aU^oR}dHNp9;d9jIwMFqj%vY-_Jqc zj3eNYhcL|tQ%fB=b!7{rERaUYt5_h%l>kz$VvB%)Nhe1M3`pgXlo%~$?6~u3*SfYV zg?)rak!6-)=F_XrM>q;+74H6WYS&{gNCUO5J2f9?i`289ZhEh53S(I=V4VQQ0s3i_ z3WvhX2tL{*%&35AEM|JX&kzq?a%hwCyAK;Sv*>tzu%>8cMn-&OVd?0a&A`a9IW^;( zfs;8o+FzT6UL#WK(zaj^7*sc9#Llw+6y;Bv#n zy8*rn5F0z^L?kE8Trp;}V>i^Qv@cVtzNaUD+OE+&uS`;AmsCw4}~Y`eiu zjO;dS*o?EsQ1JsT5;hlKQ;K_lE7g6(g1?i?>9bN&>S#w(_sV4?Pr_Se2m z12<8j_UM^2x=-2n_De4{Wxq(dBK_h_9$Xp>^%fd9sFe+0ld?9eyMSP7BL&Wbq3C=tsF|BJ^HkQP(Ey9dv z8v%o@3a~W>K>WBjsyq~iFyWO%J^o;~H?XY{6qx#R@5_uW_r{`W(0jddVi=eAOmAin zuoR?OY<^u^)OAI5OHrJPu_1jsQu|^;V0Fi)cW;zrW!0~c4iYGg343;G#3BysGOO& zWmgKn<+}cjV`iatp)kMi@L`ibb$0DWk4gid?b*;HgAx6AiO_dcy}DDUGSAFz1sC8( zS|MF3I3e``5MLI1Ry768A!93}A5*|!=#H#51z_-r`7?IK#Um4%;AI`0Y$*sSqwD82 z$}Nnnup}EdoatvawwcnrT1cR!c3}gfs9LJK(jCEmJ{9YMuL?RgyvKI!yRu8$D~-$M zcble#hv#)@&?Cj7`Xxqo!51aW6idrJrWgWxuAu(T=f*%<4r6wy!W?ib?6Cxgp>a}2 z-578y%xys_Znv0zEQ5XofGaida}rGdD~@VfVE>JyhqUw@bx#CDfq zAvt^G6h<;heAc;Zq9ys&L6Ik?Z=q37qkjCdWAhh28{DpJ&5~rlh~&D{R(#_yN7ZOM zR&bR4w3~@&#?4NTKHWJZduP(VMw4o#e71Dwp_0yjcy` znewO^TIMk|4-6tNGwpsutakx?eLWR91|2alo}lNBmQ! zLBiIuY_37n?H}X_{wOcy)ucN6j6T5;36GP5YX+3g<0wxB!*GpWP3ud4ma^;${TtT+ zz_b9Eo&ct>+*E0T69HznnEF1)NIw%`YmVQP(#h55KCVDDEq8moxo;7?+MoA+$MAVk2r4byU@GF?Bo7{j?L{N!v?k& z_RMxBh7A}p{N0PYTDJUt8K+!dQPK>osGf}Q@-0qSxs|YTI5hGC4l>!{&2us7#)TP{ zWi~}grN29XKw=HEIf<^0^Y!a6xoLpv=zMun)W|F!V?tifz~HpQwn(6o+`LsX-BYt^ zyW#Kl9$B;A^nJ8(Qj@iL<0s?mEXH|xgVtAl&Aq)njd4D=72>EtJwcK*>+6_20lZGBUSmM7v=L34w+rwwhL-fV zS#{ngwn}ewmEL@#{k!8{+%t|4$kiiJyYy%iL7A}LJ0xSal7F(nbeetA!4@AP z1ZEXNsxCfk$ScAsnB?cH?0li-+`ywLZkDU8DJl7{o0}`lvOYOZ7wdq61VBOZmN26t=F$Cg*1Kg3 zJPXLP+=sH;#L7VHe|UcnX8-j5l`&Qo=kNU96J;@W@{g4GLV>ivPWC0i3wksV%Y1Aq zF1F*M%A&3n?%RiEohwk~I$*iZ74d&@MGt72OrOXjv`-+P2}$BQpa>j%T_9EF%d*+*MydMb8kc@MQV|!{*G`10J@ zsQsmVgy33xvU2}^v6db=^4wjwfCk``Ntj+~mXd(LwGKPKkrAcDSJ^+Or(qe22=@8e zVKhQo<}Ue)43b4X=!v6;+76xWjH!L9{qVUz^zQ8lpa0V88MWJnw~0E^y}bw;Pv2@!089X^cc6iS76>ttuW=XxoN3iUIVYdh3B z!*YMsu8kR}jhEk|k&{FrJfq2^#xW&juh#DL$-&MrBy3&5RgC%{>x!|mLg%Z5I)!`{ zbNArnzRD}w!OqR&mjwKUCZQ!_FYMG+e3gUn9ny;4ccJcu_mDJA?4{{iHk)n{>j=N$ zulU&ER6Y219I7C~p@XWApKvYWhYcHN`fQ`Z@DSQ+bGw}z`auzdaIK9<%P+W3hYPih z0oqOWNr-H5KMfb&Rqb=}rI2iQZ>b@?7ZJ?&^i8zt;*Rp~t?{zGTp@2-<7E3UB^Y5Z z7#$%DqE39DEPV*AM{jm$uBiUe_(M|coc--->0+vXbDA!Rh0*mdcfWj9`@ZF@T1kcV z8l3IC>*`;f=GKz34rq^$L}`tMKDK!mf29Jo?5#zol|8k*fiHKfjVvj{cFvCGi=%Q?#Y4Xnx9wGHeVGQ2ty_= zi(zw($;oY6_5cZNtYyN784QMX#gKp{NvcsV`ceak~K{Hx-?n*n!`q1 z#<(;Gz(qz&B*Y2+RHcY2M`j%nCLNh!XB3HH^eLlASXeg2n;HffbFqkp9pgme%mANk z9ldrG&x}fjmFSNLAM8|s5aI=X^1CBU=pHt4a@>rgGwSzcXstX^wm_IheY@xra^!G# z2-I}67(tvns`%fdI!+%SJ95o~73XhhvXnL5$#~2FZ^J>rWdL^I0al*flptzilT|WW z71#$HxKg1BM@NT*r|o+8a*DlL(#!M0=6#mg)c%qtX@3lF8iecKdov1BhkWttptTLh zELk*gX-0P0j->-uW=;g08TjF^gF5x#VXBihI6CVny(}zbNPGi}g6m>-X#FUZuHDVm9$}*Ax?^BxbE#Y`ASV`E2Qb$e z9ofwzl__P3LfTNSKKQY?>76d*mTg`_?=c!VLVP)W1PViekREHK>yzMEg{cW!ufb{J zG}ns}5QgaIZ)K)8>0?2OS%Gg#D<9w|gI)R%`XV|qWOY+)Gv zs8aJeDQtd$?1s&4iaG53TnJaEk&q88fmSxc7m!nnKx1qG>WP89qKo{e&dv*jT>}-@yD6_t}TvQ z)zf-nZjV1+p$Y%hE^80={hHUjZnMbuqe7(^&MhiH3wL2seBx87u&NSJ@dYNkeq_rK z96IMw-;a~zc6oimdafAX)7Xwabuw;MsPcnq?dmOQmNcbiT{?ovA1i_xo_qjc7r~XB zszsTCv!hM6I;+B?@$8R%r}eR>X&cIkHam>g|K(|2YqQK7Gm@pYU0<#~`K9r_AmF!0 zZtl=ad*IZ5T3qmJ_ZHKd4}K0Eu*d}t&J=$n$ zU{cHJWqZSf)o6(WOC6c2^fp09MPD_bSf1ZC5!w}lhp~<_K_E)sF4EGn->z#*z`|`{ z;Z^{^*=!_MH{7Raq1+l{JIibwQ!J_a(HU_)=W8Vs623SzBCPGip^gb3g$c8`_nCHL zW!b6A$CqSp6`H^WLZetb44o2R#+S5l_{z5diymsxmHfqw$`^HbR8iSZFN-kC7@)V; zaa(H%8MY4EZE3F(&!Zd%He>bNd9{Q<{xKK}`LM9!VJa)GTzuFbjNiT7>GoAOt!VI9 zgQshgHM*$&i27d-8(AZybEm2En>7iITDJUQ+6X$c>(mb20{oja_;K*6K7B$$nm3c) z(5BFZWp}hl`eWJKawzrH9t*wtteM)OgFUSOfY)P z#!aTrXw2@n3akmjCYy1Xbn#ga5IxL&w2APYaT<98v?}uOg7r;>2+25J!1X?!#}}M# zDSRT*+=BUS1*cN*u!|5v-EtSn z2k9mL8FxAYb?frAzOy#U|v?q3D)4c;H~$Pd&E z69A)u0WQd!DZC?O=nO8AUtrxhBbRwGvP9H}18wCuFZxTQW);&Kn(}roSh>WV=@cTV z%5*1QRdq=2-A0}7)u#Lw@R`ii2ETL8(DA5^-pg`s#x#)rP3C z&zYsj9<|x%Q3Ei`y?C||?BqgJRBxeUSf$VvAP8P^t$NN&#o*mv=OxoWtD+cqeOCBjdD+%BMeuuec-G8`WzuU9f1IQkp0+#Ex!%14dG(b+ugF2t#-Yg zi;cH~|M_!;Y$vwzd~lAw+Hn$t51Fj-ii6H&{M1)3`~FKg!uY8;Sbu0b+?7t2@|FCk zV)ZIfY!upSK+H$b&iIU;kP9%b=cwzM|ZE+gfxGoDk=f0bct0_iEQuw zRa7FI_y3nl4EGjs6_o&|bO2RUVuW}9Dg@|D__<2(nLR2&D^+6PTf#m%)oofVG*O`u zTzXv>3ymVC>kslXZu@UxP5#0cwBGJ^Z&@rvI$!yx^z?P2OrhaSN}lz02ZKLjYOhRT z{UMW3ofb&L$!JujR`CfePSSk>#|ZtO`vfOwtdQQc3LDP{c!<|+JdCU^ZjMmJfawe^ zcq~Q@Lx`ydP=PvuDvx?J_X04(yT50Cy+3vn=+A7t{0gItQHoXdipS|xP{07_2!T@` zgkJFiFw47t6#{1Q{*yiP$Llj!O0OY)9)67cV?pb;1%Ld$y}R#HVTtNGrHk+WQsK3T z6$~FlnDfe;0xrl_R>*zdFTx0A4U|p{rd{R&xMs zqDYRljwt>v&n3J{=~j2=6$n+f>e#zKSRo9K*#3XetGBz|DJzA+&RtdM#n0UI_riZm z1-)>rH_;As7^TpTEfw?{-ty|d)q_6zsMkFG>+=4u?Ox641SNbD<8A|a+z3Kfv2*`tN$mSWz`VmHI zf>Ry}*wWAu0;hBU@^UW#r@Z@DApkR=|76U==8sqS%$0`ZH5ig@%#f@V@Cp1?T?+0V z?+EW#?)wevg+tEo^*8d!3QM7|2rXW@!lK|xLq8kd(#_g|?eCl&S9EM)L3(?+>8qaD z`N_Zf0|Q1K>+eO~HK+Fg4|zI(YZU_wKZ*sFrsX?Y#@k!Nq>W+i%6E(aENG8B(f*^? z%DL{{-=o;*33*=U^9*9PvDgd1_nrZ19sr=2O^pHIlum)6*bBf9-ue)nu5 z20{MUS-Zm621eljYvIu&gmcgPKX|@!lv=z$#|ZsrKkx4)nTK90N2%qJ47!354=V?} z;RWE42O&_y5n`$WRL~z(>57ftFn;diAA9%r%&+%<%=@#Iqa=C(_|roH)(NM80niZw zr*r^Hq8ES?@BUQ?DB=Ald*+W<_{?4_XRYuzV(Px{3iSlJykOzGLMo-cZhRazT=g7T zxNE*A3|4VU%w_uKd%}CF-Sg0Jt1uvPE~kKxw=VNX9=WP<7~Qhm42uAD|PcA0ViXf_poJWHBPn zGd`K?8Gd?4&SIxjYP<(X!#%<&HNo>B?G?Umgg-9j5IuW)%)G@5VjYjnhJkfodmyq6 zq@va-u3NDbOB$2*-NE` zIN*6Zw?Zvh3#P|=NSOC$V3k%?+p$(_W9t&HwEkE7YTmz1)%KP!LpS({M4jC^+Jo5-KLS1YVw22_p{lnJ@ovYg741VS+5zo9^3BTj zECFi6<^eg)y!vN9Z#S;+>OVZ>`9#JQUIRuHBp$-S5BuFh&hjgVg#l_W&qKokXl@_R z!@2_DXSKiQVP2u|!tjCm1CC|#apW)xhxzzpU4l@TrbnyMDlQZ84S#wh{-96@t$n8U zmyR#H2v5t>&j?>emMIBeI;1~;`e}u@}e$T}%j2u1(SG!Do?t-RAgl>XUmw9u> zXq|b+yIkg(>{lfrb1+eF_ocjjhyhxI_KfH4TvS7=wwM26Dgu+@l`Q#h@BZb#_%!1E zv-S3R6%&>JVqVGz4FBgu=B0eVh>G@t#vcivndrO%?X+;---)06=tfA{2#yan2114~ z2fro)yW(jZUj9IMCQO1QK=4q}hT94|Z-X84w3*9o!ZmRM`oX7r+WM8-#9F-HX}t}* zeb(>4!W`UW!Z5_RyL~5&48fo;DhA=U&?bfm`Dpvnedar11AWJxb6x0CFyMPZl3QQ` zVI937`{C|`T@R~~Ed+dg!@p`s^{4CX+Ch7)9sf_EoW41%KB2GpXJ+QH%uKCaW+wfx zVB-y({<70Nnp)R=wpbV};CiCwJ;5Oc;dg`f&`J38E0!~(Gp^+isNLN|eiNqi-@W-w zsO{{IUnbcgmGN#cK#(ndEJn^{j!*x+C!tWj#($nBU0a~Dni(KjzWg5a=)dED zwvJD4Er8D-k9Nx2J5zD9%k%R`>vIL2>7j{U1W!L3}7JoDzA6CQ}AA}?{s(k zL%>f6t#=>&LueiY;-}Dj0Mk$T7C{j%uw{WC(q=@iC39&Dci01=DSFB^dC%G$d`B$8 z1)NP?^q%Dzw0XhI2Lk>NPxkHZ*$;)FMEmyg&RT&7na}l~9g=SFU#Uu}oaC10=ZH=` z6kelG+#MeY={`@i1!8Blt~Jik$i489FolUrcr37=+mc`9NTgJZS6lEO_Tg3qKPB|k z-RrT?oc*>|2$v}~Jb=%U_58NhZ1?WR!p>0peu|aPh)zkm@&w0P^ztzgNR;`Sd))rQ#R!tU5e+*#=Lq5hgK0_ad#Zc~K2qDB>HH;=J z!;m)VLl~bSJ|USD!#+&d_xC*KecyNY?w@=fzsDZW_r33PUjNSPocDRZ@B8ka z_foswvDU5n%c_6MSE1{lkjIDWZ*?bx>Ywm!r9Lfgoy_Hb&9r^T7WdFl{W_Ki`lpo> z$G?MZkNepe=cOx3b=$b$V4(2-uZ|76ZKnmh;x6rvj&;1FrU2w`(()5^Ic+r8Yx&cW zXOSaL>#BW>TgN-;p4*M#{>mAp#9NIQxH8sAMe>R54>YS)LhsXId`9IgU z`)6Yod3V%lUz{+pIg~?5XkTYozIF)TslOOU^<$m5vsrG6*nBI0F|xdIPphBZ1U2q; z?IH_G!yWguSmwWl@@PCU;B;&Lqda)5nQJKJ+Jomp9rY^lsJ6ptfrZ~J`73oq+>P0?CUap7^N&W1iuF$$;ne*DciN@cA@ z$H>QGGXA#eIW5Qau|BwN_MQ5>ag~bxarRCnC=ReSL>fA(6@?Epi|A4kvxc@<} zR@J`xyJ5=xn5E>jV0+)?@GEXN4w2rtXGD_@j8(v#&$`~AIdlR^e@0yFzY|0E5y&3T z5tJwE@@K`@wmd6vb;>{6DepSWb52OUF3kQju9lGfI&lH^57iEwBRyw@6rSr;aIAKH z6;gQ4H`{N_^2R+c+Cu@n;`%XE|GZf0FAD{%<~l3j4T7^M{Y3*ESBJ@O5I2X(-w~3p z-raR9ELj6mHxXZXK*qLt4xmxX8L_w-f@r4v?c$ns8T(n%c9A=Q;y&e4{gMDLi-oCiCyZ_V{l#^tYL6y%seWFu`L!@RKh~nzzs# zo>^tP`%*W@n)99!D|K^DrJ29$=8U(RBe~YFn$Is%)WEUipB0bj<{mux{ zfn&+niRF6W1XpBJ1IJQ$E;xOVU&n{KIhMk6zWIiktq#bi43h(MrSDV2WR0yAzN1X@ zB~|V>t@3dWtNbqgy3+TZ!@Nt$-QYA2@)G(Lfv=qhyUveEiCS04!Di0nSW`{vEdL^> zd-+8%sZq5&PbXLtl2_&RqO`~Ix^Cs(G=3qP8uhxU=&Ha`o)Y!K)!iKH@;7FLm0Jfh z4M>ez7Z|1O=?{*+uVOx{Stgqb*NmR?% zeU~Vy7XqhPMh;im>5tSrH5Em@;d_YxOCGjP$HeH-$vc_uiq=W}!uPJKu1!)QhgTni zkCdo-pI=qio!qthQ(gVKZ=A;*dc->ajrew(hp3Z)cEGE%S~vQOZgn)!y&>4Z8$9Oz z6RidwVp#W=FQwYbdtKl(%dGk@R&DlS>I$^#>%MnU^{(Sl&?>YObafFE^COm56-h*S zrR7nSbSZyCH>6&VEv$s>{G{dWF%h!woMO2boK#}?5fcp?}BS@K+K#T;0Os@qI6s)KcpQ0KMc_W7ge06SA@#)O~< znerTNg&Md#s6H=P_a#}JW<~2esUJh=4c{fa3|ki%tYft1jNABZa-@|^-$VV>7zw0? zRdW$zo~0es``%U6b-@8>Y5#-jH!c4@zp8$rt8w!m!SOk+f7lQjrxI%qA>&^WLug!R zc##~(E^WQmcSHZs5E^IHX;sqeuwt_lGtS_)g03SmtnH}}Yu~%5$`^dQdGWpxI7z2z zocaebEve?TTM2-fr&x_824k1LCs`i+F}Y7TGLTUMKW0|$mi zz!7GG_N|8hLlI#gVcJbRl)KI+(!E)v9-p%|k8AQr+>0EY~L%NfUc0 zukXQ*lCP7MJ<7i>?@;C5aL3kRDgUplf)#IsgD6rkLh~?vnyxh7HD~wD))+;sMx8KvsQBF5yx&-5vZs90Nsge z#kacLqYd?^+&WROmFkkp6-Bqw0cycheJV4D1TuB`kY37%hRQ2lUWQvp!8#HwL*eDa zLJImE7m~L=Vj*vx<3i=!X$}UYPjR90#8A0D#i?>Vi$!raS`8smXPx6%e^$5PKwbW* zPN}*cS}VD_rNtw3Ib9Gu;jK0GIW#Ism(vCMWQV+|PwG)4ZTlW!W!lu&RZ;3;6gcLm znZZ-vTAskF98gX9m;BDnI_<4BI2BT!tjn7ypKEoEVKrd1F2937^+aF}u@3ks&Jft? zUT)o7q}+>wPIXX$yB;Bh@NzEIdMxMSxyN$ryr3PcKtlo1JX>Cud+kU$J5v!w3#=Jp zt-6^)i_g&I{J<_aL#&lGy8KLCuDZaQ9oCvvx;#&pt1h@KnCkVqoCy&7my$VamRQRT zM(iIS#V2ek)URW$DPpZUCF7V+)Re0(=od`2x+CO@A}q>P7aSKXzgw4|>svY4oXI~D zH4QeW9sYzq(S|Pl8KMWfCdZ_hL)4|edPa=0VqH-yE8ILgb%=Qw)6L=`X6mru6kw(( zDY@J6syUXa!4{d4cb!q2|%@3EvIu@%%j%*hkEz^L5L&`<@zV z9*W5wyqvyP1XP$NAJdTfFUx-c5REKkR0{*x8RwkIKhd&WO4iBM=G4oEHpz1(+Sovfwvr>Xh{xLx}`JiFup;Na@ z<~!o}!rvB*BOQNBtvJrpH39DCl8)|ieBrx&n2zJEVP+~<*e_~-)`%L(wDh)hZV}If zl^5$v0lFmWiBuJJ_%*;a#Fr9PJv_XeGX%GZbXReIa{(Gh=uBGWhsUIfD@2JrGREaA z9B#&{jvP+%zwkXZob%0g-&?~8@Dg9Y{dIpGzd!x8L+gLU<;uihe_gk~?yoiKWv%c1 z{mm!jPqjBBn$!EG4wCBgwX5GCt>kdzI}*7Am)dWT!GMoRQRUpHALMIEF~=S}Bq(f6 zz;y`g|6J{7m8bR_qLp0zhSVOFYJT8wGd*ECsWu_aTp@>ACNXW6hMTT!7|R`0Z{Wkg z55_;tIe42LxFL8KpHqx6%bd>hFRr)C0u7Yir{q|RFDMsy7~Ly$*@95n`^Y_{bo-qY zDl0?oTwQi@sB8yii%qX`oNE`V|E4t_(}JhiWr61qyg>(eYN+fL$_jMZX?B_VX@OZ| z{2O~rO2LNQCNs?%>7$I%W0#57k&B{?xyTzVydrS1Y%?#SkclW*HjuIhbQygTEX&}# zk#*|(5;q@(f@QNP+o8*z4V4{B*}ruegEuIbNr0!Q??#NrLS_ArL2$bke6DuNWOIN= z|5rX=3#cD{sns9kNI7!wNPcq3kIqI-{B+^l*PAhNK>Kd_PDiV8=`S7CcfNhkl}sYn zcidqt=(zdHjs)YQj)RSsE7fmq2;5nKt)cAbA6VkIq{l~d*rw0o_Oia z7oAx9)6wQFPT#~?X4xpC<8$XMakeW)|2T!OS=^&WgWvPc!Eei_-cEhn6;s))v!1h(+HbTk?Q-V4(Z1Qdc!SSd>34GQc`JMs$&e|)vHHp^`L(%^>=kf;|)2;4F)jW7U;*hHOzoruMFJLX&|J3YS;r~toq0R?RsTj z*K7OJJ6mWAsLwr?0O#tk0PK1Ka6K9dz};_jZFQl!pR@LatIfOOr}d-5(_-A}`Ca~P zdXBj!@SE#M=gyea{!yxgy8dcf(RK3z6|P+8JnE3wdi`pL-@&i+MrR=K60&M?JjRk0 z16{d}Uyx-y>$-`xS1vV24T$O=v>R3X&uayBHdnj6Q{}Pp?wHi*sYa{+<`{SM)WAdjo3-w>;vL6B4(3T! zX3Ox3j660d^N4sy7CE+SnKy#^Z^&ic^{KOc*!Hkvv?fR{00{JBW32NN$0ac-{cl(4 zik|ALdCr_UZK`9OOjeqXvHml)7r(V1=wRQagq5;*SSurE#9Q^oAYH${cG7zD+I|vq zFPTG+Q`Ijh>&BptjVNvxPUlWXKsy-M@lOtyB)|3^XqPWg{~`4|g7t@>8LIciylf5| zJvFdb+@^E3*Z-Z4KKylU_FW8!PXs{o5XM^+4}b;@0K@IB$Bb?+|RK;o~-f|%0J>Z z`WvDK5t# z)&xqAH5T+_$~C6_jQK}&bogh4Oc|HHa+#xFt?fzEg9>y{Y%r zQJl)J{akTx>3u%1I+`8Vvi~pNO9LG5dtHOotyDQ`V$7g8e&%QzvGS_dDmJdEXn4Te z(Z1UlBEK@yrRl%aKhQtN&u2y{YC78GRV)?31>m3wv7>5Ud(Cyoubh^3oj=~pb&b_F z2P>1Kl*x(mD(?dg6>BzDxW?}0m*sOXb}37brAzNu#*p1XqbORzOpGxNb3)vpxY)tQ zok2xnk?pct{wVMFcXVv^5AWEm^o%<@+R;0N2N=^kqhiy|Tpf)^J&L_1ESL#{mC;ek zsBx#=K-XCB?vCBq+UoC+_hY+Sws!^-ua+2-qhi(R@v7I13je5%c2B}<`;>t+t*cbY zr`*+%?@DWX;x$h~FiSdUWuMg^V@FOLNlgAxMny-v`}Eg-ZP7xZmXT&jnu*%Zv)wYw z$pmG9+Kzm=%a!(P3jrFdJ9azs___N4-GB_Ww%cH}?%QDV+>Mue*ULfvuP>Z&M8|Gd zT;fM79;&(MjFq&iim1+YrTHF;ag6Y0jk$2+WheOmV7)$(d)dYd#~AS=v&#HGceEJM zvfp{r9P-7P=gEFXbVrN-=Q18yY^>(r1oB)*X`iub$pPh(UxCM(=N>WRLOIO;-}T*voG}`>Tlg z1}k2BR#}?BdOxmFWRjIkCK{_%mi+&f!^jdLH;0lWpY{uV)T(G>Cve=q;TN7UzczAV z$#-Y9qvIUulK*w7{a}#emNc1Ddv>;?R?6JkxMLjW8G~nXXK9o=5S>@}g=>myOpJTL zX}()#I1clkZF2KjRR#7K@n)Q^;?YPMRT87>rNQZWAlFCE=wN-3`gfLK zJ>|MST)(G!rElBU^$N^l@LnxkuG^fii`paab6hC7 z5#w6yY-FY!%>ON=s;8z6iV-7|M6BKpiWf;@Vg?(T!n8Ho!A#1c#*g%fC7dGKc=F|_IA`*pR3p_z)M|Kp=yiZmPJvBe@ zAEV6UUFva_-q!JotK?3%^XA)m&{AZU)BXQWs zNK5>9g{H@g;9UIL@E1R1uS2s3(``~xq%h~?*-~X`khB$xQLVrNY zh0+tly!Es{;Oz7n?^W(5YS*K=(qTm^1|mQA*C(n8u@eT5iX9>^u$`JC*7|F{=kXOd z^|#6x_`hNdLDT`@z4I3`arcmjuB9&%zT zP8~xfOGL!FW7Rs6=H4Rz8){KlIdj2P{RdZlWBhl`8l!5BY~T?j{yUe-@9y@O@o$Od z#H;#UQRLrPbfr;LB(plUS5`jut-1U0HL-t}bMNxU-z^vTAD#cDb)J>ndUSrofw({U zo;ZF|MoMkoDu>6N!w|oTV(yekP78x4xVgMgml!O{!M^i`j`z*+QkMAxW$mwBYG!r3 zZ@l5mF1uKEWE$!IfZFQvvf7$Q9ShP=R+E~Z?2H@j$;>=1IGO25u1mR^Lwb_8%1^E> z`oQtB(_J1|?po&j$T#I<$64Njx#LEjFzcFArccWleNSraLZ@?KZ0bFuGp5bRy=K-4 zBga|Qxih*}Pd`Of%S3;P{|8o!Dv|s7cU^ebg%{pMUe*j8d0G1OyE2c7J?s3LDYH{% z<)0OM%n^4^Km4+!{T_3<9@{VJvcsp}nK?c7to%{4sGoVhRiFNkq=9Svj0pdY+Nif! z8N9G|;tt14E^i(qJc;!uCyME62~lZ{?V&7z7BRj@l5Rc5^?~44OUtOS$pYoEBV$w4 zih$O^F&TZmC?mTvPaOm+7A;y8b|Cm~P{Yzu-}1=xBbSy=_8$F6OUHS67s|z#{Cwmz zb?_WD`4*Xa)m2v+@%k{CH7oK!u@4qwU}f{5hjx5)PfVkK)7XCgHtC5nZy%%%u$blB zKJgEq|LE!~uUyStd?v}K{a1SUO#!Q}jHRJ7#B9}2wPachD;f?}3uvTBSE~9L!Ji)O z6zkz08t{794~f8UWnV)j&rRtz) zZnh5!S!x{?%lu_ihZoL}7yseiz5ikQAac5j(#E@dnkzZI#b` zc>93IWaXu|rCe+sKT#fi04=f)q2{k017v^yqthv9_8ch#B`$|4p7ZU0eA#&rIPxRxpfp<0I!XwP=u9QhJh|3G2YuX|sBN2w7mb zFgJAe{-ntnsr0<-k*aSiyr<{eQ{QcBAgo+;-F=}DsgmN(~qOkYF_12S7=UWUA^(0lboL22dj?_ zJQ-DYti~GOsneZ*{g1{`#!>zQRHB~LCe!8R@_7FS z!+T`M>mC2;>}LIm(K5&vcGfh{*_*5U$#f7O0^MfVc~`EyP7d~8FPHk8ub1*k|MmW6 zd5ix>IrzGOcGb}#-@9H8UMLf#}AH6y)*p*$62IYT|B6cj2X?cxZ{VihA$7(;h7n~#y zzUAiRQCa`~ThZ?q%_{Va9AP)0dgh}y-Y-*LIljL$t8_(!f7{w4qfJjglXJMbdf+45 z5P7p}zB68&Ev^+S7+AOe;&}P?kz=j@E7)(W{)q6S|3`C^D=sE=zj49xakZD+=sd*Z zjblMFl+_KGG-H>M=jg{R7s`xXon@|UzV6a;k#%B?ktaW}%B*M0a=VeTuJYk^*w?m< zU0TnZ7G4>q7%mi)F-x8Cjv8bLP`$ST43>oj*jZ=n((+-py4HC^E$dN8tm!nsvsNP< zhu1mPQJImeK`EODFv8_RKQl3s6(=Qe|ODbPcrCxF|G%U zcG8njq@liL?J;6!@XzgeJ5$(`ux*e!9q7Irwgc_WesB+sh&ul%*gpHpFC!IcQJND6GdV}Zio(2mzrv!1>v)P{-9-S<(UrtI!Akz=H1nJyEP zS6wXj>NISs>{X_VLG=-=SJ}t_RYrr?|2?&)tKqJx>|LjG-1IIJ9BaYr|6U`ugRrw? z53)Zs%y`)sozUk$4C)~Mii5wR(=~fRKi(b(lHKY*8^t|k!Rli@EBBsI)>+_!;DEp#pr~7|#*rTpG{`-p73aT^h|BK_kZ1m9o zW~n+OT35yDedqZhEQM}0Zo=!r23fbdFg@MX1Z2x}p8vz0i<3!6~>G!wSczUbJE`V(2}{!b61 zbst;MnY}-8guSjunbPgN|J#E@s|&1&$)2WFS&uWK)~D6(K4!-5GWO@cu7l1_bx#Jv zX3FjcyL|fTn%S=Q^ymNHMsZi+o~B|e(9Uj%)aiK;hsku#|B)H!9K~V6p?SfUwX|M#Utolfyzaqw4k3~w)=?fMETvL&6V?>R`T3#=~gdLhd3-`8liQ`J*2 zkz=O2;oj}q=MJr-j{ly!z;|0<~gDqKo{U3g;c8xGx zxVP@GTWkmV=Q{TEF1`DZ%8+oMvX=9GlkE&R;{4xt`Xa|k-?FxYKh;s6|N9=*`{pPz z^?hf->SAlk*7tvV8mV?rR!i*pz2{&e$4uX{k#^~SyWi{<^c0Nkz)ojhvRxd64)30I zg7<%I2e#1v;^?pI(oJFafA?`>vHN!4(rg9QyG|eHfBVeXyK?xvVW-{B+`fz(bpG`E z|4*~hHSPQ8SlbQW|Fc`#+qt0UQ6KiX;7^0JgR-&{X3rb;VIp!6>Z_uCG;BAZZ=J|< zg(bU>$A4#Ly0xI!2JDkg*ZY5VOZG`QICFLm(7uAR2dLc@)~j{>|EFp0dKm4yBfCMp z1gWn7_T@18D-JE$UL1Du7rOrI?J)W)j{gT6-td1Sp&R-h!Cm{%?v}oS?0Qs1>gf6Z z&#&cdCHr+>9NOK`r%rF5|My8bpeB;8-yL@zIej_~>W2E?IvniL`qzwD-O@SW_Qi3q zD?9K1*~jHyP!3%?{4ct}U zigeuBfUcRd>;zLC%Cv1?h2^#T#_BU#hGX6CuuRx}-*v2{sL;DKAly!GT@Ys98yxLg zwA)dTqPhkLU0cw3baYLr)%V>qYIRL`xfQ6_YC-o=YK``;El5>IfgTeC7R-=k$Vzp0 zJCvE?8<(C~(Jx3A>+ z@6hm3Z7EoNAFg1PTMoj@Eyq@%-2<}hbZtOq*HBa2_$w=V#}?{Nx`NeuHn6ToO6(Q2 z+x^ZDT+UO~8c(&4x?KN?t{pwh<(0LK`@2TV+7%;QCq)mMF3yq9vF=BzGtNIyR>ZlS zV|~9L>YC|2Qk zqF7XFAScsNJTZPUk4H(KbhPwNaJvl0-{pOQj&HttB57RR_(R)X@;~X9?@Oa@1dowF zaIdWQXBl&nRa;bH*ne<^TA{yB?P2)!y8T4?gbh(vy~)d#(TF@3m2Wh9Y>H zR=j@r$Ru&J9LWRdN186d8d~Pe1LSS7sejBZeDQQg)iFc;3kGMrEC=2vW6pWqnC_qL zufERTGT;AWL~EneZi~ ztK&8G(EFrB>zViFGuAWjbwuHhy|=r|D&#(Ph1!XWRDpeU{jj`*Du^k_* zV`@`_F~|7;k4fVPeH;T*Rj$>Xrz#H76-mL0&Tb{@8jtEIaC{h)r?-($wF7l5raZ+t{1;U^CKxDdYZ)8~ao!Z?!DlnsI*0pB@jH2kZlm|RjwPxjLCvCj%Ca*YJr2i z2~5UEvxJ`Eau2en=eS9eQ`O{ndhu_^Ek5|bx`Q&dpS1mB|E_6^4jEfFK4Z)Amux6x zlz03-@V0HMp7sCq!a@Ei#+=yFZOqVe;8O?hHl~Z(FUPwslfKxaTr<2UGp1(6xMQ~w zR-O)Rot)xYtZs&=wOiyAt4>}JteZ+*f2&Td&8YRx4b~lL>8Ub#fwdZpwDP=8Dm`r4 zb+#TqE7A*;6ghK(Mn%wZNsP64j9yp4Q4%JX(zzy#*(n_Oi%=k8&7Xr$_a8ur(&bI@C2`DYtWEw>l(eHAIc4V5iuv zRu(PSp&&!u?bSlIlGO#e-C@oGoQ!>>^0YgU5h9hI=w-JF{gh z(?Q9w@zdGb@B>^o+TjhKShOKK)%0Po)vApSTP~DF``8YXw@j9V8ly&em~%ZUu%(U% z+a@w85A_R{Kb$GY{FgUHrcQ@NdTB)Ut61*sbCRmZ*^ ztECVbWn`;+G#Tn|opPNK+h#<&dyq@9*Eh35=-Qg@2JH^$B}myhUqrYLn^&x^wuib` z8$_)agKCtk)Q1`FDacfnLy{d#eNdwpo7l30IGHO;)Or`R+iN=rN=Bs84$vBm5$*0% zj*z)=pdxp49zJ`q?^brb5rSO} z+O5~3Mnz<6f+@Fkg6&pDBW!kcZgo`9qPoUb6Hutt_N=B`6(QQidHC@k;kr*bmGX$j z(Er+bY8)Fq zv?f?%XR`NJhgtGss;^et?(85UhGbZfcFKeO-g}VtQKMU*#J`n9iuRE5;Lz+-PL1n7 zm$MrhCh4+LS-bfJSMDGq?)BQZ^IY%pOw>)aU*x+UcGfPs&Fyx3<9y~X@^lrOywG*N zV~{69J(D2NA_Cls^*Pdvb97y$>u-*so(X)l@i6kaEYE+1NHz2)TJ-+UG0}52b!Cox zW1i9rv-yAKE?u|M{H0sn`3|pE3^~*W>|o4Br5LKy26SDv>yltFE6lxeZnt34wZn2p zior+4uwazlAWt5F2KC~6URub3LhF~%3d6%v+dKsGFk>N#%p|MoG6Nqw8*<&Pumk*O@iy%pW4stz~RI>h9nVZT>9)b$$B$=rg~&TOHRYftjIv!u_T=-Pf% zTqDmo;wu=s_W>Rb;c_IC$&W*2lVpZDR+sIt%Q%>Xd897;#20scFCT(|i zyB@0gu@`sgvX6bn2-l>e;=T^qxCHyxY8zjKY_RsFajKTz6|ik^XUaHKEKzoSSC4Rw z8YKlKv$vc!{?O0Q+b`>9F~UQE5N~YCS!KWas>|GyjJO|bo6Fo^_T#bJ4XfRk%TsDI zE8RtIucsyOn)~*^XPy=@*vugNu8+`_ApJJt1q*vxAY90(7%P7~e+ zWfTEba1F1mtm+jV6gbs&p&04&5HbStZACSlPV4pInFq7qw_v7-!VgEsdDE^U|+pAj|{ZCQ@w%Tok^-d+zUB4 znD2a0E8ffFF77ps2n^$~*0bUU^BPe?haEuQtmka&5x&EpbkFvB#EFhi1K*nW2evyl zi?z-J#fio^@LTV>Df>A4*E=?e_Z?RSzID9KF^Y_HX5d@Olg%Z8Z=EYdwd2OXd(H!; z;rI}HhlmdxYXaMyCyHeB*1E1i{+PhyX1zF(2V7mx>-9Wq@P2Mi-|yhA?6Di3a-ZjM zUc?Q~i)!a>a5qU`PMtd-PxCds=pN%Me8K(qsJ(RbWKy!%*Ytw>)~LPCyTxSlcyG5HTSTgBL%mf|M-n>W|M)lV0#8% z!+l;m=Qa0{(zmMK{Yve;*WItUY7gGRgA2yE)5N++j9qHq@r`)e`LPB2PuI?S&wZ9O z4;1CT&F{Mh4{(d8Jx`0LqehEI-IIJ@yzic{zmnc5&vNb*H44`jQOy2bFtc{X2ktph zzVe;!^xADZ-ObY1@TvP+-^HJ~N5nf;iW# zqc@Ip4hekW`j{i|aIuyKpXf>peCv9d8;KwBegS2CpW|9DK2|*$4&&=Yn;u5dF^r<) z)U2RKQH@9s8%0ySY6#iGCp2_=7&ZiYm@=-1AHxfWqwc#W`xxKZpSusLjrqboM?SF2 z?WvvjrMp`C3R>K?Jj6Ze8+Wd+<}-Ie9PXK^2LH&ng=?buQZlO9xA+_Pf?j=| zraJGZpz&LD^)0&k7F~S{)pb9)$60N^jTU|Ple<0GqK9eGk3YK?>A+sqy02>8SGDe| z=q~vsXu4ik*X!zfU0qLgi(UPOu6{#TzoDz&pgQMQJL?VX6^HiTVy`N+w}rjN(B8Z3 zdD`4pTix>qww8%Mbocy0&Ap+TfUXJXngBJ4zXf%qscP8LrP8FuYkqUTYUnmOm9~P-bC_YZRcgJ^@`p$=-PMHR(j+0 zONw$Yrzp|b8&yf{VzvR@)_`tnK({rZ+Zqt6tpTCh8W5_j0ioI&5UQ;_Mo%3^s;&K` zYAajX%9f_GrKxObD%&aEz@@y%U>RH5%9ggWrLAmfD_h#imbS8` zt!!y4+n2T0D|$;?DWR?Xq@<~AX)0Tq+E3C{FGZ@YajV26krKB`ChF~hdYh!T2kGq& zwN>**+^T+p?Z{6Bj8 zl`0t@_cbr8<66{C+&8-7TfN=Gwmj~?Y*)v9$M%`H?^U@F&lh=K^LUx`K3poq_88zY z^P?HS6+k0rutvU}YvjwI2!uwCC|D;}so!Hn(`A**NLUtFj zpUwvMKTCj8*d|0%GL#GPc_J)<8ZPNS-y_5qe7E~WKH&IE6uu;&W`vs&YNq}_xzHfQ zS94*$5MReYHEa^11!FBZZz&ey8_K^yXSV|?h4{8qh&|~3Hx1DLjsCSh^vykpY zA-(PyyqOOay6b>|JQ(w2Kn~!{LqHx3dbUBUkWm>#DQRshELBbXS1iCGBCpc2rDK_@mB=D{-cgdY@QYk(HSB|$dKh53MT9LD16 z0mZnzJW0<1Re-TUjeuS}W%207XTcmOgr!gk=*OcUkKAAyGaZ63>yR4uuaI}vjIE% zrwN%zpovAWMaTmv_a0Eno6XQJk6h<^hJrv42=DY!fn_S3d8_!#4>z9^(^|U>;PlaC#Qh19BP7u$PBO zV0+?D*aPkK|0G&72_uu12{{?%$?1>-`9N@!DbMr(b(u?mz%r{~Gi(*|h}nSiDG7k? z6m+McI|aEZ$Q|hc>W(CsBP*ar$SizjVK>X$z@|yasYyW8Q;VP!mIIMbCGx36K9$Ii z$^_((Y83M57?=wyXJdfbd+X;Jx%#Vf=XcO}Me4y+CWG~2pC4im(%YrH) z=f!}xhz&;Ok%f5}zAzKmzYv2Lr9&y8^mh#ZJr|b2Rv`;w0J(y8AulGVOUTqE3t>4R ze+lK6qH}2$ECF=pCjxTwaXx>KkpH00`wxu#qlHhJ*?{rODulc|7cfv*C*&1{Py%I8 zBjlABxe|j{HVJuE2Jrr>Z9*0$Kt3R|KmaxtRDjxV0OS|633+u4Btbgl(EnHG^QI6= z04G3fG`;O%5P`O))HkD%cEL0r_i?FGjw23}izd6v7gyfI2|7 zxJAfo1*Fse*X9ETuU!VMLSB~(H9}q=1Jqs5`-Sm<%pwdgqO~`alRAuhTlt2BF1pbJ zWb#JJ7o)eh1e%4sX*R5fdO)u<1C~LXkT+xdW-k@D%z!!}Z=D14pa@D~xsXe6xP$<1 zL-Dq1AoAOjpiIa+aCAqdkV_K)qj#nQ<#!RxUG+lVod;F0N62N^zQ+OT6`gzM!%iA- zA8+n!7IOI#A@3Kk5Vi{Wz-*`%(l-M(!4@IQvViikav@jDgF0vsawWPeal8uIRXA8h z-6}G$svfopS)L3zfQ<)v|6nDw3;EC-`u`yW9;QVPFBGzZ7FA%ZVyBRg5X>Xm2tg+f5@$ttJ^WS&IksRYP?xlj(& zJ)H#eVH4n^hWZ*WMrul-LC9y)VKyv*Mj@X?;n@P%0w_F}29?kzitcY0t6{l5#PUFAZ4%Il{%`wVBF zVf?ebLN+ZE@^b?E9OGXs2aJA6{`WTs z86cv-USWt*VaQBj7#UC{408qOATc8=*h0!k_(qIP6g<`0LdO)T>0rp3~ ze+{$=BO2N0JSYN!jou6`!r(hHgU=GifOH_}0muv}gc2{CGQi+~oj`;GqahP=p#Vw% znSnLX08P*)jQwI@3}izdU~s=BPyuy7fH4AQ!#qGg2L0FsNQWHo=Ch$9R#h|shT~#j z3}gd_;|gI3Q~-wKwnB?A_|I}<5XJ_j12Th<8HCIrWCkGUf&B#b6S5%>(BVUgk_yC;oDabgW5n6?DAkGd<0@8Qj za=_3C6i1*q0=W^$C6UIYd9V-|HzT7V8M0sw%!g7ahxNiZCdXn=sMUcj1&S%nGH*!63|USH#Gw& zPbG*{D6Kk_Rvo$% zC{HVc8fbtfXcNZR7#IWDkVpTIE#%D-sDL`y3N3=~6#xU{>H&j?MFS2Fn*;Nq6xPEQ zXohxSq{jonq|bo4Py|b%5;nm$*dq)+FB*p@LI(YR_&h-Ha3Vb%BjaZSj>oeegW!kCP+$xERUHUU9oW&t`!cyTl( z2lny{kZ8d0k&VzQj4X_0VT{j*Mpm0JrY;f2Q5ZXFAuJch(a0Z-{LvLqCyeZL$c9`f zfD*typ9zg@>||pn8#~itfcj~h>HlLAgmFwEVEmX0z|b*Up+y+e1yDbo7S70rYN!{+ zOdQX|@l5n)qBj%yS@Dnul+9WXTZD0J42*#SXc9(F1}ufm!Z#0h?#0K_wu2Ci{5=o`-B+DIk-F{j^#8mIqaV^8*p?E zigV`yg6GZ^#^17l)}9v+=$zLsjQlcToSzBXfc*Ai?(F4`lEzfi`hXF;Pd{!t9rybRsTDqycLF3*7Z!2ab;^nYQtFbWp}4hx%waRm;pOoS!SCXB1b zK)EoAkSl5z#)4eH`PBq`bq!E<4F<1S4h_O6PJ&WE_u6@Yoofl|+O0qU*HM2RHm)lG zb^gDu3@~&Z%GWgkihTAnt{($9y*>{L0YleUKpkv_7GW$DkO1kB1Nl%4%b*H2LnE{b zV^Itsw+OjK$Sp!{(OC#CLU0j+ix6Cd;0+!~f=tMT0w{qpsDTD(f;Rdu2F5@(2Wl#m1>HlSoylEB2JswDc zOvr@-D1kDlfd*)THeuWw17jc?@}LlwKn2vnR%j8%eF7379cBYZ`+X(AY;oUu*dh)! zxVK^4#}u(V9+)zg&w#m53``lzYXIlVn|;N}o>cEnVcg#)j0X^Z0PzQM0J{%h_W|ra zfZYeS0A?S+tPeRKaz4!ZFzdst53@eZ`Y`K5u8cU#5+M_Ep#ZQ~RtCtGAy?J}`1P*9 z;0g?`!0`$kuUH5eTu}}6uoLzQV`VfXLpJ0=5iEl$*bI%(DvVVgNP^>73J+rV!30PLbRNuuLRbRGKZyK;TcJf5 z4+%i_A!HxQfqW>2Wl#m1p%Gd+U>^2B5@bRy6hH}-K@BuO6SN6~8%9RO7|4b^D1;?Y z0d=qyT7<#PB;%0;NQWHAhhkU;Rj?Tv!P_c~M?H`PnUD(wPy%I80|-Bg@S`ozCXCf| z!|Du}4fB95TfH3Uveos_1lX-4#g&YMN@OdsTZ!FD>{ep861$ZR^nWFWD-nLo14)nx za{$ASA^aG^k0JaR!jED2u{L3>L3RzYYmi-o;WY(->>6a(tOtTvgX|h)A4m4_1W1P* z$cJKB2G#Wc5)cEK{~sVDRh5A4wPa##HWa~9pnM&fS+|`2Ux#Dv$r(@V z6h?KmFrGy4Ng{lT$e(Hw#?wiV1!U#vg~F&w24s5U85}%Y2RMGVRT$6FAa11@&&_~& zumrXWV|_e$DO{fq&Cn){=hLA8i2iwuJikpC8*%}q4Vysi?-52V!POE}Z7Hk=^lQD`ij(n_(L$!FFN18Ux9IqgQ7G&R)gI zt4jb!uhu}lFkZ_RM!f?nVUI9gp9eJVjiti)*K%Prp!4P!;QgEUd8&|+s)Vt14(t`idkKK^_i+3k_3y0*48NZ)3~mG(+o<2R4AA*-t1z}#2;(DU zKf>-ur9hC4JB9J_7Gdl_en%Q$=M!vx!uPSp&T3)oqHtFov4E zKUWz4O{V|9a|q)*41He=7;h!&9|WNEBXvK{h6Z8$gu$Phg|Qa{dzS#RKNHl?82))P zvhh|~??x6pFPv*@GmV;`G3)AU=OeladXb`50dRM+M-PE~j zpk0`r99Rxb!i?ft+Keg!Dx>xYvmg8YFx;41X~&B9EY0kn7|W!&mAN79;uqM<;T zqo^B|4>Tg#0oX{c66R>^kDd$IO5uG94M{;a1-aBjFB@9P9Vv56t}qXd0fY};3a!FC zqzv{5^HAyzZ4+i1M$>3TS{*bAb1d((&Py*F}EH{wM!xCYkFw+yDSeS=n z|8Rmn9Dn1fAMeG`gn5ACggwH{h=)dDPNW4B(_lVSL%T31Q8y_=n3Fxi%p{;G7@M+J zm`CEA`!;44`co;Jir&;bD1=Jb2FM*X2i6Po=yV{Mqw(X-&J<=gLervQsW6Wbuw0na z5t@+<^}?K4B+OZJVXH8Y9Rtn6%)vnp4sw=34N#Y}SD44e1LfRSF}a;$9$x@eK-~%W znw_mb*v5x*fagQ)hnhh8_ISHx(;oJ-;7v?DhbV?2^73QfJKeYt53G*}pIc>Qx zxn*L`p=?gOFi$6tGv)yf&uA6qnG1!P=YVV|hAqN8ivZ5T$JqpPb`|}9P6FgZr7-8l z07`SW3iI3~C>Q46Q25&t*elHQ<^Xc}7|l-u_VcOB-vrIVJl_M`gn0pF|CcAsdGXL7 z%nJ$ZqUFN;JMsm{6zmk{#q))E37@CUOLCwBnuK{NPA@G2BArk9{CZ*jgV%qw36onI z=4Cj!JR2}pD4Q6^AVv>96I{{^&e0S*>a z3-jt|VE=0NuU-f(!n`I8P`HNrYcO2w0rrb4VW%*!%?E|1|q+cpzh27`~mbI@RAxI3O=IY^PK6M4+~+vFv|oWT*f}1-OMtATH%3YKz0S?D=1&F z37Vi?m@5+@7pj1=m6WX_*i|%a)n?c!%<^=YE6fKSWd6Z;-YkPn!hASQn2%7o8o|df z@;E|kdH+PFFrUImO}Q|iBY@`!;JIv|{<&hPhGt=|PlPVeHkOlel|AtcDR6+yn5oT=+q(d$g!gAOIIH;qp4#hf*)=^$ZaCI%he1Y;8GJ$fg zbj=s)fbxy;fc!?vH&VV4I~%d{Vl*KC;yn8Q#idXKJB7K)1L=?lr9kyp-xve)p#iA> z7qbWCO}?E(Pk}r2b9n-=zMn7)XO0 zK<2FyC7$&^I;(@ zgDR+pCSm>?ga4-P-^H+1m|N3@`QCgWp!bpAmIXN4Rtgn>{cYI)Fdj0Xfd2oG$`7ld z0a}H*9i!VbVGfi)IZ(H~S(qQiKpJ55qawiQN1FhnjSe7y#$3Q=BRU@=_c6A2;P4ad zezIAZI|*!OoiKM{YnQix4TYa30!p85gLYwlmJIpOD9k1tHkAN|n%MswN1tavG2r}j zRkl}{U*O;i^uCx6Wl#@$g!v`Tza*$H%YmT2Y!znnTwveZyi=I}NdyZ1!~3sz{fgJG zdHuQ+aQZbtwFpRr9GC}7g~^8t^P3i7?yeB#PXzPJ44~|nCSm@X4$FnvHUs< zu-GD(iY<1dmR4-Xi;_*OX=8)Cqm|vr$WW+dH`Gzb#6(4BR7xtUxulk@vDj@&bkXDP z#ck{zyH0!5?WfoE=lywqyqVuTzvufr&-}ix*D$Xih-Q>e%;+XD#*0d{iP0J{WAf22 zW-Ku)M@*81ZZUSfm~kABBWHX_%oRpVY8G0>Or*v{Vv~|V-sChfEUuHrSTm0`*Oa4*lbI~$N0erMNX!CGWQ~YfNYh0WSllhf z+b3p8g_xyf7!>0pzN}iz^{J>8b3-OLpUv~^xR~WxC=s)QE3=X{D_h0nSl~FPTg;7a z_(7klRUKk(3W{0XCg$b_F}E;8UQ7%>8Z)={in)!X{J5Cgc~xsD^xb|jcVvsXlO}gk z>@JS)8WvMHB<5~n_q2=oex;Znq=57HdeI5i6=#6_;zE?6hW#%d5Obdg6u+M)Kg<_X z!t@WMqCw1$Sgv?j5%ZW&%;RlfO`sex_Wubce1haB5@PriV}9Bt=1F3eJb#J-std%_q=ouVxGwr!{-6BB~{FGsHfTUypZQ?s5yLkX^R5vSEfB+dzj=?s?=@gV%xP+zrq=0xG2H?;iV+g?KDFQP67vCde#^i; z)aqgV@3Ptd4@vrnz(=iOVl3kQ+QgVFMsjRW4DZ$E4Cl`<%o&=UA%2GV#|-f?$Dd?l zK+NwwXcO~?sF*l4<2_=|Qm-#0<~)yo6fyl7VlMc_Tr3pxujOI}TG{`9s}=L_BoET) zKXTD6=1&apMU9vt7vf_6Or!tI5%XV}Vupzg4~gOKhxtoB0tg}|=C2(8wFL}uiKdrm za;XX5JWq&8xKIY_B?iTOSw+&9rDzrNH$efK!Ab6TnE&Q@Bn9nazDfp@e?{)sJbq2i z|1^k7h3Kdh(b3tWe8^Xmj2a|F)r)epq6fsrkUPeMYSF4OG10M2qE?Y8zaOQxLA$6! zJUJD_lG`vSdO3?OuRy2hxZH2CZd@5^(ToUKJ1!wQo8shw@uWno2yC`@fnRL0ojAg-jHIf)j~PBtD5acRzHJ9}S?;q!H1{ zJ}|&!;@lC@$ssVn?jOea2__;ljahec<2K>mzcbRfb0 zU*#6PDi0M1Atst;AsZA(3!+z)?|eFwyqT4VfP(2hC{h#MX9x4z*O!OKH*`UBRLG+4d@`^Ia%dA8M z6rAq^1?Q7DzZp?5zycQ-U;*(3#1{}>K>oEJkbiA0I#87m&2l3T6$l|Fy3j&4D6o(L z7WRrRVt_^DEviHW6kO~>F>29{0a0%%$n%otCC}S0dYudTAn&>kBt*HFq*Y4-9ME7% zujo=5EM?(R7A}o|20kCk5CVmkc~A@`zU@Ni|;3qPeNLfCHeph9$@j0+$cpW$XQE+wG>+0CtAu7 zrR0_}Y$>tQHpE5O5nq>s09d!KU-UuhJXnBA_W!{U2Q+_hMD)j*C`KJRMEwlm=hz<= zU7rjuO3;i>u;w4~(IEN|jUFl&EfbLcFvC1dig1#34LFzAMQ_J2d4XgSlA zM?`<(Mjk3eAEnTvg@}o6r1{1)&}?H|lsj2kk%3(J(GP~%l!{Cc-&73hY^p;L9iY~x zLD9zy-0-shk5TloQdFV=t>{7=!=jHTBLmqeL>X$(jCORRA0wiHRAeF-#i&3Xg6KdD zgQ8CuxKZWhOFl|bi3YTy3vmpK{xlgG$VMT`P=jW)qZ|Do_eq0PkpE<_Xk{@fP$&8` zVn1sWeTtl?g6utYtEwng#ig(2l2+%U7A+w5k6yGRhGEfvCSK!04Z1|1HsJC<9Y7G| z{hT^K&qN`r(TZNt&E#$-zBwNiVED~l?EmHg(OQbu=7B=BA#{lT!a^AmqQ7hc@n_ti z0JrM&nNHC3gQPJ%*+fMTKO3-|JwXr2)}j^^5+xSoAk7 zqA%x&wgg0X@O&pj?4<54`UT5Tiz))aKGEGC5ZK)=y2qdhEf^Htn+X=}Z3Fpx`;ZU~ zF*Kj;HIxJLLlg~BBgDE;1U(q|U;9LKp9@*YLkR+G{l0n*Lg+*xNWC`twRup${((Ze)3oQ+b@ zqck~6lVd6HfhNc5 z&<>h}X%ePMm?q(Bgg}$On8LX!whB159bU7*SFGBki5$LVo`9w+E=qK5rH znJRjcf+sn7l42dT=n{R6q}K{T(rbO9uUCqmqTneSo#K3_z>f~mHw;3eZ{~vMZxx|O zw2LNhllOK7xGL{h$VZdtyVQO+%Kk?=hz^NzQ&In=SMUvn5J42Z7(ha_$ASwURQdSAEAHtR{T;9PLr#9k75T7B^rHfBRbqY& z3;)Lo21P&a7X73_v^N_=qQ4KIRrC*8h=5w3lKW{1$oq6aG;WXv*2IfYfqM3zUp~-y z6fF9T%l?@g4E0$d%29_980fP;jEH{jf)@p#$mgBt0p~wYh@QiTyuE;2ew34U3+q@Oe(0FF_4xe7+kr{bLS@^$Xk}ub;gBZ(`*2lh@w| z>Rh1N1#&Lrq6lTE1_NE_0R1lXBatq8F&SAP`69^|Nxn$(#by~L!k;U%@38)K+4wAx zyVpIsas7rz(iSaPoE0AXJ!{9ZZ~mIuD_g9=E34$N9I;*Y6nm;1ldyEz)1+OF%Gy2jB#YfgAx(5e_!B~8vRooAdn2|3R?Tb$>ddgpm(tMh`>ATK%F4(B!Jb?21R>5PBFdDD5z>2lt7-f`ZQy^Zts zSPPQnIp?g?=bV!U+16OH$C@|Bx#T3AFT>mSSXumkGshd>*=H>Z|81Xjc&w35d84uQ zkkuT{KWwcU9UeMneLW-m^%*N|N_fr}){SGrkN?Grj}EU*ShrY5Pb6I$-T3Frl7ivg zCh6JH;akTh?HU#S%1SzTdANO2(vorE3A2-4nb6p^H0l2EB45&bmo>VxlfG!YcX?7y z<6Fy<(!>2Ll72X9=IXJV9$A0$DsR@ej|;zjT>R~$H(ZmGG;LJ4VO7#?8a{q|(u~U* RFD&QJ*hu)3f~3pM-vL_Y7=r)+ diff --git a/data/system/data/fonts/ttfonts/DejaVuSans.ttf b/data/system/data/fonts/ttfonts/DejaVuSans.ttf index c1b19d870590a7bbf0d238e0cefdce6689d3f342..27cff476ef317e4666f7ffb77e82b9398a90825a 100644 GIT binary patch delta 191590 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

SmCXCN2eR{n!rxXCa97n2>e1Ni@e>u*|? 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 delta 98173 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

    j^iNp(=>X^d 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 diff --git a/data/system/data/fonts/ttfonts/DejaVuSansCondensed-Bold.ttf b/data/system/data/fonts/ttfonts/DejaVuSansCondensed-Bold.ttf index cb48a02b4638b1e67ca5656362c7da7f52b6f74f..9edd89c3dcc333569ad86607f37c26f5e52d1836 100644 GIT binary patch delta 189896 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

    )$R@S>n0W1U~mqGmF)gwqZ-3c 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≀m|Qd6L=P0f`AQQ)v;dp`%oy=brw|=e5?3$W_9#xx?#PNpvEj#!wW7l&0$Wj_36Zl=d84ILX%9P^5%rTYFAkcyP+* z%~Qxs(m3Lvnh_J=N%!{aMJTSQtAT`|CshR)GxSO$ub8ZKg^GYwm{8c2*Y`w2X3(RW zNPLWdGyr4agX#5<+>qJ^Ge7?PT%q6$9R%RjaaG8O!GLXP%0&H!^~*eSY0UYcfU>VC z=n7mFGE_xaf!9w*7kY5fRHq>Y63sFpn_(6tX0H;q2z%ij=~oKZ3O5Nyfnsu=A;g0L zbXpMcieatH?5l++lA;u9{q7=2OK}#}0R#L+b>#iM^t;nyb$ZgR?jmqMNFDfERHyU0 z8N^f8l?N<6 zSwFIP(7>BuS=EFBE5vJ&Nq!E#4k{keFcTf=T`9lt)TK8C)jL~jy)(n-%kUHxbo4++ z?P>B=@R$jsH?EqTSx|&Ma1Cv}1NAuQD(jK-b$W7XUdCQu#h)^BZ>sPGtSQeW({(;g z{}TyMQCz4BifU9TSN`%KjkkJ;%7Iyt3Pr#%NO+(e91$w(XTk$S>R71I$Fxx$rw&NrbnaN>NUoqZ7#6kQd^~4b}D(Q)*$l+h#9Lcc9;?idy~4dz{Mp zhbm?)lF*@J3J1?Su`;HoJ8WePM_w8Wu8bLync&h`2uZ{c(VPMdn9d9-1ui(-WFfo- zkm)KN99QI7Nf>}(?^?cq`A1cN17FMk#bljOL+u?`h9(GfH9z1LD&OJ;9lZZUofWw_ zm0`O@CE=a^fZifUpSCHTeQTT>>uyK&71^?`@%ODqlO)LcS z2o{ze84P(@kl>R>^inP=fzw~vO>iUR4U#sQ35I1FlDNwLxlKn#ljX+1;nAa)<1u6Y zO`>yR3*}}YoANgB!Qk=k9p^XH-Tb+D>*qJsHO$@N88>)a(T1!wsHoOwNu5_xJ+&xf z+oI1_Z_g;2T3s@?r@64UNL-V(p%C?1`NhJFK6|R|^$wKOBc;-2uh?}m@Z!t6DjYp4 zJyy|PZ?D;1o*|V@**Iwu-Z+K)*);hJ2- zG|eOkH9XylB;!qhQ=XR+d_#m)NeQQZAHyRJ9PaUQHi;M#q|CzEebSlMDW z`*NC_!mytB=&*T1ht6|0f7jf+t*=zx*Bcnw+>+s`EEhG$>7K*#&(JsJWlK%Ta>Zrz zKe18%3v#rsUA}$({O!xvw#xV`)GKh3T||FQHZ3bFms8QjSKg~hZ3w|V5Xr~5vH?sR##7R&GLDl{$PTrB2v_Mr~t_M9Op#mnOVc> zdxc1oeu9#TEyxCIP^`pE1iniU=)>+Bi1wAhDhn|SMkS^Ik7aIs#wxI$NtEg=Nx{xk09a1dFn|!qFbfa8$ zE8MC}SvSg9w^-Gjb&{}7v(`&s|4$(#Cl?W+h8$S_8#sj)a0P3sTQP$7L|8}$Y@y#H zUAA#@8`$eXR>Fd~OG0m0cC%NXP&vIrgzmH|G-@h!|Hq|vF zEort%JngDzDtB!qQRy39Hgfc#P%+DQ`_^xYw&(ScpVMmgrNY!V9LG* zl6Y%_v(sTS4c+1ZpoZk>C^AH>Gs)96MU_G`HQ}wO)(`pLWQSJ_`C>19AuUrmBiV8w zW)`HAsYnvW3z+3w5#&S4D1GO^GWp}>m%U$#Gfl4KWaJsO&2O(P>yt^->E(}|t~sy^ z;_*ALnv-FZKTAh;yEU^C$Ca>@{ci`yPa}K408-<*JUi zeASJ8Ct2s1W|^&ylw8;`(X)QnKc>!oWggoxkxn)cfy9~SS)@so^;JIX@9XI4E?aj0 zbAcb9zkgY2hOI!nA-&JQinMJ+;%)+oV;_mcd5Og3Y@gN_ByN3LWB8b4P zFV8H$tY%=z^tMo;8#cdeV9jOanGY~o#Ua8vxW1&k)|o4fu@1AuA%nGl7`8)#X&SKf^Nf9 zxm~byW&g&$_y75xiovzZJKj1cn$B3!VNKJahi49KJkQc+SYGkK8taE_FOf@p*jh8t z=NsPJT2WR%aOTx18NEu`W}*n{Zdrcv@V0Todx+zssJ)=p!@BJ~T~T|tj+i&SX?RA8 z&pWzLLC>C+zCL?JuGg2EIdn+x(s|pYba!TIic|;D6n<|Q9wY35eLnYtz9aUL{!p$`8X@D410y?q|zykCOGwrLi{&;<$DR z#uTGYOA%g}EbV`6XL07T{Hi-XrHRvPVAWJ^Hr_7S?YjkWLfZvpd_`HGQT26?65-J{ znc85<$q$Q*%KDm)Ex1Mwna2uL)D7=p+Q02@i@z+iw-A5{EFkDi0k}gPQ5AcZF;%jVLR7F48a) z*0z?~i+2xJH;mQ%z)wOzb#FbAEGQvAoC(_Il_@PCZ9W%voKlw1~L$)LH2?CD82*z z>5geTAA4li8C8(b^E4OaC{?8KOO?*7#ckDaf*Y1)*P=!91`ho0(MRWBaRvI3N|M+N z8uJunMSxN=2hmLdP*w*!=6Z3iXpfdeu=QMtZq{`r}?UjgH{YM6N!++u6XJ^!T}K6rud^5jmRZQ zs*4`LD;g(no>Xb=nLB&~NqYz;>;H`njC}1bIn|!)N(9PZl*jh=ZYq=!V!AAAUMH#uR zwnt!xthPb6<6Xw}7k41b^D7pFj@*J*Z#&8DGnY@H-obt5AIW)V)V=C`c2BzO(6NOK z_+r@De%@VcR;t_DiDA(YYOQdQupI#EKH&h2Vgwl4CG&tI*at~jCWhnzV#0(J)Zn5x z=psXinSjRED|}2(4v4Msw+7dmNut2sy}x}5rCh46U5oGXDm@{MK2bd)AW@Y*a>3XQ z8^?b9@tt=-n!qJAyJH?%_ddQf%d$X9bJ+#q?Afzl2!bSuGaMF|wh5Eg^g#wvp#IP49ZW6 zPe@p0jTp^&>^akGXF$*Ja{=2snl^A6$evyDK|EVUuiKJzkK z{uXr5;+n0NLw&v+HvdA0SUVrVgI^LW%@fsjFkvk;w3}X-ZTdWg{mh1+m(c;wUAQ!4RAj8-#&$2vSY^OwH`N^egy#68#=n z9c-9z#_;-_BK5ZZn@X%k%gooQ%D+w4BlZ{CTqxnl}*ffZ>Bd3BKgUW%fg2IsRqjG$oB$4aA$%AMG$f@KikZv9_ttSm2 zNp69Lm$ZN6w=|)n?S*BQKcef~zb&&|g<*UgR`W&B>lx6Sqo!BH|0ZAHC^fV44Z-p! z#Q!FJ0_9K>>cds^ty({+AXtA>u)e;X&B1cg4yg|{Njp{0P&qX8qUkm9lod24C?s+L zF4G6l@?;b&-+a8bx8>PP{2nxTsl#uBztYPNEBR~gNf~;*c&YiX<~P&mHKh)cUV=LB z>*~C(s{_|)9eq2-b)YWh9>yv`VX#BwVMYyw)`9O4+ktBlJM=!pLg>TPO79;Rhg&KU z21dfWYfMdGQc7Krumj@o7OIi2q~%9-90$VL3=NXIZ}bX-1H!nzbrz6AStKQ8)j5$k3n!lsS92_4VPaqkAT~(@b?dj5k6|U z7>sPG3yw%8*QMUTFSsr}q+Yi!q1RU#U1#l!UnuQ^WiihooC4#HQ!N+M3#4JVAPrJ3 zq*|BIa?)V1oHYa#s2x3FdW&{cYY^I_*I7qTfXyd_=-Q>%Sw~M`eFgG>uKO!rKhwc*wguPs^v-(C{*_!8D*vvX{ExU60?~; zI>)pY>O)6axp}ZsejY8SkXT^toC&r=h7t!GvW$U-PN4ftPv{#`%Kt&jp&6 zza<^KVZl|~;3JNxr^W|yG@2^yFDZ7COfPub14QjSaBQ0^4>iGQMumQhsR+*EDBjo~ z4XM0m^fh7*!aXaNr-+U*X9DuSlZ&Q_JH_gb*DlCP^3Ih`|JCPc809(Jx6d~DpJxIe z%3th-T$2F@X3w3qXh3Gs>^hBXmUa#RGN9{Qo93r`mx?jhu-w-czsEh)iX~z zjie_|A;F(n(qmJP@W=L(uf6LCJWqMxAK-z->I30)vf%SVS%TqQ0(k7o6#Gb{hrVA3 zEO5(}mhm>*6xmyhF(-V1m%1~N;&ILQf;t9Fr6%SsvM%_tV1V+VZrhtw48N_mSfOpyW|fnJFT|> zC$43zHr;PcVhxE|v>fm#QB0_hS`N6B)CWAOm9uup1C(}7m>Sgwi+Qx1wR1vvOf8qN zL@%(0lncVHj?)8C24 z)JFpV0!q4aXb&_dR6lRqz|vbB^Xvn^6Y`UwKoDNK(p8+Qe)wTr$FcU)qb${;=Y!+v zqb>jFfv#%*VTxrfy6X6{^DG;zN#?%`cbonp+|d61Y)b|~jaVV~&%A;~;g*lI2j3d~NSm-%L>^PR99 zz6<6|_&XH7pB6@0THtyfe242$b~mYSl7$7(Cce&W5tf@u;lf#XxJ7W7FBWE5%7jVc zJmGiZCSe&k?}GRs{0u((tuz_NBUg-OzS;Q;-9&)Mrun}tch$wu?r&{n(f8|d(?_O|maGjX$UgK4oa zL23{tn3~|{YvEVo7Wnx)`wRo|OEFK_W-5d4>F_gKm|&KKUzzKK38bDh6v{pnerb9I z{=O&t%JdZc{9Z^m{aP4k9tWSNLj8?GvFS4*&2$pJrwiMpr{JerxWSwQgIqkrx}t|xyfYz+Q9 z0H5K2615!P8k ze|{(II{wH!iyKLzu>Sa~^DU3}Fqsz!$;bDuv>Zm@3#YHP98SL8d_cHcIwV}*e&1@# z4<^ZX_HXUCt+6}_*XOLYJf38E4<^k~!O?ztoh9dZ)rFRUrXv#{IdIw35i-`5KZ#ixa4@#XfvZ?p_BnMJ|fUa-lMlSDqj&z$1}H(4ei^Q<2C zgRtz~Y&n@^9wp4SZV>AKUvc*zSNHrs{{Q~`ah|1)mrT#6yo8Vm;cPprGxB;>JDU(| zWD6lQYnI6zguG6+HX&r95JCtcL?N`TO(wJnu@FMY#4E&(^|_trGw)ZQ_xJU_d@rBR z`*Znx{5w&-TV6Uh^z!sU}w+v;vMI@K7y>aJ1W zk!!RsWNBD!UbRu0#LE3#hw_GcSN?9ihW+I%&QEnMaK``K*Y;K$39+uNQp3aHZsRE) z6xYk$5fAfKJX&qU){fO1MYZ~E#_S+(7`~7fgul@FqMvVUka}0MEHLipjnl+F8JQe^ z!@fusaTy!KZ<7BBZ%m$fw*UMF)ex`f7}r@Ft%x~0BUq{R( z4sxGqP&b^{9X<#L@?)gVY-_l~h|`0+ZKcltJHh{B#a*B9BK$84{_iaMKe#6NZ#s@R zTU!5b2}Tsl#{XNz{!N`=Ys4zKA##n(<)N7pd7AU^j9ezC|M?J|vM--<{2ve5|K8X+ z|9V>g=R{MQIN(3eO`dy+S;VmyDgRDe`(6B)D&?WtfxGzy6p@2o<*%G|$MF}_qFQQK+-v;vh^rbsQ4viY07+@P}OTXWEOxbIM=)C>{nuy{YtFj!Ww1O zZsAvAmHkSrvR{c+_A9Z9R6jj#Y_b=uwim3n7p%4ythN`dwim3n7p!K%=TA&7sIV7Q z*b6G`1r_#!3VT6?y`X{x+nOgAtg#oYu@|hd7p$=ttg#oYu@|gi!GeW@eA;+TvtPXXIs5imUS|7} zH`w_%*!efu`8U}4H`w_%*!ee*|D4vzhPvzpUG{=5dqJ1Ipvzv+WiRMr!70xhn+^$o zJ#MxaY_>x;+o7B7(9L$}WoH|}BPNk!u%@S<^Y_{&Gxo0IN8Pxg)4 z*%tqjahd(qsZ8f(yYpp!9~*uVm19Ug-eD}{6Q%mnX3O5V-({_vKPOe@E5{JSKw_;{wY{ydw`=U} zT6OR8#X{j?(+-k7b`7wN+4U~lJ$JpqcE5>g zw)@-L#EJ7bPL-qC`ge`9oxf|8ZI-<~)!v>yaR4KW?BhK9_)L47Ke0RGtLzM`?QKQS z-mS5>YwhiW6Zr%^WT$Slj~}+TkJ#Hs?QPRU8ZnRA1s8Lz34fD#Z5OX;)5cnO4BIZrXWlS5G^iZRxZN!sGeVmV|fHE@WFb zZ7JK;(~9ilW%l@Tds}ReT+DX$v=#R8CHDBG_I4%P(rK5mT|F(pwr<+x;c<~R{Wat3 zs33o+_XwZ2K3aePDp8Mi^oj7t!_pLwY!smy%r%AQh7l5ZECJ~t$77A?2jh=3{y6I% zXWip9=)xezM4m`P9)Gm?L@@{Ds7I$ra~zV9j$Blr4$TP9Q@EMJPwGejaZeV2#-41& zfXGumkoPHKpW@=4CiZFaK26@IDg1OE%F)Q*GkCg(gE5hoSk#C-!~PippD9Guq%QV@ zBF{4SY&IzPY&R(OECrr(BMDr@b1moxO+Gg+(n_vY;##9qNPq`9 zC_*`^(Tr{kAtdrb9Ef`%3wa>+g;F%46*T%nA2-*JToi&lZ4GF_2*}e;!|m}1lBAs^ z?Id|o5QAb2U`*sC0$)l*8c6sOb1zj0|Gp4)7!v6y5qX94SIG5Bv&gFn$OrSU_G4J& zH4hrmD$*H=0GJD|_lc}82L(4|gDy9OL^jgYM#eXiWFuo6yD=!zMe;5ZZAwBlD7dMM z51X<;^4Dqd^-hs)3U)W}Nu?X{sKJ=XmPC+q%c#hk&D{SUuSgFAJxsn;BJws(yiJ04 zNbpXtNN!8Rsl5J}ec{c_LAnx6Cw21U^-p6?#=Y2V-MvusQT;zK+@E*;+ zN3-v7vF}mu{UYxF`{iKZ{SkyjK5&B~A5?;|{wx%r6eR2?L4TjfhZOpdLLV~sVGBA% zK4RTRT+By37!ui@fIJj|_1nq0o!ITfZtq2KP-GwpO=t%NKj!@7eAI*UPjryv6Bd5T z+^6NJ78y)L6`CwJb(T$ME=ds8EF`qN`Ib&bA;e{W$-2X4iI3Qq%WJ6306`=ur zB45UU!e5r4OXRCK5c?HPe?`Hsng2Qf#=af~W5bakZa4|m7!mn~V&CM0*l&parc>nG z0+ew7zwH(IE*UK%BRW?xh5X!s0fa<;i3PF05ckUn_y1Rl{z?<$I+z&GMUBXB6#Si_-%0j+yU5OXlw(LF zM4?a}NE{jy`Ga+T)MHd+R~|ai56&liVBJJ7-&Vw<2<@WqJ%*wL{cI}GC5p;`nuZop zG&jaX(R(n25Z{e>P>28;G0Z=1NCM|Z2Z)JaeMB8t8<~q%QFhZ2izZQ`6450}bT;xu zIVU>6L6wC6ikaeOz)kVpIo>@7B-(vIl)ogP41J>P!SNnk!5*ck0r7j#=_A`@5$7jq~DV?dsd(UEq87;W(5aD*((NV$VD;eHkO33 z9LG|~Ohf?PqF9Vut^DM{EU-4N3^cJ1vHNiT*KFjYQJTdb_|L#gMu^0_%X3MnlK{DEaGN)P>MQ!YyflKBv8Z4Z+Mm2 zMW9GZBC0_0)L5|h5$LNxlPGi2&?(9>aR`WVY%(fENn@WD-V=WubH_CzB+B1t{%57#8I;K^(luMj^^jgJw~3nakzsb4yVT3gnK6ayoOTcZss79Ce~B<{}qU zZ*e0!xc`g$F)B)4BxvT0M6{wulrw!`?5qH)&@M`TE-0K&va^%m2QlZk!Q44TVE$ar z&-Ee)6hC)Rl!834KQA5RJ1;mO%K6D?!LTS7knjSEUQmo4Q3^>^NTEU+ToQ={Fu#OE zOG;3Q2DGCW% ziij&J1qq9q& z@=$_GG@u>*qFkH?UgnDfs1jubFYyY_SMZ9h;MH1D1McmLR&=2cL!w+l;Y-+;7Wo0~a(E_@^EC$3~MzPCk&>>2|gF-ML2#IoeG6JCC z%PDvT>#yJkHh^wX{*jFq?lp12B8-VrPHZ`OgV#~;x>AgYvMLMp7!_r8 z8R))(z=}>$*3jr0#@6Z}@mgZ8=e#l!>~CQHhANQshH+7DOh+CXLBX3izKJ|l#8p+G zPn4U}x&Jp)P5MSI`@R{|2-j5>Jvfndns~nizxRcU`UkvS#*E9 zC=E%VaKor550K zj|bz~km&IdQJyG4uPDtVZ*CXm$pjRkTa>5r!PwI=Anxe_QCd8pa7##(XY$Y?%Cp&M z6y-VAK1V^mCsbOq&GYrk4IsXg_|A|h>uGd-779>`YBZq_Bcg1G18X;sZvz*w zp^E#zfvecii(yeV3JBUr&_)t%B+*6^Z6wh~5^d~6KSo9AibMi@$N_O(H5dR*Zen~B zE`9__Ja<)1L(n!C~u@87tQDbMYed6 zjY5>62F!0^eoJ_MOq4g>NCfNOWc{1Ps6ahhMd{%pdbr4*Qf@_0H3wW}4_En?AP#i; z7M;G;f^H0o@^%8ay0>#sgmTn@n74^}I~+4E$~!SgLORIvP6;Z}fPPVWneX)=3w&d$ z^pdEz5gq6QNwyNSl_Xn9vXvxTNwSqBTS>CD9laP9Wt$)lB-}>AZ3QR=SGtW?;@wyj zq6|G45~a_JY%tyzY-PhlUw9%U%6lw$FByL1BY=KU-lxd>BzeCb6z98V<%2{}@B<2d zPz~~YK%NiC(@&m$^7NCZpFI8K>90Z~I?#s^-ijaUqI?(+FN)CuCO%^Pqjcnfp;%nc2R@+IeA zQsB!nQ2fh&jEeG=7p15MV_z}$btHmWY)Jk!i@y$uGMtAJbc2Sz@gWCAC`X?t-}=!i z%6Am|jw0VRqf3+##z$yoWB_BLe9sksPt5mCqU?wP4eY4KxF|nx{sZU19~k&yR2060 zRz?{dO+q^IP=ZP{pdG!U{1^|K`H=>GV$Dx+@E{8XAn8xlXcB%99Y#eNOG7T|!Md@K zC_l#{eE)xD@aF-HiSmmV*{DJz21WTb4Rs*Vcmm4Mf^INBJ}$~{F-Sr>@=yYD{6?|g zhDG_Ex!)Q4omc7i5m9!MXJ-MLxc@stqJ$_Mssv5^L4jTI$U!}rp9qL5f*dqqP*jC6 zH5cV*#jvPa0*Xb|6H$pejEU+Z&Q&2Qf9Y5?(ou#g1iRVvgT==6eR?!lrxIFHfcLkUJSn&J{|QSWMnnmmB9 z1NuPI2N0hS19Bt~laP%TbfI6=1M^UXMo|x9{-9C}1VugA50WG@nK&*gA0nuSP+&UU zPG`|{UZ&|JnLZ}!p&m4V_#`)y(IM(#UNnh%cr0l8@MckupvVz4mdu*uYEh4jK?TTl z6zlk0K|LzSz)>VSnxaQHis~WALoyGO9y;{Yp&MhO&Y<9oL=ZcJ`5DDv{fv6Fq6b3= zi8?bD6q)HqJ_4vhBRbHB5$^vix2Urck%n9pqXP9HaMl3EMD-HqCC*EnmpCtRUgEsO zd0WwgA%sMo9gAf6k&ghX(1;H7VMNpvo%^2>&w&@&Cd}fGkTfMEYHBQ!LDJNG z1W*N%rgoqYBcl3r#KVhh6rv0@Xhs(XFed68{xd3dP9oBfi(*uu9BG zFed78ZX_ZNxhMv4$JL`1Js3hr)W5|d8Ghs=fGRYi1AQ0~_3t|3x&MFna*&Nel%WRA z=)!=g=}9OSH6szkW)Pb}YzDCz#AXniL2L%G8DpYmxildJ zq6{@?Mi&M!ChGBSBq9yDC`JY9(TW}nAtY*6ERx|zJ_4vhBRbHB5m8Uj5zh;Jf|rAA z6rv0@Xhy%NC&q!t!--ia0Ppw{c~qR(gieHGMnyd-5()4j2Sq4HJzCL&A%sNDjzu!a znO(>mESsX)6wRh+b{7UPChEyd}fG z3?U@yf>>}t3$js&GB=wVG^4w=bl5mJ$i?MwaXDOE4i~qOi(AOWEhPU!E^Z+gw~&kD zb2)Wk3%Wu6h2%e#{HK!t)GQRB6xC<~IZq|$siUHv7KucpAs5A{Km&K=vag4}x0du|t4!-sq7={n*;{OQD>UWhW(fY{TCJ$(RUqAqeH5oyRp zF?VE91qbzLMGuA$5_NGblHo@_0;obGI?#s^QS)@f!;5Sbq6{@?Mi&M!Ch8e(Bq9yD zDCUuOMg{88iXIFhBZPN_z=ut!@bMr-sN-e^0{~U+`D{&^M^$}TSq*+$VMSZd^Sy-P2#gje0Cp3 zL_LStbBH~M*mL|K?>Xc>rxJB&K{p05F6y~4-2ZcvIPif+&Sk;5EI5}1=Mwzi)d=lpjEH(6^)B>q|1Zn~0T;HSSJb6+xzrCjT*}zeK~alzBp?mNs0VXJ zJ)rqz@yJ0n$gzxOFNy=XE@}p2%Q;?7-sLp1oFuHj>Waw! z4ZJEVSigexmw3?$nk%Uh_0m{S>(W9Hb7{AzD|PPw%6tw=PysqyNw+ImxRMT6vUnw3 zUKWEy_>heP1W<{3w4e+97!frfpkN>gX~;n#N1Vp@#6D1|IOES=0x~ z$;YGWL!3WEzK7aHZKSbAjvH&hIsgBPs1H-<5rQ8f_|X`Yh}y)yiH4de+Efl2ZR!T` zk3}L0Stvp!n$V45Q6G;)5?KFu4vJ8T2DG3X!=gTs!2N&1$3Ye-^aO>Ts0M*g5cotV zdO>h=Bog2O@y$gbwz&yhNi%WHqoO`3hyk%rdeATGQ(W=Wjc7%es4a=`Bf$M{VWNdA ze?|w1pQ%CzMnru!9@(hDfT+)rsFjznH5c_567~6HF#bGio*x(W1usg_jF6~p6{5DY zroCI#7dd{Z3(F&^dIe?CuDy97*hF~Dc1>LwppxTziE zqHgAVa~V2BeVs(F)AZ{kd7ZiLG*p1Adm{!k^F}2&-$Lw`EO5SMNYppU^JXpZni0V6Z;`im z6^pt(4iw*>55@PhCT_1`YCaP!EsSP9}@M8c2S4e ze-#UoewB|>km#!p5chQwDDZWYsKb${K)0yhB%uK2BrfMd%UrHxHQmjf?r6wZF698N>bGNwS>;ga`;Vi~0wP{vg?| zN-#bVgBsB!9(f2K4~wRxp+__|AM7>GwF+>o`_PDS(OlW+7R|^)i)ayXATFX_v`C%* ze>E~0xu`@ZNWPmJeWFDX7@Z@UI{}>U-X+>!8bsTpK(v?`g!d$h35m8RMfc1HYxZnL zFUCZhmI(4sBmcB+(e{c2P3_f)APZxQK%iL;Iy47Fv*^;Iur(^$-c?{ejskHMjH?65 z_aV_f6x@gTeL65A+F!jW17m-!2XXtRqY^!$#m9j2_!9Js7Tk}4{jx;cpZ)#}98e=# zLJpcmJCLyhv%wV|I3n6X93RwxQPB?Ost%_3!7ZXC>Y%AZ;z8^o#7_5tgkb(Y#E0N#+fp z1|;O$XbUK^fUyPSTR^@A#4e~rBihl65$=CZq-Z%L$YC<40pp@A z%oFX@8qrRpq0?A!dI8EnGpBc9R5ZSs)E1F^5wVL{yNI|&G_Yt`w8a$Xdq-_CbBhBY zFW)n2inWbnJ?W|bQ^4%bwZ^N{++eJHv zV&@crv2){5fj)#pD%5^&BpFxpb~MeK{hdvY%mkat-wN&s9N^3)F?B-*|4NJBo#M7xhB?(Y(d#z#S0R=O3_!#MSHD5 zv`&(Dc8j(?5ge}{7HtFTHqgYzIFPK1Vw-9D^%l{(yF`0qRJ1LFqP;mL8o$fZ-WnI} z?GDl2Ax|&)x8-vG-^~*3U4r^3_FklD@9Uy{;1{i*ppU9W+n$UO(FO<}AZ~z#A15LW zjD1{;3Ji(%3FDtMiS}uOXoKYaEMK(G$@zJuXkR3WHbky3SwCDO8h>u5ecR3b|1MUv z?~jZxs|GSPk^$#?)H)VEf^F1 z$Sg3%uZlXqBI=%i=rb{^RrJ|IqNkRNeoT(&>BMC;iawV${&vylm5Dx|u^=Dk>L+B2 zeqyue*>2HK&I4C)N(}rU*(ogK15JHF9K0amf>O}*0%CLGMPJC=!Yv}anY|O z<{zEhD~`*FD<2j8x*U-7I>xUX6P-t|zRHh$1VDk+6j(hhdPR%qYiMQ-dDliF8?0SR zOz?U-y1oz%7!keF2aav6?7J}pir)|m4{}k23J`lk7Y0SYQ3v^MWd26xZ)E;P=5J*F zM&@r~{wC&cV*aKQ)NucAYUf}`^r}dBQGgmWfrV8pyqSeJC%_L9-^~2YT-D8eps`yL zk%a&n!1yhrqTd<|F6h=mRH7B+t7g2K@#;eEe|0swz=GRIbXy*3Km)fiej5wc>7api ze$c===GW1{x<1gr?X0_<25t|425x8kcJkH4f*F@|c zB-@>=x|3|RWUD1xZ2)AeWxSU0I>zgAPyyoWhD5(B4!I~rBYH)@TZadQr~~Wo5qLrO z_Yikazv%U`AYXkAZ;kpU4!S^l_mbe=1o**%dkMIgg7@}eT=e@AL4)@NK!f)&e&49* z_s7DALR6v^;UZbT0P+Ry{zr2g&vz*&YmlY!5Qdug>~Ij6Xzs4^@Eb z4-JXl7>8Vxq7l8KKdi%pLezovj|jY=`$vd-q+j$$V?n-0YxufDq7;qj75xbv9u%SutZ$})W-n-GkMK$__ADjd)DDVvHo?+dyv7o@S zHRu-oIUVGAt^%E+w{qT^g&Mx@TL(pdJ{bYf%nLjc+6ur^puH4bqQ59e12Hc)gCZ}{ z@Jl3liNY^2_A*IdrdUUV=&z9Dl~&PT^`KMq*ZiV)`b1wJhbGZCkar{by7=5n@1oEq zf;RKadOZ>>>`p`t8ZjvP8!UXI0Gz);{1y^#A;}ij@llfA!(2}bLZZLL`nPH7ZJK$9 zJnzt4FY&!yqHm?%R^qnBAi(|K)+hSAoV=Tj8Vrcumw-YL*f%cvdj!5WCi?qTqJKcb z4;n!e{a)08m=ANn_($;|&vu#{;DSCT{$pZ4A@-9pbcz0{8@Z_G{(m|u`d}Q=LDz#U z9^|S9S@ap>pON^pN_1dM^v{#Q)qY-ub_|LB1qr`MLow>nBl-{x3~@ZvC;FG<`I7u! zGXEt_e#tBIm5v@Sq`$<1b-$FNOY~o3!1=G_`L!CXAJ0My!pFlH7yUP4g1?n;&?EZq zyi_~mKqEUxL=PpQLi9gK_6G}hWrKvfszsm3L3rN)8kiUtmsFxvTuL6wF(~}dB_tpn z1tBvI~h>fg91A;8rEe9jwiqa7eCZj^)ie@}|KwNGwDna7iBaw|NG@?UXez(}u*gmm3t>D<3S_s|gg_izKlujAbr17v*S1 zzqm{tabS&Ej~;}?Wl_Lt5!c>6^nv_wtczn^T!*;!p^1IQ#PwI2*f*a0zi*ki;$xAI z0dei;1;zJI21)m4Z2u8)9gv7@kn8{oB&4BBTn83lSX>AB(JZcmlfZZ)=ZVA}5`$9E z^mN9i7lItq$$e-n_y5pDkoZtKIu}-@ zr{LjPC<5ybZ$K-$!MY;^T;LJJ9g&6{1W<`!JsY|_q6@GKr2% zM;!*mbyP8kJ-S3(o&s^r$Q9Sj1W;@ixx7v2#F)5dyO9s_&mIw1N;+!5e5%gX z9t5P4AeBYFSa^|*LX?3;zGe{TBhEK2t~tcbNk$e5P>O2Mz#Iz9>Bp$Jj)_D9e8@o& z%2CJtKZcHv>BgYAj!i=@icx`jw4w(?2#G6=qG=RO^CKStRG|?a=);J(j?)njFS1dH zGSr|MUEr_!xsDqX*WcVoL>h8Yj0)7F6+IY2NL+u9MKb)zM*vl5L_@gDfO|HpGx$8%N3)8X+naC{58K?BE+i7P7-31C4Mjb;^~6xC=#C;Blet`mqo zf!Gs#$N{k@)S(647{s`^PK-ek(z*X9=Ai_YXh1u9F)Xf=1aa^n3&fr@Dz0qy*)*6< zgD1O@h%{t_SMX$BK|VcjojfA0Q&@Kjjhs>nYAj&wf+2C`lp|QjrUl&?1j!e&_*4>| zIxMc!XyCLs(7V` zT3o>WUtG#THJZ=~g7a8-1_{roM4hyoQ099y2c&tZUXOsNw zkhsoa{G57mo$CW*=MI7Kf>^!388K=s=&i&LiNwnt$(n5}codE{uxn zf^4w<0xsYJ&I?&v$Z_F-xRwyRBn>pbq*YuOy1_+V$lTKK^M5I?z|wAU6$w~al!tn8 z@poBV%Q#*}k&9xGj|vcbQNOsBM46IU^7ihU?R6)0XjAg+s9cd-X~ z2-4NXP3T2PTq_bm!WE?;;R=ea7!}tgaY#ooYCxe&hQ(DvkrIlOP^6?1EuhGyI+8(= zOQ~@wH7=#brQ_mSnE-063~>Kf)^k9Sl@z&*B9~F*vLaN2B9{$`E8qr20u%{QBtVfs zzql?JP~`Gllz}3bQ{-}rTtSg5vQPqQT+xLQaa~D`E2(iMHLk4Y{$JV7!JxQGDN^c1 zJ}6R3ky46WMUktr5fazcbbNIyM#Xgv1+U?_jCEx>;Jl3ZYm3G84-X1K^FbO3R)D#3 zj?25nbsdde*CDP|;rIV44puXmLlx@Lj9>?w9t>avA#vU8Mm&;{hHT`c7-gtJ zJ(|&h9t>avA#vT}Mm&;{hHT`c7-gtJJ(_t{Zt38l2Ll*ENL;tN5sze~AshK9Mj5J5 zk7jhB2Ll*ENL_8M?cYw|EEt~=7uF0MOs zz~Wl&b6qSF;e{W$C`15!!PV8E5v}0sg-@tlcQJN1Iqu08S3O@(_XTxv-B02MFDUc? z9!eHhBVSyPkgSOY9*Y&%<1ylTf<6#)Yge5!XhKxHggV^&)Y-F(j^@I&r;CzIS@K|62*{qlx#qq7S*s0fIjs71yWZ z;`%&YTtm!%T_vt>tHt$wCq~4zBM}Ya`XOIjqZIp*xqrIFHOBnU3;;>3_#F_a$R|ALmF;i?cLqFs#07BO}k5hJ=tjNKE(*dtzyJ@dri z8xbQmB!*QYMqIKOe@zl2zEF()d&M}AwFfbm$olC`Vk8ZTaYTU_N3nKBj2JWf#PAM? zkxD*(Q);9Yi@|T%jLa$wi!rw`D2BgW4E`9vn4c!b@g&bm2aTMVAjU~vF|t{l-7m(; zG@8cVr~B9bku6XT+K zF_!m;QCuU&#T2=Oge9yg85QGF&Q}hKaapSvfm|`J$QR?PbTO_e660Em{{!XmVg$=W zVq7;M#wvnW6I?;@HREEerLpTNSlJ=Q4fSH&*d@kI6s=0bm>4$`dkf9nS|CO>1#TlT zZ#Cm~H~Ph>!5ygOye=Lzbr(7Bq2YS+-b=pw`2D|e|Bx6B6n~Ip4-Jd)aG@BF_`uks zonkz$i_u&m##1C{85iR@j~LGvi_z90#*1ZQyiDxNH1KlxxL%BoNF*T}0g$(&3#@-7 z0mQ$Ok1Fs}7mQaZ^lBU!c$EaNHjD8ZO}s|2&T=uxo-GfRGp);*ka# z*iZ}_-B6EK^k4|YZHz@S{K!Wch}+2X-`F@HMwc5T=^{ZFoo?cM6IZc`1)B=Mf=zWG z@upskh_RU~-JFPYC<>s4qJqgxQi{qOd0kc9%2qXF$0!k8Fu zkl>A2BqI+^=tMt4Vr*f23+uPAo)09AE!7}q3o%=W*)l4|n~_LDHj2?9Mo%1yxc@yA z>=_W_tr(;u06KiDSB$p>6nHxi6=)XYop?~Bm$_aqicl}cR*Gz;fvq&YjpW;MP>xoN ziSaHCyjuc__YvEdiw5q09}C`#fgc3C$NBsD=oRAw0zb$Ci9YBPqu+xHv}06^4--Li zAJ(8-jE`vcqdJ7d*zN`Swl|3}K(hk{VBG-u`TKCj$9@D$*|cI2rht6K8-J{L9H+Q#rP@` zj0eA}6ys|Gzh?2*9^{}1<){OVeBFy-F@}j7PCz;eP>O0ap&P_}6A5Cz@qt|56rmjC z`i5NJ5cka>#>M!SzxQT*o5Vpn@=yX2eoNrDy%-kbJ3$;g$U*^1LELvuVvOXXON{Ty z@jW@dFF_?5&<^r^Po5p**+HHi-<9pu?jdOjNx?I6*PPV{3`j2|MA03UKtgmToO z1>G1HW0bhjBxIoom1saadPNc8zlB(|SHzL}9frOQNKowNBtJ{d(_UTP}Co_GnYmjUMSDXbJ2T6$3~m-g0x9jv?Zu83X}y*B!K z`L*`MqKHyes@gUbMZ_t7caD3Z`&9R7?p*ij?nUm!?mYJy?lawIx%1s;yU%f->n?Dg z=RV(kfxFPX#C@TAsk_L%%zcr2xx3hXv3rI45_gIF(%Pdgitq*9x43V0SG#X>uXEq- zu5sTXb?!UeweC7;a^K~?+kKC_-hHq8KKK3Z2D#h)fZQcNxF2*sO+TG%Q#{I1OId`l3dG`zMHmP^FyI*v_)TGfA|lxpH1{%NP1Cf@z0EjtAM>x~zGl3+pSizzfSF((XdYx9 zY$lqAnA6Qe%_Q?M^KkPBGub@SJjy)U^q4cundU6hYtA-P%v957&M}WMk2TZGc<33^UW5Yx>Q3=6v&bGs`@|JkdPK%r;LpPcavmIp#t$c&d4tnQNYIE;1LJdFC1B zndVt$zInEJj(M(GV4i25Z(d*)noG{0OUx4UQgfwwnHexI zH?J_SG)v8^%&X07%rf&@^B-o=EH|$+SDCBL3UiIQ*1X=VG;c6(G;cDi%$v@Z(3Uo~GdJI(dx26Lm?Wo|Mz zo3ESQ<{Rb~^G&nIe9L^>e8=oHgImpQ=DTK}`JVZ{`GMJQerSGVZZ`+akIhfaPt8H| zGxKxv3vZoU zA@dJ&mpNgHrC6$^S-R!23@gHlw05(itZ2(^?QZ?W+QW(oT6u~D`E7>~II?6iQ@>nyhnbs`J zYt6P&tW?Wq&9RQLjBj&-h8V4Y{3Z(U#&T1%`8t)*6xwamK6 zT5c6v7h5Z=ORN&>QfsAknH8`ux2~|Rv`Ve3tgEeStTO9b>mOFoDz~n)R#~g93TutE z*1F!Rv~I9&v~IGhtedS{tXqRtwRM}d&br;IvF@<$v}&z7>n`hV>mIA#y4SkTy5DNB z9abq1UbSAcI<58A25Y0$Wo@!HTd!N))*IFq>rJc2ddqs-I^Z3v*V<}rv);A(toN+< ztq-hz>qF}!Yr8dIeazGMAJ;_e+COT>yok$JEc48sF~9AKyCW7GN^0%qhKO4gPwgoW zM6Av9`RwTw-<-*P#^gS8azA%+@1NW|=~8_2o%1=K+P5Fz5Bq0Lo_Z(uvnTf{ll#=k z{bad0ljY`2mYXwKZq8)6Ig{n)OqQE7SuVrl|lw;7!g zU#QXZ=G!S|%$uLtHnbrkJ90O>#7xi3Ic+}W{%y?Z@AyTQ4g zh`rql`?<9Tz8&#+l+*J}Pv)GqO>alsuEvF5^qDhe+ph(C`?X*{vn_9H#6wDqGwpM# z&hX7?+qo^`>D{$i^L%X&4@T@2b#TgDXKBh@XKBh@`(>P&GS_|;XQs@X+4kJG5l>I! z%k->2B9=tYO||dC%(Wy=A02y|JH+ zpFJ5r+kPn+w_l13{u91%)9mf0*-y@=q}CpxN6tUUXWx#DRG-~PM(P~<0@&LZkdZn+ zqjtF-nN%BhK;%T*?Rw+_ZH`@Wex}c^$lk8N-mbvjuE5^zfW3V)*w3lm9uc`TI63Xy ztNEGEy<%^F-LSXs6?^+$vA4f0*xQY=w;N?|f8oy0bly4a?S|P;w&%QYIG@btybIWv-xSmd9gUK7-v1XE)Q?&2n~LXE)o~r8v7( zXXkTvbDUjv+0Aoy^X=UXr``;^UU1e7r{D~y;0&kW45#1>r{D~y;0&kW z45#1>r{D~y;0&kW45#1>r{GMd(oE;dW;%sth70+ftM<=odwuuF{Ud@5&F3X>cHwZ& z!r|<~;q1bFu?zRbF5DNpa9`}geX$Go#V*_zyKrCZ!hNv|_r)&U7rXEaG2i2L>Un1v zLHpDx=yeKuoq}Gcpw}trbqac&f?lVf*D2_A3VNM_UZW+bKBPDLC6HINK>W+bKBPDLC6HINK>W+bNjh6ijgnrZ@#toC{2G z>ZOG11?PKGoPsG%!4#)pic>JfDVX9EOmPaPI0aLjf+pli@Uz5p=rAaJtEGn#pjQ$#9yof4T&iA<+Nrc)x*DUs<^ z$aE@XIu$aV3Yl}A_g|({BGV}`*C{dADKXb6G1nxlV<-lNFp-)Ia(D^E;LNP9?un$?sJ1JC*!SCBIY2?^N@HF~b{8ogyNeW$T`{V-$$sK;=H#}Yv79;C z?1w97PB#1DIzPpJxUzHFwjZvXIsMLbvdnZkoauBp)9KK8EmE9kZZO4pG5DWMEaL4S-Ir0WtX`!F1S3f#ML$t8@W$Z&>j9gH@~Sq>cV9!&YL{Rn0k^q^<@5( zlR2KLC$pxWc&DDEOg%}RdP33Qe^i|_wJImeRxArR{cv*elEP(^CsX^GlQ}gkb86V! zsfFfF4VybPEa;ya=bswqpBguBYS_G~Ve_Vj{ZFsY{HbB{r-Wtv>y-<7QaJn9wQ};W zYt5KBr79;=!e&kloBG;k%$gcDYiii+so7>bVL|)$XUv`&H}xK6q)ttjIyKBUHJxv2 zm~U#>)Z3ad^|o?y@si-5_cdecedT1zwNAaS8B^~oCsV?v-q(z&_luJ$VN>r{rYAV% zA~L7m2u}WWBQmGn2u}W$j*}^2Q@`#ry;H-yQ^TgbBZ4WJDO2N8rp8UZ5t&nO1SeCf zPQ4MCQ*Q((Q^Kac#WUwj7Cj^U?&oYu+|*Y%bLuP1$&|3EZ=B4jZyZj-VQqUSL_QYr FKL8K7$!q`s delta 93568 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 diff --git a/data/system/data/fonts/ttfonts/DejaVuSansCondensed-BoldOblique.ttf b/data/system/data/fonts/ttfonts/DejaVuSansCondensed-BoldOblique.ttf index 08007e0e16ae48be0eed1799cb2ded4ad4b27e27..e2db5ce0c15965906b0516ccfbcc4e76d0b09b11 100644 GIT binary patch delta 168444 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%0A#EbVM=kX6bY6h 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 K|2gJL`+ot{W2PVg delta 80960 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

    bz&xRb-p4Raz6hAU=nI5e+GEB-~( zUha=Dl=6lamT#C#V2m!Yyw^#vwx)f|N27&DqPsjfeERqWb6%J@YII6e#8dlXe0_a= zVj}y;4IUKVHzp>=H}3sKbcdKmw@=J62gV4|<|kr=CxhY#4UX#{8RG-#n0-%0M5T-# zHSvWx3&u|${$!V^r~&39F+z-(HF3M8Ax4k`1nntv!xO@sVBH5Sm-rEbE|fj6+Qasp zv`sg)U4+7GuUWE32sY7kkl-$DkpA?D&{>$gTUWE!XkpaAuJRl?%p=mRt2`IGF#M&( z$}!!_c4bT$MsXuuS}a*vIic2D{I5V)p!`eAuF=BKR#U+XU6`b8ytG(ThHDMMaHGg4 zF?SD@qeM2NFXJzrWlh530(n(`iL1VBMk(}ZrqIP)^dG_7GVwpc6CEvsas<832S39? z@FP}C^Kp_YZI$*TrgF=q6~Y$+^|Ewdi62=JwC&8hRts@4Q`>1}BCghaNv)UbCZ+U$ zA}+?Ob9d{yO`#8pFwsyvDCQ&7V~_8TgKcYs4smgwLcPv&=B!JTa*`kGKER+6!~j^) zMl~QiAH;u=$8Ti+|xUUT)pc(#{ab+giwT``V8@BHVT``}kcb z{D;RQY>i~RRIizUf^I0#wF+fwaPY7KPW^aZuh2zelcuj--mnfVp0l7a^fR$kGeZqX z$N2@)kZ4rFwI!oCWAyY7_v36EmE8AFX zCA4gN3)6g$g_8ijyTUQQZp6yjromnXel~@<+$E>0k?SYfTQMT5vetkd0GH=Eg}%Cd zHgs!|R93(YyBJd6+CxBh%^$uj{N>)Occ?F*0jT--HX*vr`n~Jd%jN6WTPI7OHt#W~ zY!m!j(W55zpFGbTU>1TbkD2khoqG)R)_CJ7UVO%wo8F}n<`u<42MIqLFo$dT(pwt} zHym3>Qw#AI{|{Z)2cLhKgUmuF%TL9^f3;rdt0MX;Uc#mIl*q&_>aPptlGlZ5!R@GJ zW{Gfw3T{=F&b#mvfj(}B@q;30Y@1CQDii6tHVVV)6Z5uGp}W!Tl(1aMiLFua5;Axh z)(Odr$=ezsk8y!601lsDu%x*0VdqljVE~}=y5h8ZC))WpOzCq}@VfgT2*2Id`)C!>rpMPIs z>Bh6wvyKQ;Xo4pi!Xun3diL_bYkGJ&&r|wBKC``ed$IiG8&|TjvgTb8yl6VJAeT^a zRbt{Qysv6FDkKLFjHPX)UD6WvphWu+zK6uq?xB&r@P1|Q`0lhDjl>Ii*ja)NiR1!! zA1?%lp&{5u&Jf(q^n%c#ooo|?;UTd;5nk49+Sa}y@-=g}3qqvj*9*c%YHUOOrB9>~ zyqP>0ZbWQGLwfp#^zrrz4e<@>>Fw1Gk8wNyg!=aBtH!|og!IG_^W7Id@eOX zph4Z*3q^wmTQ}=z@ZiBV-J!vQH+u9OJlJ<6r6c=GFC|l&{H{RB$aXlEFN(tK5tNRw zX8QM$Yt5^^6JjlWFADAUhx-wnBzx%eel|8Iu>pNoJRx4xU@p=7t7ZO{Ir-wNf#$_; ziusm#yT$EP!nWjDbDJ_T))MoU*q%z_9kh4mUNOird9V1hpxdbISu6<$#5iint`IAz z(NIMHkoRI_EA!G&YqC@?1Y&<#L{D)3Mc%(ISu^l!nW>z=Ab;ke)$@x2wmRz?>33lz z=da6G!C&I>2EYz`yCl-EiB9}i`iUAw2t$4#5bJ|@LR2|ILU;zcAlRG@*;Bn4-%I)nA)c0vZ;J84D6VdkUy&Bkg(pG|bi^2gq94b&C zU{}v3PgG!@_AT%)DLko`j5C!2DEOkFP${6}#0%h+7j}BEnh6OSya(38K`V!Y%|f&$ z%HiN;hl9=JlID=ZKAt*L?Qf=oG@UW1@FtQ6fAI^w9nZF3!^=H_x%*-9{YP+0j=+nk zpL~hwTfdi@#mUgeD!_Q5wT&(C_BWX#4f%qW_;K~lM;z+;BvZzI0+W1G3w6AXCO5TE z-y{fR7gzVOh$mI=oAAm*4fnpPg*qD_buH943lZdfMg6Gwg;5E9GijD@{)_r%I+m&P zx1_$-;5TW|J|+PpT6ulSmX4R<>Qz2~@rF*kRoUxS?@JB#x2o{c)ic)jU`LT>$%P#2 zP3_1})^8D?-nLHjyfzbt2b<@=EABInvq-g9>pP#Bl^Wb_&vdc(3whT?iQLOwky1Y;wb~y_WXnjEr5Ksm0|gJar}!(Ncby6py9}uT zyj?zwL{iKx$}6VQ9sY`Gx{Rx)$}6ULvl6{o`W?M<0=FM#YnCU${$9K`*`7U6D~11! z3L05FEK)&d-6J)y0v?c73LnRL7-H|Fo?;H<-{pRA;L>kI{H_@5H>g0Ee7%_sJM;=s zl34e}LdkgB&vKSMW1NQs<6$|=*4jqTWBs_##)a5yzW$!C+d%!fQT2% zy9_!ZU;0FD96z#fbmaOTMXTSUYwvISyypEG%Pu_;sqNA)^TpC0QRx%s2wPj}KJHCv zVqK)SyO=TL^9PrUPY85Ueb(p+`-tuI5Gg-BfAaDxbCxfNG3S3Q{%u@OFG>Dra72l` z^Xf|voYkinB>YwxpI_7P^0lM(xIiPTe6wT*uPlP7y?6w6ZrZ+=lEvMyEAiU1<9cy7 zE)V0^T-Y9+{T>Q_Ohd}<$Z`Jj7gsyYWk}IAuvE6t@cmSGMwEKD? zT6$6mL=CK7GaLcqDhApY1FDBK4K-ma**c*!1lb)3s;ppGLObw?LzHN>A>Lu(&OoJB zZhrFh-g>`=vvNObqpfLlYP+lj{h#O*L960>=C4S4)bvu`ZMy08i#}Ik`m?|kKjN<} zFmaUVj>kD%msrt?$k?>bdfo*w5DNWeFX=1c7UXa%gHZgovX}G|uGJ62L8zw(?=zwN zcS#~6VreMyiY~=|rUYq@=o`v=m-0h2tXnCaiy!lJ8(Ei=HvAqN;uZXJTc6M{??8RK zU%GhGwyguZb`16jleBTydQYCZ+C03!U!WM+YfgBKXc!bbB5`=1;OO|r-8y)76K=`h z%T1%!e0e1)b7)%Xj-Mw#Tb4N?v`<+7oUP|Ke|KZzl(dmc3;)wi5FZ&9+b^kCN1vWa zS3J9wBFl|N+^#_FNDo3ZuEF7_vmUP8V>Fa?8T>Sq627mG5ak-pU`HjM^7d*P7M9p` z*wlVccK2$&&#b7o}S(Z7Em6q|;U*$tk zTV8-Ahbw%>3gm0(WL3fj7}i^Mo)iOwiR2A9(;%Tv<$o6|!AC1RxhZ^&;RtKeVYa?W?iT-3;k) z@EUO9&+G|PY5npp+O`0)de<=*iZW?6E&Z(@w&Y-VF$DMS#WRV z);Y4ZPkYZ8LFzm4H~MsKU4FkoPtEK(tWEo=|Jk{I!d!3fNBcys3`iE1yhUs7Z##Ef ze(#xBda{*UPYO$2)qlirqwl>P|T43)Wh!XbT?Ds7o|10`by@Wfsh7DXkpI#N&-T`}iaUSpN z`Q&SMD$D$U4@ChK*d`&L4ioXCEX)xcxY>3|AMsAr-g5Aa_z|UE=J~avje1+=e#Pnf=d;?->!LuXPrR)jgth3O~0%^rYN61>vOga4yNk;yj#V zsCz_c^^}VdPMy4!@7^t7%M(l(2QFNNYK8PMfznQW)T`Ap7F43!Ic z!EapQeTPDrJb?4(xB}x9g)ljk|CmyyHA{M$ZGKe;;W&T&9QDn#K7$i<#w+sSmP6l) z9&L<^v6YyR&yFRT?0+rS zZ-}9irB$O?O6hl&1HX!&Q}fc_#6nADlX#cnhp_hkA^s|wx8D_qns40|V=O^`iBqWg zrF-HBmXyE6k%BH3vr!>wW7+jU>@9eX!&S%vJUB8CKTbM{uA^?|CaW0l&NzCU=F@BR zh9yxJSL=+4_&1{RfjUAKV%1uh2UHWXC>qEGstCyepOXS)02c_!#q5~7gOJ5Y&0@$e zZYE?&Hh?SqOHsL{SpaM-!>X_>4M5qlA^>vBQ-M-KRuEtao|styr4{$^1;&l%2+4zT z-gQD&js=bpvI>E$f|FG{fTM)0hT>`uAPPtXU~n~bR_6mH0F$W&nh06r20(5Nc0aO8Xcw%PFJwn!Y01|){AOpw)Ah;HSYpa1e0CMX*02o}C2&4j8Kt50cpmyuM z00g`qHCvwspyulffl>gKS&s^?ZzLpN0s?_}BR-OWDZnydD^L!c04@Qy2`O*~!hrt3 zSRfNv1MC0}0X4vNpqY>ty?|(-ijbF*fOH@ifW1NlTv!Ic<_32FHa8eybOVfT$Oa05 zasa{`E&&kS=mkUrLx41(nvhK}w5gVmqBsDuo563!-z~7SA^#18{Tzjt^WQ z-I{+LXOhNk}L}6tb0Aq&&fn`7wA&24Uh&xb%+aOT1 zz_A#$KZ4VbP=P80Sq1x5 zw+T6(2pD1fcpV`h#{>BQ3O<3-CouZSC7=;#CgcPHIS~k?0$TwD_-QgwhM7zPp#Rwr zARAZ%lmpcOY!hk#g0e%5P zU%*IB2Ot4}ks2u1WB|E9K2Qvt0AS}dbWfxFG|EpO0>GaEcP1W40Wtx|pQ%9mpSe!R zmtH`BUn+ngnT^~fZW%x`!!_F zLgs8dPzb=@IX3{oox|}rYta7RQ~*^#El>wE6LQ`Qhy#)V7&{NA=b`*<7y#vOA^+_K z01m%}{Dnjy9asiH_QE0H1aJvJ5Z_5aAb>!=gU#=z0FeF8xD_Aez%c+0zJtQ|i17Ok zKopPwlmSP9Y5>MA!q`PG0ERB60hs`dU4+a<$XvWY$R%)>z+JjY$PdK;D)|G-ey9WP z5pvlBh(h~cM&y@K@FODoF^`bCKp+|@0$}J$0+0ou>? z`32>_Ab?+>^h*;VjcLF!pplSYrvPwrD+Pe@TkLx+A-^R7_}&B?P59oF3S|N;IMfqRuzy$!d??LZg9#BNc-)=w$APO)h;A0t32&zz$r5P6hDKripPt9sVi5EFd2! zCRF1FoWKuC1QYxmECjT<01CAz)LsB?5~?c!DhPFhup5lF3Iy;ks_F4BaOpFEbNI&< z!vGj^PXn@nLIA7C#TPhl3n7pGKr#S9 z4+P)=&NC250T4_(D7J(1c2xiZZP!F-`*;8qXb;2fZ{uG;fQ%Q6d!+)f>s1U?<5$DM zdnW-n_O2t;2Y!6g@NaqgWCCk|9fbP20XX)BG2dqVJCWHy4RDiC>@lfd2Vg7!8NX#f zAy5h&10d&j2|y73?f`=D?+-xUAM*Z?_lLYc|?*yMg&<{#S z`v)PCAP~V*fEwUB&`fBE7Z42$0n&k7pa>`fs(=fGc1Bs}G~f^b-B1J<3a6p45ege& z6+kti;o!m(0qBK8FT4rY5#4}bw131U{E&Em0D_Tqghs(=)CoenWB_?UIiX$S066N3 zAi6@in>$bh)Djxq0f2*O*odA2KqtC_&=?N@GTl*;?#lq!jK%j@$i!YEG!A-ksc8Q= z6vjcJhXe!y@jx;F!5%2QZHaGZeSM}`0=2z@jdD8)bc07Lzd zk$&L%qlS+W0EP#kd_X2}fzZdN00=HIjnILRA9#q+K|_E>LI`1g;Z0ECnbbbhsN31wbeXPLh%V7)dH6^a(EjwHOgi=*SMhRzj2e12+jB z1v^hl0JzcMM#EuBJaCTCr=b5-9id}(5c;$SumvzVp%W5-azbB70pKWo3V0+4MuebwV=|fh?c|K>3Ug0G!VN zHv`-ZIG71;CLGVK0-!T17=W``)r4jy1Eqw{M)~XtLgx?w-{%-l5IPq^a~lcGN(YJo zL_RMLC;~3v>GT936DR?i2wi}(1zA7^q1l1J5CAr^A(Nd4Y{if6dI4d;6yPYqzj6e? z{-T?N=77tA-P{gn|6C~M))I=7NxB%{7Z(D@fO~{4K}MGB0HCzg9Vo>wmf-I)I9Ud6 zIdqoi6S@L_S3t+;2Ee$nhS0qJKsj)Z(3KL90vsiD6=YXs0&9RBX#Z7*@C6F1t^>`4 zu7<$sXdoHL0N`wOF@V~xt_JD=1h)n?S`!5%0;xb2kPnmqaI^-F*EA8j)(r>-5`YvS z1IPo4feN%gPB7`(I^Z6mIKiarqJTso6@XEkVA6FZz)_$UxJl@G0(1c4fFvLt$OVdk zGN1~$05lPr?*;?|2|x;v0ptP2fUyD})j%C^kI(`SAP#_F0R#&mSOCES$Q3}Y0CEM8 zdl7OkMgfUHDv$-_10}#wpcZH(^d&bS7)St8fD9lHC2}lQWfg+#`?f*&@ zzFYvB2z}KJ2nG^>6d(i01B!tPpc<$H?h(4f1Be0=fm9$1$OlS*qd+ZilhD@)&;f`8 zAp06*U&{dUfFiX2Yh?fwUW3AGb-+DBce(+=0F-tn0qH<4Py|4JXBBV(Xd?7=$i5EQ z*AsvgAOpw)ih&BC8mI&A5nAE_L;;CFD)4+3KJtMQ;3!ZF+$8i30(1c4fFvLt$OVdk zGN1~$05lQ0%MAzy5`YvS1IPo4&CT9Yh%K#`;90e`_w+Vg63m6N4e+PyS!pXrDAP=YjY5)XKDXBnBaWRS>N&w0T zJsbuk1NYEdk05{}Fn;75&`hW$4wwSKu%#Nf1T+zP6vmEr0HOf|cN75}%>b4GML;P4 zJ4fOCXdQ5y(0AQ{Kma!19Ri^Iy-Wap-tQ0K*Intc1fZPI54IAD%Ukp#cK|{kts%6k z1ZX7mIFvs=LFgyx01Tff1n%MY+Qd|@OaI*mwABdXJBz%pP5a16KvG!uFz5ad>IXZ z|FRT7z_oz@f~bXDZ8>n8(69OfHwpb3dS726^lTW~|7<3{90DM4E*{7Npl}X?--H3# zKr^A|*AV*c5JE2y;5wn-B?91Zoriu0-S4A;DZmck9HAFe0XVtT0mvithhU%zfbL~? z0KP7>v(?Kmav2UU*8(u~V-f%(KQ<9smjFPy4yn810VD&30Lrey*;Vk@+yLlY%Lj0L zJq&=(bvUahKq9aVI0iHm+5p*xtpEbKVMG)+P}S;E=L`UbehCC}0T^k7jYfQL1pg~^e$4_-5PB;Zm;#g$`WpiIEd?kcv%kslkI}{& z`||P+*bmQp&v}2|pZEK7?s+^s*LyGbc8l_fN7Z4zFA-L)=mi;~F)3)qh^XBv>Lh|6 zfp^GtD$sza=!LE-ZYn|IMI>AlL?=I5?!YS=ODr}bIynoyq8AGa(1dYOUTV=x8W9zZ z%K-69E##t2bV@ubF)Df)3y)`hd<$6YB2o{h`ZgQpQY#yQ6HQ-3*&~y&tbB083 zC;&Bi;XqTUHP=EsJfQL1X7pe}G?iDYG?fXd6ijVG7br51rt{Lk*gVGO@hHq26m=(o z!fx_zq!2G4=#4C3K8u;3jBF5}KQ6k!jRvrY^d?M*E@u8>A6V>S;!CnQ|4aNB5?xw` z8c=*GgBcm9MO1Vd#g}!6E*E5h0?S84SEQpFeWD&0*!R%D6991!d7gIkU=ZV?E8~y? z>a46P;AU8KRjX(wN1e&!%ue)y37Mm!S%L((kqtk}5fQ!F3l_4vU-TB5Wm9Jju{F$F zOU~LRL@_41E(OKlAlGq_>!@F~ZbJBb60jOCgWg(D_*NR;>O&b?K;HT^5L-{t^*y2+ zV!_-E8OTKi>d}Vt<3pl8K_b$T0~Y100}J(abN+p-ZXk+tw^3u;sAwKF@`&ZpE00IwHWxAw;QZfKi%#@| z;`s@na6X0eDV*O5#_}mtz*s>V7%O0L1uckRM0C3YH@v7o1A0Vnk3}QMxx**w&jx)8 z+fg+vTEt3<>cRF74=B20OqADFw3vkyw~Fp$duJJFwsTapg#8iY zwxKr65NGw<@dJp^evdDWYMepPOelO?0YE-nE6;+e? zKs-3g2WehYfEGkWAL9OSK=cTOjx>nYvWSOWp!v~O(MKru2=QZWqK}f(K)nX$oM6Ex znnWKX_E?Q*i298=qK^kfpNK;f=l{tp(WVa3r^-e7--$lmE&9xWXfyjiw!r?gY!G(63m)9iOq@bzTTH)7!h zHO{cj^G7|yf+B4598%x(i@wDIx-&%Irp7yN(RXt>|2+iXW2Ns`h<@M`?Tr)tFkbW{ z;vd(G_R;7Qj_Q*-(NBr}iUR$Wa{h}y^tUW5S|Iuv`JWNvZ8rT~61-@`i0J1u9-#j3 zYemmCiJqgzxrpc>@h|+G|1VQSzasE;8Ae5iGf)f)d{Ztu5-a*=8vV6e^l!TCOWm{{|i7_!Iy^5Ovdc;`i zVlHr@T}(`w7<)v_g&krh$D%^a#f)FvB<2z~C>&Rb2{D(JV_3`-9~hrP>@q)S5>M^; zHW0hq3+i3LSVFv*t1zu9N6gi%=o%VdOT$?dnw=%)h6XVyjLoI_+&(e$DDLhRGoQQ# zG)(IdvoHk|TS)H0Zj6apLytG4127zTH zEu;9dHjIc_PQvmG6r&F0EgulGg1i+es2AfAxKV&wkmDH=vy$zV?TCt5m5d-*(5gN$ znas&dLXhv5$?RogTuc^$tN_};!*z2u8Zankbs8wRnmAWEbIYih>~z$NS;PGrimt5? zv(ASRF6WMQ=YJ zr`Gm1&j0pqHb~w+CWb4OxjhLP$Uzxu(1Z^3Vh9sr?ubVUvQU5u)S(4k=*Nf{zlB8f zU=SQsVI0UQ?C1O!l2k-e5rHBm6|ujA{T&fRF)F6mfeY#I!H)?sJ7YodooVo*7?r3K zQ^K5*1PozJ%&sQ%i3!9b3Cs!b{XQnZq(B9j6d);ZK4}m%-c6C+6xr>D2e}BK8ue&J zCz!K)SWKya{8I8uv*AY&pl9|EXGBihk}L5zzji$gLz$VEA7 z(Tq;?fm|-jX3v0_yZi{E9<7Lg94^sjFZ1^@e{VISod3O}V#*yPfQRb)6xql2J~y&K zv3)_%a6jAohsE%Ah^c5pH)vQfCgyGn|mo8LzobAPdrkPg#uKd4ozb24S*xL&kM%xW4qD;`<3k9FQD)tY8;}*A!-~V zeux@}h*vRQ6%kWSthx+ioc{+bw4(=u7#H(k9FpNdF3M4hW{isYLH7UAFQ$fiJb5uS z9bz6D5p$SD9PSl!gxHZTFu#_%wJe~vil((Rd^m^}L@)qiM@c#wKs6XUO7S1km^T+p zU5%I@d4)fqfg3rfLmPU<97_aqj!~z+84*N5^G6-HkS-?i(GfAnEzszAH5$<>lSIDP z68?>wUk2uSCtG*!+rNA7U9S153*6z0(yX=9mEow%@VewR_~G{hs~4{ec{}d+iVHkL-`_KKm1C z3PlU8=_)@7{k_mijg@2excyK2J86&;p*cm?YPU1pxyErh*E-iZ*E>nh3}>b@%Sm=- zJ9C^HoD^rSlj_WK+|G^8d}o1^<}3`g7x9VQXpxl~*z9u@w!c z?6h)u_7agdLp8gs(Qq)pr+UMWlv>#rhR^P|3MYp*JYc12cN diff --git a/data/system/data/fonts/ttfonts/DejaVuSansMono-BoldOblique.ttf b/data/system/data/fonts/ttfonts/DejaVuSansMono-BoldOblique.ttf index 5e2ee0339c9b8366b84b9081a3baf4ea2600aaf4..0344c22709d7f3b7524c96d86887ab2bd1f8cc4d 100644 GIT binary patch delta 40430 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 D`k^X_ delta 28445 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 z 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 z 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 RzkFAgI)+qkFLms6{y&*4xM=_Y diff --git a/data/system/data/fonts/ttfonts/DejaVuSansMono-Oblique.ttf b/data/system/data/fonts/ttfonts/DejaVuSansMono-Oblique.ttf index 9789ea057c55f42d67e6d32988ac1aa011af1c28..bc16d51bd50e9e0bc575ebe6268857e738b91c57 100644 GIT binary patch delta 40590 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 delta 28234 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%0DyqQMp`0;F$j+97O{chaYVfAe!kljQUss?4NNH zW%{(Tcc)L}4YOX_mg`SoS~QfsMfD9t2W8~nwCp3k6s9TbHvSj@wyWQuWs_~onsTw0 zjr^O6JYsfdu6=af_ys>7+c9~rtzdM}+p%hoQ*01o{sWQ7FF5+x2CxO9gHr5ZwE>(0 zu>iDGynVDm@{!w1(&E^=a{Qms%09ZDm~|$%XIy}&!Z{r_*Pd!*fW4+w8~Sq{3-3%4 z_iJ-$D`;1?fp##?pvm}Tnlv)oUXu)ST2t(si2Qn6)rIb8ckJ_MGGiZ`#u3NfG`(Z* zHoYX{KVX}3kg=z)-m`ropP+c%wk3zoSX)LUnWhZbrnCiOYy2n3?bUE|9lWIv9eX=S zSz^p!jQThBW+C#j9mL*Qhyo_SqpbqexHV&twh9oHI~UYVjnA_IqJzO)Ngref8wc~a z3UnfH{FU_R!Zj25pn&Zwr$AI;3z#M{!zMlq%d#zGTFKSLLZMs5Y#3ylmTNUFU12UW zdyB06hF0=b%z{Atb^2%mualX%#M4u3f!OG!MOt0gkG6+nFSZ1_j7kcQ~~j}&?PVX zPHo#WPj0j|nkjp&!?);@K6bR50V=JM13xaWDt^~&o&Jn~bwDB%%6|Vq!cN@>KcjHCwA>IXcEL~*mV=L`8Dzw$k z-Z63hPmZ_+oWt;+>s3}ktcY`$!=%Jsqa`KxW=1J(_Iu>!E=pf}7lnf(_cEp+cWzdU zKh1BN%&xV+m@4SCp)N0}4%e>jByD}h$W=e;wQB2*V~{&W%)!a&a>rd%ZkOD+{X|Wu z{3X>dFkMouJDaut7P4@%o}O&wE&C#MX?(-TSVmB;?=0%~A6tGU9eIXr@C;k)Xh-HE zH#hmCoAPLbTYGnj^tk7snrRnqwu+RBngt^ODa>AH9FDP3D^f zoT~=@HB{gY<4-SONOD($rw_)PyOnO7*tH0rJ|Ho653xYEAKGOd4MJh|uF_F&fYiKhvCe~{FsL)+WIHA?Wu0D_BElSub9dCd?;hP*{0M+90^u_GgI`)!>JbrnLR_HF|@vEC7Zx@NY zL4t#Ag45ju8%WF~nEI;fdkYEPVRxcmvCP%m1ZNmKJu^~dD`@sngKdJgyj~l*!^*!R zV7+%b2|D&`9eekNr&+D&QhN0HQ1z?KEjLf+YK2{N%-r(R@W0rRzyXY>d(6mjin$}l zy;^5Rjc z*WcRv14iMTL%0Rp3-8>t_oal_*dlvu!%|AKEU?;$xF-4zdl8HKU5~2pZd|iK=kdZo6R|A{rwe{t!0Cc``P(*t(*?hkJ6+()Bd=1icWuk1G%vRmvj^M=l?=Fw+;~Ov zyRiaiy0;u`f#yg|es;V(%;~M`r%MyfPRm*QaB)oDCtfb*K0$%4K)@NLKf6uTqHvn% zw{oY2ek*rcC|(}lLcf(eE%dY51DWN`1g?r3rSSzStlSx-t~^3Ba%aR2(q;w}HU88N zQq$CqJU3q6%#p^GpV>rfMeUmdwK2untrU$hd6%ZLmI7gKOx`D69y!Cvok8l}hH?^W z7n5hk%grqr&po~wf!HYh)oF>S0=d%#QTbpTIiuR?f~b5_Ozw0+yga@OqH+Rz9l7a( zfKSIO;=3ST9^VD7+>YwXR-<~K?E*$MH`wet;SOpmZ#FIJ$j@wI&7cdAbG{nx7*m|x zqCieRxdo!5+B&kM+Hn*e)lT4v#@_7$XPP;3uIsw;%=m=t6P1C{b{g1O5W9QjJZfnc z5ZeX+hun6-{~@p%o!e3%ywmOj%t0tK-jO(WG+SEeB)276X`*;}{2=iV(1=p>_N)0J7VnIrMkr~e#La`ezg9a^(1B& zo9@U1_V&5Y!+8ovL1+537{;avHD72F^qgw#Vz<$qnzZVBb9>$AVL`*+?gVM{U^vLyM6*UMHLApCV&ZJY7n_ICg;9=oZKd4 zr;(G;RM-AQ`R$He#^A?nwR-8d%o;)!%4`d{@<5#8u6RY9{O zq@GO8(i)uwEX}qHPL#jo$eZ6i!Tx1e9yvk&ihB(*{Bu;1u-ycX&4LawIUDOZ`LjkI z*9EUR0U|e_Ab;JFyGyjW-N)igOVH7_MK2GSC!EZcaaZ9E7I)=hC3F{x9nk^=_{2Lm zDsNfqjodz1WEU>8;yVHC6I7h0`%bfgW5)(-e?B)qod7<+Q^1~V+6U*&Su7VB-LA26 zd;iImzY=F}A5-&X$Df3{XVK=E@{a8)yFQpJR?aLkUW`0V58$b|IrOd1Trl9E5)6;j zH%6+>a0y-WcXhtGOMBz5h5GbCr|O zIh&&^iX086Nfi1Rxn1OFtzqhsSmUzh;LD6dj@2#W&>YE~U%9w)cNiLZz}k~XhzfAM()$^+eA!@TxE_ovDV6swbtSjS}Qk_VavRa+^+nz*2T89a*f>C zjs)xjS$-QbI&C=wco*7-og8^|)>?T>YejeA){)a%|F({M(AV?qdd8S%x8iZSQ(ELC z;L4pHnhDs_ysaF^HE&GLx|5J&A3Zo|97SibdlAqyuOpAnVg{-6jAv|+qIaJC>~9r5 z{ecmfOE%okjz76=FmgLR%{ZaiLw!F|9n{;QVIQfkfwxTfgxzla?2*V^WOUZ|mVF!T z;XD>;?al7Zwv)5Zi;b!i?2$Wud_x@jNWMLda|X$B6FJX0ffRG!&^+7f)1*Q*@~MV> zc9r^CLw@yYMUh*FF8Q`mg^CnvDVH?>!j|Jn-&kHGfY2}^e_ zy?^|KC3D9u9XI~6%RgN=ch0(XbLOs7S9ZH%+_)<)8$a%HE7-7p-U;8;igD`k!se^4 z7&rcMV>Wj!^S%)T@2j@*YsnOoTgc)}6 zVq?i5m~5UJHWs0buhco`Omz!PjTKl!fwL*l%Qw}U@^1cs0t?mDy1Tzpe^S?by7Oc7 zZvKJ1>t2hFoT)ab3E@#^9^s?DsCn3O|5?kMFQ@NJw>8oW-zNOX9rl;QyG-DumsOUN z8b5v(Z;hi1js8ZRUMbezw)vL47b>4nJXb63_E*%Q{TG%Ax1X_@csb9r;4 zGL?bdU$OJ}y(M*%zEvOiRB>JQzg2gCUAte@RG<3xp#_?3w}viMx{G-q&3nN9{5$$1 zalbEMel*TH-7ox&_X&Om?)*Hwmz3Hck^gV~tVkL^5VG3VHGG4Shi^yDyQ*})s|v@? z3|$@yxGz>-IeOR6q`H>}>4{0j*6|B$*wUQ>k$-yUCUoK|1mA5~)x0gm?^qd!k;7K+ z1b)G_L$4~DUqXKa`gxQ$`l-z?wdm`XU7}x43tc}-U*>H$sN3nGn@8%to&n)0q0>g` zbG_j!mo2M1QlQULbx+=`gMM{I-Nh62XIk~E>wKG@r?u~t(8|fWcmK1`?0Bj#DW&+d z#4uAj;~wo%_4${ccS*aHo~PzEKNS9l{`EhsEs8B;XZ@D1cj$XcWwey?^==xOaZht| zI44$0Pgdt>Z=1RcOY{wX|M_N}OM1Poa;EO4k~-sSr~Up~sjl_vq}M`o=IX1jWS42> zui6ztB3YgfJpZJFIkaQ#o^XgSlI49TA%~SO>c`qUa^LEdo{8s&PMN1WBwg&d^S>GD zJ5P@Y_}{e4kqz8-KCVtY`M$)A&GEcYn`p>a-c{P+4(0}UM(|&1HF|$=jqCzRY z#NKr~1A3N9891nW2S@nKN~2X#PFAj}AW(`s+Qq zTiplu=n*RU9Cdoa>D~C3aC(nWzlHh&&2K4+7wU78md#yuBP_KMm(W!*6kD7P58T;4)R_e7H@;E zcZxspi_n{Eb>BeZ0nG&sql+BYsk+$e4$uZ1DU1yJ1IT(NBIA`q7_~fjf-WXKLGF~n znlgt^(3vtl6R(X^>f3ax4dypV{htX~HzzoXPwa5$wRQT*QSf9?dIv* zyldGNSNus2_|p|v3~L^;dDN)QdONQ_?=$Vq(Rp^Ap4uh!$B%SH-HjjX=arW$JNcou zpXh#d*L|u#_7)_qj@)eyI-+>?(w;e)-^!})o^JNnvfVsBzpsz-o6zTbKY3?%^T)Hz zuVt6&-z`lWe8K4TUEf`M`;?vuA2wI%B7Q3SR`Uf9UVL%Yq}!NY5-QuTo9b45t%tVh zGJMx(tKVER_SEcS(lyakTi&eCeJJ|AgY1Vgm+VT+P79LF4Od5{7R76E}D+zm!XkYEb*h9NKtNHn+@R>5}I3)od)SJ5BvQ&9}_VFhe} zov@$lG!+;=gyBQI0f!Ia@S$n27;yN|R@e=P#4J#4--E%Hc- z$fI6JgDlu5QpI}}T~$>L^{@vHi#$dPKSpammIHwTUP=MO$2P$ZpzvcyMgCFytAIj~b?-Eg2%>r9J49Yg1f0Fd=X&(@ zO(HMl!*-FEsm;stVVB4&B=-tsw`0GZ0NV++eZR=7>42|S`TiQZ*XD@4o&u#nqC2wb z{~fg=Zw!H*tN{gZROGEpr~sV5MRGfFx)b@|rUCD7BYy|ku57^3y99VI2bx6Q$JhHC z;IPQg;6jEDge7L_loRK zh5mq_{pGNV{@-8A2eREy5?^%$f_;VZD++x@_Ft#K5TMZ4IQtsgZ@f?pIQ{0RNCUbC z5^GotB-U_Ti>z4ZUVBO-^Ap*Ns7gp)&CMgA#}1*^b( z-wFFf{*?|xfS~`v_Ft8-0k#9d{&h&?TY-+yA9A4(=D-SA1)Bl;Zv%&UX%ab10*BLJ z8C1b0*bV#Ph{$)DkPXA300{aWLBHE7@;%PKp9Tc}0o@O!fS(_#p&s_YVUZ)W+7ZhA zmsBD5Bb+_15DAl=xzZdaV5Asu z8ad2%-2AD$GHBut>J`8dQMwrBz+yn|nFbATl)pOYg;dCg3Q-9uPzuYS8tP#W4;&-& zE#r?q`f%uHi{Z!6-y8UAe*R6O64L+&iRSYT*vFqSOoa@X4=bQnRGW@Kxi)1$kT%<4 zFB}qeQhyi%c~A)GPpSfZo>VU?Igrc?!eoTWdqka#qmwZ_nM_YUD(aMcSS9LIFHqxC z_rYONDT~?43XsfcUOwj|Sz%C$>};ZOi2P$??VZiA>)oTO$! zG1S8mQKysn={PP_P5?4mj?}_l}h9Nbru;Pz$?YpQujMxD($ycLaQO z&IKyg8QacBMV&DUiY1`Vn8ODOpRrq18V=JiOxrB#ObVWf?##V#L{yhV$O9a7LDm(0 z*ZzQg*D|0?*X@99`e2v?eD6lNZqr~stbh%$UDR2bP(}ZrMS<=^0Hf~Is(U@`fy1IQ zypRSMXJkV@lt39Q0}{``J_Gv_rSgf_C2ugQ4Up53%g(+VBa%=0zK10 zO(~wP0c1Uoit3dN^I<<67u7oj(xE?)XYV{H1oG|OB zzgg5^0(2M9vKQ=u!=f(4`Gw1%LDWULPzlF*`k6$s37)-I)bDfPkf@70LMEWQ zc$cV4Ncs|d4%sB?(oBZJr8pg0D(W(VTvh@obLIfGyd3#3vL03;>I#y&qMEYbvl;r&{4*HS(&14!(;J)%YohuxyCpT+QK221S7s`NS zCQO4Pq9zjL))ZI;`$QF|LY1i7u)VDac8Hq9=SewGFKROS$+XI3;*<=b|4YcC1g9k{ zpc=M{nnLqTDFD7t6`;V>-J))vCTdzDRKk8y)BD3_Q8NfIBM(-<4pB3cVH%(-O@S;p z!f*7D&DtyKjzU-=YIZ99KYORBIXIltAZji_=VCA~AGX6GQFo>R3Es))GUR30ml3?| zxTw2uephc80;7NccP)kuKq7bTgQKGECZW4CARF*;Hx;_O9L!R1cP;D!61cmGCP{_< zFdT}2;DHL*1Umqyfuo}4Cqo9{bbdaRKsi)FE$o5@XcBc#Dr7=t3S2)jkK^#7t=d}x3sQHxU{6LO#cN?{pPLp|()!=gA5R!h<#3x-1xltBe- zf*r6Auw9DnQf!xEyA<1{B~T7kP)q+W-31NMB_V6wIUfZARF?b1j?a`{$Ekchh5MBO`;x1g-pnS0w{%L zP!0942M&vR&R}IH|1kCsr$H7B2eZID zjPb)2unBg+J~%4skz~k#Y{-WaD2FPjg@3+IJS>t`*;@p|M+k|6hJ9(Penix&MCb@C$*WkDRu#e= zz;@LtsE0jpSk!7Sq(K&t#A^Jm#_#H7Pz~6w#&)%_Z4$L6mHuCo3E40lil7WCU=!?s zeL#UHypRgmKY{%d*#3Wk&nKz@f7SS@CSG-*oR=y%E^2KaQ2VvJM6D|kwVr_M(XHPj zYD2N8jU44R&Ie>qQrPfRrKnAtVK*EW_19$R4LMK*o8YLZr&9pir}_T$eoXqXHh;|A?mqo;CoFf)Ix)(S^?~83jv3vIx zECv#OelzTVy>M967W`~6$Nw!j+d`l%B(jBITjsz~QFU8IZ5;)xM7_`vHi+7W-HTAq z_xhcpUg{6IqF&Ai>|SmXwVgn(P7}qw2lX0dUdQ%z0`I{0js{V0P?0yikP2n=|C`%I zy@hgT8Y~m_w+z@L>g~lqkhk~3AviATo%ukZcPR7Deo?yw(qRY`!hBc-+hM<`cLhk` z-CQUGl6x2Vd%b}q-wUkbWjB!d`v~7h`2JQ=y9-5qkO+BD2^9J}`o9;$2B0SYNQVMI z{|~J!R+G747E|DUFb`g9YZ_>5qm;b7k? z*a7s@=QPvj*-!+u4wrz`=d{ijy`ci-AggOCnr}QQuPLa0XDp@67!F4&(1?0i*BpfZBh5MAQ$X0H;4}7j+~B za-mw(k0kbE3E=48*#49T=zcmR>gaw^$4W*0CsovclL0*!OVn}n$B`ee1p*)63x^@l zBPy__dc6NXL=zYR>5J>=M)3)eFG~* z_v;S``Vq7r&id^W-Jb&eGocVD)PDyY5`8W~&&B@SQ9!VBH^6Qg$5M%(A8Gw(0 zS)#K@AZrK|K{-^z4$*^<4=Sbq2W=94UJ8)FMX5j%7ZLEHU81v*b55_b>tT=R-}CwR z4bUX|Vw_)0nTu;hUm`FZszeXTgfbw=rTDwF2sQ&{hGH`mo1v5$O2U_!{=Y1p4}&2O zaCq4!pzvk;;JD}PmI(G<+f<16p^p#$y0Lop3%^wm) z4>#-;eGTu|5a-%a^#8R8@-WWJ1{~xOByT4)h`ufjkY9)Vx-wV=^{`L$2of7n49G?x z8$n{%Q^V`$Llqnnou3LMmR|sKfQ0fl1HS*527!ED2>3?=j!c9+pzz4;fYA-eZpZ}W zHDmxDnlrl)Dk1HzL3BxaiU8fPC~c`hPTv(L3RY z=rJh9P=hfP7=wHa@-a9nz)?XCP@n*L!45bi`leJE0>!Wb>H+!9DS-TD{M@_&_K6;g zY%D&;(h6fY19pY!^nc+fJ}iUnK(KMWp#bK?CfFAtVbOEY%^|rt1uzGyVLKcWJ=aVB&&}k+aF`D}M9<3ujP6VnT_!-F zyNY2IkjUM+z~{SpXdenTR@xzD}XW!cEW!8 ze*umb=D;+l0+LvGSaf-BCFz|TnGbO&5Lt3ej9M&|DYLe`5cq|GZW7atbUbkrf1d07nlL0*O3WBsxfdAo5^? z=!$aKCHkQf(JOJdlJA_r>d+q1m8mcd`227dpnI6lj}!xCI6u^n^7&B`c$Aor?xoc@ z8Pru2s+td*0O4aK@EA3DY!oa8j2}BB`Y+2wKaTz5b6_)IyUGhVT-6|YbphaOb*1Pv z>5u~iT!W7__s~(FGsJUhf02^n*I6EA&Hpr4H#z`Aqil zXCC)+8~027aOj%rJpb~_d*xA2kGe@CJnMXeXtzB2xUpVwp&e^l`)9%Fse7x2yZ-Q!!}Tj(q2Nz#|)mC)HYdJ44sH+0{Po(sFk zGT#Tjzx)2-+vEGt_mS^o-(KG*zE6Fh`S$rf_k9uiqCRbc>10s%l$!rh5sR`kkI5Yo-6wMU+{19zv!>`zvO?}|B8RR z|5g8M{@49G{BQW*^uOib>HnMmZT~y|UH*6d@A=>N?+*QYjHhR)bAhL?&;P5x$=_U; zU*H*{wY(6jxY@HeGe*DKrQ)zFr)oClx^6<5r+sSO z!WEv5D)iX{o+s-5{GexDLfyzpkH=FNc+_*sDWQipdQw7v-RL*8T= zy+8y(@WhWSgmmvdr0?)YgKh}|i3PT0kDPAZ7u+fP7{|FdKH6hI|G_5~U1^TvzXYMf z>K=oKX4m~`aS?>{=Pcd91!34}bU0Wvc1Ee7!GB?RF^+XbQ_2gE=(l}^r)8$Z@>`j7#F+y&z$ z6;B;Ix71TFM+@>y2qlD+jMYz_kbm!oQDkaj&44#C>8F4)%+O&~R8hjQSDLg!&2b4C-gai>O}`FQNX9_zvpt$}BbA9u0VGa0#M_K z05EK*Cr)uW-TMp?qQ*`iJ5ER#Up{?`kXbZ+!en8cc)q;*V)m-s$5}ll4oD!T;oHA;z`#n|}*88gsKL>akz6|v8+Gfdv(u?iC zq7Z0!6u7L%Z-SXTB7X>0?K9eE2+^ zP!hjezE1?PxeKO0X*d(K(9NmPX^PWyr@4aQv;bbwC%B{DIng=IIny~u5S)7futuHp z09gFa;{e6ZCC)RQD=?biyb!PyfI#5<0$>YZC*T!8wewNu<0ugmoX-Q^1AGYh6!4|< zUFZ8Ke**jlKp=9q2!f03;^GqN?&9mx5(i-btXG#fKzl$(KxdckE`3}Efz!m0SUnKi z0J{Kt0S8@31|)o0z?2} z011E;K!!G3o2%`o9fJA@Kt7-lpr3-D>43S~1^9iA4Ym@s^?=QQ9e_Q6D!^gD>)KO{ z=55s90lcrhuDz+fqx}x`9{|4q9s}wTHAR4v&W+ORymc*fAt<8&vARV3rU5ebx*Qa} z00XdA1l=e`JPx&DU5Rd{u0pp^w^X-U_kwN!3y z@m&`KmbL8l(4^ui?^qDbMGMU2=5p}MMMdB^1cbU1Ar2}p+s*e(ePVDKX0GAKKFfo^7+l@ zFCPnK$X79^XV_E z7XvQ}k%sQc-Soc^fAUClB>`eH(TgODK4J#xC}xV;WSp2I=8__*NSa2bNM+JeGD}(| zttP9atAJ4ixK3Ic8oT^J2}Dv#%nBK)M!^~SCcn%S9Dj%39zVPd!E2{J5RRH z`D24SCI@kj z_qC?mA3LI93luKG6_O^X|FNs(7~IkWd_W2sx|69emV_gX;ACi@9%&e#-paLozrlS& zgv>$x@!Q_8B|Tj4JbwJtQX#Ei%ETfevv6X`SRrR($;6pLFCfNZkDNAsijc>CM@^kj zFi{vcol+KK3eFAP6KP#yzbf{N1P2(bQ^qg-r92S?TNmt`L5TcuLW+mTfGlq{dlJ!f)?Sd%o zU}*_WNF*5QB!16|=ka?18HXrd7B4eZIf1z-#sOuXjzzaAT9+CfOE_-8U@oUfP!XvZ zRHZ_)_IvG*+W%=EYJb)Kq1XPYeX2FMe17X+UnZr zl64()opfDv-E=*5eRTtMLv_#ShHGEdzNp=x-K5>E-Ku><`K>M!t zs`eT(5m9hLf`E80=gHWEe zEjm%B*17215VwPLVY(s7ujx)Me_jb=`Hnbp3RLwAXbbw0pHXwJ&HlYxiik zX^(48L)_(T?lM%h06UGRE^NDam#3e!2jYIbM2dg1>WHk{C^Z+K4 zQANPYPDpvZb@^z2s2h#nAF-E++VAZxV_C}>*77WCfxjrDv=E3p1`y%aI-05q{k3Zi z>$7r6l;Ml4POY3`F%$lI(|Kqu7NrZ)jaWfuYpNbdjZkmM?A+7;Rk=ofQ@)5S_UGWe_}rR zxV8RqtH)7~BOix94t(75alqpikNqF}J@$R<^VsE)(*vo_QunCt_qw0!zODPF?rzfGvdNXVV*oa*$NI+%LF4_Wqdr>G!qwUG6*Ice<~+Pimjm z{#E-&?QgZe)LyH-T6?zkRBd(b{@Q)Duh#CV-BoL>-CVn|_J!IFwd-ov)~>EyRlA~g zS?$u==V}+%F07q5rFKSbNp1h{>c0#5uK9P~-+6o|-Fy9B&Ar#|9ldwt-r;)(?p5Eb zy0`M)vU^MKExcEBFaMh{-wgaF=x)ZH-|zf*r|!=EJGHm_-p;w5Q82z>Ou@6`>&HL! ze$Rc4d!~Dedz^bjvmct>bS-u*a-E=?B9I!7?hl9|q`OZu9d%qSk|6faVsOeGukVV@ zs~h6wuPFNf`l616QXBv{iTY!dZvxH%@&WGvE(3}H?*l#nOa>t35kCP;1t9eik-~^& zfV+V20TqCs6?hKi?;P|v8N~tuWC5`hB^aVWCz6J75V4g?V>yWLp_~br1sX6SVPFd4 zRg?=jP{t%oBCP}-3`(mxh@YZd3)l_(4U{hnIA8q`2jEbG1kyJEY{n9jE_n>fXp~4m zt9fbFOQ7!0hFfz(4O=L%C`X*Q8%H4Kr$8N zG;)3!oXeEsGbld-{Ea$@Rqg-})PF?T0uYG$|4+yWwO>4bY(81En(n(Ms-#QU}oENA8UZq^2PEK^ee7?u#;*gWL~gD4-)~`lIX& z7>fEtlp{FcIf= zs#b5{fD>9ly@i9k4dp8wsOr`GImkOu9^oLrh!UElAn!y8%~HTlBB)_jHMA@5LJGbJ zuo(8I_HqLQ6y$>_!GPOx)DNMA3Mt4K+-(g9`6$Yb0O}8~p#+0&7+ih>ssN+P$ z4gNquK8tc62kHZEbUx}E=TIJk%G^%k-~viGiW@r0AEShGxP5^7bwO~)v3ou0I5P+o zIjB@9odB?>3ib{3=AfcDoJ9mue?VIxd?qj$buG$RKpg6BC=&n~sOvpY$pnnVK@iGu zfC;FhF>nrGF6y08!gdr?*(jgqpz4ZpJHP~d4oV0T2x+M!VkjZV3-w}@%>ivupNA3? z2lYiAwhtNt`v;B3!BHGg!gAE1q995LwW=U}5GJ6Y`UT}n0H|06&kusBf)1hn2qoYNEf{p{gi0UttrvY!FUXK#-BB11lp%m_sAIJR=K>(HIv?c#z%!^9 zq8v^^kAo6aMsiS3L-{NRbt%d*fcc;)L%9&}I_m3DLdxKas9!<}$$~#Y{Zo{m0lq^0 zTa*wg_#x^LB=|SLBh;UwgqDJ#1vMZ9^9v!6R--`)Nkbrw#uFtRC?p(pNEH&rK@*8G z9*_z=#dQEcLJh@b05VZ;hZ2&9^h6z+2tjP2prN!7hJprtLLgiSgwku$QJD!?i-t}p zAzjE0)Q6$m1;Db>Oh9=8a1!-OToT19prCfgwQNT=?`du z`tv9QIcS!l41@jgBWRZ6AcBKt1xiRqL9-HN44@6_t5C*q(5yi@7(k@~Rpt09Zawi%@O?yox#`3%dk(2ldS;Kj7fB1?883?}6Wn@*xMO{el4N3gLP+ z8mduo0#NQ=LkXLQgL|j5DBI3di2!#Bd=2Touh z90G(RE;!vl*#poM^)FEN2J}V!7VIBB00#i4uTc&H3_<-a%4YzhP``(AG$0>!ND)3B zFah^4tyn#}!#}6iQIf+sSfG@bbg|amOYI1?PqM<4ZF7+t;1E3`rGs-*; zS~}n`0JNmVs)!y7n1wpVjo!$CUI&bZFGL>!9s)#zndmd9>tU~GI8HPiN81hMT@G5< zEBXQ8d*E{gq4kd(w7pP10XzjB48}kU6trNl4dO-{c)GS9&WZ{+Xko_KsQ{Qp3npX1 zSnM3sVcOVo*gqC_(vHEwJOH$z1^02yIcQ<$I4sXN=$l@ljEm!-og@hRV5)t-z)waQ z0Dx3ljI|H+`=CWF#@e?6uom^_QNlF)HlV&r5FTIRfcp`8;VIPj6l&9g@F`ULbP?(x ze!3C>pU}RIawp&=)ZyVzv09!ULj6OO(9lz=q3bANo~KsSKNSQEq_xaM{U*xU0JLdu zqeMFe9kgTp8(?mUg9!rptQ7Dv>XQWW`C|Yj+F7$>a4(|QgbLGz0%3wMQ4=oA6?O}y z!ej)j*}^2JVZw4@8?Ix_a2n~44o&S&4%OV*zJPclil3;@bB`7( zEf!&iyIOa|Q1YT*Yj~c!MwlsFuFu0|t^mt#@(A^6_h>uyENdXAt~vaoGa&~Jw|4q# zC%Z=p5rW{M(N*I(oE&=LrFe3{knmC)vcG23OMxOeWT@C3=zkD*3uj?i7*_75p}kts z>Co%wZa@D+javKJTlX98qV*uoa%kVn=&NRZW0k({d;Bndt3A3f z|7FfuqQY7J%izrL+{=`;*Fmwr=I+Z!s0iy{4JXz3^*4O*stZVNz8a6Aoc5-Y>YC1b zO~ep?+sWg3>peMKoeHjUFt1viV{osEC$nlgSB)i3hl+v1B{##l{l12?`x8i!;g|hI zq^M?CHExy6F&sV61E{|aM3Xr+AqO84w74JkA>_Cr>PQ=ZxG;KSSaxX$Jh zG#4O3q`J^ON-P?|`QjI2{=wijB-2fXjFXt*hPs*~<7a zxE=HJU(>i1lJ?^oFk~L{>p5F^%=CbySgpDhCn0hSmprbs8BQ%1(5V8+| zwxe~23_Fkc8TNnernTXy1wO?5+ycE6-gztM&O*6kv)fzE7vuq|UtouWhPWC(|1E+C ziG$>5$83mna;`Gl=$d$}#kDnq3H8cp@WM$n09zd@%>`jNhe=6SpU<~ctPU(CBg9gCQDHm~X2DUpa z#BiTP=K$*4!ayck@gvRz_9%HX6M0}ILX9}KX5O0}=)yaGx=kn+o`+h%ZX!6n?j=h8 znl|mg$1J$SC}jbPZ$*>Uh8Xf<jo6Hl1>o%sC?=;B1M)S;g7F zHixYjsppYN;9v>kY$)e!1m}#dx?Tum(FlL%&&Fe|BEVt16sEizXjSvIN_*i-zS0XO z>;?ad!aY`s2Q{asCTFuBGIV@9uBT&Cr=;J}Zhgp-4ld9mC0Pm#QNyj&A zdpnREHk^1noK)4^dfS!y=?~}HAe{N0kA?;_&$l5f4U^6Xlh+I@fmv-hcD^l{Ww?9Z z&udn*PZ(PUh|!5gYh8_D=RLn*Z0%qg83u2)OprSGE%frdc0i}B=`A@ibNDqp0} zD)c)r@&;;Qp%doS=xoZm3cNcr6)35)YF1y|Pe^V}$~)t={<}#zc?Gj3ZlG%^1d<(N z0e5%Jv1_Rk`M&0dPfa9nH`zw2u!W{sXDhQsgR)vKLrB*RP2IsJ14Pp+k0b*oKu(N_E5QCUa;2x5AP>VacY_9Tqs2*v zCwJnVnYeU!GbDZ;-|n~o!7#>h)~7YbII4OK;Z`zim0~p89uTcNO!oynREj>ml-3on z&1DwHnLW@F$42`J_+yRm{TO~09DNj9wX<9P0_sHDIKbz!Rm<_PWdps21%Em(*{yf% z(7-O)qu^UuzmrXl6BA_ZP|18tA9)B1BTN7h_GkE0mOSYy-45wS=n&+&*eoc~%^s}A zFnYs*W6p-7cjqHpiu)!WOKUXyU5nq>4QIab^G6B};(z8aM-4xt6${#-^-XArrGL8D z4ME@fwb;~ne`l?9Ydb0!zJATu-`J>`c4qk>IxqOvHnDx@W38;S;V@eH#I{x**=aO- zoknwoX}i+l3Ow!~HMrfg^|iH9lV4+z>~%vXS~m%snNSGo(DORh%I7U%eH~jHqTuT^ z3M%tr9dX@a-cB?c>5dvcw9jj6U1k1O3HS#M7PMkfK$QsQtZzJ8c^HRbzN4FR_wP~( z!oY%BKXSNcbM1DbKgN0>O=LZI&~b<5c}%pK>=FV$O{)<26X^`C6#7cwhw+Vt;d2!{ z*JY!{MxzRPCbD^0fI@7EHXN-Bc0Pb!f6&NdxLMb_1Lp{I4V3Bzjs`WIfyXPhfIB{j z_dm|$LF{3@@i>IMh_8s6#SaFn_4K}?AeZ5J2Tvh@is2QS=WdNp2q%F8T0E8{(7XvzMHz{cFh*!#>Mn%iosnJ9l3F@r5OeHvahV=;obO4}VnM zc;}53JH35B+I96KQnE>kwPcpgFDt0edarWL3oG8i3J^rWr{?C*V`JN0ro54lq<5vZ zNIujW|0c&R*zqs&dGQ95rtvpj@&-!k#G(phCul_P%y zZZ+aequ{XgDz(_C^A?^|0Np-C;iG~KXQCMEQfJE1b!K#f5`F8&4?QiBLz2c zKGNL8%D^@Q@jo=qO(5+^FH>~_=^>Il({G97p-4AR8Zbq0Vc(1T@lBE8F&psRt#$Gy zHp`!EFsOjx_gjCETQNM&OE8KJe*x~z@>2AO>J&x^DSQcDy|`kyMT>3!EP5j>4Hu#O^TEYAT8ZU#Fs*j&>$1NU$G{ zU}kO}0T+zqeH!F=62t5En}%f*f9HV-lu9TURxvfQQ(1cYC6rsSdfe4gdxpP+-gL`} zrbz`ght$Ub&&`y^@y7GL$xF`FLM}V(Wt`N9d`>TUduT9cZeQ{&Nv#$FSR+m~U{cI1 zcW*Rye}*pxei4i7uQ5(Wm~QnW&XR^7^*8-AkhD>gTx0WLq-8*eD#+gz&uz2}cE9yg z;-`r}x%WQmHgMRd0k?*mdJH2mG7*i_N0CYm7CyM2W_mP=T+{eZp+`d3Z#8U2oO;W{ zRA-^1DaJbmq>@ZBjhH~%i2h}aY<2=Cy8y;osIlQl(~LWdh@UcMh3Rw={DcIU&J>dw zV(=jooe2pH8+$+YfmVDUc#Gmoi~}Z)cbP>*nwWv9p# zG0d{%lx3sphIxlrQ2peF_^!DF`pie4BXa&f`^>LG{``yOM3tpb&bM?R?{2P75hb&k z>KPog?Ox>-Ux ziPRh(YN>~z^hoPq-hvp(MCSPR$3e7|%E2ol>PcoIuj5nVs%bVV5qYe7B_e`mQn^EL>Aakv-_^ivgj zy6RFnz4alZ=c(s@cNSS#hhOOgCB_}o!BrX?jr(o__Exs5O7L8UXD-r^XG+r)Jg0Z$ ziu*cusRpiW^fsxZB;-kS1<}c<^#d4AMs5hRw@j2TZ9J1K6>x ze}fjjXrOb@8bUk6^GjKbKkL^_3k3|%FIh4EexgcvPNC;(6!Pm81<;dos%D3@f|;el zhKE@eH8Kl&*ytS?YD~{gfY~^W#%J++1H-qoby$H3avDuAno9tDfWrg}jBn2*6N8mq zM;gbu0MSGTqQ%DCStOJ^HBOpEy6TBA$9hp7fu$M^GXxR8Op=TR%TgmhO&p073MC8h!+zSwebva9oz@UY;lknXX=VoR$^4wrYn;?=P@uTT3JzJBP@< zo<17&LI=+fx1HXJfjQ}OP4i^k)8nzD`XqR#Oisj-U#JIjxHN|6`vnr7+&)eW4|5ZJ zlxWdDQ%npJedHJnJ#lDWaYrvnUH{}t=kmk1FrPH}>)4UK6B2rljJ1SUTRO?QdB^8= z>^S%MJfvLkEO{QrWe*q`n_yp44}+Spjt9U*R7>7& zqGAvlQYrU|nPMlBB*!QtU!h8(wir4QLzBz%Omow@>Mg6P%{Qp_6Z(vb{Tk!u<0cBS z;$MW;Y+zYKhfG5Hn<-OUz!cz^>I^EA%c46E88$3}6xDaVnv^(ucFEAB$iB1p%EgH{V`2MADBwv~}V5F0R$2_wIJ17VkbiQGc`~A)(}`-rM`&!;RV58y|9k=0a1$ zA&@idAIT=ACMR9RRrS?ZCExlVs;gBuz%G}b`N(fVi+}pazj{c5gM%o-*5_A4$BH6o zO5O$<-3!6>F+xX7!kjMLL-CG4LahcxQ`ZMBoj@Cec?xu$>;WGo;`1lUa|17STk_W2 zIj5I&Te2i^cxBJris6Zg!z*%E26R8_9+ns$);`>0Wkgb_s!zK~2g>VbNP7*pUg+6- z(;Y+mBbIxUUoA`5CrzpP;n4K7=9Py^>c6a-n$^5zm&pT2V2jR_%c0_~6G$1O5IvvK_hVfD`9tQV9Cg2mg?W%aKzCd;3$&G6G9}%8~lruqqOp{QD zW;#X)QXHMG-6RijxobqH{EoreQ!RQfzW#jQK+~yHa=y7;@50Q0fXu?);z#D5a}G>P zPM&sPj_6e1pUMgireN%C%)z_R>3xziB`SiSPaFvk!|9)1^6_?)S%_<&k{a&i9VBz- zm)j6Gl45EfKV#|UK^e~u?ALbk$^K(ErtN-uXryoZ!44+j&3hI_byRfiBvJunF-P!!L?E???LBAL#` zb><|SEeH}KB8;?Nk!M50SV56KBu+|(tSJ$xQj(Y6P37b5>nG2yztetX*XZKPS)|!Z zZ~Xkl=U1w-Kx`zMdOa;k#x(7q_VQ9`F)$WXbT6SPCCZ=u{<3r zjuSdyE^kre%k~Y*i_t`gcA~`_V!Im)TdxakxNGpoX}@Scy7e74@z_A4vmi= zIyblI?O}->n*0)?jp4@YBZr^Sh-Jl6uh=wLuh}P4+APG_LUm~=n(zfk51nBym)lI^) zNH4s|70`gM5DE>zt%wibZ0HFUN%BgGNP;s#&q<*u<%+2f7n3jQA7>QyjM4WWF?OWo ztMAUQA4`b|s-aHZ<`R$(KC;rfp-eZ3?Oz)%81hG}Je2$#heogLcNC8z2p{rkfZ7 z*Gp1XB~?;rawuJ(?W4lfKH*Bh#2OMcL6W>7WBz%|qqpa!Uk}ZlzH3I$@K$}xdYX@l z1G1k@Z?WK~^6On@zdE5{-`uW&?fb;#jPD#w^ry!hSlqYol7snO%7(U!8#pC1tFU`i zbxe;D3A0PfDo1Xdn3h(wVMKcI;EZM-J@RKXmD(O8k{j)X+iklndEO?p!%irTtL9lq zLLWWd2CYjf;~<4ZxD>XfMWrY^ zzP>mobo_PF?b8Wv-b?@lT6sPEhbAis-ENYSL-4$di6p*zCU0T~&oh}z^&cBv{A5w; z8P5(ARXyrAN>g+_OE(RR>9F|bj=a1bHy78Bk~a0M{Y=38huBdP8zV zIYk_kk6=KYa5Wx~hDv2W3T+tlJIf$tH^TXOmCYH&53s`%WmDoBn21$Y1QX)Yi5Cqj zNqQDb;?yjiq3#`S^LXzdC%XLT);IBb!qAyHU8eSn&7Qns{ff!i$cD-fB zvt2qr+bO6`&v7L)O2+kU(`CWQIh7Ze=aRF%XZ3F#)pJs}-2CjggpR`(jTyM1q;uzz z4FlUhlNlD8J~%PCcUtR6eN?+HBP#~wzgnKtZT^wQ%dc_vgBb81%a5Lj{M-72$f7-( zy0iNr4e1&Z%4m$IS3)N({w31VtvXW_zg#~$#n&fgbkFQ(JGAgk**mFfRwr8sO`m_x z^61?B^y?u#X6&8OBcxTI(w^qS#3Q6#s7I$+`&50Rx(v-9-nDh>uEX>5I$!BHapUmx z!hs!|dGs7t)?tkP;F5l}=$n*Rmf3MkPGq%5hn(Et;f6^xGbX|^_(CuEf(8f5i5VFr z{$+N$N^`6uG}Qu~M4$VRSEBALcnLUhCvFl9?1zL47LAtTBzFYSJ15sj@kOuxvVU@-BqdF* z`sLN4cSwm!BEGkF^;~CY9)X7A4P4PuISs=Xu=S7oxYBh<4Jt_S z5dDX|xO8HuyN^z89vCul*^5KGyvA%UN|TbFTNU4}uxp5Al{$OH7o_@{#y6&WYag}w zXcYMDOcPQ-F-}I&U2Hx$iHSxc_y=&u4TLaozo}f zWj6C_5!)Bzmdig&!_#ORNpq5d7Ekv`$PA7tfb}ol&zS&$n4b-`Rtb zhG$3lB=k-R3G`?g=^c|5xa}fg z==iM7({sDUmA!2cSD5v4kONlS7Z;iJzow>j%KA=R^mJE#Mi%BYS@e0bzg#Kcnm4X& z&^uO0#gvtqK{LjRXuk4xME6hv9NVPXutH%XXW?ybzx{{DTIhfaGT)oY@^*e3G zHTM#aQ^D$|tW%6D3fa)zTBy7Yy*`YyK7MJ9shgh!<8lIxKFVb=8edWw4dS+>7h{Lc zAJlh7pXd`O!g>xZ=v26GPB+zrVr`GY3Vmkoj6t!<&y;0Ec1eoRTx^lp%HKUKS&T2- zU6v6uV%-D;XqW1aecE~s-umUzbxRHuwvO&Ku}i-hy(29dAw6g3c_TLpN^b2(9T28m z2F*01Pil}*#5(U|OI%U-B4a9Ij&B1KvLm!98U9~F{4VI>0B$&|7qzZ{y@KC$Fb zCGj~~C0*+{W&79(yGqkDrtO-56RB1+F030k?8VO)mR;R8lDrNjGZmkPX6U;1;yJe6 z57`9{Umw}Ku^UpwKE16uV}1pzrdA+&(gTl5ti-xUV8DqNm?KuQ%KX*|OD)t78`3Mq z#h8HZgWgR;KpZaDwU5T68Z29f%PQh&hggt1D#@$KA^BPf1$rI}(k5*mU(ZobZ-Bd> zGO{QN5{kkKs5MvJ250;@p+S@gqSra>=Q5FAei{{_`4`{(#As@Fx!Z`)NH4j=oHri7 zF}p*jiK_=#e*I|UB+|v=9n^K|fc{f+0@VS@aa;T8r{>@@0@aDrN(y5tJ~R#;YW%Qb z+0`|Jn$?idamMRr)8I|hx^$VgX>iiCsf97wWkzVkLFF`~w8ck$bt5YI^a+Qhs`h@m zk?LHm{QI#u23FBdBFND9$xi^jP#7a$Bp156e>-&d9`OM zyVj9KlAvlPETa|1+NC~QnUj}PK4(gFa^;Fm%o%B99D`-b z);qftVfRN{T-;9^gOsTOR z)S`6B#lN|i+B>a9%A|s4Tg`oYSxuI>AF?!$?mA4L(7PzB zW!rJvrnXB{dyA4R8l7EY`j+Il^j~V4Za!EQo7+CHbJ?~LFOW8?*NxsatIN}uhRy08 zm@&4z)2cp;@;ho~TYjdi1Ps$v0?BC@SDb=g$WVfKG4l#Cw#pX5#S`XS<68akgL3@3 zCzU*e3xssSax`E$xqh=@S$>LWhj_tMl@VcD;boIsSJK!;BcAS(x_JPX=c3 z2XU_=`3~Mls-)ZNY!3N!7bex;r2`#;-NNO0^eI#obt%LF9!haC!_V3^(aHr=Z#Okr zr11`EAqJRd#^fZl$QZxixdr1hqI*y65#F;~C*S4WK3p{EaAntyW6BqlkLmc4Q;X)F z>jL7lA`++0s93P%`DHoj`CTKtB2&U9jF_CNpSX2=?@jAhEGWzGV_O#VkvCx=WF*3G z(8e9Sp-ET1ohdn$F_)5sTf6jH6kYo%seW#V3qhjTjC^E16W%F4AS`20{^XRlQ}esD zOC3`g+_qEe?19nYnSNQNZ>{XB^9w61~JnqL+an;##Y z7U`jNE*tUrjWb<*qJ!`x2AC;=mi~WdNbJ<||D7S}|0_j8xNt#^gnyz?g^63kJaP2I z1gSO;05*N#3IR^7*yRH#B1nwn8xO7)Xjp?Nw^nT7)gn+!%@) zHKOO-Z37Aq&F^lBX_J=|6WlhXZE#}NlF2!(druU9?7wZpiut8u`UUz1dTQ4Bx9Jd) zy}oB)dZ*6e$s-2!892Os|E2jU$wixt0qy%Gg?7QGMFzzV?B8keiVeN9^0RUF4b9

    1ztOwY{k9E$L;r+oa{5p7zg4oW7i&E~988G$W2 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%0Dd$l5xQ zb(tdN^ee9fZBON)S7dz}c+K4q3?6UriBv=)4>joI(~gZPA{$Avk>pQjqg`ZEJSbin ziUKhI86H2wvj((B1M1oK;4(Jk`68w~pWWYG8h z3edhk1bLv(e){b9fdPIHj2JMO53)ea2gH0(&G!GG9&KPmZ6t0B0l{ra$UqJXK!>(I zkq?Raa1_GPgf?`Ed=v-ze3S-qe$;{vkoRMj`r~Zmi?s8&oyVV$;}iSm{}U2?LeQrq z{xk$JAkn88=o9%Y6O|$ziAY6*$mbrki+sWKi+GUui(+(&e3^zU_(VGC(@Bl5l2Ie_ zHATN>O?{Jq3bub&xJXwVQb4D!0+fq<8-Z$(f6(C{k)XprT1391*mo4^CUH0OzYhV0 zzbDy01CfbRk$+jp5a}_IjeHRIZ$TD1z!#qJ!Y%Rx9e*I<4+QJ61rBV|}8Iqv&xYK8__nt^iHE-8K=2Y*eBiZTuS4EnYP; zh6e43rf*T`4s#q!5tnBw|h?<|JZHszVdJ1fJA|KECae;IWKsY`dtFlR#hy#X{&9QUPL4 zDHAm=5NXH*vExZPzC%=KEXZ{#(^DC682Q4;5!Nqi0(mF2hzgHKnW)oJL5z2zDQY55 zCK7Zyql{n;M6mP`K2c{7d`2?&>L<~eqYw*X&MZcSsIx*42NFdJGQeZb8`atAU|?sr ziJFv)9`1!5i6pe}eMxDkVEcRM5XBNk)r*>vg*tSKijDyDq8miT&?%-#)YJm>iaN&x z139Nz)L#M-f;bQx8-oONi#peX6y%FKkC^j_Ki>jv=jWi6?H@<7xNLNSwJV#6ts%E zlow=(ooL!Phw^gg)dJ6$u7@BDJXV1#V_vw^REa*IO0IkE3!}^ z>Pp(Lr2R@_lHC{uo+rm30ZpQ=N(6(uidt7OsH-|fU0osS8V}q5nr=}kj4Y*H)ZdCk zT^ovOQGbsFBTP*LNv>nm*A)xX61=W3j}@Bcs{#8)D85#p;*+MWKrpYGEsAR zJeQ(#iMcTewB1+(27FUI+yACwFo+Bf^3f&g=2)blPSm_)P;4G?^BP3mG77mMK_>B; z9inbcMVqMk6qrwe+e~DjSyWaeXj@=`wgu$BJqF}k=q1_0I#JmnsO07!bX-KzMZKc# z$b?VSov~;Ul|xKUp{T_qTHGLNNd!to-4zIuI7N-9K^27>m|YEe&+>ERvCle3YRE&FDnGsP#dJKs-{BjY3qwhgNip z+F&9W9wZ_ixhO^z+kZm?58BZys=`792&^Emg1`y_E2=2~yr+GK&Gn_`iSY!JAKK;8|jO~h>?u97(38LLX- zDv7JiL_W$;gJyK1U(_=}h(J72k&QxBzz1(D|8$GmY$6yQBqANTAb2yun+e`bEN{Ej zvlc=Ti)3UXA7!XPGdj^PswxN(h({{2QHToo*#1?mJm?m+#Y8YXNJKhvQH&}ypdG!U zp0f~&SR^A8`6xpTn$d}VQO^e<0`W*iHVRPzAKU-=RvvVVsx}b}4-%1%Toj`U4QNNN zs241RA{NQWL_W$;gJyK1U(}01h(J72k&QxBz{mD~u@&8-UNR934-%1%Toj`U4QNNN zs2U5Qh($6ok&iOepc$R$7xi)wA`p*MWTOxj@cQ_t72Tp=UQw@_2nL;AjYlf7 zK?gokQLp;Yif&P_5&IgkuX&J&bmXEKRcJsvdPTi%Ar!GlMkd?;^?V+bp$5(9M87Cs z5F!wdRAi$N74V@I-J-Ud2!;oVNJlP;QH2JyqgT{63!#WbGBVlz+wxHcg0~U8treZ3 zw!1M3k>KTcJFn^6b5Mjz)PtAV?Yz)z=cT(o5D|z+DzZ_C3e=z(b60DDNhCjlhhlMhC^$A@-N%^}DD?Ry2Ry1nrr;a&!@mqdG;MD1gqqkw6>sJA0g zDyn4^;z03t$nj1M7~nfRe>Z~d|85!@(1vbN?~&*|io6$&SR^4GIVeOqNb(*<-(!I9 z^@wUUF$xi&SZgvekc%QzpbpLGK(DCxnZMsY|KpP?wZBW$2Ne3CMN}J|KlF(Dh=F`W z$B#+=aj>X%lDB7rB%h{$B%krT!wsgN2Z3ClGpH|^{{?YhW`M$-%ibb!e zuhZH7U-ygprb<*-8p=@(g1Q*UwLH*f4temQPt?CXVE(^({zE)k zMEzJSsy9{CPuU>x&!dn8ivL^>`u!&o8R!+&mk-*1q1G=gZ2w<#P=*F{i~21Hv0(N5 zMv~uHJN<%WRH8@Jffz8b15Kg^OvHnE2SY)hgH8P2*o_1fpp%P<;*f`W(OSTB?WIA} zU<4r(KGCLyWR#;z^e_*yP=#*M0pUmo^8@-syC~wS6zz5+4K1RFhav;?8Qw4Yh%(Uk zNMesH1Tj{)Xs?ySgC@}2d9%gD4zSjC#={1%aS#WDF=ik~||DKWTQwt zn$DvuMW2|53N)cp_%mJ*GbRm1s1_Z}V1hHyD*7Z3%0!P10Sk0;Bw22Na7JaH4%s4dx1f5!dCedLO3(Ev?6PQ0C4dv(-9ZsRsSb)m$j$|6yFZ%3CP+$@xpHw4yGQpE` zP%YX+K@Ulyg1}mtVj&wo(b0lTw26+1KrYBXH6P?VCk5pAiyO3gV@=Vq&7#jG@Vo@{ zi$1?fbX>9MX#`A<2MJ~{Zw5tYbcl{0g*c?603?j3{enQ`ph@)1U?hY2GkZi|NZ|{a zCXh3sP4q?K;QgPzs9yBNv0!=$2@_3FAd!GX5+oL)2JNE%N`b#7Aqz#QMhp5xUmAi0 zFpn?()|YmoSM+5u$VIE@Bp(>)<T3d|ze zEN09ia26eBb)sK%S`Z?@(xs&#NAzskW_O6bAs+O*fn;+`&^{*=9wZ_ixhO^jdPS!f zik{0_xe?x*7b&&~idvg^Q% zMS+L`?Td;*hefpCLHivfx`RY_6oU9WXus1!BvMg;YP5;YF+qDy3TV$EPfm~M#i5{W zF*z1{Sq+Q(L@yz52?dvwqgC`>Zcyy5EL5Ngy`pnNkce!Qfp$Lc(RYU<8F{Edhv=mY zY-t=aQHo~tv(2gHrN5WFUOs@FideQkA0Fuy1gt1R6`DZMy@Fs+GmVBTZo zd5n3FHG_F88QjWPq`;fcKjmmbr|4n}5lBOY=*J^L%;R06S9ORkp-^c8^1wiz2nUa! zXcN7fq^k>20|xSBFp5CGG7r+h^D-aEw}v|2HCa5M)0#@ugG6gXk%U|@h_%h4*SV1l zimfBI+(IG>&?NdP=08RJQ$3>BXMmy`Xxk78mUIIPv7sE~+R!DsB2e^3e*dU9W{Q3~ zMD*qe(N*1|xA1riiM9~<9Bq7{pr7Y?bv!CXzrggR9MP`?g8{ulTx}dmMb}aMwF0z= ze%%C9U$N+|e$CyA~P0t?!Z!1ixo#_o2}Z$yfIi;=$7Dtb>UNZd?YbB$=; zaOi#cqTgl!yqVA~%zGzW^t+v+c|V|A)6gq=zXhIu-~rFuh-vE){UHnRAvHdtFTWGk z9~Xl5b}xn6yG4JJDEd2gR0an0Gmn36 z5&fSc(R~cy*G$pBk)%IO^nn7=1GF8?7egw<;H=i*Y?iOC6~oLHV_3Zy0X1T{65$iW zP22EHF^;Gb!-^DRM4uQ(6^g-mC3mQ#F)#+n$VIyt#{{EDjAJQqT%8y}&0>rs$;cit zj;H+uj7}9}49_{wGdRyP#%7`z^baW)V_d8l<0&+uT8z_D#F*GG#_8mXh!Eq<7BM1; zKfBB;#-vg)CO3%TsSqP79EBk96c2L5h-S%RcpOuME-|KtA_MfB+9$?2JpM}(I>d-& zFy{q}aek*5GZ?@Oa>g@1zFCY5(m>vsRbpHi0S1}C`#&Qg4+LC9<3&ZF$i*bTxLu4( zXuBjABur%9rSW1U;qrVju4F)0Q8dGi zLShz@d||s7*}-6bb|#A9196Ki5Vt55_1y0y5@~FI4y6W%QiDUOac2;Cd}oIkIc}t& z5)5dufKH2(LEGYfF_wgb=Sxb_F2-G~t-Es2AVzK=(m}qvX}`NkjHMyS00Zzc&ExM6 zjJygl?#UBlS+E$(6U4~R6=MYh;h3YRVid-q22J4kL#1H)a3)wg4_BcX z-C(I7A;BYw$VM3$&?C$%3PLQ>Q2+*2M86_(J<7aCJz!vu7NQQFtObr%#$$APEDzP_ z5MyNoNU)NDtgHut#Uv;WMLv9DJnja4R)v5DH z=s+Lazcf&c(s0Bf1z9LSIqJ}YE-{`Ej6x(5kcJ!-p%V3ILys7%-3UPpl8}Ksl%g6< z=s+La|H(jvBMvFZLIDWouxXUVBN>@s>C0HcFn<$mn;6KZcqEHa84hwhlY%U^|1$+V zD2Lrh!Of*&Jj>{x<@vKM=n|t!FbZ_8B6bVKI7cwHP-qK<_~nGLr5z09Ir=}>BgXT2 z;PLY;$n)fVz5{(?RI?z}qP#@L33E`}-nz5Q{{l zA``hNL>a2!Lo?dZjeaq ziCh$-3{~)<8SP?hXVq2v5Q;ryKMj{RQpwOG`An99)pwAu>?V)WCZOuX8d2>8c zL4m!Yh(#I5xwjeZqC~6@wZ-2{*Uq@u)W*@1MXsKE`@)-Vn;$ai%*m5$lmBX-J63&I z``9gJvl*rzlQ#KWuhhl*alJ~H=u-WJUag7nt*0CkA{P@L51dz~=#91bi9L8SquW*8$%IbOn4H@Q;$|i_O%M^2O#k z=eVZum)9@3qFpia3V(6k;F>Bm^0Mr9og>R+r`+fIi#+R!l}6XOuJc^yyW(8aT+_Md z+cw!=(zn>0ujM}_H!d;H(^6PcvBZqK)b*O{b(hbz)wRvF-Bs_};o9li!DRcJkAJ#0N<6+Gss(ZL%t@XROWEvsRV0#d^+q-m11@>yH0 zZPs?H-r8a9w02ny)^4lOdc$h6-n8Db_E^o!aZdZ_LhEoRu+mzH8d8vukh2H_sWaCf7dxkeM-JxW~0<{>_n|X;HO5uQsE!H)`_P zPD|9}N&e|%|8y`iYI2nS`4s;&+CPo)PpA5))BMxv{^<<=G~PeGz(1WiIQ2x@Q*UIH z$3Fm%e*hl;06hKyc>DwK_y^$e55VIefX6=okADCj{{TGx0eJia@c0Md@ed%%9)S1e z$fzj)0HXW@i1H60%0GZ8{{W)=1Bmh$jPe(Z@)wNq7mV^3jPe(Z@)w-quQSD8X9{(^ zY>cQW{z6myg{JrmP4O@36#tS=@fV)rFFeIxc#6O96o26<{=!rIg`=HS9T^qvA3(H! z0MV0OUVCqdiuMm6+CPA3{{W)>1BmtyAlg5GX#W7B{R4>h4Pj%KL)3a-1_nURc{2!}RSSkPj delta 39976 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 r)Wk2Y{qZ=1`YpuQZ+H0@9&vTBPk392T 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 YrRV!DAGqZkMK?M4#n+KDi`t9+6JeN>)c^nh diff --git a/data/system/data/fonts/ttfonts/DejaVuSerif-BoldItalic.ttf b/data/system/data/fonts/ttfonts/DejaVuSerif-BoldItalic.ttf index 1b55e27214e4e934551dbd77848f7846da308ab9..ce9443eaeadae72b832a4ca90d4d61d96700e1fa 100644 GIT binary patch delta 92548 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

    v!2R&cF06Glp|IK|gI&_j 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⁡`#;1Ll!Zv2&;D4Ej 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

    otyg*kn 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 delta 55366 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
    3BBvxe#DB4k9?Dn4$(| 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 diff --git a/data/system/data/fonts/ttfonts/DejaVuSerif-Italic.ttf b/data/system/data/fonts/ttfonts/DejaVuSerif-Italic.ttf index 4464868f7536612758568a1d90efcb415a00cf90..c1864a3071c67157f9b3e0a4146d9c5ef0438348 100644 GIT binary patch delta 91928 zcmaHT2SC)v^8fC)+)?h1gS(?CNE1{L3kaeJ2&f<^7Q~JPPz3DQ%UQ5@&xpMR#TYww z6Ki5gHO4e!)R-vAi_e!BW1_uCw%Kh7EK%R(reu=d_N=N5p#atu-w1i zzhWk$-2wGc`6$pov-HPz0=|RtM;A{$Hn!jjvFoj5MQV8)pSTr_g zm{;NLTSV&i7wUf+JGW! zTL_smaNLBvag(NLo)ft-29UGSi1CkHxfQ;VrPo)x`PZea#sEN1{7)brL=?6YD(n!B zA$MFjj=c4Ra2g+HgtPc~N4S9eMd1?imxU|HUlpz)e_i+-`CG!*$bTc;NB(=ckWjfu z9#2Ghg6trzaKj*7h^IbPpGv&+Y5EM}4Qgc2QQO*$ zw>I(CW;SKTP-!X+^EhK^NCb~(L`SE|kL1VlQ~57h(MTF6jZx#SX{ZU%G|_}>A~o$a z3AP&=_Ys=Knw6S$noXJ=nmwBRnxmRinsb`>G#_YgXuj0k(LB)nq(#C2NwJF-}+Dz>L?NIFqZIO0@cB*!^wnV#ByIQ+myG6T8yH|Tq zd(5_4>uq&#a4gB_{%|YlpLKLA@`2% zfQA5wkz*4;xMQTFwVh*vV`qG%1A003bA%{4<^l=;;{cNZGXe7eivcSg*Ew!-+~K&# zalhkH$5W2yQ1+hV2aY!!zjVCg_`vZe$0v?ZEXS8l#7RSllg`P_$J1sxIRU^V9hjs8lXL;PCc1E>k$`r91OWJ?OD9&M>xE1|0GOo%vvdUjFiQt!>A)-< zn56@=bSnYt0Gj|i0DA!Y0kB+97NP_5bngK^0Nen43Ah7z0QgDwME6YhQV;#mgOPe2 zzzyJO)%)s$^v(1w^-=m*eWE@^-(8=nAD|zqAE7VOPtZ@*&(@ddm+DvR*Xy_Fcj@=) z59*KU&*(4cujoJ0-_(DtzpMXI|1bTo`sey8gJ5tl7z}2Ex53X4YzQ;7HncUw8IlcM z4LuB5hCznmhJ3>qL$P7HVUA&;VYy+g!Mee)%}{38XERo7so^h!;v%^?xfosCT^hOsxHNGIcZqaq=aS&k*(KejmrFmFY?oY@0+(?vlU-)I z%yU`nveIRp%O;l{E_+<|yBu{n<#NvDJ(mw$Zn%8ua>wO?%TF#(T%NhSG!mo6s581* zjh;qdW00|#v86G}7;8*4rWm^$GmQg`LyaShMaBunsm9sH65~?iYU6t27UM2LjC+j- zjmL~8c5Uk#=bG%= z)wPFfmg^wb;ja0vV_b_}r@PK^UFd3E?z+}>gX=ceGS_{shh0y&zTl&zxk0GhAXLnNyEOqou-qV6ZV)Ut2$oxCw{*8&ZvEV{ z-E!Ru+{U?0cAM!o&uy{WO1E`xo7{G|?Qz@hcGT^Z+c~%Q+&-|n-EjNT?T*_6x1Zde zxIJ@wX(A?#NoR61d76ApL8fM=mZm6EtSQlyV(MM$p$ULR9 zY;$xi9B=XRlTiQtI&UW-fPGRKpYQ1+Qv2}AwycvdOG-w~TRgvy=Z`DBP=1Z)KVW(B z8{Ym4J_d9UwIA}ScG|k?8d~WD)>NHB82Nf2aU$=Q#Y!X#&%a=KaSYG* zvKK5b1oQISJP*F0{S=;u=-V>&UEM`j{@H;yD`R;&OX+3XqHmz}<~5ydNA+!**W&>_c3}Di>=f5CiC_0?y;)`tt6O7=K zt>ukQusr#m=j#t@;%(x2d3|b9dHEzhP881%hxqhz32_XN?*qO0!hYLimqpsm@(p~w zvPs5ngWraiY>=~^^(HUq+ZgW(ugPFN=$Dcme|zvz*YLcK=dqV#jDItpkS1J3>gB~` zF3C%Hn}?ilXF=m^V{5mbX(Z=)K8VNt~HveJm=}nIA zRi5YTFK*@eIre*)Le-o%c;5rOd^ImuwQeIHXS-y=I93P@cr%^Tu!rU44Awz{He;Y? ztX$;kC38z4aZCKS@_61p@W0zj+gZ8j&C74IwG_s&wftN8UTeLIYrI1k$C|5}VCVS} ztXxQC0||>cq9?em;5J`W7q^@IE2s%(ZKTe8oThx@POQB!p5-;stX$>@NrjxSQaEnF zv6xkmZ#i3jXBFfmpSS}rzs}3w;pNA8{>Rr7(1*PIUEcmTRxVuSZMZQK;(7W1F^>45 zd>Ut5;Si_nYc`M|Gs+}4KF}Y$oNpSc4UsysHsWYbSs+J(8!}PL^X*x=RL1j*c;8fQ zPY}axkw(YMr?PUYsy^eT&E^_v6`rzj>4ywii7&Hg;d7+0K0+w+0vSt!2-_@@$zYtZ z7UI81vY0F(ZAdBEK%&Ve{1-#E;lFldFL{f!Cui_q2XdQyOXA2+E zEINr!C4K2kI+F~f<+Pj(qWkH7GMN5IAChePFZv4^N?*_yWH_}`JIN97KawlR@FVgB zcfo^961;^*WQyP~_>);yp_$N(%of6gFk%&=geWpcNEVXGT%o&=LFNfPg`T8D7$6KF z3xsLHbh1#`AZ#Fug-1A>FA@GF{6dzAL&c$Fg*aTyAuGiqv52e|$BJXg8gaZhfvgpa z#bUBfoGeZzZ-~>y>14e)Q=CakMXP8f8$|0uaS_=lE)kcI&Ehg~IoTqv6jzdM;u>)+ z*)FaV*O8s#CUFzlC2kS7kT=Ec;&xId?h<#A-C~*eHrXQ{77vqyVue^i4vFuGm&sxA zig=xz5^so~k$1#f;w^Gc{8IdyoELA4x5*{(f%t%27Jm_cA@7NQSj9ic`%;h;M6O6* zNq5Or>3iuh`BeIkY$D&v7TJdqxux8aI?54p1a*=VJE%!x(6~^urbsiIx@!+<4^dC;S?yWsrTtd>E%nwu&_19IoPTq+ zzN8JEtDLK8u(Mq!&?Y)rr=ejw2b~iQ*G20RXe(VG-5lCpSE5@+MY9>M3a4<#KVuEdbX!9;wVkAPhv}8Zx*Sl9D{t{xh!w5nLfv(7cN%+RbQu8gN zgxRzIYGrc@i_vFy@7>Lh%KStA_#9`R5qGHlICuj6H(l)nf z)JPJCKf_2e|C^4WQxWOK|Mr{6TH^EyTre{Jvj1V}@t5Js?JQDO#_FgQ#q2`^ljTl) zNiYc~QBd{Hq&vyNKq^^1)W*X7n)IbQkf5lkIH)Gwr`C(t)G5T9HQ&$GRPw`YX81Pj zKcFHM3$~NZ%`r@KMPZ0Agh+hxWkiVX6K^p?%pktvQSm5gBpwrw5kJ1{{_=KtI|i4*vd1f5qQt6cIme zG$@~14VwvkYJpEp`P7t8t;WIxJ~d@igCaG?1r{W& z140&Tl62iW_)b^L^aH`COp>ne&&$}T=W27PW9?98tv9SM3Z1aTtSLf-1VKUMF4W`% z82ygCg#dNWMx6je_9FG;=(s@y8zPK28Ia8biBphMgNbNI5#>V=ND-_6X&|Ug2$FKQ?9ogF2Jn=?i@?!C&87-v@gN`^sW5 zOVp&3Zsa$?8L}`0>wZ)`CU3|365EYdVN_$QZWY&aIojcWddL&cg&}o9cy>9FZWqaB>I&h2M9>4v5hy0HC9rru!FZw(ByZF2N2l$8h zhx#Y`r};1NUt&v%=-p~qSZ>(Fuqk2F!>r94hkJ%M4iDecWlzsNeaqd;8NKC^sL`HJ#2<#yYd2yff{2p`AkVhNC0DZXiQiuCn{Z`fZRCNDAWFy8PXK2tb4 zn|=4G|7QLjfkO}Aa4fPF-E4al=`Rlr%LyB4)3x!k2A6j(?^@oy zJimNK`JD1)<*UnIJ|oYXJb&-`XU}iFA_}p;fXyWKAMBUx7wzxb&)QGhPufq|kK2#f zci6Yu*V>ob=h=(x6YQhyMfO5_fqjsDfIZ9J%N}cQXK!ndvParm+QaQ(_GWgo-KbP6 zuauX{i{F3z{dVP7l^M*{!l`Wm08aWo%{p%GQ<5D?=-rRW_+?{OHc3uO5B= z=;KG19-V*m?xVerc0JnmX!D~t9<6(1d$jh^>PM>{t#~y5k@eAxN5zi{9_2r>raww~ z6!GxShfg0qdHB=A2M_N({O;kBheZ$5e|+(y&kv7&`0;Ye{-5-tJ|;>4{05v~K~13m(L41gmlAdHDy0wOE{Ae_koXC&Mi5CNeKVI|-` z;Ag-afG6U?56@|aXiQh_ywedi#2kF=i(!ULqkR1khZIu0-eeSbtc9RLD^ z$4E;6OOgK#>2ei>zmNhEaVN^Hh~tQF0@&bsz^}Mv8G1y3KaqY4U`PUR046g0b@*?Doo-|w00JZ!8W|jtu`JR+ zq*xMpDf06W5ZwWIANdlTii|h#QH2j+iSdXJsFc1!3U>P75FukJd}gR1cS5>A1-Ua) zQ0sFZZMq-@AwG}^xro3;0K7te0wIl%Zv><@V~~0RFo~uFsUM(|6(7K=Q3{|N@`sW3 z0Q5!v1X57LKywZ$s9>PMgpCHPpt*o_2w)bo*|!x^f^F5zPqXre!<8CDL=5=uO0HUk;VezkY9x~ zQ3dT8RES-#1uO@E#q63b;C&Sw{vsq0NHcJFfz$y2WF1~2H3D3bSCD!FyqNcg6bJ|U zBac4TKv2!V5mW~@QNdA03W;Xm2rdL}1{_3Qi}X_!92*c41d183dp!&RzZ`iVq@X?+ z!s+CTG#=0ed9({23K)re7}8OIu~>hnNJ2t(s^HWf>HB~yXoLYm?yKMwhx8}F&nU-$ zA-@vR6iesS5$P`~IDbY+Gb~Xv$d2<(q%Bl%{(_KDAQlRP)_zY<lL$suDL-lCZfm!aOH$t>+G_!#rZ0#ZuN)S@lW7UGay zjHC8Aa@w(yT%_%^Htjds721_JiaWonol2%@$K%9aVk=1uG|d;*lJUYyVU@6&Oc!jz z8lj}(Oybk<9@@i_V|A`Em|zKvTCGiN1Iq0r+x~;*Tlv?T@({J$s3pa$HR`=l|1;`C z>iT0DS$|vA_@&%G3Ti;fJ`&)a4iQ2wPO?e(z_Lz?Y zBgMv%9@9ysv7vO7ZReDiUh`uh>_95n{)04L6OHareWONLYdbcz1zlb7hJBro8u~P=(`NP+V;v6X{eNp_G>1wQm?;Hz^KH)z%Jc(c#cPE4NYVMaCZSs zArQSCe0umEKsQB+k*+cx2=fQA;b50}x!Qg-MngM{*4<{D>tS63m=O-nwB%S4x_A!6!{41-5aQZH|&Fsy~1udel$m==RTk#oI0fCJW zAs|pQc2AD*7xo{t?X;7?1+?Q5G<2aygIWp7!1167TSMG5KnkEQvntju>`uEv0btC4 z0!$dlV_G#`RRFGqFb2GwnYwhobUpsNz1*C$&sNcF@o>s;Ub&z1GXM5NMzZzcpE)8eKqx(`1Sg#RF)4lcS zvWEBe0LCqO?<}>q?W3iggZ1gs6J9;e{)705rW+=Ov%}P0ZeXt@l)xF2Kex4A=5L*< z9QLF=Mk=YzXC%wv$upWOsUv9*Pv!8`^X38}ZI9Tgp6pn(Cwt2*wo>}n23IGsQTSd=}@`QMJ-jXS6G zHZKd>yC!k_DC$Ks3V$x7U6m6^lp~AM`wUsL5Iz!H5q0}u+M3EX0<09a1(Yub-5Z#} zhO#tU&XnbURC7yaTe{rGx|$xPId$Ehf*<`jyH@vnTyGj?VtV{zoIe?R1=|E>V$e%% zuZ+|@S1lYlV*m9uTCi{%q!5Vb8hV$_z;vp!AJgU$pJ@D(+Oxzx>>o)T<$J(yRf}_& zZLo@8O$R1yaB#Ug7*~4Gl8PoPk5f9j;_j+19Fy)tSySaNhzTc&2(3RBku79kw7)h` zjL-(sS?A2vr_JZ4Uh}**>YPRBVmUYJiszMr0xlK4g@x4*W>vi0_@U@^R@08&!Y0!C z6XzCyBPl1ogUyB6U=m@cmLFlf0;z^g$dsS7TGm@k&hU(vG7f)qK_4i_W zlj#X5!lGG%;T|23Qhk0__5RP4V-=z09)gvalqhMY6v9rPv?Uu{9az$8@PCWDzh88O zR^#v2CNerIC^||A8Dgf}s(%YAh!ID)Dy`_@fW}o1%>tz&_3Sgmcat(#*&_uBN}v}l zA3+bDqJde8Pso9b-;8wB=H1?O@PNsD>fo{YY(=R3PaM0X8Mw!W+eiaVaWtZ}JD!q) z&$vb7boocqsA$j|6&)2E7@(mU<02Vg8u*Z0-=hvMEgeq~u*q}+tRUIsXPfiyl z)Kdt`^!Ay#bk#{|JavkReQ>FG`K(S|1C>Rml(NzEz20fFrY|hrw~`}3=2cvKYZx6U zklsp`^i-Nb^o+$c${%N8l2UzWS7oqnj73{|_dyHF>+ab{-QqI*FLVU zeJ*crt(~ABI*j@s9b)S`jQaZobqMAC4WZW)9Ttmj^tF!+Edgt)%I9*!I zu*Llk!|Erd;3~F0XfFU8R?fT}aWTq6gcAD*Hj?V)*n*Grf(IinrIWGPe*!jX9#b^8Ii`y_(>mE7Xq#%#McAovBQhx1%bD<{{i^1qx>v|!c>7J1G3Ty*m-Gu~ z!cOU1F5UJU9ESqCJ&1c}L%0WgMEdOS z9mEmp1U9GRKBhzB8oL6@Fp&6$mJeiWcihK%L|kCM0?MFQnucn7jR&8gHJh090YcMi z5W2(1@5Rg2_9{ZR|IuD0Smh{h&*tTx9wS)gC_Fy9-AZ7JrRbUouvnn1PaVZ)RYc{9 zd;;E~roB2r`Rn#IP7&v*W;kzO&r;Ql{|;{t3kSkfC#pTCK-1_S9n=ZV*6Yw-iIn}g zx*~`MgM7ud`ULalxjK=dsJ#W}Cm0Wd)Y=OtJm{5*uTL~&HeWu>XW*wE=4eWVszInQ zoQj}UJmg^O4t??>{?I3lj14a^+E3KTl2-8dGetEHj&_r^0VbA35uInI(a#z;zhk0v zlS7n`Xl#pa)lU@1?%_1|KY?xNFw@CU8rm*EIi!5ow4GEk>aF7U9u8A>U9;W#U71K% z{PNb;5l90d(MV&4Qv1REshuh+BpSQ2EQx}j$qjf!MSE!Q z9RmsY z+QWKPLQu0-0bmX%Nkh12bydW%x>jM-Kn&j(aEjsE!Wh2nOu-iMZGr8ZY+IPiH##1; zsnL=a`m|6SJOcwtjf3Z^8cP72M@jK z+H1Y)CdeU$%A=!aqvdY*AtqnedVTdBQFwhK^ZNY$?uhaeO0lr7<&2bi?r8P?m&!6c zR4%!Y3wKYnV^n!KMs>$oC5-u#btA*+F;J~9h3n@pvhzw*a3~f1c_t7uYW*=`Bs|{( z@O;02a52dH-L0p0_=PIxm9OS0Wrw{RSj&_bH1yc}{{D-OD_=y=?w-og0;-)Q&MZ8A zYQZ+QuAZ06?%ou$XD?nd>lN9u@2$2I6B~z@|H2E(cduhzCd~AOG8p^__vjksTTt9DXt<8o8YD65`8KL$y@-a;^$P8d{BI*II z1xCY-2j`Hg{-rhq?j?8d9cf@=lfNiU%x*%R6J|6ysjLc`F?2@IapjVb(PTzKwM$HP z6J?wE+>3J-v2Ar1+TlGaD$3MhnqR5-+HWHMuAKUUzQ8wrqgGN z4)_oWk)$<<^z4MU8;X~Nh}Z!ocZ(SwuZZIz^eO^+6&Mf#oPtAwna52cT6>65Z6ZU& zC|P4Md$@a;G|?vJ35!u;ZvW6vKA!!4c|@1u80!enMNQtw|0FiD#emkGT6K46MSK0) zvYBRF^5rZgK?-nmUXW$`-Y;a~nV9L)&W2gh*FVhZ;H4aK4~*|=?H{Kf(l9SLxo~rG zw`v+GDQ%Nx3=UPMd7lmr7#wdjP)E&NdP)9B`M1mnp-Q=uC9cJ4HN*#y2J+UZ=)WJ7 zM1Is&%9~FxcIr1}M(Dh!o=*#YvIyfX=L#S}B`tru(`C7`>6e^g>u(F&u!{WXR6XF& zI{`Hjm~||Cqt6@+l@?$V@jroVQnEBVVI{rs=!!IM9Vf)osBj@Lz+e?2y1p9P+TDZ6 z3avSBqYww~cxn*A)?ibVTaYlZ=+MkeZ!d45{ffeY8^;ca^)S22o&l{}CA6Y$Z=Mco zLT6YGD^<-pPU%%YQM@(##iU8eVK-=#?gPueSTLvL*4}|h#rrQ# z8L{6w!kXN=fl-oo6&HV8`10!Q^}}+02?)6J=gtSKPo}BfN)%#;;5{u+>kzyS`L;(z8Qcv)=6F)asmzmE^yk@yJ9;V}u z+wV8_y&?LqqG2nmXPCm9_fk3)&~KMDX;OU*2kG=eA+_+v`AtU{LX@a+#NeDEO# z@}n3|hs*>9)`?u4l^q?Wwvh!+acPSO4)&91phfv^z^MU;Er-(%n`wSf`nl=Nhe=J9 z=Na9zhaGS)P+HO(1+-+;yJHItoN|KLu>1=s_hGvqjD!g`)<1;X9uI%Sb0AkNn!~6! z`J0}a&yPB;9Q34`%;grr8frP1NuTf7YoSLiD|S$=r*c3!Ir_YLm9k@6f#5~=PJh3! z@O=i;mBQ*<1yZQ;10hfdiK={%nSsFK((08!!*ENF`MOY!a+DN8nZ(< zq)pADPg~wk$gqDr@KPlW@t1s` zUMje>ROz&!z0u`Eqf0Z-fQ`b{0@|xkN!qs^feXdqKY6{u3V|%a9?5MkkC>SAk zty#q?gvCN=BrK3tY-MIv%M?YwTiE-{!~Nr_Gi0!OU%NBg%ru!^{B-u)!Gn7+iPed7 zFHgyw+Pa;x?f7ON@!bOD)|b~WD84@HOQ~A|-!m)aI4Q|ZBf|Uxfp+#v+10k=vO5j7 zoxI$*b4-U8g~?;yADrE)<>s}2?n~_`(hf1>bDc*-Zg-LcTQB!~FeOURXyio`#|{b) zjfh?{X`UD~wolt2N;hqJ`Nxh@N)uz}*!|X&iirU;E~&XbUg7T9XJ>POTl z`1k_T(>58aGcOT`?4@VBxnY`jv zRZm`$^7eK=8ev;?(c<2uX|v|xDV@ib9&i_P=gxp``}?0QtN7&38aaIrBzzF)G2^iT zlW#85CUtvd1ko7tk=V)u79qrPrh@iAYN59+yOmyX2h9bvmEbdWtkRF}9Xq!AH|1hM zMa6^b8YeIkSEFEMAKSv8`^f)>uF4hnfBs5vjv`5QY`y%rbKr`(hb_tm|I{-x-g|c# zZS($&b%BKkEp)_CF%NO1?ng7a2iuzeJKI&lfhSS>J-kpEE=pSxYuonkcsKd^wJ3z(-%Ek;;^$P{eU&6z=D%XGRa8~Il6~y&BZ#UM)|N(5 z8r)2~rixXet~yw5YTtmvmR49<+rIisIa;}Z`yQ>Zs&pZ4$C|FLt1?PYuzQU_m94I< zmGs1Zh?kX=wialF;{o>DHZ(a5Ydt}H<3v*7T-Q2auTwP_}W7%~x?Np8wqKI@})wzNKF;SUK zt4nt{({@&}9{yvo{FJz|L1+Y3$Dllbrxl97kOoat9)Dn|K4>}j#jCPu)O6h<^s>kW zuTDyzy_{N5Aa#A!LS9r@$Pfa7(mo)h2SH5TF&@LoL>HXdW2V`q!n@OuQFfJ9C&83e z{VwXYRY?V+zUueVubpYE;1E#iuA|{*hXBSe#9w|E+Kbb0F!3d%bh(Z;ZS)&iK-VI4 z1Nv+IR!Bs!fCa^p{Z@KQNByjLJUdAJRu-z_N7msD&3JZ{6$SiOgtx6^y7bcyUixX?;69npAQ!wJ9=P^ zS0BxH)JBwf{LJ|`aR)G(`~JZp&NMg#ej$SIeD61j@!0$l3q6Oi}qBWBc@vjS{r7ymZ2tLCwt#Bc_%tq8jXhfppWzRcU?x*s(q- zc2485qaxe;W-C7`pKNv2w4D|c*S06cjQ^t3^M1fSEx9?(qp$SwONZGBMMvOoQN{otGvmA2MP_-U> zM-thN)Jq%aD0paTv`1sMH5vK2i`}=35q{fcp}$)8R=Wuul~zRqlym)aXo%u7`J9;@ zx(cg56x!hL$JG(ajD=~mEN$hVLjUUB1?1$>M$|?FW9gj#lJ!%No=xnbhZxIh^j%Ko z`_ofeV-1~sq-1DsXNca+rgVb=rR+@rey<0A<#6eqW^{cx)R+ahyyY*@atG%`C`9S9 z#*FU^{2S+g`Gx!|zJpKB3#0955e903!qcqK0g{IA+D0`m8^|>LehUYp+IG0BorYh4 z1=P0Zlkzt+;&_hv-`~ivL)T9MU0cvdaEVuKJALv_YdTuQPlMF29#QnTL>Hgbw5JbbC*2w9 zXm5?(r8Aq=3DU5Z9DOrs5YVt4>}?#a&F#^%zS-Cc{r+98oVa zazS|#Ve5v$Sb5F0AT@^If!B}rRVd%CwpV)8TsB^p5K3X~PfkduYb8N)JE`eOLo{?^ zX?S1iL2V~H_oW#cF9aaqCQQdK@z{JUo`eMlg`2uo z2Z*OIgw~$il|y@r87s+4>W}Xt-j3ZrbkH=1Ch#{h?A0|Zx5Jpr^HozNd-HMYx96G` z!$w_Rnmm%W^urx4e_g^B66i7B)q9Ns-mM!+{Zm!i3$Z#rHAC|od`aE15v#>*Iv;uf zhL+gI%}`l{XOd0S_L{vaiKWU&>d|y9pUVy1HgmO@$XEo^I)@8E8_Ecgnt3kz{w>B@ZS;iZaH7Z%g6TVOWYy3%v`6n9u%)aL~3 z{W@C^%r;#`o;^Rnj{-UJYWxl1SdG|&w;O?W_>C+47X)C@kH_2o#tgUD?OusZt3;LDI~>857&x4h`&Q|gQNW+AI{ZrV6(dg-L{8rJ(rtCsVAfZxca5Af z^0t?Lg6dS>Ti>Hz^>t=1nfL;CTe6DHYV5v!Iq&D!AoC_iW)+;1B96?PrQrqC?u9jE zOQUhFWv2X$SC^mcTu5IDR!ZK7R2+ecg+k%H;VXDVMaR)_%1?3#tMQOud#d%viIas( z!UYz}VF5RGHi-@wqT=z-MKse;zm$%heX+r~xlB247E;XT-!`R2#AW*Qv?#BfJqtCdHBmmOV}A8$>vxVd)}wiFmclZGZ`FY?bwPqGL@v74_Qx+$(rP@#`c zSZLyc4;G7KP*!~TYOBs82lR>D3|#H-L**~w)P>_CT8;AvTErtkf;L=4L{jzg;zX3V zaFDQF#E_ikKdgU-oSO3 zMVVv~M^7HMu`s4>!KUF#w3A1W_Y|)ni<9zUVWBu+@r@NJDJyO)?g!UUAWPW=9}o&8 zEeY|aaY6)U)*@7@VpJCx@ec^6lwVkDtzdYB|M<2g6<>~-d~Rm*hP}shDyqY20z>JP z`FyOhbV!3k!=DUtgG*xbXU7rQ_dF5tq}YS1&_mRXK}=oG~PLu*4t+gj?&RsouH?2rI=? z$=5=cS%$sFp+<7z*}C;+%NEX;Z9q4g3oIH4`3#K@79`e+i}LPkR9Y#MuU^LbFhug~ zWf}?Gh{1f7h>1R8+Y$XoqThB7k6X-*_+DBQmIc3vlxO^qvC1jkK!k6zwqs(QQHgJct`h{ zym3h3%J23Tr}%fWuJ~eA(UpVi#&ubaP6 z9HR=1_4?vD>{!KOUB~ep?LU}2j@^Hg00UDUe%6Z-P6r)i#kD%0H2>1 z=y1UecEexhxg;rZ@h8;tO%YW6}$8l6^4C#3z7XRR_ro+JGQ*|QNGkDJO`xpB~tv8@aU4Ea;#leH?ly zWB-w(eU|MBeNz_^pH$VWVZ-c=m)=^E*U-Iz^|uQX%j9{fiB4mVK3=@z@s{-TEsuAk z+m_93NBiE18Q3wPb@M4+Ar16ZU#-15-5M1&uwa6MF$E+c7O2V{;d6KQh>6 z&T2l{@>6K1_L1Ic!`|J$F6LF9u-oEq7M+wmgLlvG>)ljt?ckp>D!%HY@aTq)g%Ja0 zy|L%Oq24q!B&g8bJSB2d_l3ivU#@m-7-SaS?PooEbo*5N%bV=EhxP!3kFl%P{=i|Y zu^FlXd2LUm`Sjy@n_fy;owX=eZ8hUnjX^nZUjCxa2v;4i<(fDEda&49Yeq!&%ls6a zF&4vMAZ~`&n}N0Su{FXcyI`v^5KI;WRUeK?rwkdz)*+?Q4wghYI(Kom9vkNm_w)|T zUe--n5KuYddv7{6ZtQ?~gWfxJ(xy4XI_mGajxE3S_`G#aw5y?W{=C%IIej}dad7il zbnfxIzB?8bCVA423X^ja{X=@p>@#3N|FF@tUGGL6^E!1J+TPo{{m@SR7YzyzAGD}{ zazT1aC&$3()PbWDMwLy7^@+(Gy#P$)clK>GtvE+H|A3@=dcfb1XvhI*vep@C>A7k^ zEZ+YRK;~D_&r|`dVX82*o&btzoWI_IaAv9&zm`8Bfy1TD9u6?^3l~FGY4f1k#!MD* zfUz=$#!+VAG+Kkq_Frb2MYDHG@BYnJczoNYD5tN#5YtpCUi$pfJa@l6=ZBQd>CZLW zLPM$1+;hyL^*ee@{oI!1VV?Q!v*j|;`8706*XS%RigN3)Pu%w3H~#RvR(rED^2_IE z$N8kJd$4K#FDECl-<7K;nQhQjgdZtfF0QVsuT{GRM+J+A;AGKP7-Hl$omY(BOYbkSi|BLDw?>t-aYs*4I_0}+YyM2Ohhi$)a9DjIP{Qsu; z_(WaNPifTaCh#B@oOU%az$ye^HC9Rp^5dr_?)pLWL+bV&EzMMolxu^fH}U(ol)tvL zYXF5~95~==N?$ti4Yhv#n7vceT-mv#U#+@T;kr$n+IMAsN9QW|yQ1LKan!25cwh`G zl?B#32NIF^w=2LL_Oyj>2M#;|GXHfLFo+($TE@00T*HS8bV!J0nKI6`fyE%|JY)Lg z6z26$@Y6btJf`fN_SFU)3$kWz+Vge>4XNk9;aDJ=NA9r}#|gCUfN|qSruevOJl*G( znRL+wYj9#nO>&QH)6%s=w-)X?jf+prz)l4p?#y@4bX#$WS!%EC zIb%b&R*~M$2H%7+eH*1UnM~VMOx`o1nJQnJTOg2~lbatYbSm>}81Vsxg$az_ zHhH$eg1}EXl$`QAQOCUquAzH>ovx}zGLIeU6|H? zV{w|ZlQCgp-!p?(4QymKjoSX{^kGNmC+mLH2c+h=>pE{lC!NkSb@qUR7t0&DjXV5{ z^5}=sB-r$n5gmP+rsTx5>7CTBVSB4jYR>ZO5JI_5s}mx!n&+QYD+gq*Kuq!WP4$^qIpT_%k#orEhU%#Sb$Swsx)2Q zG>3Q8>rE-v?6}FpJA;p%^Aa0{_FFix@2reqCrgmml<-z=k%>LR`!62clJAR!-CJrk z@r7&qk3BdwKFNAq3}ahogAT(wCFdkG!d42qjDPQl9lMS}QrSD{ddK@3qsI>^yW{C^ z^~KV;?mWT{_VBDUhA2#7gjE@bM^GT4@V_ZbEHC)8$8rneM zY>C*WJ73~XJ4L+Zt2n19ZG zLsjEQw5KM#Ic0}E_9l_NJ)s{on7;q>;xXsv#dvsHkA6`!e1FH*!uonHTlI*>Y~!$+ z&o>U_W_cHnmxN5CS6n<&XY_gd+n~U;2akU4C;3c0GBKw8Ygnu zJX_~@2!#&jZq@;yZi5V;!qDI$1juNcl9a_Z~##Ux@z^64{NIFbC|Tq^9sKaCT9XUf39k49 zY1n7Vlnt6(WijeLm3|XbwT{}xYBAwlRT2_Rnze8w3uc1XT-KJ)? za>#b+HEol8wOM>xKxm)tNv#?-j_uYYZB91cm{anJ^jPR#Gm$BfQrp={${%bZI+Y{x z5R-|T+bq&)3aKZ<@GT?EH8BasZrFFLPg{?|mAiW-jPDVscWT*XP*jsn5e>wi2Jglm z4Z;IGB#o(ATyVFQlln@((dj3rckoHb>(a7UtiOBnq~g9%-XwB@R1UJYi@C|EDo~OUAdqn%9JECuFY< znKtn}Q#SrkQf#yFyYiV$$Ko|p_MAq^<7SoxX78}jesdcI2Go6=J#1DsG)_5|J8Q+K zk3aoPXjf1@{>`PQE9j$w>Vj>Zl6bBvan!p7zO#7*dOynMp@hsJoe$90=; z$LbHh@X#YFgln}Zb+%L|#O<&sqGk7A{Mla0$>Gj4Ze|@s9*O1&jhUBoh(R79-ohjp*1t|jyzJYX2?i7T@x zl4bje8d`_!Fe`$2&z^dWz$FPIU)-k>?Tu_Nl@ry>D`F4#Za_A0n~n<|w#Zh#%KQO~ zy2k2~OE)Z4&vQZo0;Yqftxrv3Z?hVwoEm+2cGFMG@T6_16jG?ri)krmj!~(4wK|0q zQlRkLGL_Baz-BN0vikqSVJnOcmo&MtrP^xg_dmJ&mt%eI{tw>1lEp=JyyYsm3-@4Y zpcIdE7^QfZ84Z&F!Isi2)pK_X4J}nmEN@cT%BUFzYFJ20j%Nf=`(X&=VO1c-nxJHj zD5~pHyGs7r9)Fj^v1MjOGH=hVS)e1L$)aS{31c;W2PzQ0GF9VoU&Q9IYPRAPNNduO z;Tfnpz;R-G=EHFJuf8@g&rs6Vh6(YiSp|x%}X4x zaY`@Kk@|WPkUi~<{_Um|4vh73uI}#W+PqU{_JDMcm)5}aqzIu!;gn<3Iy6f!>e!*E zXN#$u`opL-8?bC>)i_m^TJ?x&WNFoN^7ee?tCp#)yaM~ZG2RrG%FM1nn!{DQ3syH^ zw+51WfR6CzmIG`T12tx?0cScG6Lz(P$J%$xa(q2KM{mA7hK5_y_#;0$9tzfz3e>Y` zv(krpeiGJKxw+zWXqZpN>g&^Ie6XrJomZ%s3YBcxS)P7ktur5b!QOu<&mf=$Qgy-0O=w~Va@uep$Bx~6F>9Wj*T_(f z{o$g?ad%;_qH0X9Hv9}Tra>yw&11en9ARW>)g+X8krPuL~#`x(0^?;AyOJz7#bq5qCbW&GieE+d?mUkVye@w8a zd%o>NuJVLx(yTN!oN6r_qQj~Vy6f7FTt2rT-H7M6$!&yAoo9{gCdfTkPaBpL#8z~| zxfNN?-_yn&tgDpYn-*q%y=?5>@iFbj?;X===D3_N8Z+)KCR~)9!P>3>``3qEoI99dFIU#}m%vxecERYilRDP>cbh%5)=?cXg6A2_1 zCb++*1^A7dd@5R*Y^s|N{K05Va0tIp_ds+3F=t-^Kc<4$<14aNfK86qP=z zO+Gog-|8WO7E?yi0^8PZk+a)|C%OBzv9=2`dT7ET8>aQ?->gyE;ei?R`}kD7G`Yp) zbO4S9GYub}kuZ5!XRFXiNoV5Hdc@Yk+`VgNjm>K%7%Z+42^r0cVtft00YN4wXTiat zM_56kWA_CoZw;T{-T%z7l#yk{iE^7MOK=m9WfHKPnN^Dka|^AgHIe_^$jp}NHI_lO zdzkfqY+@Ig0{xFItP0U&#zMUKkd2x^xL55N3+r(Z@fa+gx{Koo4W|JIMVt@oxCgTu zN;QIH?o*>!*3tb|3~KCZo{%}%vOJ~i;E_HlGut*9;*i)YdC}Zyk#oOV6Ib;@Z*HH> z*=7mNFYOl`pH-h}3u(}*!h+LFGyMHO?bAPg^!mQ3i!R(AJ}-lDY1Ebxt!F7O!J&ab z`rQBH>^k71DxUxCdsh+?LdsndLVCG`KmsJBk&pzEK$e`nu&S3)TMKYk?1?Cj3$%~hbe+7i=N!v|{^J{puh?&{s9M}F!#?!^ zZVRhn;Umyf`U+t*!-{Ej?j2id3PaRcEQvTl(vt6b;3Jr-GWMWX+_YBA%sR5doKbrl(KJJg)L7*oB;qD0WH*@Vpj|1@ZB?4l;h^CHO zY3CD;hQ7U(kOuKFE>_Hr2omRt#;6vlY>wIaQANjq&?&p$olyBe)1;W-q8zDha&U|2 z`WcaBU3xbTUVU}%@ULQ$!~JZXitfMg!FvPiWmw~ejGK@#t}-^Lq-(dB;Ha>AJ)}YZ z{p>vqj~6jbX29U++pXf~Q}4De;eOvRW_aZbBj&F#s4EjQ8;q67M668USXjS>@kz-O zv_HHi0<1lz@WqMby*hcaTv?sm;FE%&3&i9z4k}33(V*a)O?4OqJ{(#pUNZ&hv4w)I zx?+(nOz&ITC^Xc*_WAyEcMeJP^Y6h;q*pyMkpzn~8YU8CG*yh17PpVlvzva+`pqfJ z>0g#+Ow1{cvg*z47L97l>bD#;YIfIdi-#4N>gA7lq(fK7iluWW4(pScpUTZ9wa;U*sY_xZ(Ow$2WBBUT5#$eP;V6ea64>Tb%MUvT2t>(hd5tpz>wk3 zun1Aj*b~{%qH?{m`rx4q4&_5te=Bi8)Jg93@9M6AD{kCM8VF=1kI zmm*9hw34X3j2XVDYy6RaVSxZ@g02g$EmHoUBqh$J4LiD?Mu9ADSMpPX?zOeDvKDxd ztCwDSF?{&i*Qfpa$tFXDDGRnAwMJ{}>#=LJ^|eLrZXNg7ic?j5buGS9GhoW|b4ojZ zId*XM$(25fYXD-U^_!8Uo6MFuF5~_3S=UNe8u+((Jf}Qp-j@a#zP3&c>p+l9h zQW%l(a~Kh}%M>S6hbnREj&IPb1ISzX!gJ({iYIl6h9b%N1e2Db$m35VCS9zQH3~}TFKj+aWacO<{)j!$nuNb zC_ATOn6k(YwZ1w4X6n+0SV6xEZT$2z#RZ-OKy! zYuDQKqwTvO<+a$#Sck0)`8nbDv9F*0iXFLlhIBs?W1F(&1n>)r3Gb8Q2+ai>Vo1HPYn~PQsw=W@2%o#p{`33Uq^u(aEqrIvQ5U zl3BW?JoJsXcH8={9+n;)klT6SFll%O`_%GEr)`&4WQAL1ye9v-znH6ISLx%;tI!x`6Th+E%Y>-`^>)&p@a#6$bp-!@y#0aDF6*CioNoQ+)& ztc}Ud^Q)RzgeRtkVyhg6JPOkm4c14^%`)=~V&eh=GBT&c4hhf5EQrpC2{0OCn&3N7 zLW>D$sj1e2{8Xz|cwv$?6+ugMO!H*36+P+6whEJkskjlW3yWoW2#r!FO?0k}T`JEL zrsfz6x8xcMt4k)ZFR<8ft-*}cln0hLZO!OJLtb_&x=BCbxJBW+bFMcSf9%yj}K^RH%?o$?oGk`{r3x(%fB>l##$iJ zQHy5H2aF% zHs-x6d^dK7YMC>7;rQl7cD);O9f$n=(Yjfu(2*7_fBmxmB$*=hbs>?jG#vv z9!uqKG%y(>;s#!40GD54E(&ve9Kn*11bUZ4j$kp;E>O0~!`N1vP5#vRKHTGr56Soe z@(>@Rxms@kZK#EWXG%@saZ{3*fn*}#@^?{4fJdd!4H zP9C_E4iUIRqb9jXNvHtt>#(qnp<;L%&B=B95da6@ZY2gY_vFEUBv2cvVnZ;MBF=0o|hvFwToAZ9LzRi7)h2JFWNfObe zLK_x!G$u+XcAnRDoO~Jf&{d)Q14I9^7mcL_>SFf;!7zYeFj`H=##h>Y8c1kAZ8(nsMD6N&H z1Uh6zG!ThIu#wvzPC`S-TyitRTvaarVp+ANVayr1rFNBYmq(r+ zX}3JKXx#?K`k5=D;BN8iG*&dtvHcoGucc#os(kUqad7RjJT}ad68WL7)Vv6a*1&;; zBTps~k0AuboV!#xtL3DM?hRtzz0`SL?#!xx&yZ^}Li?1h>ay;>b5rG-%+Q|2k91)z zt&=*g+0Y;;BW)u6Y%sI9lr_9EXj|FJ&g)ti%irVI(nmW(RmvPdX-NHaA$->((FjSx zvtTP%nG90!{t0|Ozqd&~KOPrf`TWag2S^-caJotHVR+QV@aft&``K99$$qw*36t2R zr7yR_-eqq+ODu9bezs*&P@vhe@5<$gT^h8I_sf|Rf&#G&o8>>-DG}SQLuO&xX6KFS@$+K4jjI-?Ui+7f zl|1?Bkm*~epc(k-LumIR+KuIN9X+K26Y)3&J}rwdS8QRTe+V#PzSwJK=VrFZGDn@- zEDSR5-m}{*Czuy^o>P&TQU1OBm3j4>SqbTEb-QQn#jRr-r;QgP8ZyzxREjC6>~Z-HnT6yyLaw3JGXCc->#9lV+Z#7v*U|e$EBy+pA{Me z#Yc5u@uTGf!&u}{Mj0x%THF@F5 z^a;Bxg2A$DxYf4m4S_D_zV*?WGap3=*j$ixZ=m5|*PDhI{aErSjhLgRnne~rj(hb9 zwu)DVbTcPj{mA)NyuDnozp*{C;r18gm^fiLKI6!nvUk`H?cT)(4VklW={87P#D%{% zO)d0e9X$`@MF5+Bujbjg0rk3OH_z`wzvtBBzq9LFeK5&@- zb5P!py>-MqM8=E`GU~sBK5)7SpWtX#!t_Kxa9RNow#2TO_ibTEo;0(S=9$jp*u=Hd zJcrYC>RNajZfmBX0R#hxew3=1*^;!z^u-g|{7q)|fO&>oZ{s+5@R|o^n%P(8XNEGY zxoh4K{!ML(jcUH-ZD)uGj?t9s2QXHum-zDuIAqGjVq!GITY|-MdO0><92H#iiqO_- zZ&f9Zq8DOoHoh)@K)njYoLB~?=uVWUGOowdeRxFJ{7oGCGDPDg)hg(-g4tl_uSwKq zh&*p&tNu|j%O1HnW3*%&lrc7}SGV;mMwc{*C~hN&xKPI*qqRr3?6%a=wOeRd()Yvj zb9!cVn^r`uBexldr{gpazCz&H4HLrTgeNkf_}`BRQ6Zo|f>u@+g`@_7PDOaEZs=_UEwvh(tLA3Xm_TkNuS!SBq3-_gG7 zYmBE=aKedLRPmV}yRm#$rrDGxeh7@_xm4OEO%12$ciR2;uS-n8!5#e{35mZhYCTO0 zk~ciCb0b1z)^qv7p2Myl+|LZMbaVf~tHXLKp>qHJ&6;!FAaK*;mKgtN&cjQ-aH62H zgo4W4?JLc47-FPDN*KwBj?ZCMt*vxZ>M@s+H6k-bnJiX(~-9G=O63PEJUcZk9PhmxH)~m z!`qmb3^|ZlvQEcC9Q9zSI$0&aFrhHg6l|09_El76V#CywU1rf~etOr_W~bADxQLFpGR4!`B`73J&q`WgLbF7@#Ex4GO$im5pBzHZ@`O0%o;a5VRnF zRsg%OVxBpuFf{DNpy$IHWQRn)b=0wA@|>{HCeZ~y1$~!;4T=UmMsE|IDP*JDvG}4f zqdPW@s9&#L{ouTT^JWzG8$7s4biH8>siSPQ(8(?= z*Do?$RKjf-mM4hkie^h@3Qv3-xZu$Rf$}4Pvt~MbcHSffvKfJfoz6|d_CjY?VWBYE z*;R}zDspT;#wJO+0AY)8)ZkLWoG>GWIi|cUhzx?mtJb-Bm~^w1Feep~yb^G1XL#hJ z0l!DjyFs&#I)+#cFJ5#Y;NwSOi#Q0q@Y7Yt9A_^vsfn;$pzPqvOInHxLkP$>YG6W1DHK2E zg|)yA0jZOH(EFi@`Kip*Wb@)D?J3iT*MCR;?!j*3BMP%;54u0WPq;q5tXWxf{HalW zL!6fj_sp7XXF!n0jy7H$Mm%rf3R}f4h6Zun8c8lPwwwmPn6=y z<5^-{=DMdBv5JBR3YxS`DrGCcJi>)mu(;I_m%6b73*ovj(#B4&e`&CU_ zk~yR52aTRAzZWY0_WID%F#`&R54!(kZh2)VN7g&+6FRW>JIr`7lI;0RPQ`d!k$jyp zIdPY#Oim$XLZ@CG3W|n?g`L^?L}=K$9%&tVjfyFYtyoktq}S-drL$X!W4l&n<}DgN zQB+n|lyYd#^$mMf*k+8vdtVtiFc`)uz>{%rPlF}Z3M*z5uxtC9 zCRh`n9!={q1`Jso64AWH_@cnL?j<=P@KFUTo5)voWUlF&Gow|rdcip@dri!3nQ>;< zsFY0MkA&fUr)RY+YMgjqYSRva{>z$UV%s0$LVC5y@7^pkyn)oZ=<59XKO!EO#$FNr zr+4wADcsp2OvkLr7Y;lUQR5Q!w5fS&)3Q+Wq%IQ!Kdd;I7Uo|++StBLK(Mi1p9JCE z9j%)Stf0+8A*e`>-ajMHTI7$kq|IV;$KkUbhLIJH>I8b9#237d78VvIg$p$Ays^#Lky%;o@W1|- z294snR9db6^+F~FWkoe?6qAw@n*NOZ%`?xi=&BUwAB(Ugc+f=yLD02huZklK0zM+r zcabETY9;iKuSxg=MHmDay`%^{NvTXb0O32iq8rt9Jv%LPep2I<#1Q|GhI!dj+nLI8 zVq(qV;g8~)W5w$EO`{tIN2E0`XxeyQ;OfTB%#neCdCfE9qGQ>sKMBF1smZMqdoJwI zrb$9nLHq`3Oi5wA9~ZP8F9?&{KiD&|b#i)xAbsol`K@hpTbGoiuXqxiV?&EQE4GE5 zw!|Mi6rtxSQ*j6lVH*B}1BCxkLR;1SC@(GB<)U&1s6ox0p zCd63Nq$d7Rr@9BSCV@TWQ%QcoD707tio!9A$5>OF_&0i;T`wwPOPDUNeh5pnPVqD7 zSyXh{+5Z(4$un-`*AEE}u}pLb2^=K1cwbkr0EbwhMI)w zZdj7*7eRVX=oM-*V8&MvT{TdYgTu1iuy0%m!ZvXM@X&v?!D+5|;eWz#z;YBACMDSw zBD^Dvz)~R&zCt~YNr3{U96Ece$V#!e)QbU@_WkaYrbRYPY}})FNx`CNV;Yrr$ZXy7 zskwQ_=5`qp!P*y&n5$4oevQg~0-2#374t!c+X&D9m|HD&`dy#>EaB zxY@4Fc*fF%k(lw~`vtG)l*sgYu}@{YRxyp@ld3xQ&`(fiyS~ep^|$t6EJc~_5<+rl zx(iA#Z(9+Uxqjy&#@ZD;Ft@bAXjoR={5;z)_|c*UzDsm`bAffO&Uv2&vzFx1gIHqf z@8j!#RWPys#AXxgUur#}{`kg$S%ry#Eeb=0j|!Q-@Z%!+$3k|krPbOpCA50>zuAX| zpeXi)Fc*_&E53YLv+!DyMEbksLCf}K^*ZIU&-LPTDf}Zy`jC`mYDU~F;3zTc$C;xPfNB4A9uMfkqQcovIM{Kl-wlV-DG{Py+u>cr1j z8!-&)`miK*f`{2o|WyVn`-^(fSR0t|(f2y1*8PV`*1^7stW{BpTwdXzDZNzhQDrbNC zaHitRv-IyOj0sP0j#1C$=<^i|b@P}ezfU;eL22`XW8qhLYUwRe=|UP<^e%qOaS+AQ zB3I+T(_k_6|4ratp{rcmn z@exO9FyVk2Zw~t%;w)1*@PFqfGQ!nQenl}6O7a4DCWmW-s28L&!gL7muGBtqz)fOD zA#xlo2x)ji#GDTvdqE^4co#U5aKiB(cr3f1e?%>Q->3M3cuwIF)jm=sJcvsYkpY@( zCeKoH$DMGbf6L<9@6o_W{gI6)^Cr6%v(~{z!(O$S_o*4Mi0ZJ43;F^M?+IGd!Ho&*pH#@1y01 zxgVpYo8d7w4Fqt=T_K>~XiPvqdvJzV5=k)h0UBzh62Qs>2C3phyh{4K6OMh~amTrz zH?#syX#*d{JygM5{EmB_>m(T6N_ZWrr_ovDD&=tg@*GSmwf;CtA_2Y-AON2{`YBU= zg6kyt1;Bf9xPnjq7kDron^)?IIVLTWL@J((os7qNO;Y_1`l-55G^i4CR~*fzxCzbS z?g|9R?IF~Hd%FdHlo$RkFZ@voKA)QIGfhGJ*}R=fLo`ydNiJPK90#w@RSvUf7ZVKPV?>6{)abb$)-NIXr7jz=!DxQKT=V0xQRH@PK{4d)!MU4{ZL=%aaav!LHR zu3v@B1>qpChF30;WsrA6e~q(+=OsV|Pd|zu(Cd1_N_Z(*)wd4-~G1CpjE7DCZ3kNHi@*|9}VuO*b52Muh-g#tZ@+hy>UF?OFvmXUK1)8{e+` zQDaEoz(^US6nr~!wLePu#E^Ff4F6H^i6P@icMov+Qt@^}X!}*I@E_h|gzjjFQY99e zFvNtFu5PRdJ?qQiLqLGC-B6DMdCydQ5GXWE=6d+#3JoRkJ6<7DexC}^12jOs#}Ry$ z`hjaeGXs-o@`ZwxL)$ zhhmzHyJ4Jq7oQVf;BcM+h(`xBJ()0CU*^r>O%eTeQ+DVp@%ts5hwg2 z(nD_M1O_Uhj-&Zcj3;D9$O^`IGDz;K?k61x+Z{uGg6W)~mzt>n+A+1xkBB9yN6T=iHxK6>u;jw#Db~pon|>98 zOczl}pS@7_KylhoePm*{(YEO9-A#Vj2Uy_P?3|cYLS@w>Ywb&(mtKl&__if1GdgwB zgJ=ZLj3kH#+&l2i{*nx|?49fCeLY;6l z{~7Y!YZ%Lim6Dw8J&0RbVeQp#Q<{T~NBb23&R1mh$5S$S3=_Q2Ygl7EiTQXuaxOiJ z;a0BU8wUHea^p|%;On0-o`Sap9)|M--B@`!#yQUx_p{$YcZF#bGpYnen+ic-S{(%L zbK_6+;Oo~LzXAS4Uwo2>=~ES-d@kfcwroJEIhSL}&n#3rA)HZQ`e(d4K}#Q{)03Iv z>FHVGfhIj@Oh&HgeYHC6!N)`3S|9WsOnS7Vbb1QB(LM~EVHl5t{Vr zk7w8$M|*gV+3=2PLOZz$fvkd$g(sPif$ph8Cxl?mU`wn)8Y`K$d2I;%H?9xGLsmf_I6RKp zoF4R1iee1ecX{J@1_s#$Ngv1(NR2CNP#&r7=JL)` z-U|K%JiJ11()Te{-d^|;uP~R(Td6S3Q^BxQ9kN~(R01S#1%ILkU;m;iZ*Tmum?xw8 zkj+BJNZ!vW!ZjdSqRX-FH$G&s{Gnk?sVBiK4%!>P=F@p4y?~AR0I~<1Cl97KqIEOI zAh=}1F_L}pJJx|e0{CUO;`>#A8!mpS7J>JufaI@`a5F@4aECew@I2GL1kmZPjTWuD zp7t@6mF&kS1aw(#KgFfPUKY<7twvPB2|dPQ7-5cBG$uh0!lnY$*d6v zVKVCINc){NgC8_e$Cc27$7xFFal$d_ckTx*JgK%4HPN_JiuXFU{m%WM{vDFDQl0xj zrF@5e7bGXRE@JH-gH=O)oP<i1%FeD=f$UC14ty|OAB2T(BgBEa>6R6JoyLb6982Sgw&=?^9k2*XUULtS93kHwdpS8(X=zsgokMSquuO$B19&9zm&O;#WPW++4Q%zO6 zg%BJs(eNdtzrlA~-L~2V9Gnk{crfqA(rz;&8=MA3)NgM(^)f6i)CnI=0Q{4N2nCWL;hl`hp z30Ow)vSp}~!t0QPsbrE)BA2D4py7HSL7XS36+G~&es#l}46GZT&n4j9jzeLJ5&$U_ z6uJ_^TM|t{?E?KlMd!0>6Hwr-eBkJ{UkqrYFZdY1 z^Eo`9hMgN<^|^wDTgbfHi~>lfu3kGPT+7w%7FKvVLuHKjI@{+Xdpsw{|;QII{)1HC$3?NyT3VwOVlprAO@w z^Lat53U4@Er)dgrNHf$1Y^f$G_=$F$xMGYA#QvNJxm%gT6=^gOLpdBa3WRwLg!7Jl5KO3V$PNVV&LPtxG%zfVJ0 z6V+J(tEf8RQ*VWv{s2R;s@nJ*KHVFRgA-C;12+~Uyj!r*6a(`GLnzSTGri%uX>wmB zsx{66++>PjicXih;j_Krt~qFjqFt*IaWA!x*pJ$O32+|lO2)ZLL5UY(7^2mPz@aun z9F8L#9=L8lHgq53DtH8NlklVb8<(gD{^)JsWXecZacc#dQhXaiL<5noxCM@33;4=g z;0VzGUv(S!YHzrtn0?^4V77+f-nRpE*w$*r6g9X*jfi=mJlinw=uZKcbXe+JWYs2Z24*7a-I8XMOhq)n6UBIYw z11EsbZ6=F1zH1ob$-${hso{72L5HaCy2~qwp8u;;>X-eo)9N3e>7e ziqRe6jrqinIya|5F@P1XVFIR zU%2|>z2Wr9Ktz5oFrZg@kH2S{viPZ-wX6tmi5KV~Lj8w6BGfa?2b?HG$g}zyh5zwh z>)n#7a+!F)xx{!GgGBtf6sufl8D`h#vah77cn!CtBp!lPQijS~;_lhXsR_OWYNj&7 zBNNJXYpUdXE#7d-fol|_cu#+VT}|UEi!CPwG*RliJn$+Gm(&8jVpynHXeCwfZum4r zYc<6edBc^xPi5d9<|#KDaA_&<7Tm)eVuff)fs>I6J`!#qz;*QImB^wg39?bR&i}?r z!Pr3&qq+$csD-mMRK@Eg0UDw(x{kVGY^^$kcX32o{`_{Mkrb?`Q0==o_j*G!U(=-!Ai$<2I*oT2#N^XPu<@#0lH-}Ak!-9Z! zk?NWd)2Qd@<6OUrQDP2Yhup9v!0J<7)AN8yBe*m%q<~13UvMK*>P*1`@lZsu*Pl}yom57-8v99xM5Tmw+TWelL6C@+F(0E zB*MZJH!KCPe-X@Jb;CNtNl)N->)kL6c6}KqjQt6|PubQQi1)yC)L zrrVY)^`mZEj$w%QgKCvaZiZ+~stj!49ech`2I9~_o#ixs)%s8H`v0o4J~8N3j$=t~ z2`C&A0WSnkxk>=rhPNq)Ur-n@ZsZKCss1`ec)+jEYP@(BXZS^jA(%q9B4K|*9`1=| z>G2X$OKTEOBtf@e@PL5+f$)RZ9{;{;|JvKg*{}OJDqX_y4*c ze)85RFGt>h)$?3xsXR}aY)+5{xkC(=wz74r-chLoHHi{Z(s zHB(0Ui6)_wpS(DN0>7YNby{IHN_gMv+dbE>Zu2#JE^htVx>2LNN1!TEwgh#4y3%(T-rHBK-(qYIoYq^0Ali9(npSel2h=fuEc zZ+9P2n%5*c63@&Aj|uUUbq2rW2LzG5(z{J=Nm#J8L8Wt@{BPj~{4$(dx*R1;$1KX5 zGMnnrZSwh|yloK2l8kUU=Cn0R=iET&lj8aX1$ysw%bg-|5=1g?{E-!UntN95$ zp&pwGp0LLfmK~CG@WctzvcIN+T`I$A&+aIrHZ9a-l7J?2*i>oF*=_Hw+GbjIwdQHL zuWXj3k*tDU6Rcv^RbJ7HnVevJw#g0+3k|Udk4gRInr*v|Y$IO6gitnH2$G%7_vF}` zu{hKwJjUxS(_unmAxR<4#qOLN|Ho=ElZ`hjkROQ}6&^dWZPk0ywzF#_V&|OmQ#n*V z$~Lnf* zj@G`U5eP}hNdQlBl7K$?9XRpVN{*!VYz~Q;LCoO#glW!S4|<7t4ref%8bGOY2>Toe zo4}y3!+F)v4;_FTKnHLwJsX_hQlLe=|H#DIM_8Ery)?4CzlrGJC018dszO7HH5^`%Pn86gv6_&H|ZFAPS)|^O*#(AhJ!dI>-?AfHM9D} zbm7}@!T+i1eanTHnBc#+de{nKkPz;_6)}Dixgf)2S!ZlzOba&oKjZjtm5?dbl} zj8roxW+JBQWPmqQt08a3jyT?5E$j>QKZeFl{%^4mJTP_faUrJq>BohD7E=AetSRou zgAo=Zyeo{>H^fO9z=Y2|Fk^R|Z{m2qWx5T*Xm&|~>2@pl1gnkjU555~Tf*nOp48O4 z(5s?1l8PfvHyHHCfdd9{`CesOg?TaPDHGo1_+D+*E|c6ns}o7L!P9_lw=ZGuGJ{!Z z=T122F{j~!BSGwSHB=|EOPo$UQdA@^_Nd6iBp5M~biB)aMebWB)h%)l5;3PWpmDA> zUKita;b`@1cM9!Lm~w9tP>3oLP?#oN-r8H=4&50?_?+wi&PbYW74C1v^_Bv94;|kb zM{AGcN_Ro_64^aBeCImibYfT;w&G&RGyHBfBJVOU9dZNnF7p*R`3^-b-Z&tL4q#tH z9YtyxHaNY8n3rg7A>zeAT@BUQj+Z37+EXN;FfDm><;|^ckM4}45VO%5u z=+3yBjc5|QdwY^cgmocn4Wf)QdhZQujNYz&)d(d%wQ~L4qXg~^S7G?>xa$0`^zL3O zspFV4tXTHF*nme8UUeiBS#MnyUR&f|m2O+dcbL^l(5J3ER1!wJo+0aHP31{S1S1c< zHG=Uj^RkIM)k{?k`xYD@Pbl4qU)x?}V&1SX+d*YnY^ZyW!|n zM~VMD22$H&-C2}%iqxxj>JUs-XGs3ji#TFWNfCeD!{y$X(WG`S%xDsE*OAm=<;#^X zQz!%HJ_cAvPkifWgzi>X@_05L6!M0_o$1b_f?W2kIKDPgH%=`{OB5{LmZ+Djye&?x z1}VV2Ev_$vBvCc~ud6q;8?G(N+t=~f&Fyj2(V@owx8+!4LX(naWOr>C_Hr+E-0MFy z$eH*j1pY~#+R{_$NOc;L*6X`jaa~eSbj-ctU8QO;tNPbOb^8WA;=B`X-HhLX8Oh7{ zYvTMT1n#BItyZt7n&`m)-_tl%jmhJL?#`rV6x;zn*05%@+TV4l z(U*>>D2ArZXv3*r%90Z|87C@)vc$8cW3ac-KGP7^sg>5;Uy{`1wL*1NhJ z^zxLPX`cpbt$wr~Ym%*v%h&(D9C}1r8@Vo5>=C6h?0oCgZNy$U9{=wv0gsV+A-ny8 zhO3EG)BT-rHA(o^k?Iz)MgR?R5&shc|D=u}-DYif?>+ITt8ON5am7A1VN9k{-8!M!o2bXdXV@&9e& zc-~WQJtC04ExOgcj8#<)x9yJG2v@l zb+k|Ge~l|m&v&ilRYxQAPwFa0sJLt%|KD9ynt!jO2VNT(nhG>#?%po+e=n7^VWUar z9}sX4@4D-#`@b3i4e9?w=%3exEqU$#-lJpD4Dik>@wKVj*SW*|f4jM$ZX3`DYLZh7 z^R7(ZHU7V=RBDU;9trby)%`!Mr?toUow@f~7u=OejVVPsUJ{htA02P~26PLu7p^95 z-|^2QsoOH+J69;U_c;DNlDQL8w;M%ws8f6Y?^adZp|a{ZJ=T49Ty3XCtE0sKw-uQt zX2r;~N_Q5sR;RXV>a+oh|GcMPt+LXS{~y7BQr8{--EJ7&yGU`?8hHBl&@)u;NLa1w*1xZ{ z{{iSFr>;`Rz5e@uaqkW;{@)CE@BjUO8d0R>QP)3h zqt#vZbor31TP4+x|15kMJIH-SgkJ}tBQ$gu)Ns;p9hW(J(Zvv45$R2rM|jzE_tla< z0Qg=l`Nees_2^1UKf*`7zSXCK#J8DMX@CIyrU@s)k-drZt9~h13^zvBx=LcDt0t&= zxcZxL@pY5LTo>s&F>boWXb<$!%X&OzAU)Ja&-dc88xn?zc&xAA>B!S*_`kz3i_qS3 ztOM&FDIZMZ|Mun&_}SQN^Uuv^vyrX!A^aluP%>}hp1ZIP&-X?6Jl_W*QXXZNO`^1f z%F}%lPg_92e7Zk9-!}ojqyd2J*hThpc6Qe0Jd2;oyMl&(VA`z1r9y>WVmpDd9O`*$ zV9}k_4E%%jgQpvwZVtBJxcG@RMSl09{FeQDbFUQUx9(_6?EH1|-_2R~hVnt1xNQCn z`=!@k`^NdXP5Aq%4I8)Jm|wj!Ry-sk32}eijkVzpRwUgEL}FWHxuWL`aUC!ZcLOO? zT@J2Aqy#4<<5hs*h;W{FGz_WpCb2Zu>2T9DHrIUc`f-aqBX!}6T?b#E-mzg*@f-P^ z{QQc3?0EBM`t>cImD4cNka1$#v~%{G%>MSSOf&oFp;yOC-;|lzG$t3xm;aJKY#x}| zwD)!vxNxDPccOSk5?sH6GsZc?b*-fPcS4u)8B@LQ|k|G5s#D|5Z;sOSeUKvHm z>IeB_`9&}$FR_3zGke6tSWPs`W?dD=p5uJ&0$XS8dYAp3r!&neSMqXpQeu&Rvh?PG z1A1?l|6I5bqG6OH#BfmG8adi@2|P(`7(*tbh%9=Px}_DjModEFL+{SEFw67o;m+ml zCfq+Xb&!xYHO-oj1hF+ogeCJbGg;i(;KG)%F@w+~+QjW({}s@BJbohctULLv#E@(q zts~nTwT^om)c!^1o}D)5v7K|)T7(44k)cA#_Hpc^-YcyI_KE3(#n7le-HIFNf4FJU zAG_JsV6)qA9?~DVSs;FXFf*|2r!n2)GY42ebTaNne2g+nP7TVr0Xe-=oQZxU&uN^V{~VZj>aZ3VPg0 zo#tqlB6g65AzMN_=&}P+h=xTNO?0~@K8*U+j4qdui6v)e8AN*B+nN+_G6ErvF4sWC z0xrQQf6z@pWZg^56sXp)wo^^4pzC2aHP;lEvH!@Kip+W`EbotVEU0+0@W@{IPzz&n z)~g4OS2UCA^>KdGrAuIghEcJtwmcX+F23zcPfqFFIjNYKhQyPIe1yXleHJhixn_raywEIIZECOzLNrj^iS5*G@V&8 zJWt!o^Y7vnb#h()7J9*yoZ(2(I8ymdzR~>G&)P3xz| zaV3j7Xl7#;R~{aBP)c{if4{$Setwg|f#p31OlY{=T85NniBk>xY|g526V7~8^T*Dk z2??JL=|A@Y;r$aUj~;R!~O08}b&EoRw#XhTmtn2?+m?0OCr*VT>=j z@XV;!EYWiOFS$d;+zLZx#oP?JLy;I7BDd)J{1es;`6c=9>HisCGRd-H>&A}~tt$== z4r5!LpFVxuV$=U|g$iSzOytj$+T%9I$~iLAOcH zHGE~5tc#+A7Z3-i8hMI0%H_sW(kXe-=&}2-Y|bw1pNe4r;26UsPh39O48q}yqEgyb z_Ov{j+&izQ<*}_B$J-OF?JJ$S?UwDOFPDlRg-FDCx31QVT|2@0So`qe6)jpOu-)Lt zdH+M5`wU)P*0jM>yG9Iu=FL$f1&f_^lwacf&z|+#)%o+HqYGG(p>4apWIw@pSMYg^ z-3(k~%uU98gv+^#&M2cSxDQ7T*;J(qbX6B76)z!mVv6-_V^+@mrf(dPKPh_1){U>n zrndf1$fTH$2W>Kc@X*GDxCfuz`nGja{;Vt0>Fp*@ z^+Ewxw*;((N+%mkKm?{HPm>LX7YnGeLlSjjcDBMY8QpRwe zMA^+*5Mys#`!FSz1s+)Jh>T^%*9UDGmpv(<<3p2|hDQ$Hl4Tye@%6Z<35#d$%351_ zGv?YGTRu-pI5vON+03T$^#u#JOqsWP)Tt*QIyrCtzUN7$dN2`yktNVoK!28iyYq@l z6Qn$rO;G?JUSgv(lXoiY7S}#&|CqkU86yW_=&U(6UOZA$ zZvXX@L~2|v5dY9qx_P`>kie6Tx(7`OvWas7DPc@ZF~?utUpY@5D-#=<(Y_=m9X@iv zB0sm%xqgg$q>NG8w+ok?2#s{OFKBj^>0d(+f{}F?qGY%k2#ZTaW?&`xrRd!$B8kXD z>Cl3X7?NS?xzt+)lFy$u)>mNhUgYmFC{G6dSQ>k?dBf&(%xR@K+z!bMm%Iy?x4UhDz zmmRyN4)Kt5ST~Ct1o13t8lCji(1_M$Vsva~Zi0Ey?c~K=|3O^Y3yfJHDV{u>Vn}jq z6fIF?qVGjX#3PHDWR9{`*uv!>yX`hRZjoCHab;B2$<<&}XaEQ`d1Jyo4HPiMiKaN)XjdD5;WGvr@4Zup^V zuN3Frr;VoT7w!>cB z95YPXICgVIS6M!H^5pQV-;C)oxO5u3^39m;LrbTB=ObXj)eYjc!7$^HrWf|l&5)*b ztQLgu_}oU?@49$o&&^B0i{`B4ri6g4&S*I$3lVnqZNHJ9c6@^>q2AKAq&@QN@_6EyIM(zSju-CjGd~LTo zW9`mM0R5Y75C%B$xCA+=*06*7Ac+7(Q$--IWMHOP8$oPdkVIiE4g3UzcuG2C3O+Hr zCFGJ+jI=z5eS{^67-C|}pO$s)8X2CS|J|O53-Yz_P6zCV_Q%DukpD6vC}P%<3G0&v zr;mBH>hr;a8ndX11d>)!`98~uBz$5uND!J8wwgPsw9Ses^7B(Wwv%4j_Vh~~ zW-n$VhJDny@r3c`*F9$cdcVDM$!XS0p0{l_LO|%#wOp?9L$rz^g&5h#PWUA2j*&H^ znFcSFxaT`z!D|-wtz}Qm^hU2PZv04D{1iinyx#Nr_azJBeo7(}D%bb0+pmAn>_}qb z?&uNgH?!ANSI>#-DrDSp=f>2gwlRe%%YMZvspBX&506y9olR=n%a%g3KuVAt7-99xVU> zMxxK4sa5zH7)xk)=e)DEuN3om0~6QJ(>n5ZE!PY9rV46FX$aL6pNv1|Xv9?!QO#2}l~&;i5c zM@*~BF+0T}s%b%fpJpN}ZA`%e`5YAyjuAvwN&lr{qa`c>t4A>*lqXBZD}I=Z`ZtOQ z|0VL*Y(bKKj*HM^6{@uZ)^DZ4^W->g=vd^}gou zeU1+1$)zPkA;mQ2ay(b12n>_DDl9HcRc{x=Z4_}d5PRePL-2wHsd~cBzAzUVZj(e1MooNi#*0x8^tt% zF+>gKip$xIE*)zw6&_~w4_VmQ3&Qz=6P&D=CQaOv_+ds z?G3+T=M-T{Qm!7G2@>t_@+M74@oi||dUB||`cmXXVWh>mdDU4q2C7m9AF=-IovD~N^ z7)HZmQaVe==VT1gHY*n@@43l{J z80X7KALFcQJ{Rw`*>39WcKy#cC?hJ>?Sovjg^-*He_+BTu_^n^EQ&UmC=+-n`lK_7!!%(q-Dc-YMdKq&21Fj;oG`jz+_BTL zv$+eqMbMDSe<&YaG<*2r-7Mh5>Z32z7?oaY zIt~U!MaL9aAo%oFul%E?S;0D*y734?Izx@o zkT6)G$MoQIDB_f|)wKrRGlQc%7GanfQFCN;k1eI8|Ke|z+2w859{;Xe|D2?<-_x5K z2F;wA-fy2=EgzPjeRAuCkI22m{EH3vFa;ZmOg9!2*=Fb*JI@*+LESsTl7?t3vxrWM zb5F}A!|$`LpSde8du^rcI(Yeu7A=or@7W%mHBD}Lnf5JMw#)*aaAcQ=6?hwfULiL2 zMM7kwxQMLF^_zU$RD~|#9WBgEG_Nsrmc&XoH?#?(;U8oOspt_bWn}A7<-Hx7 z2eF3If7yXC<;97WM_-_AK<2uH4emD~FMOO)dx6YMWGx84X-g1&h%xWlwad%~RkO1@ zwwc-A=50IJ*=jb%d~nx6^H{OBt)_=qVYAg76`!-!JTq3YLOkYRcoxz@RNokzJ$!c& zV^C7I8L3@7t@p6`=lQabJa@?4WF`-F7N^ZE)t|zi>T#R!;8FI=QTE3L*4cg&Eebkp z=o%hGgMR$svakfcYn6@N9ki_mu+*w(pDq8r?r3c6f_2R4TxI^=F28m0lN2knCk=V5O)Isa$~&T3D~Dn6pKGG6F@9}-7K$O zKVy-*U^$i|kFmUkuO>pJ`Pf&&*~eJUSI5kX6Vj*N{IA`hv)OJg(1+aoS^pq(>NhV|hHTV{X;-xSaMV2J| zUu*XtSLfUZe*As?I6t;s7qMm`G-8cLzdM^yTTPo-XcI!SHkpvEkz1V52(eh4Oe~fy zgb;;HBNhvdA%qY@$g~ORd|&4}*Y4YWKkobS{p0)H6~^> z)n7j~O&LF9$~v{?p(1q-_HUY^JTYb6Uq#kiAiTrz_$8O{ZCbPRZ3Y*4f!~$_Z+o;} zb&|HnZ7PA!{Blfo4$0YkAky`jTAJ%nZAz$9ukwAAsh#XP^&g97PE=!kiSxBgm+D!1 zTh5G}*4yT5qX#KB`zi{wnZ9QVw3W&!zNlr|Rmvg0hn8sz6=@w_rn%gcF5}$w^S$v- z`LT84W!e|IZ}LiQy6@l$ZGT_K6`DiW{`_m)ciu|vFyHbD?O@->#oCd+pRdrSv_8B_ z>vMR24?H~$ezTw8IIQH` zPP@r!D|^SS51ZyrDbNmnfgc~h==5sLU;+vL^YfXV=UE9jc7HEW<6bxzZ+$&EZ?jqL z_j%e9_%?B;=H5GQ7c?Qz{?~%R&s`6!XBEVkd~kCKCUl%_CE&BJ|7}9HHNKTSYPQCC zq+~pwcHldgof;3Mw3pEyvf9B=A(qDA)M}bZ)!s@WTV}mb;-20sy%l+T!E1bvB z<~KqT^3mGrCDsB*1ls-~3Ow9u^L7sH7r9OFA)3S=X~hSgS9M$CJauROos8dOwWnL{ zd4U4F&OiZCR)_UvKUM*}q+lED%tqF0~ z1nWyatTrddTJT$Kt79go=pL)h_mAp1*8J1$@$dMGi@*^)KG61$`A7BNt??{teBSut zD954J5je@}IClIDeYF*Es?`oG_?)$1YU|NQpX-}kBfL;zn0 z$}8tC_0`tqa_tj`m(L>%amkgECvOMhl%>uyb*DR?zbHRh+oLRE>1={d`j3ql){6{hKwGk!npF4P{JJ&A8 z%O09p`cdkI)?i?w%e~y*!@&Q;``5%PoJ+M~_cF$^v{7YsU=Q{Ef?rLh1m>M=7rHJ` z%-`lEIhQ)3+_RXM=_pa>GIomgd*F#NM?1;uT&gFyXEV6K5wE8I`ygY-xX)(Hnh;2; zAI;az1tu18a|@1HeTk2g_SSiJfxtsr03|~gNQQ_X68|$Nv^ZkX+>q3q)Gh6uY0P5O5mhiRQnz;BWDdD-( zB#E(J@3P;33p@!tGVr{9>NJ;kn)R0=)?0DYB6#)vhzMQ+OSViuYBEnwiH=N8ns&JM z_(4Tw*EAk{@MYJOZT>6$2qog9RXNIwQ^to+KJi)XGycQ# z`-VRsJ87T0rX5tcJbKE0H&wl^I46gWFWjVVt*ouByrs7GmX>!8@m_M_y=>Cvq>K-> zuY2^=yGo)LF1{l4pu%z8Q?%&1J1$tx!;~WT1|Kv6PnvmIFz{sT-(TzES%CEvLcQvJ z{XoS#<&8G$t>?MHch9al`hh>!U#(1jV~Tpl6dwIs^_EMy@5BMwHbemId0~O zhT`Wz*6|I`GI;3VIZxnyU^aozxmI?osejE6JT2Qk_Mz(fGcom=aLv$;Rik-g_Se+E zLY1s)3gt0A=O0bG+n>E)-;~{Q7!Ps$d!u?XFGmEozt8_`wi)H_=XqRU(6{|2{^-HH zx^?6xZKLj3!j~5v>r1^|i}GdPuDM&gZ_~n*Fug)1JEr=7b6h7k=oQ@AFOaMFq{B0P zBUReXO1iJ?b}dJDZ1%VKdT!SmBlLALLBB)}cC7XPq9@CKj&1&>`fD=R@u9z8ZTlpraYR6VdWqyJ4 zF`4V!B!{?;mCv0AOQ!Q2$#J@+%2`0(eEH1jmnqH$S?v6tb^-ZUNQUEMa>n_+&p5_q zkz+sE$N8#MIA8X+IiHZLop;JSb+!DihKon}z~84u_}@{#m$$X4{;xSsC%AlahyIIy ztD{=VG1=kdP?t-&9_oL{ae%+sd8WVFalXuSg!->ni~Sp1UH`w>hS> zaHO27edhm>_8JmCr1x{gu9isWLRrU`7v8Nl$r-KLJ}pb}a#L8xj$YRP#8`^*2bzRmx+p6mb7Ig1DXMcj~g$YSEBJ7&sqoR0$6cjP%x zoQ%C?xl}^*4*yenhg`zV z*u~(SYa9LdJ0|(pYAyaD?D2KiYR65uM4u*e)e)I=&%N4| zeHA%IQ)IDrktFfcGTRq$T$?=kSfI6Md=cwX-IiwfE=LSHE7%b!#*H{T$|XzR~sC zHNNEAG&A_qU4EZ7-*Jr`uOH*va-a6DP9@j-s_L|9M|>;k*1f|2+H!B<8@q*j3FB7o zC3@<#BM%;u;Hv*+>l?1qj`6P0zvjmv@B{hZw-<9p7cst!?V11A?H2i*8)g-EOnbK< z(Y~Jc|JXW%1HPF1wTLK}kGr}}{O|?uqXPF+|5a=8{n{#pXYYYKn863M_(T3{*xuW89R*RSL!{|7lz`9-nmY4L_tErd;6**{B`iIDg_EIo}t( zQG0{0@43^pl{>tVjoK~RDI(3>h5U_r`@gsMjs^RjqHg4uw8r4}@7JZVwQRGNH_32h z2X0#aF~^1eeqZm?TKGXcB%I@pl?je*a)on_{};!pvS7kQxye=G`{QZtP&YTY3wh)j zX$^Zui&DJKKM0*HYdLYZJ159`ZX6-}*dL)U6*1yzs zn`BIQhwXZ{asGv_t0cqqvVW;F6P%~WC)(Ar#Z}@Tay0vg zCgsQ_u5meUIgg9a>0ipZEPNpkVapxa@(+Gk7E#cJ+@hB6?I+QtB)T~8Ag0F4I_Ggx z?Gpbk$K7ljxzD;?HajkqN_VXPeSYBDCfw&=>dS1=>UFYR);iRpZBrEMQ7Yf9A0dV0 zI?ET{s+H$EN|mL^h0ngew;kw9w)+CxE9`a>+r5goe#hVNHXzUV4igs-n)f;y{lEL_ zTD1p4UB%Et&*ZiSOff?Mhny zYDr`;_a&`C4Gf+lvuNraJoO01&ZZf;RjX6>Vbmw{U8_hip9F8eqSXf%zQJ1f25aFP zjF)^jysDia9J$dNxzQTAk&%&qj#OA971l@vBg;GY&RJuPtg%McFw*wJ?`mezGuyg6 z-nvY&E(3{HS&3FziB?&8R#|ygN#*!^jBW@-DuKDHt)f>`bT!v!Q`~9^WLqtVq*#r! z{e3jfu`V|RdaONI-8!#FdrJ56n#;+NNI?#YP=PwMpc?}i6UpS|^2}(YBM&90LIc{d z6GI~Nb%Y}UwIT~*(2GHlQ_9dMlEtr9Ssi@U;HgC-r}51BG+vxMtr8<53)yBfDVy!- zBs!fJ7|)1AlgOD&JhO{0tzz*U`WNw}dr>KdMHVw>F@0y{p<5(33hkhgMg17{iWG)`;6f4=u`7sOLF@`*R}gziDu^pOoxq|9c#w@kl%p2S z=t4h6MJ^3N6qtNzE{a7i)4`m}m~$C(E>HCpeyE)lxLK{_pswU#tmJ^MECM^fvJNfa zz^xnr2WM3%m|7A64=AIgLu7R+7{8L#R}z0!7-Eo#d@z1hH5x(uRlOJ%DRpzRDvjWZ z2P7+{zETFSX2R7Z{6{KAMXsTcvJ~`*TuXu1wu@Xx(bo-$X*VBJ}0y;%* zsKSuQjXG#o6ktSTO&)qgZYtnrb<<9+42axZBT~tNl}#eIWMWL@)<%)r!a<@c`l|Xx zZZ8+PBS&OyD2hd@qtPOACv)#)?p-k;*SautfjKo?uVH>ohsfRJySs#6yWD8tX5~wl zz}HSnEsNY6ihNMrdaArn2g&Xm5~(9WU8l(XB)h*6!y*r)fW8gcBK5@9SBN}Fjt8qn z9*RLF21GU%i8QcALn$cY;Ybkku(w}iQx=*;HbE8&J;LITrh-Y2Rfsfs zP=^+g$8}J^uvY8BehC(=nlogR>| zld;YcRH6>e=md+u#@yF3k%wYbqX~hr5zhbX(a1#uhDEj+hyW9}F=<;l7~3|)|Ims; zHdw5SzOD{l+z_N92ZdhCH^JSR zpxs@81~B0*9SNubN#5rA+su1A-&Vqwh2IX0^@_X`hFsA9PBqBULthWMd+6^eMkVLJ zrM0SLLLUs_mg9Ub!p$1K82eI!`(7Q2U&)>}kaqqdoBJV|^5T&RDId>Aj zlenG4?W{*LIynFDSBSh%@((;9@dp&~!I;R0p`eHl(~*Y~k=_LKhFf8&3 zMSMcSPliPLa?mOADMfr*E%I47$nzQVKO^_&jDOxC((eYJ_%B~D`HK;eFKb1<%0)4# z`YWpZstr9N1H=q;iG0oY*ChYCAEP4QRET_=B{G-|`o1IXyAF}>De!yxzh}-5EcAm1 z?IJ^wB0uVA0_`8Y-6B6x(N6^+;m-vB9EK=VqE}=%9~3oAd$=BLpr~JpKmorDVN7I~ z0T$Sm0LFjK!vGi?2}LxjL5|(DcN6Q~P0;Q>kYo=F{6^<*fh|F!Zj_(`HE6)F$nSy> zM1ZkBVvvejkw2O9XCZodww@01k9F}~dyMnOoQ#))A_D)V(cdCoMPhjMunWDS@JfQB zh9L^6=;2jQu4^@5TpPrwD7qWO>5SiGVg~Uuh@V0H z4B}@HKZE!g#Lpmp#sKGk#+WEahawv3$N>|MX2Q`-IJya)=);I8#~6r23WzlO zC7SEeT#v2;^JWq^lbt&@8aqWfE(>`e?zl2kasFe{!C)+%vFv?ZsVMQ`V6PJl42hCh zi7`=}`7b57bX1gogo<)a zswib7DkJb(7V}b6d88=U>!RG?#+WEKvPWy^Tf_C6D@Cbn7v)w1J)+!3o+{e6_lt4| zd$_h)lGIL(0ucJtmtrWktm+yJ30%Na6qf3;| z9CV8ES`3Of|F4nYb%I~7#GokKsD2w0y23!;8{w!BV1a%X?5{@~dN3%;7Xp%e5d(_(f*fCzq8jA+q657c7UfGf zBH%$b3Q>+)G;{vH?BYs4Mn(B51W`yuE{ai!dbFVjgQ5%w!VrT@PnQbf6c*qI~a01U$$_A<9vUW^|z+qoVu} zf+(aS7saSVJ?H<2Hm>wwP!yg5Dnnt2K_>E1ifS~X1HBj)zY_Q>fxi;?D}lcf_$z_G68LLB zMnxG3K@?Jvi&79bLfi;(BgBmmx0|@##O)?-H*vd*QHgrAp$CJa>=AgwxbT3$Jp}F{ za1Vid2;4*99s++O@HgUqi$NyxQHp9bq657c7G>0p2zZcm ziYuweMZGA02*MD9Oyr{!)o4TqdNC}@p9Uhqz1yGMt^QdA?o0lxLkqY+`Evl=d5wjF zoMTxiL^|6>G>5jaNR7=eEg_*XR2k%tnn_+L%vLO+NbCvKdC<0Kp}KpAR4+;}JY zFv4Fp7>EM-{OpXMo$(XrC(hr+`S%ZCj6X{VMKscphZ0nw0UhYYh^UHzNTeVKMW{d> zTF{L_QB^@05|D)gl%WPq=!CbAixE*Z10>Z_k&6;kp%DaX#A!pK>N-LZjTGdd03_Cl z*Bj7+ZZJn5;SF&Eks#hdyrT#es1w!eAlN~$V*q2KIzthSbmXA~RcJsvc4A0WmyU2G zAPWU3Lk*hHi9U>o>NXIG6y%@?72y1)3a{dn(7CtHm(MU%D2$;%VPURd<9TSz`iq)`Mw4+zl1BpK{ z6C9ZXOF>}=(ti-e9^^q5=sTzxJ4HP>2D$$Y=l{PC*!>-%hKGTo!YSsELez?SXe#pU;BUmhg9f@GUh$57OVj>#B4n*`|0HdN#^BP=4AOY;rv^*4pJ)Xuw z{NAok>i~N(Z4hIk9v*^7c#wsBknD&CQ6tMlJu(W!9mV|V#7$2D1x_zOuc%RVqRt2f zV_tqoS7)SyfEiRaV?@-W!$IO>2snnZV+v3OiaDkmL!w3-h(;EQP=zLRV@TAQ2ADsS z{4?31neCz;OX0_|v&WXAPt@bGIseBo;W!#G6c7{GGC5{U)L0V4h9epj5la!VWvD^} zIzeolj!+O6mxVkOf!MezQR6up@x&&ubBQV7s3aMPMjq!siJ+u*42zoVK{;A5B&vsM zJrw4t2klv0pGE9!H?mO&PRsELVBYbJ9X~2+3hk6)bclKau_rL^gf>x6B;Sc_PYOpq zytQ0VSt>!PsVGIWsA;s*2uQ03N#{`Q92T3yp3GsvxglVYxw$Au1G>RjI!7cu0x4iT zy#&>0LYJr+?U^3jL?#gZ?Z5bF$cptaedPrG08TDlsVPX^fp#FX}@27czfgALl8JP{lQZLC0Sg4>=)MW%NtHGG4%QI01k}n?; z^&$@{L@jiK{=%K2UQGPOEU<#bR+J!codQ>o^Ah%&S4h-L=r4*uy{MNKfLxaqi+VYE zE^p@i7srTN%wRE-t{~wR<>mT0T@{Wz)S+M05@JfYzS@8XEU>x; z?O^;$3cNBBrJ`O%L08p+{H2+k|I%_%uVvD;OuDuaofs4Kx&&l{g|DOkI{JCTQ4QQ< zdZUnuGVBz!oW64U%Jb2NAyKb)gB;iAfrYQHK{L8Vy+Od5HxzUJZ)n1Rs5esKjYS~A zjeVk45L7{51q)TsUr~(~^kP)hHQ`7_0V>ddP7I2AQwUh#CdO`J-c97ZiT;~IkplW} zt^&XRsW%UZT4{iR%0e)qlKx8iZz0hwB)Ww?yM+n2(0@z6sJH5fK^`j5gkDi^qyM&O z(0?0wZtKLTs8#e;k)w*EP}MDgKZ8v(Zxc^^AmFuW-9ShYY zpbQ^=j{z3Frw|ojfqUA~3+DSm5Dgad6`=;q_4R}CTE=S`uVuWp z0Og$j+By(ayA#8r-peBQvdF#Z$Oi@8TZ<-9*VDd_qV5|NwT`&D2&90%Iuh2EgV?$j z^k4vEqVk@xdVd0#e?MdQcZ>Q!B)k=(Zs-uTo{H+3@K7~a=%HSWh`NylHnPCRLR6w1 zj5P?tkq(kJRG|?&F)ZrCj6Li@0m?znhr2+|O(7uXrd-bdCJNZp0FrKI(q;lT_lw$? zDe5DsV8Wx#7!vg{7JIA?^fhIpP1MKThylqSuMzbL0~GW`3&`^%?I%4b1i7Ca7PXna z<|w3c{+pTDT#s&yiuzOpSo|ppd#VRxqCOpoYS4Zr1lge7!u1xm&$4|sux$g2K1Wf{ zB_JDRs6~gUt<9o7&rUwyC+Z7zqQ02G`EMuaB`SKUQq(O17T!XVms8LyY6tC(AyK#H zi~5R=EYNi;!7!b9aZFf4V&?V|yEczBn->Sts2-rcu4gz)%u!DddZRivAU5?DV(a1&_8WHFp7WF;my~n)w zn8*9R>U&in?|Y2DH!AARa8TIJB2=RtgQC74&iQ}e!<9UgqX|726ZHcUen9^R^nXDA z2fdKA2TkG>%8%LwFwgkSby zSk$i!Q1DmG|EdsGApR@Hzhc3GaHOIL6gbch3iN)>z}Ft+p&U)ugvgdq#1XhOfJLnPqENOhb@tB>aiEpIGRpB2d6j?Vy04>HnGj zpXvXZ_@BE${BSh#Ise0T=)jPuzl0$RrD#IGsJlq8ivo6)fdY0B_iF_5K*C@9L>&=C zBNtU@197{F+fCf=O0;8G)IG%Q$wwW$y`ugW4i@;W3@q>)6GxdingNxYqxziaZ-#GF9Fwpk;>$ox?n&gY7 zgd-O<7!ge^M7L;KI@s!h1XN(BXpS)Cp%KJ8Q&9yz@W>U7GBD4bf+o=>goE)3J)%uy z?!-#*Y7<9Ao0JWb7<3wypdd2}MQ8>wylkTF(||G2_9dQIL9`HJLMSGrU$p%SF)SKy zzia!~fr2J;eR2)x4`n+g1Qa=?804C=(<|BmIubyF18UI)7Mx1*skx{`8wN!S3qvMK z!5)S6iFTj?k{(FX1MAU_UQob6EO-!wA4HCWIwkP`Vzq-=>)--V(81m=E(SykXCT~z z3Ji&MNDfGJXf7HtD%xS`Xb>$T62wKYIIkOM)2c8a+Tl8)(I(mv%sZkGqfh1{NAq}M>~eU|I%U_xiThNY%wS%E&>F^3raC8 zS^|5PK-GznsK%&hNhM<m@o0#CnEAn^g!FnH_~D(TJYeBdn3NTXY>+&w0W6v|Cfcb{$N~MQ z)}a$aqMa5B=ATxGTJ(vwkQ@u?TSzh4T+eP7?er4S&Tyj&gQA_8#rZ#z>T^ob4JIzi z6KydG7q^LaRxw6I%Oz>+I1}MMR}!Y*O!ZSL!D?h63p*>+L{{CZfX>*l7((57VS3Tsyalw zgGJU-NHsa`>=Ny+G0|!w(TSa+-A$gmS?nGiwV=-zihj{*z4=^pi*|2=XzNLE9~IV- z`2V|6(e8I63{mhPlbyXkmn$rMe<>=MI+kK zg z^kNXBqCMzF7^2`oCg=abToj@dm8eA{+R%kw3}RHYhujE56g^kPu725vwN-0&Kzz>SRG@wA6iQHVNl!`kFV z0=QjmBHyMK^oh1P6ZCDSuMv-gpoa7RXuW8U)r!^>Cfeh4KAwU+5XA3u+T+dO2KqP! zJV60ZM1Ytla#4b6G@%OvqCF`HhX*+*1_eLK4ZOJsJ4Jhnx9&vDtJMk8swjG@wl8<~ zilKFv{&(;PhwB4+y83{+L9JIGR3B0|stxMH>Lzuw+NeIF zKB_*ZHmQ%RPe`wPp+2cLt52ya*%|YO8!Aee$XF%SZCLZ+yD`uJ7F_eWtSE zo*8_MfZW#_JwxwtCODsUKId$8wmF}7zTkY(+3tMFxyAXiv%|U7`HJ&ZXQ%Tu=j+aG z&MxO0&NrRgo!!p2oNxQGWArkZeNuI;XF*ITZ)UGKPhTsvIvy54i`biMET!1bZ4 z*Y%O>W7j9HKG&zN&s?9o`dweRzI1)%8gPB>`o{IGYtZ$b>wDJ^t|8ZtuAf{#yM|rA zxOTaIb&a@oOOo?b^>vz{5u0LI4uD@L4F2B3=tvLNuWuDZ!H@h39(fx?~QTJo+ zCimmA-u;B!%b%(~>27vE<$l`zjJri1c0cQW&fO|^x!c^&yI*j>=x%qv1U>Ws+3fCizvX`0{f@iGy+hWz-<2A<+qW`7pVRtWfWwaqfue3F>W$$HY$x@tDzMJZ?N;JZUr=PZ>`e z&loMnv&M5qtI=jWZ@gf$7KO4iwFUBt8S7XH3ZR|0AGe(WyjX#V(jWOddW8CnYVk)L; zYNl>FOsDBG-R1;yqB+SlOw-)Q+}8{-_cQl5C!3+>6!QRcsu^Y;XdYx9Y=)bMn1`B& znGxnR^KkPBGtxZLJj$HzHKWWK=F#RcX0$oeJk~tUj4@-)I5XZ%FcZxrGuiZ*v&`A% z@n(v7f_b8Ol9_6znRCp!X1bYS&NELoGtK$t0`n9z%RJRQ&0J_^o2Q#+m}ik zd6t=Lo^76Eo@?fr=b7i57nu3x67xcHsaaqyGnbpwFER_wi_I10C1#O%sd<@sxmj#p zVXib+nI-0G^Gfq7v(&uW{7382$LnhyN}BKKR6fyT&b-!lQ}ve=CAqb7j()i^A zvWsKl;^H?C&()PB@xf+7g1t?&w@LOk+1`5WE&oL=Fg+p7-p;YNbM0-qz0I(<^ICsN z*EebE-1OEvGxZ*IMsR&T#M26hPYx~|pB!8`J~_B>d~$N@ic|CjsycUG>l3Hy^)7Er zVtlMMCow*lBQZXhBQZXhBQZXhBQZXhBQZW$d}4gC_{8{N@rm)l;uGV8#V5uGi%*OX z7M~a&EIu)QUU0pH7`EPvV-geW0ut;366^x(qnDUq7m#2VkYE>(U>A^J7hoT~#00y5 z1iOF)yMP3{fCRgML<;b7*b@`&0ut>4672#K?IVzA7m#QdkZ3QMXzy{NyIPZx`_CiVaLP_>QN%o#5*?XE~FPvmAoMbPYWG|d#FPvmA zoMbPY95~dhlWZ4|Y!{Fm@3jZ)0_@vMqJ4WwOtuS1whKtM3rMyLNVW?|whKtM3rMyL zNVW^`*adj(0z7sBo>==(d+Y){_7U*dN5Eqj;IS9>q_r+sq;F8YR>Iiy7%L%LDMXY2bail_CJbM()Y ziE+Wi8LYoPPv0{!_){C3kucA9>v{U-1B1Jj5&Th!&9K+WNJ?%!`h0z}G9h@}GG?Xw z-n>9ho@Ixp1&=~TTJR`jqy@{$NDCf?jI>}`8EL_zkdZdW_s0eLJ+tT7)yxSV_Kdl~ z-OQL9Jn9*9gGW7MZt$pQ%(d5>o9MeWUq8#fnP#Nh;pujGx*eWwho{@+rQ7AD+vTO( z<)z!@rQ7AD2X7@A>Gs~H2X7@A>2|s4cDV;-*!5=E1!UL-WW@Wv&(|Ze13&(;85#C6 z8TK+6_A(jvG8y(V8TK+6_A(jvGV|s$W@}AkYpu+7u5b4xdYl$BXO{2qBE2{)P;gvq;I7-+TDwI%uJx`W zeWMZ*><-?G#Kn4MwI*JsAMf(o>EdTuI}#T^%i0mP){d~Xb|fx7EtoexEtoex%{pB4 zTjz_db-vgJcPBo0bD|yGo%rC*iFR;z;)6G*xc%ePg8LJnW*3mwdhu%gn*;U>t~WRM z$PhO-Dc+Y^rJuwPU3ry0^+0!L1&u7_*gFgak$@A<9^Xv)p>s z-boz7nD`hE671^`n7j9SEZ37A7ae%)lA;oK#$^`;wsBTm Q?40C4qjlrm`Vzrxl1kyA%!&32qctH69|ydAyfec0@8a4NJo%%h=`y_JK+!k5fyx~ z0RaMnfc_P+V*?dMLxLPA%MczAl!ii}sU z6Vmn|WIQu^@)+ks7Z&{f9wF^}g5jw#!=_CpHvA{;f53InmnT1G$F~)PM$Pv zdW$ZT`Vh6+ZbGJBoji5aC&-()**zLV|7`5v|x=Y{MYoWIMC;`{^l z8O}dfKOt28RQ-}D>Q|0O33V)VEF_BKF~?&#U*vd_Fvn9tl?V+A4T>d7P+U+F&Xa>` z5EhggR0~F{!X#2~hlWrV{$xRr;-H;Zvgcvw$LwPg%06YElFC9w7=(n9=%BEmFcK3K z5fn{gQ5y~Qu&BcXb-198;3^A-s~u;6PXh!iR7mCedl#KPYFFi^^5yx^hb;s;&m9VQRFRpjKCFs}0m9YL41g?WA^Bd#nA`q3URLf;v^5 zrOsCusZXja)wSvdb&L9n`i8n&eM>!}9#ub4zf`|fPpjwD%c}F5dPBXVG0m=pXc1bh zmZYU>=~^SLsn$|!uXWLSYI)i~ZMZg8o2X6KW@`(y#o97$wYE;%q`jnV*LG-owS(Hb z+A-}j?Q89O?Tl8WUD5u~{?-g#)dP|8p?Vd)s$NY;dh7L2GWF(qYaDa+Zu$dGy`Mf< zAF1c-ll6!7x%xsNmY^(0c}8EaZ`QZ!ui<-ltw5`QCgz3N9lrs zW^B(x8Hh3*Wh}}>l<6q5?F;OSaa@M78f6{ICX|;@wxjGo*^6=zA7ygD!vS*x z76vQ{SRU|9!1{pA0b2uJ3)mH~FW^wXdjTH>91l1V@I%1afQtcF1Fi?$3M7GgU{GLK zV02(YVD-S-feiwi1m*;`4eS)yJ+OCR|G=SvqXQ=dP7RzDI6u(!qAjXQ;3t7!27ViO zI`CZJ<-lu!Hv;cCn8WTmXG>~Jhy&hmz#ER)C<{>F5eGctfJYqghyxyRz$1?BjvWqo z!vSwN;0*_y;rPt)b-^)58%n<@2n;?-T^B>@xDqQxx!P80nA}_2kM3cf+MZDQAEXFn z$He(Z#sh>Z-)Z|@hbkq3uY`7qV3+wNtHM#rO@XT6s$IEp z!HUWgsq4px>aO6(MYfl;g}dj#O#nsuDH9wKb}t>$j+E*ZSBdj1;*#b!qHc+9lJum@FYniJPn=>&Yha3i%It zi+oQ`k&EOK`IAP{HnbD%OuNu-v?qOl_Mv%n2pvj?(Q!1NPNXyF!*nK{MPH`d>3Ld2 zuhU{i7-I_4n9c%NAak%F7R*9eD2rintOaYyI|)5_P|Pn(sNEIPq*?IF?!E3yBJ&^Uf!~#`-c8b+ zlG~zF!Rs$gF9Wdw5-@Dogz2Q|h!GD>CM`!!7&nHr$Imd*Mf^U1!G8kjCw>Qu-;vWe zJ-P%~0}c4)BQ_;EdJ!0{nuelx0g#DbMf~Ci5F2rjXp%%~k_MzHX-ztjo}?ccO2(RE z`kB?wm)Go;JSq{w5mbpbj}M#2_e}g*(om>TicG*Yc~tqR8-kh1N%}4Qj(!iQN|R_Z ztxjvW#%9%M7Q z1&&9>6h>DbR%R)WD2tRQly#uh9kH&O&8s>cOTgNh^g!3j@Vf}VodL0vP*MdmAcgiO zJ%Um=E-0BWT)_hH;F_QDIg&ghooR2!BG6FM1u+UC)kqV>nIWzrjwghUZjQ%s-A%%R zstei9Zb8)qkc)l7Is=ju^2(NoO#m#ALgWg~sX*;4b2kv!T45Z%FN=@i`|#Y~Fl zDn-MW5Qe!}U{H8aWz5UMf}(<=gF<@-#RNrS)<;Po(qIK!$yTvv*c!H$J$ocICpqvB`9&xwCLzA*l9{D%p3 z6YfhGk?>r?iwSQhe4g-K!i9vJt~YYB5}!%hn)F)In@Ky9_9QFG0m+q;t0Y%TPD`$n z+&;N$@*=@Zf?rO!;Coj$K_je61bYSgQ@wd2-?B5Xop^1ZjDcY`5^x!Yf)|zJu1{JdGzr}tdK}i>uE(Bi)DEg}Ci=xkqJ}&yO=$)ed zMLUbO6>ThX7p*CB6|E{-QMA11>7r#tPZcdKT2k~x(c?vniWU|{isZsPp+d=l^&9&-4F1fA;)O=YKqZ?EJgu51ij| z{>}4moPYiNtLL|$f93q9^Xt#AJ-_1o9i=VKf5x$c zS-{RP)n<^x(Bv58;2x1+I4A5VhA;LZ%2bq3%AxaNf*ylL*lZ8247 zIlY1@umZ1eW0XZGPvZO(j>}|WXK~~TUjY0U9A89%QuaR_xsIPvQc$j8^_mDg$~jw?}~!+8OYn^3ml{4kE&QQ&?Bo>bpL zfs2)sI3i5ydpQ3N#}81B;T+ymKSqJKl{3UiRJcREi3`*~3q^^;RZoiA`D9Gi}Rmwd{7n*f)n8#UbKri4w6N?gyRsDd4ONWaRJJ1 z+=U0=xEBQ;(Bauc7@dfk>(G&S0`X5gg$pk5N0i@iJ`6`#op>GR({a3kV&EL^hn*xT z73UD1R2!u^&Jltngf0of`O*NtapXlmfMa`<&Nx4aV^@?OIDZ#M+|DKS!ubbqT@q@@ zi~bRgs6o<5oFhY%kW@)%iuxBg!jL31FCAVQQg|9m#y(x=+ z8%MMpUUVdF(r%PJI4>q7SwV5)NB7_aZsNs;8YYLJRKhuOA{p7si;WXklf|au2rne3 z0j}W)PbAmDIhd2%prF<^E)O;4#TJYsYMZ*8J>cpJq|}0oRW<5cpPiUVo$`erj!2w!3pNcVh3T$8?xA|;rO{M zcGR}IS?tvbfgFM;5Ias%QTtRRVE_QBtx!7Rybg{-QO4jr6UT8VlW-2Yv=?LvaKcS# z@1qOcgOK56vW?w%)Ji9*Wp?RlIJ?Y#ft-m-FOe>7|vnfjW1-u+Ag{A zwJccSC1`=m(}1y(sW`AF#{WWDVenP$6SyGX{6 znYNv_gSNMn2-{a=0-4K-aewj_d6bMG6K(I&-nP?daSxGs`c_PI7Lvz_n?}$`-G!CU z4OmH7hjoSh_TR`mw7GszzoqZh3$e1`SggN59>LP+CjE8S%C0HlQ`rJCh0SI2*nBdZ zJ<6PHTEWq-f7Gj~f2Rf%j|@#Eb1-t+^n-lt$9#9N=NJ8ycFlyR=?7hBW=Ds5iIESS z*kzydHx05gCf;)eCnM?)D*1vFPGZ_c*0N{A2r%l#BQ@|`IDmY9Tiq!B!LxZ`04~{UBRIz!)RK+vuf^(j!2>+tuai(axaC%A0g1&=|2e8YbaU5ByzO=|&$0yoV)DJt@VhKL~Lq zz0r&1NO4LZ0XOO489^UZNh|bB^pk&$(*xeZ^G2wv{_<~l&!(@a57)01u5TzTSph?z zMXGQ^yRWF4iB#E1oiK3)L_aH11p}u~sz9+`6Fqktxu1dtmu2rO#)`_wF@c-XRGNYtLGDY8xZKBR zHU~tr0UcU!Q{8w1uMP+7#aIX-ZZ`c!rW}OSWa$QWQNhBC1M8 zqpT)b86h;KT3Tx3%&c&b(6B9$TUzgLP5Vb0Tk9UGdZ>9NTX=4#TD2pdYF_=7RnKQ8 z2RDDB>J!Sr@wAJvcl@R0#@9XSC55Ket}|rS;*NECX0)N{%cT>3f|qZIZYs zZt5CTFUmD>O;qQ(oe(4}c>9pr$06x4Yedq|r@QC~gnJo!hIRTMfP)f2oqzuo;Xo;x z_Y5(v&(=i6JUZ1+nlVPdAvB#GKd*m`arWTlAe!ll0Gy{y~2AZ&&LSlYi3ex zU7Lv~;p$oX1Q3@!pQvrLpLoCRy1KS%EV4aJa0rCR_Ccch(+aA)_fVQw@cp`P0y-iC zl`h&h1hfAd8Mb7EH#sXAF-%5y5oS8?P(<G;NAq9y$qL|b3KQ#Hd z+BKQO;Z3rdWHhQ`(~-npRZX%`aUimqq@|`*v+1NDEkX%WfdYgIQ=li7euA^qawTeNy|#ejTu3Jq+QkZ|_hC$?=j8tgM(dWgPPEqQxH z*!(BmeUv^OI~Fu37)4#b?@qTZ;2A>~6ja}nkM1JUwQ?`U(Rh)=yhBjl5*>n^RH03C ztOr>Dua%xtVGQQj5kC1Zct!s6E}$^VISr#2=M~v*-w2Pd*0->2$hA!ZE?S4J5i;!% zw~I_6uhASY{TsX=*JIf}Kl&rK?=5<^0%5Vb}$R za9w2wEe6?KZQptoEZ33+{Wvt^JoKSD3*?5&IkT*gc0g1JjS`0N3EXH=p{=M;7O&AF zUL!9rpGq~RbJRhA)Jhu_gwS?30 zOqn}f&}%mUe-&_@Oc^WF;v!63AjXC~hTDrHe)rb*|_>kU;QEJCFk&!3T9^ ziRg!>c|<=%ue&b4l^2UUizn&BXomh3N@FWr{SRzPg~)F_zu1}!RpHtqF>8~fDf(md zq9c(%%L^7BTn*n;*1s2`mWV2K@SL^P($SkjRJ}u(=v3Aw3iNu)Ej{hoqW&rjTHzYZ z(XrYaLb{w1^BCj^^hVe6Ls2o$YctAV`84Nw*CENg+h;<_r?^8*=Bt7kQ$p`_Q(`4^ z!r>~;pjdU9K+72x8Xh}|dZm&-Kj&GoQCa0NU@&iqYiw_GooYQFdd%3^6+OgD|Ge_J z=O{vl^wg^gzs2fNg1(W5hq@1pdqf(Cc@GJ56&wyj^}a7dA}u_9*vB_=^1wZxWmYfb z2=|S&-xn*HTOQ%e`fwo|odDF!!H>`GHo7KqW<9YCRx)oo65n~Z`kmm4LPz_J$lE;8 zRCcSf6B%k`Vi(dksC2e%JC^L9|QS3%WojYXqcfS zl{*j*XWJXh>EtsQ8@5}F4_Fz|y15Zvd)@C%qkS9kx zG3>XbVrW!Tl5IMl++l8qfl}wQJ9@Fsf0u5IsxoQ%v_8Fz-yeD@f)1?G^^Ng6UrkIh ze*4ZaLZVybJU(%4%8=S)hYZg9aq!?~?7N>Io;_({$BssORxf{Am)wJ!U*6mKk#=oI z4nJ8dBJ!b$NYT-r3tCIHU8t^T!a#BDI`efETFv#puWNJ|-J<^Z_7mS9G`L}d=T`r3 zd*?O^ZP9eEk0Bas#kq)ysu;ju^z*~^dYHdZY8Fd|=hVEmn%Y{U5RchZ!c;;sb` zT=+|?nTWpE0|&PyBue^_PmnDqwxStX8EAwVk*?OCq$XSmk4a1%@IXdJ?2tO`+jr>n zYLA{tb!kd|cs6C(Pq-fYBqe&xAa&%zoR)R#4n36|T6xgmmo65}1h%Q`?N8!pm4X}p zU8VJY*<)yf)LM9sPqbDvTuI5QQHh45W;jqK%SKyAzLj$U)3=&c-g=9UJ{n0+RoQPm z&~kqS_8!p;7C(tiVn!#rj~|PFHx9FWQt;KEA7a~CJb76-EWx$)Rv!&XtLnRMpJYK< zeBHwG-Pz*Y!0O{3-4SW5OYXAY)zFA`oxfhiHN@zGiKU7*+1B>69zirx1(Wj@uD6U< z;Wq8YsqpAl8;To6)@YoyZ2929bzBZld|a1-gXX+9WbiQB`29Iux}=PMBa)7OcCHdt z{Cjm*TTer_j}%PvYzb7pCd7SwFsonKF_3m(?#)58Pvk_;^L!l=Nwtm|^k+2%ebJ=C zz+l==i=2A7I={$GaC|XFJ?psmxK&@%F+x`u+VDEP+nC=?T84(AK#X0IqLJ~aycmFOEeJk#@?nk?aPsIK6dfuP@SQ=*1WT?rNp8$CDGVpKhq{m_>)#Bc_T4`z3awZ}$$d_doymYSBz zZ;YZEMO8_pW@n~^SBa{UC6EpZ0!|1(lPslGiw61aCmtO*xMBV0TsL0r)JCN_&8CbB zLVxYhQo1%=7Ik)J7PV>GlBtsi)~%C~wPeOZs+aDtYfKuKnVm4$IA?sev2sk;M`p}! zdOwAx%aqO;b@7KOa{>eYDy)%8a~#f+`aHtd4M{#<7LfIU!}x%^QaWZ5hoeLC)}K$z zQrW3WzVsbEH}w?hFv@2$y29_x6!_(m+C#5{aWj^$%TirqqP|TEdp5$h&y*T;L8%PK z3`1MbSICtb91|2;crkjS65Gff<9#Di-sFcyeqE0enp;tye)1q%w!stN_TD&zWE<7(# z4a|Jy`6IEhQ-=i&j8ER1vnFL4>oo4j zhi8BI@ytiJd)RvC7e6#|i1CpTWPCVeWHDZ3kZawz`$r(D?rPtEm}}Lb`i0$EP&?(W zs)vF8C5aBtNPun<9>!9tsaSYuQavMyC_1z8AXTrwuk!wFztN_xTkrnuL&NAirR{4p zc{X+fw`!mA(&FjHAFHn#f6}KmJx_ayO~So)9i;u*v^M$}FYPvdnLKRdNn{f9n&Tj~ zuzW=2jEgUzrHWiYfOtA2H&T%f^#I1^#xOn+V;?&PHp^<|a16?7))MQrAT>*9pcPh4Y3U>TPSL$olzq^w+kH*5y5DCk^VYak zIaTJfceI2(d}%_#au`}dc{C8<_2$-jA-LvkLVG=>T@W6OwiEFxLM# zvAoa1?J;Rbcs~GP9BwY~(a{H?ixT>t4z6F zm^+lF>2#ob;%FL0=N2v=O?&7u{5IZ3X47s$AHVNG2Z9zi9xCWcGeO6D{_zN$&Qis-ypI&)KTm4V-7cZ?ktb%T zu%kXYD~utbajD8wo)M_-55m9(5L{1GceVSCS+HNEKGw8Oiq$W%(k!aC#C_U}2KPzM zZRRPj-V%4nBQ&bB;0}uML4U{xOP;>4{ZY*Qx$jqEUe#Cleu8Pti^3TGh-HE>W|@29 zBh(W!S)z4^YdUxwRdF@o4q&}TQQLM4eh$9v2A%Ft1#=Doi=Imx*CEx%QLc)|2_{7&`l zyr*}h4)|im@5eGaDbcj{!_PmmJIi$+4LvgZ?c$~h6P7slWtg|I%X0_x+q)Gvu(KAA z7;&;zt-k&HJxFWQSo_IS&UtU{7*PE6TW=rQ56`&o{7G+`wRsG+vE$ihebk1J>`6_+ zQn9}6Yity+nmOQ!%4A9FwNuZ$-)|hP`F_9rn|G8LT6^Xu*!E0!TItBbgH8IKU3l^I zaO2fWiw9BUn+tu=O4-V}anR4l5@druc+q3cSZi$ZB zQeeakzH>EdAWLLZFmHlFrlufHQ$Zeb1sBJFY-JpHjMvdCG*M+i1TPEyyWh)&z zSSX`-NHtKus7=P34}>OA8~nzf6ktVPE@&h>{jTH%)=*Let@dDk-^irjz9>GLoIfHz zk=1x{W0mL^b{VmW`NMFT{``9DazuWz(mQ2b?%PA}5080{u4(-8#BDEarN-u=ljc0S znf`4ajjcP3bs3vR&fSXeGtWl0p>P*vt*Cpc!uEE|f?;^1f`WCN6vaH+*ssB}HqHtz zcGT(~LwB?=K8fm{b6*tA>}GU`?Ou~@$Y!7ByfwqPIL^2{&e$^Jt-{4BHqtj4%9g3i zwKM#g4Hc48s1&bcP$k8toD7=3ael}j#W|174>tA&JKwmEU4L@^S{sXW54W+&g}HY2 z4t2I>%h)~*YZL^J>?t1SWnqSBKE&hsh^ZmmmDQwiW?E`Bpzx@#Q4`i`MDQn(bs9I$ zos^m6NZd6!w^r@2=yAJ)14H9CPmBu=uDW>wJDEMGXL)dwH@C&$q*hblA%Zc98}I=P2qKvgj`P78cx*E$I27^kz-Q!=VGZPjva)AY=gR!y6s89}-FB9uEw8@>s_>l?&D z_JTf6sgmIoYjh=DA%6;s{-tpyzmu?~a7)o0Mn;G}lbx!%mb)xxb$(8(Cwt5tu0_1Q zb!28gZ@b!IU~DGNg34e)kp4|X|%RA&FeWmNw~3c zrJAjJre!pGFsDj%DjXPAxpo`wzo-To4I4exuWn=u$nDW-oXasc)aorGvU+(DyqYqZ6B7yZV4MXVhoMI+9_elr$96Gww!0{fz2F>) ztat>0sUq48?9C9FiW@23UYKY;;odbr>q+8(h+kxSMAU1Zec#;d>=sCmdiCRjqpDTw z_h3$TTwG#O|9;K0+08*Y^aq|EasB!l7hjK!qt&vf6g;UulCs6b;D_RaDu-n^462rm z#!1!eZ*z<**{oV-cvy|h)WRvr?1Yv&gKlK!Q8$dbsDe4bnq7iiw2W#f7A>ndd3S)7 z0NLwSOS=&qTC-VZ>(HFII(6#Q8{eo=L{(a)U2rO^(Wm<$M?j>> zZ5P;Sb)Ue1`aSddw+#;8x}Z%qTi>*E`$kRXgargXVl-Ve)LDiU;F3lbo z6cfF$d7FB8K_)6Du1Cw>!|?V|;jJ_l&k85iW;sfD6yJ_uY~M6vSMeW-+L!0(tY_SZ z>atqysCuli`&?btAOh2y;YJwWS`}t)uww=8q4ii)c!4=f{|S@b5ppw>`^kDNzVjMI zJQcuWhgsSP@z`Of(p@}Ws3Eecudz_wAa8Go5(bg9qH&KDR@J(BrlZPw72h(wtCTvsv`Y zXj_JWFQP2~w_EDDd{_s$ya}k{{>yzLgH?_>%wH}NRfrHqSVU9TW}*gDi+5XzZXX~V zfH|gcKm(wiD|C#>oEZz)17v{pw&D>c$WVh7Sd<9B%}pAc$6umCqwHxan`Iv$_VY%o!9x%HObc~@kCtJ?Nf#7ZeggK@F7yt!+0;D-IX4-?cslaD&!Kg-6 zv2UxNk*5XgqXF+F+_FL&BK*Pox(97ex$CpC2r?L<2n^~q8Dz3k1R0E`f&(%sv_L`M zSkN!W4RMy93|@sm3ScQVy|r3s6V!g?MQ3k1K9 zCsQ&(uGMxYW$|XERu%GQ8DFYdYJ0Dq!}yX5XOo)=MLpE3!mg5Cgx~NxaW>D+Qx#8Q zBt7g(;(H<4PQH2#j7e|I5<3F`XU_{bI6NLF$>t2Q;!=Tz1cTxz&QPL2L!t=yPe-*$QcUxeCq)>C`c$a=^;N`!`=fR-0Pd7e?E-2 z);UMC@g?7s09QbQNcH1QdF%G1h}Qjs5#hIIVd~mu!0uAt70mPDf2_}exu0O(y zhtxv?-O=dkhd$&U3bgY8&=`V94Nct>Ulz!SoecfJlGIf6U^?Rxa%30Di4Lf^TJ#o2}N_dYNYPu~!OMt9oc77%&!n z`b^tk;L#fj#aP<|yc^PUww?v}gCadwse42{#~QQrnWon#fyg93f{jl!U;uz|F7f0;((6dCiv2Y4OSi{oa6z!tFY!}*D0bgv) zvcGTkYmbX?oAfZ~O%WGKzf8 zDqvV^dSVn5Tru-?pPS*EZrU{q-V7)k!0 zLb(AD&|VBRegfEXKmISu@Vm8*CH(e0Zv~_QP8)NpKhni!4d&ZVml3c^+wa|WxW_iG zlmHvr{59TGO%J~9<+nU2JYjmUz23>oFFaTkE)iZ>V(NhR?P?&o%&=0QSlX*+Hm>Y34kM9Fq3DUl{h;JU^i#>U; zPTmCURJsx-5uy+WAK;G+fdlqyM zo`zoFWzWLjtU-?g7lykx=d$_~RnFy=lJ|y^%H9n^1Qm0y?I>id_mRQ-btxmv-2iCk zDizC-P$8b_W9LVz-f=Dr^KK@v;A!~Y%mQvQ$N12v>AeZsb2;!~WNo?dJ_MbMMep<~ zPSb~zBP9q4w_OiS)ARVZ=`02x_z3=N!GfFHN<;+~0?Id+a6`RtRKUZBOo2fKkVX1a zx^oK@^!CgJ!p4dyQc2Wqu|RTR!ywGWKo}oGX2MHpdLPe7DJ+^R*$a4q@ZRtxLPc*M z<)}oeo+sf_zBGzg&Z&>^O!Kh{dpDF~8HVb-ZULr2C2(h4`S9M!<->C%!^FYG0bdE6<>D*Y`i6gy2^R+FAVJH$rYY6_u+Wq zPNxUT;Zlhhf}Kd&W{t-9z{djKRKSPHW@l|s0(`wNxR2YEA`D&wI1ddf@{BK>?{r#Z zRz&Kxb_N0QgjtIoK8g_EcXNBe}xn|ZJq0yPZS)sY=8yej%j6>hz zL?&Nl@{R$@w3UL%%KobiZWA>^Q`3$LCK;NmC85z0{6ce;er@s~G+K~fXs*(CO`Lod zy(QF%{(ca5QFtjts_wiCym$BV>4%k}e^pinuUwlP$R)0Lt$+_FPvb3ksTv6Jlv^OA zt95o=)*NHwL;;s>2K;`Wl+!)G*cS=7<>KoMIU{%$1Lp$H%Kq!@VF90oN5{c}$MUfA zx;JJ^fow0Bq>Hc9G{MAo!96129YxJ!OeH07XDeR6vhdzw`$Jjyu#(+$y!~@Q^M!&w zb4m-^AgmouT*8GAWzsK2TrsHJUz&cNfRE_l3rFtQrV2S$qTZy7%}U@~h9n?YD3>GM zO>=t&nCymtOK;p%!h~`pmA$=RQr%?zOkr|goER%;17R>8;lSV$xU)3eiH&q(2&PHp zG7RHGGMrmlP#^y7-*Vu?Y5US}VQe04S}xornZPECLTEnyU{|FCC&lX!rh;YbCBMF^QZo^jztd4`nYKUNxZZGEb zhcLL^R$11>>}HGkmSHchmtRPVX_ASP(>H87(x;JSqN2Xjx6yq3lS1SK124Jg)A&n{ zz7r3znN(M(P$q{}DexsB5aT2ali+~IW91l?$(uhtUtzpzyPRUS+W zPi&B$kO&T6cNh4xcY$M~U9Ozx?gEEG^nd<}ZP%fAV_60P-{cF&?O$I_ zUUXfQ#9# zCNe-3n+W((DCSeO zRP7xJXG^?rK21y2-ZkM11>D&Yu}5!&8Y6qS>xjJNEP-FS3;e%#fy=x2vT}YakKPHz z==(}579sfkE^y>X3BBi6RDgHcsoI|$uIKW}I6T)1aNcF7YM4g|_(cIn2t=2is{IAH z6Aa7{2($v(Uu&3Pix7wvHXZ`eU#DvSlW@97&?CmOtJeND;Rpp3BLt$WPStLja2a9_ z=iPLwcFTk#x%v1n`)K}(-CTT9nDgAseD`7D2TE_`Puka0`tjHbGk3|hD;uSaV zv}Kn+QZV|$(ett&B^|``kC>#27eKuI7QLc=uY@9Ey55n~(fvkWw$-zk8{l5tj}34x z5a6e@EOnXfX<>D5nukRcjJR;4>@>JrJWyV$GvUuW_?=#9xNr;egY%JW2mels-l^n1 zjmvjR1l)3;AH$~@n``m+UiE37!2)xcPKT?xQOHGGWj>0rpTsq2?JxMzUh&SwKr3E% z(b*YJi`BWl;wf+{6HQQe=Hk;uTuf&mA?<8Pw_lZih;i; zqqFl~x(zb9%G|SE6XEOZ3+K;D#d@Ck){D5FX+F(;hCj_^PV_9W7%o&#__^>Z#neXN z;6m|Mkj{SQ*Hra-%IUF*dJB&U9EC>$gcqG2l~+Wcf6?DlsIaf6oMHwdzDiSO-u;Mt z-X?B=FiRK4h?xn0eMX-m)>?ew{Iwcgfm+1*zsRfUB4i!g^8iFjejm6~z?~*SOobN6 z4DG}jd<7qaYg6^kIlk~wxDmW!lkIk&Xt(H@;7JLWueI;wueF;m7V#uyejdKbzqQ_5 zF!7A$FH!0IW0w$u8LQq|y3t$&x?#;`DVnNslY4+SQMhs%8BU);Sa=iODstrq_ZtIQ zqEp1if9&B;aQM`%q^l=#OyV6`HGepNA4mJvqSrgomYx@2nxN-!{sluHIiKQAua$58 z`myU2B1L_ym&bH=R$Rjwwkf{EteB!(6u3Cloxd}tvvd4fjzxUY88dob-(2@ggV++L zuPm%Lm~Gc<>KI!Ae$$-PtN2b)RsIA^LJ&6-zjhQ$ugU-70*H5+#QQ+pn)jLlo~G~O zw_O}x*n1TFL5bGi6adKLUnwn-RoH19D^jt}pr5pMuo3i9EKg~Nmj&i{VF&^HLg@|I zbT2H{^E>-Wz-D-1A)q_MdHEL^&0TVdp5K*Nr7>XNdtoVn1#@2g6kyJg!eM!6plq%*;KCn*(Y`Guolz_RtFtld&KHnF} z7JFe_-Y1|_Z0d@_?vq(dwJ>@HyF;BkL-1k|5>r2n8BiK7_~vA6TxT{GmPEpvur%xi z#(u{tVH~EbN#d=aCWO6h?1-Jwob^n3_piEH$LT@ZJFD*8ms42x<}+fAT}O7*j^Da) zhH=$6edYcEZQ^UwW?HwUwC>(qmm^zc)r0ypk!5<;e54zVr!V;YF+jSUgksN4Q_=277W&Z46|6Y9xU%10J z?D)6sfJZ_BZ@VjA^2gp4k3<81NGZJ2tAJ;nX}~&Rz^QT#NQ8iL@jOFK{*8kF$8!0( zfj)RV1oqZYTF4dn5R~9e1-Pxf3m%y-4bYzz1{^F5nZq8n7p5#?Egkn&!pnFzs-!7d zT9j6!adKpGL+$x#cczZED>l~EZY(uC>e}1+|8J_Y!dPl&U2Tee^oLuvK;jI~TD_IF zHZ;wKE}9Mwwb|AbZePKwF{iCHKEAjGfVLbV)c5zC)cb4LrekYkY~lTgtsTb*TsH_B zD+GaF@PXgt>*i?$CAYxGWwrz#$Gyw>JeW4?hfJ9*h0Hc$y;0m_&H&?B!N`qxR~lo0 zj5ETRL)u3W+Kw}DV>m__lS|U|i5i|C+9m*S47e$PH!X#Gh{J%J%xO^gN9jF5A7QXPt z>ugh$Qx750Furn=tXPU2(~%KkH*Z=!yj-H_w#xKPMuQH0)N^F(tlCv$D(L~C6M|LM zAjoxD>O=wnJY_#_ZX5-(Ps0J1`Kg!az82Y9`gltUvY2^%2pRqA&44$BHztWYQ=zG)+AW z8W^Z7vWzxiJ_eTH*k^*?M^o1RaSUgHd|#8zKCqKTfY$4crAQ!J~1qVyIT(V@hifOEvm!Wl*FrmHT+1 z46XAXnqL_v4>}^AL^342uaM2~?uM361AZrj^T9?on|~HmF|Cy&mIwb?p0mV-YO3H29xs&GBEh&3k1s+p(1w_h@*DC#R

    FX_I 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 `tR9KG)By&p4h&hBg5*^hbu40R*U^Z|P6ZM!#Rm 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 V=EwYGT;7u6`JKUr3Qx;^{|A?E3&{Wg delta 53387 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 diff --git a/data/system/data/fonts/ttfonts/DejaVuSerifCondensed-BoldItalic.ttf b/data/system/data/fonts/ttfonts/DejaVuSerifCondensed-BoldItalic.ttf index d141211def02a9f047213bb2238fe199693d948c..e2119573440cefb2a4072a6d877be7c0e2379ff8 100644 GIT binary patch delta 93037 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 EKjluZ{r~^~ delta 54970 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%0A_3J?{Q5wtEZKt<5|34j7Bw*Vgu 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 C76AzW diff --git a/data/system/data/fonts/ttfonts/DejaVuSerifCondensed-Italic.ttf b/data/system/data/fonts/ttfonts/DejaVuSerifCondensed-Italic.ttf index 437824a3d2f426e21c1916532c0d89378cd4deea..275b26d953747cd400cc33d7d648eed2b4934e14 100644 GIT binary patch delta 92040 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 delta 55356 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 XxcSz5tGrF4hP5dPJv3(6&BOi+h<&mD diff --git a/data/system/data/fonts/ttfonts/DejaVuSerifCondensed.ttf b/data/system/data/fonts/ttfonts/DejaVuSerifCondensed.ttf index 2fc9db9011cbd49b14c8b81ab9e8db85cf6bdc17..83120cd9d37f69ad3b346e021a486fa5d78b17f8 100644 GIT binary patch delta 86788 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 Date: Sun, 24 Jun 2012 16:17:32 +0200 Subject: [PATCH 081/349] Add missing space before opening brace. --- headers/os/interface/StringView.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/headers/os/interface/StringView.h b/headers/os/interface/StringView.h index 283bc8a2a5..a8a36b61b0 100644 --- a/headers/os/interface/StringView.h +++ b/headers/os/interface/StringView.h @@ -9,7 +9,7 @@ #include -class BStringView : public BView{ +class BStringView : public BView { public: BStringView(BRect bounds, const char* name, const char* text, uint32 resizeFlags From 9f5864ab093a8e363d1eba0405c57f0e2596b83a Mon Sep 17 00:00:00 2001 From: Ryan Leavengood Date: Sun, 24 Jun 2012 10:46:17 -0400 Subject: [PATCH 082/349] Handle the scroll wheel changing over scrollbars. * Extract the scrollbar change based on the mouse wheel delta into a protected method of BView. * Call that method from BScrollBar's MessageReceived. With this change it is now a bit easier to scroll horizontally around the system by putting the mouse cursor over a horizontal scrollbar and using the wheel. Fixes #8631. --- headers/os/interface/View.h | 2 ++ src/kits/interface/ScrollBar.cpp | 16 ++++++++++++ src/kits/interface/View.cpp | 43 ++++++++++++++++---------------- 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/headers/os/interface/View.h b/headers/os/interface/View.h index 8418f03e21..4471ddd1a6 100644 --- a/headers/os/interface/View.h +++ b/headers/os/interface/View.h @@ -584,6 +584,8 @@ protected: virtual void LayoutChanged(); + void ScrollWithMouseWheelDelta(BScrollBar*, float); + private: void _Layout(bool force, BLayoutContext* context); void _LayoutLeft(BLayout* deleted); diff --git a/src/kits/interface/ScrollBar.cpp b/src/kits/interface/ScrollBar.cpp index bf8fa2dc75..a12fdd3b9d 100644 --- a/src/kits/interface/ScrollBar.cpp +++ b/src/kits/interface/ScrollBar.cpp @@ -642,6 +642,22 @@ BScrollBar::MessageReceived(BMessage* message) ValueChanged(value); break; } + case B_MOUSE_WHEEL_CHANGED: + { + // Must handle this here since BView checks for the existence of + // scrollbars, which a scrollbar itself does not have + float deltaX = 0.0f, deltaY = 0.0f; + message->FindFloat("be:wheel_delta_x", &deltaX); + message->FindFloat("be:wheel_delta_y", &deltaY); + + if (deltaX == 0.0f && deltaY == 0.0f) + break; + + if (deltaX != 0.0f && deltaY == 0.0f) + deltaY = deltaX; + + ScrollWithMouseWheelDelta(this, deltaY); + } default: BView::MessageReceived(message); break; diff --git a/src/kits/interface/View.cpp b/src/kits/interface/View.cpp index 87fa465557..efbe9549a6 100644 --- a/src/kits/interface/View.cpp +++ b/src/kits/interface/View.cpp @@ -4350,31 +4350,12 @@ BView::MessageReceived(BMessage* msg) if (deltaX == 0.0f && deltaY == 0.0f) break; - float smallStep, largeStep; if (horizontal != NULL) { - horizontal->GetSteps(&smallStep, &largeStep); - - // pressing the option/command/control key scrolls faster - if (modifiers() - & (B_OPTION_KEY | B_COMMAND_KEY | B_CONTROL_KEY)) { - deltaX *= largeStep; - } else - deltaX *= smallStep * 3; - - horizontal->SetValue(horizontal->Value() + deltaX); + ScrollWithMouseWheelDelta(horizontal, deltaX); } if (vertical != NULL) { - vertical->GetSteps(&smallStep, &largeStep); - - // pressing the option/command/control key scrolls faster - if (modifiers() - & (B_OPTION_KEY | B_COMMAND_KEY | B_CONTROL_KEY)) { - deltaY *= largeStep; - } else - deltaY *= smallStep * 3; - - vertical->SetValue(vertical->Value() + deltaY); + ScrollWithMouseWheelDelta(vertical, deltaY); } break; } @@ -5721,6 +5702,26 @@ BView::_SwitchServerCurrentView() const } +void +BView::ScrollWithMouseWheelDelta(BScrollBar* scrollBar, float delta) +{ + if (scrollBar == NULL || delta == 0.0f) + return; + + float smallStep, largeStep; + scrollBar->GetSteps(&smallStep, &largeStep); + + // pressing the option/command/control key scrolls faster + if (modifiers() + & (B_OPTION_KEY | B_COMMAND_KEY | B_CONTROL_KEY)) { + delta *= largeStep; + } else + delta *= smallStep * 3; + + scrollBar->SetValue(scrollBar->Value() + delta); +} + + #if __GNUC__ == 2 From 537a273cced14e2da799ae1e4c3474a9fd74d663 Mon Sep 17 00:00:00 2001 From: Humdinger Date: Sun, 24 Jun 2012 19:45:33 +0200 Subject: [PATCH 083/349] Coding style changes, no functional change. Hope all's OK, Filter.h is still mostly untouched as it's quite messy with many exessive commenting. --- src/apps/showimage/Filter.cpp | 309 +++++++++++++--------- src/apps/showimage/Filter.h | 46 ++-- src/apps/showimage/ImageFileNavigator.cpp | 10 +- src/apps/showimage/PrintOptionsWindow.cpp | 6 +- src/apps/showimage/ProgressWindow.cpp | 6 +- src/apps/showimage/SelectionBox.cpp | 6 +- src/apps/showimage/ShowImageApp.cpp | 2 +- src/apps/showimage/ShowImageUndo.cpp | 4 +- src/apps/showimage/ShowImageView.cpp | 122 ++++----- src/apps/showimage/ShowImageView.h | 18 +- src/apps/showimage/ShowImageWindow.cpp | 16 +- src/apps/showimage/ToolBarView.cpp | 4 +- 12 files changed, 307 insertions(+), 242 deletions(-) diff --git a/src/apps/showimage/Filter.cpp b/src/apps/showimage/Filter.cpp index 17678b53db..b6a8702471 100644 --- a/src/apps/showimage/Filter.cpp +++ b/src/apps/showimage/Filter.cpp @@ -1,6 +1,6 @@ /* - * Copyright 2003-2006, Haiku. - * Copyright 2004-2005 yellowTAB GmbH. All Rights Reserverd. + * Copyright 2003-2006, Haiku, Inc. All rights reserved. + * Copyright 2004-2005 yellowTAB GmbH. All Rights Reserved. * Copyright 2006 Bernd Korz. All Rights Reserved * Distributed under the terms of the MIT License. * @@ -21,29 +21,32 @@ // Implementation of FilterThread -FilterThread::FilterThread(Filter* filter, int32 i, int32 n, bool runInCurrentThread) - : fFilter(filter) - , fI(i) - , fN(n) +FilterThread::FilterThread(Filter* filter, int32 i, int32 n, + bool runInCurrentThread) + : fFilter(filter), + fI(i), + fN(n) { - if (runInCurrentThread) { + if (runInCurrentThread) Run(); - } else { + else { thread_id tid; - tid = spawn_thread(worker_thread, "filter", suggest_thread_priority(B_STATUS_RENDERING), this); - if (tid >= 0) { + tid = spawn_thread(worker_thread, "filter", + suggest_thread_priority(B_STATUS_RENDERING), this); + if (tid >= 0) resume_thread(tid); - } else { + else delete this; - } } } + FilterThread::~FilterThread() { fFilter->FilterThreadDone(); } + status_t FilterThread::worker_thread(void* data) { @@ -51,6 +54,7 @@ FilterThread::worker_thread(void* data) return thread->Run(); } + status_t FilterThread::Run() { @@ -67,24 +71,25 @@ FilterThread::Run() new FilterThread(fFilter, i, fN); } } - if (fFilter->GetBitmap()) { + if (fFilter->GetBitmap()) fFilter->Run(fI, fN); - } + delete this; return B_OK; } // Implementation of Filter Filter::Filter(BBitmap* image, BMessenger listener, uint32 what) - : fListener(listener) - , fWhat(what) - , fStarted(false) - , fN(0) - , fNumberOfThreads(0) - , fIsRunning(false) - , fSrcImage(image) - , fDestImageInitialized(false) - , fDestImage(NULL) + : + fListener(listener), + fWhat(what), + fStarted(false), + fN(0), + fNumberOfThreads(0), + fIsRunning(false), + fSrcImage(image), + fDestImageInitialized(false), + fDestImage(NULL) { fCPUCount = NumberOfActiveCPUs(); @@ -95,12 +100,14 @@ Filter::Filter(BBitmap* image, BMessenger listener, uint32 what) #endif } + Filter::~Filter() { delete fDestImage; delete_sem(fWaitForThreads); } + BBitmap* Filter::GetBitmap() { @@ -111,6 +118,7 @@ Filter::GetBitmap() return fDestImage; } + BBitmap* Filter::DetachBitmap() { @@ -119,6 +127,7 @@ Filter::DetachBitmap() return image; } + void Filter::Start(bool async) { @@ -136,11 +145,11 @@ Filter::Start(bool async) // start first filter thread new FilterThread(this, 0, fN, !async); - if (!async) { + if (!async) Wait(); - } } + void Filter::Wait() { @@ -152,6 +161,7 @@ Filter::Wait() } } + void Filter::Stop() { @@ -160,17 +170,20 @@ Filter::Stop() Wait(); } + bool Filter::IsRunning() const { return fIsRunning; } + void Filter::Completed() { } + void Filter::FilterThreadDone() { @@ -179,14 +192,15 @@ Filter::FilterThreadDone() delete fStopWatch; fStopWatch = NULL; #endif Completed(); - if (fIsRunning) { + if (fIsRunning) fListener.SendMessage(fWhat); - } + fIsRunning = false; } release_sem(fWaitForThreads); } + void Filter::FilterThreadInitFailed() { @@ -197,38 +211,43 @@ Filter::FilterThreadInitFailed() release_sem_etc(fWaitForThreads, fN, 0); } + bool Filter::IsBitmapValid(BBitmap* bitmap) const { return bitmap != NULL && bitmap->InitCheck() == B_OK && bitmap->IsValid(); } + int32 Filter::NumberOfThreads() { const int32 units = GetNumberOfUnits(); int32 n; n = units / 32; // at least 32 units per CPU - if (n > CPUCount()) { + if (n > CPUCount()) n = CPUCount(); - } else if (n <= 0) { + else if (n <= 0) n = 1; // at least one thread! - } + return n; } + BBitmap* Filter::GetSrcImage() { return fSrcImage; } + BBitmap* Filter::GetDestImage() { return fDestImage; } + int32 Filter::NumberOfActiveCPUs() const { @@ -247,15 +266,19 @@ Filter::NumberOfActiveCPUs() const return cpuCount; } + // Implementation of (bilinear) Scaler -Scaler::Scaler(BBitmap* image, BRect rect, BMessenger listener, uint32 what, bool dither) - : Filter(image, listener, what) - , fScaledImage(NULL) - , fRect(rect) - , fDither(dither) +Scaler::Scaler(BBitmap* image, BRect rect, BMessenger listener, uint32 what, + bool dither) + : + Filter(image, listener, what), + fScaledImage(NULL), + fRect(rect), + fDither(dither) { } + Scaler::~Scaler() { if (GetDestImage() != fScaledImage) { @@ -264,13 +287,17 @@ Scaler::~Scaler() } } + BBitmap* Scaler::CreateDestImage(BBitmap* srcImage) { - if (srcImage == NULL || (srcImage->ColorSpace() != B_RGB32 && srcImage->ColorSpace() != B_RGBA32)) return NULL; + if (srcImage == NULL || (srcImage->ColorSpace() != B_RGB32 + && srcImage->ColorSpace() != B_RGBA32)) + return NULL; BRect dest(0, 0, fRect.IntegerWidth(), fRect.IntegerHeight()); - BBitmap* destImage = new BBitmap(dest, fDither ? B_CMAP8 : srcImage->ColorSpace()); + BBitmap* destImage = new BBitmap(dest, + fDither ? B_CMAP8 : srcImage->ColorSpace()); if (!IsBitmapValid(destImage)) { delete destImage; @@ -287,19 +314,19 @@ Scaler::CreateDestImage(BBitmap* srcImage) fScaledImage = NULL; return NULL; } - } else { + } else fScaledImage = destImage; - } return destImage; } + bool Scaler::Matches(BRect rect, bool dither) const { - return fRect.IntegerWidth() == rect.IntegerWidth() && - fRect.IntegerHeight() == rect.IntegerHeight() && - fDither == dither; + return fRect.IntegerWidth() == rect.IntegerWidth() + && fRect.IntegerHeight() == rect.IntegerHeight() + && fDither == dither; } @@ -310,6 +337,7 @@ typedef struct { float alpha1; } ColumnData; + void Scaler::ScaleBilinear(intType fromRow, int32 toRow) { @@ -343,7 +371,7 @@ Scaler::ScaleBilinear(intType fromRow, int32 toRow) columnData = new ColumnData[destW]; cd = columnData; - for (i = 0; i < destW; i ++, cd++) { + for (i = 0; i < destW; i++, cd++) { float column = (float)i * (float)srcW / (float)destW; cd->srcColumn = (intType)column; cd->alpha1 = column - cd->srcColumn; @@ -352,16 +380,16 @@ Scaler::ScaleBilinear(intType fromRow, int32 toRow) destDataRow = destBits + fromRow * destBPR; - for (y = fromRow; IsRunning() && y <= toRow; y ++, destDataRow += destBPR) { + for (y = fromRow; IsRunning() && y <= toRow; y++, destDataRow += destBPR) { float row; intType srcRow; float alpha0, alpha1; - if (destH == 0) { + if (destH == 0) row = 0; - } else { + else row = (float)y * (float)srcH / (float)destH; - } + srcRow = (intType)row; alpha1 = row - srcRow; alpha0 = 1.0 - alpha1; @@ -434,6 +462,7 @@ Scaler::ScaleBilinear(intType fromRow, int32 toRow) delete[] columnData; } + // Scale bilinear using fixed point calculations // Is already more than two times faster than floating point version // on AMD Athlon 1 GHz and Dual Intel Pentium III 866 MHz. @@ -444,6 +473,7 @@ typedef struct { fixed_point alpha1; } ColumnDataFP; + void Scaler::ScaleBilinearFP(intType fromRow, int32 toRow) { @@ -482,8 +512,9 @@ Scaler::ScaleBilinearFP(intType fromRow, int32 toRow) columnData = new ColumnDataFP[destW]; cd = columnData; - for (i = 0; i < destW; i ++, cd++) { - fixed_point column = to_fixed_point(i) * (long_fixed_point)fpSrcW / fpDestW; + for (i = 0; i < destW; i++, cd++) { + fixed_point column = to_fixed_point(i) * (long_fixed_point)fpSrcW + / fpDestW; cd->srcColumn = from_fixed_point(column); cd->alpha1 = tail_value(column); // weigth for left pixel value cd->alpha0 = kFPOne - cd->alpha1; // weigth for right pixel value @@ -491,18 +522,18 @@ Scaler::ScaleBilinearFP(intType fromRow, int32 toRow) destDataRow = destBits + fromRow * destBPR; - for (y = fromRow; IsRunning() && y <= toRow; y ++, destDataRow += destBPR) { + for (y = fromRow; IsRunning() && y <= toRow; y++, destDataRow += destBPR) { fixed_point row; intType srcRow; fixed_point alpha0, alpha1; - if (fpDestH == 0) { + if (fpDestH == 0) row = 0; - } else { + else row = to_fixed_point(y) * (long_fixed_point)fpSrcH / fpDestH; - } + srcRow = from_fixed_point(row); - alpha1 = tail_value(row); // weight for row y+1 + alpha1 = tail_value(row); // weight for row y + 1 alpha0 = kFPOne - alpha1; // weight for row y srcData = srcBits + srcRow * srcBPR; @@ -566,14 +597,15 @@ Scaler::ScaleBilinearFP(intType fromRow, int32 toRow) destData[2] = a[2]; destData[3] = a[3]; } - } delete[] columnData; } + void -Scaler::RowValues(float* sum, const uchar* src, intType srcW, intType fromX, intType toX, const float a0X, const float a1X, const int32 kBPP) +Scaler::RowValues(float* sum, const uchar* src, intType srcW, intType fromX, + intType toX, const float a0X, const float a1X, const int32 kBPP) { sum[0] = a0X * src[0]; sum[1] = a0X * src[1]; @@ -581,7 +613,7 @@ Scaler::RowValues(float* sum, const uchar* src, intType srcW, intType fromX, int src += kBPP; - for (int32 x = fromX+1; x < toX; x ++, src += kBPP) { + for (int32 x = fromX + 1; x < toX; x++, src += kBPP) { sum[0] += src[0]; sum[1] += src[1]; sum[2] += src[2]; @@ -594,6 +626,7 @@ Scaler::RowValues(float* sum, const uchar* src, intType srcW, intType fromX, int } } + typedef struct { int32 from; int32 to; @@ -601,6 +634,7 @@ typedef struct { float alpha1; } DownScaleColumnData; + void Scaler::DownScaleBilinear(intType fromRow, int32 toRow) { @@ -637,9 +671,9 @@ Scaler::DownScaleBilinear(intType fromRow, int32 toRow) const float deltaY = (srcH + 1.0) / (destH + 1.0); const float deltaXY = deltaX * deltaY; - columnData = new DownScaleColumnData[destW+1]; + columnData = new DownScaleColumnData[destW + 1]; DownScaleColumnData* cd = columnData; - for (x = 0; x <= destW; x ++, cd ++) { + for (x = 0; x <= destW; x++, cd++) { const float fFromX = x * deltaX; const float fToX = fFromX + deltaX; @@ -664,7 +698,7 @@ Scaler::DownScaleBilinear(intType fromRow, int32 toRow) destData = destDataRow; cd = columnData; - for (x = 0; x <= destW; x ++, destData += kBPP, cd ++) { + for (x = 0; x <= destW; x++, destData += kBPP, cd++) { const intType fromX = cd->from; const intType toX = cd->to; @@ -683,7 +717,7 @@ Scaler::DownScaleBilinear(intType fromRow, int32 toRow) srcData += srcBPR; - for (int32 r = fromY+1; r < toY; r ++, srcData += srcBPR) { + for (int32 r = fromY + 1; r < toY; r++, srcData += srcBPR) { RowValues(sum, srcData, srcW, fromX, toX, a0X, a1X, kBPP); totalSum[0] += sum[0]; totalSum[1] += sum[1]; @@ -706,6 +740,7 @@ Scaler::DownScaleBilinear(intType fromRow, int32 toRow) delete[] columnData; } + // Flyod-Steinberg Dithering // Filter (distribution of error to adjacent pixels, X is current pixel): // 0 X 7 @@ -715,6 +750,7 @@ typedef struct { intType error[3]; } DitheringColumnData; + uchar Scaler::Limit(intType value) { @@ -726,6 +762,7 @@ Scaler::Limit(intType value) return value; } + void Scaler::Dither(int32 fromRow, int32 toRow) { @@ -766,19 +803,20 @@ Scaler::Dither(int32 fromRow, int32 toRow) destBPR = dest->BytesPerRow(); // Allocate space for sentinel at left and right bounds, - // so that columnData[-1] and columnData[destW+1] can be safely accessed - columnData0 = new DitheringColumnData[destW+3]; + // so that columnData[-1] and columnData[destW + 1] can be safely accessed + columnData0 = new DitheringColumnData[destW + 3]; columnData = columnData0 + 1; // clear error cd = columnData; - for (x = destW; x >= 0; x --, cd ++) { - cd->error[0] = cd->error[1] = cd->error[2] =0; + for (x = destW; x >= 0; x --, cd++) { + cd->error[0] = cd->error[1] = cd->error[2] = 0; } srcDataRow = srcBits + fromRow * srcBPR; destDataRow = destBits + fromRow * destBPR; - for (y = fromRow; IsRunning() && y <= toRow; y ++, srcDataRow += srcBPR, destDataRow += destBPR) { + for (y = fromRow; IsRunning() && y <= toRow; y++, srcDataRow += srcBPR, + destDataRow += destBPR) { // left to right error[0] = error[1] = error[2] = 0; srcData = srcDataRow; @@ -797,12 +835,12 @@ Scaler::Dither(int32 fromRow, int32 toRow) *destData = index; err[0] = color.red - actualColor.red; - err[1] = color.green -actualColor.green; - err[2] = color.blue -actualColor.blue; + err[1] = color.green - actualColor.green; + err[2] = color.blue - actualColor.blue; // distribute error // get error for next pixel - cd = &columnData[x+1]; + cd = &columnData[x + 1]; error[0] = cd->error[0] + 7 * err[0]; error[1] = cd->error[1] + 7 * err[1]; error[2] = cd->error[2] + 7 * err[2]; @@ -813,27 +851,27 @@ Scaler::Dither(int32 fromRow, int32 toRow) cd->error[2] = err[2]; // add error for pixel below current pixel - cd --; + cd--; cd->error[0] += 5 * err[0]; cd->error[1] += 5 * err[1]; cd->error[2] += 5 * err[2]; // add error for left pixel below current pixel - cd --; + cd--; cd->error[0] += 3 * err[0]; cd->error[1] += 3 * err[1]; cd->error[2] += 3 * err[2]; } // Note: Alogrithm has good results with "left to right" already // Optionally remove code to end of block: - y ++; + y++; srcDataRow += srcBPR; destDataRow += destBPR; if (y > toRow) break; // right to left error[0] = error[1] = error[2] = 0; srcData = srcDataRow + destW * kBPP; destData = destDataRow + destW; - for (x = 0; x <= destW; x ++, srcData -= kBPP, destData -= 1) { + for (x = 0; x <= destW; x++, srcData -= kBPP, destData -= 1) { rgb_color color, actualColor; uint8 index; @@ -847,12 +885,12 @@ Scaler::Dither(int32 fromRow, int32 toRow) *destData = index; err[0] = color.red - actualColor.red; - err[1] = color.green -actualColor.green; - err[2] = color.blue -actualColor.blue; + err[1] = color.green - actualColor.green; + err[2] = color.blue - actualColor.blue; // distribute error // get error for next pixel - cd = &columnData[x-1]; + cd = &columnData[x - 1]; error[0] = cd->error[0] + 7 * err[0]; error[1] = cd->error[1] + 7 * err[1]; error[2] = cd->error[2] + 7 * err[2]; @@ -863,13 +901,13 @@ Scaler::Dither(int32 fromRow, int32 toRow) cd->error[2] = err[2]; // add error for pixel below current pixel - cd ++; + cd++; cd->error[0] += 5 * err[0]; cd->error[1] += 5 * err[1]; cd->error[2] += 5 * err[2]; // add error for right pixel below current pixel - cd ++; + cd++; cd->error[0] += 3 * err[0]; cd->error[1] += 3 * err[1]; cd->error[2] += 3 * err[2]; @@ -879,12 +917,14 @@ Scaler::Dither(int32 fromRow, int32 toRow) delete[] columnData0; } + int32 Scaler::GetNumberOfUnits() { return fRect.IntegerHeight() + 1; } + void Scaler::Run(int32 i, int32 n) { @@ -892,43 +932,47 @@ Scaler::Run(int32 i, int32 n) imageHeight = GetDestImage()->Bounds().IntegerHeight() + 1; height = imageHeight / n; from = i * height; - if (i+1 == n) { + if (i + 1 == n) to = imageHeight - 1; - } else { + else to = from + height - 1; - } - if (GetDestImage()->Bounds().Width() >= GetSrcImage()->Bounds().Width()) { + + if (GetDestImage()->Bounds().Width() >= GetSrcImage()->Bounds().Width()) ScaleBilinearFP(from, to); - } else { + else DownScaleBilinear(from, to); - } - if (fDither) { + + if (fDither) Dither(from, to); - } + } + void Scaler::Completed() { - if (GetDestImage() != fScaledImage) { + if (GetDestImage() != fScaledImage) delete fScaledImage; - } + fScaledImage = NULL; } -// Implementation of ImageProcessor -ImageProcessor::ImageProcessor(enum operation op, BBitmap* image, BMessenger listener, uint32 what) - : Filter(image, listener, what) - , fOp(op) - , fBPP(0) - , fWidth(0) - , fHeight(0) - , fSrcBPR(0) - , fDestBPR(0) +// Implementation of ImageProcessor +ImageProcessor::ImageProcessor(enum operation op, BBitmap* image, + BMessenger listener, uint32 what) + : + Filter(image, listener, what), + fOp(op), + fBPP(0), + fWidth(0), + fHeight(0), + fSrcBPR(0), + fDestBPR(0) { } + BBitmap* ImageProcessor::CreateDestImage(BBitmap* /* srcImage */) { @@ -936,20 +980,21 @@ ImageProcessor::CreateDestImage(BBitmap* /* srcImage */) BBitmap* bm; BRect rect; - if (GetSrcImage() == NULL) return NULL; + if (GetSrcImage() == NULL) + return NULL; cs = GetSrcImage()->ColorSpace(); fBPP = BytesPerPixel(cs); - if (fBPP < 1) return NULL; + if (fBPP < 1) + return NULL; fWidth = GetSrcImage()->Bounds().IntegerWidth(); fHeight = GetSrcImage()->Bounds().IntegerHeight(); - if (fOp == kRotateClockwise || fOp == kRotateCounterClockwise) { + if (fOp == kRotateClockwise || fOp == kRotateCounterClockwise) rect.Set(0, 0, fHeight, fWidth); - } else { + else rect.Set(0, 0, fWidth, fHeight); - } bm = new BBitmap(rect, cs); if (!IsBitmapValid(bm)) { @@ -963,45 +1008,50 @@ ImageProcessor::CreateDestImage(BBitmap* /* srcImage */) return bm; } + int32 ImageProcessor::GetNumberOfUnits() { return GetSrcImage()->Bounds().IntegerHeight() + 1; } + int32 ImageProcessor::BytesPerPixel(color_space cs) const { switch (cs) { - case B_RGB32: // fall through - case B_RGB32_BIG: // fall through - case B_RGBA32: // fall through - case B_RGBA32_BIG: return 4; + case B_RGB32: // fall through + case B_RGB32_BIG: // fall through + case B_RGBA32: // fall through + case B_RGBA32_BIG: return 4; - case B_RGB24_BIG: // fall through - case B_RGB24: return 3; + case B_RGB24_BIG: // fall through + case B_RGB24: return 3; - case B_RGB16: // fall through - case B_RGB16_BIG: // fall through - case B_RGB15: // fall through - case B_RGB15_BIG: // fall through - case B_RGBA15: // fall through - case B_RGBA15_BIG: return 2; + case B_RGB16: // fall through + case B_RGB16_BIG: // fall through + case B_RGB15: // fall through + case B_RGB15_BIG: // fall through + case B_RGBA15: // fall through + case B_RGBA15_BIG: return 2; - case B_GRAY8: // fall through - case B_CMAP8: return 1; - case B_GRAY1: return 0; + case B_GRAY8: // fall through + case B_CMAP8: return 1; + case B_GRAY1: return 0; default: return -1; } } + void -ImageProcessor::CopyPixel(uchar* dest, int32 destX, int32 destY, const uchar* src, int32 x, int32 y) +ImageProcessor::CopyPixel(uchar* dest, int32 destX, int32 destY, + const uchar* src, int32 x, int32 y) { - // Note: On my systems (Dual Intel P3 866MHz and AMD Athlon 1GHz), replacing - // the multiplications below with pointer arithmethics showed no speedup at all! + // Note: On my systems (Dual Intel P3 866MHz and AMD Athlon 1GHz), + // replacing the multiplications below with pointer arithmethics showed + // no speedup at all! dest += fDestBPR * destY + destX * fBPP; - src += fSrcBPR * y + x *fBPP; + src += fSrcBPR * y + x * fBPP; // Replacing memcpy with this switch statement is slightly faster switch (fBPP) { case 4: @@ -1016,6 +1066,7 @@ ImageProcessor::CopyPixel(uchar* dest, int32 destX, int32 destY, const uchar* sr } } + // Note: For B_CMAP8 InvertPixel inverts the color index not the color value! void ImageProcessor::InvertPixel(int32 x, int32 y, uchar* dest, const uchar* src) @@ -1035,18 +1086,19 @@ ImageProcessor::InvertPixel(int32 x, int32 y, uchar* dest, const uchar* src) } } -// Note: On my systems, the operation kInvert shows a speedup on multiple CPUs only! + +// Note: On my systems, the operation kInvert shows a speedup on +// multiple CPUs only! void ImageProcessor::Run(int32 i, int32 n) { int32 from, to; - int32 height = (fHeight+1) / n; + int32 height = (fHeight + 1) / n; from = i * height; - if (i+1 == n) { + if (i + 1 == n) to = fHeight; - } else { + else to = from + height - 1; - } int32 x, y, destX, destY; const uchar* src = (uchar*)GetSrcImage()->Bits(); @@ -1054,8 +1106,8 @@ ImageProcessor::Run(int32 i, int32 n) switch (fOp) { case kRotateClockwise: - for (y = from; y <= to; y ++) { - for (x = 0; x <= fWidth; x ++) { + for (y = from; y <= to; y++) { + for (x = 0; x <= fWidth; x++) { destX = fHeight - y; destY = x; CopyPixel(dest, destX, destY, src, x, y); @@ -1097,5 +1149,4 @@ ImageProcessor::Run(int32 i, int32 n) } break; } - } diff --git a/src/apps/showimage/Filter.h b/src/apps/showimage/Filter.h index 4419361df5..8021ca133f 100644 --- a/src/apps/showimage/Filter.h +++ b/src/apps/showimage/Filter.h @@ -63,16 +63,17 @@ const int32 kFPOne = to_fixed_point(1); // Used by class Filter class FilterThread { public: - FilterThread(Filter* filter, int32 i, int32 n, bool runInCurrentThread = false); + FilterThread(Filter* filter, int32 i, int32 n, + bool runInCurrentThread = false); ~FilterThread(); private: status_t Run(); static status_t worker_thread(void* data); - Filter* fFilter; - int32 fI; - int32 fN; + Filter* fFilter; + int32 fI; + int32 fN; }; class Filter { @@ -142,26 +143,27 @@ private: // Returns the number of active CPUs int32 CPUCount() const { return fCPUCount; } - BMessenger fListener; - uint32 fWhat; - int32 fCPUCount; // the number of active CPUs - bool fStarted; // has Start() been called? - sem_id fWaitForThreads; // to exit - int32 fN; // the number of used filter threads - volatile int32 fNumberOfThreads; // the current number of FilterThreads - volatile bool fIsRunning; // FilterThreads should process data as long as it is true - BBitmap* fSrcImage; - bool fDestImageInitialized; - BBitmap* fDestImage; + BMessenger fListener; + uint32 fWhat; + int32 fCPUCount; // the number of active CPUs + bool fStarted; // has Start() been called? + sem_id fWaitForThreads; // to exit + int32 fN; // the number of used filter threads + volatile int32 fNumberOfThreads; // the current number of FilterThreads + volatile bool fIsRunning; // FilterThreads should process data as long as it is true + BBitmap* fSrcImage; + bool fDestImageInitialized; + BBitmap* fDestImage; #if TIME_FILTER - BStopWatch* fStopWatch; + BStopWatch* fStopWatch; #endif }; // Scales and optionally dithers an image class Scaler : public Filter { public: - Scaler(BBitmap* image, BRect rect, BMessenger listener, uint32 what, bool dither); + Scaler(BBitmap* image, BRect rect, BMessenger listener, uint32 what, + bool dither); ~Scaler(); BBitmap* CreateDestImage(BBitmap* srcImage); @@ -173,7 +175,9 @@ public: private: void ScaleBilinear(int32 fromRow, int32 toRow); void ScaleBilinearFP(int32 fromRow, int32 toRow); - inline void RowValues(float* sum, const uchar* srcData, intType srcW, intType fromX, intType toX, const float a0X, const float a1X, const int32 kBPP); + inline void RowValues(float* sum, const uchar* srcData, intType srcW, + intType fromX, intType toX, const float a0X, + const float a1X, const int32 kBPP); void DownScaleBilinear(int32 fromRow, int32 toRow); static inline uchar Limit(intType value); void Dither(int32 fromRow, int32 toRow); @@ -195,14 +199,16 @@ public: kNumberOfAffineTransformations = 4 }; - ImageProcessor(enum operation op, BBitmap* image, BMessenger listener, uint32 what); + ImageProcessor(enum operation op, BBitmap* image, BMessenger listener, + uint32 what); BBitmap* CreateDestImage(BBitmap* srcImage); int32 GetNumberOfUnits(); void Run(int32 i, int32 n); private: int32 BytesPerPixel(color_space cs) const; - inline void CopyPixel(uchar* dest, int32 destX, int32 destY, const uchar* src, int32 x, int32 y); + inline void CopyPixel(uchar* dest, int32 destX, int32 destY, + const uchar* src, int32 x, int32 y); inline void InvertPixel(int32 x, int32 y, uchar* dest, const uchar* src); enum operation fOp; diff --git a/src/apps/showimage/ImageFileNavigator.cpp b/src/apps/showimage/ImageFileNavigator.cpp index b9ed68de4e..bf32b106c2 100644 --- a/src/apps/showimage/ImageFileNavigator.cpp +++ b/src/apps/showimage/ImageFileNavigator.cpp @@ -374,14 +374,16 @@ AutoAdjustingNavigator::~AutoAdjustingNavigator() bool -AutoAdjustingNavigator::FindNextImage(const entry_ref& currentRef, entry_ref& nextRef, - bool next, bool rewind) +AutoAdjustingNavigator::FindNextImage(const entry_ref& currentRef, + entry_ref& nextRef, bool next, bool rewind) { if (_CheckForTracker(currentRef)) - return fTrackerNavigator->FindNextImage(currentRef, nextRef, next, rewind); + return fTrackerNavigator->FindNextImage(currentRef, nextRef, next, + rewind); if (fFolderNavigator != NULL) - return fFolderNavigator->FindNextImage(currentRef, nextRef, next, rewind); + return fFolderNavigator->FindNextImage(currentRef, nextRef, next, + rewind); return false; } diff --git a/src/apps/showimage/PrintOptionsWindow.cpp b/src/apps/showimage/PrintOptionsWindow.cpp index fca276f913..782e43e70c 100644 --- a/src/apps/showimage/PrintOptionsWindow.cpp +++ b/src/apps/showimage/PrintOptionsWindow.cpp @@ -15,10 +15,10 @@ #include #include #include -#include #include -#include +#include #include +#include #include #include "ShowImageConstants.h" @@ -73,7 +73,7 @@ PrintOptions::SetWidth(float w) void PrintOptions::SetHeight(float h) { - fWidth = (fBounds.Width()+1) * h / (fBounds.Height()+1); + fWidth = (fBounds.Width() + 1) * h / (fBounds.Height() + 1); fHeight = h; } diff --git a/src/apps/showimage/ProgressWindow.cpp b/src/apps/showimage/ProgressWindow.cpp index 08221e5d91..70df9875f8 100644 --- a/src/apps/showimage/ProgressWindow.cpp +++ b/src/apps/showimage/ProgressWindow.cpp @@ -37,7 +37,7 @@ ProgressWindow::ProgressWindow() { BRect rect = Bounds(); - BView *view = new BView(rect, NULL, B_FOLLOW_ALL, B_WILL_DRAW); + BView* view = new BView(rect, NULL, B_FOLLOW_ALL, B_WILL_DRAW); view->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); AddChild(view); @@ -106,7 +106,7 @@ ProgressWindow::Stop() void -ProgressWindow::MessageReceived(BMessage *message) +ProgressWindow::MessageReceived(BMessage* message) { switch (message->what) { case kMsgShow: @@ -123,7 +123,7 @@ ProgressWindow::MessageReceived(BMessage *message) if (message->FindFloat("percent", &percent) == B_OK) fStatusBar->Update(percent - fStatusBar->CurrentValue()); - const char *text; + const char* text; if (message->FindString("message", &text) == B_OK) fStatusBar->SetText(text); diff --git a/src/apps/showimage/SelectionBox.cpp b/src/apps/showimage/SelectionBox.cpp index 3fd92dbefb..08daf1701a 100644 --- a/src/apps/showimage/SelectionBox.cpp +++ b/src/apps/showimage/SelectionBox.cpp @@ -109,13 +109,13 @@ SelectionBox::Animate() { // rotate up uchar p = fPatternUp.data[0]; - for (int i = 0; i <= 6; i ++) + for (int i = 0; i <= 6; i++) fPatternUp.data[i] = fPatternUp.data[i + 1]; fPatternUp.data[7] = p; // rotate down p = fPatternDown.data[7]; - for (int i = 7; i >= 1; i --) + for (int i = 7; i >= 1; i--) fPatternDown.data[i] = fPatternDown.data[i - 1]; fPatternDown.data[0] = p; @@ -170,7 +170,7 @@ SelectionBox::_InitPatterns() uchar p; uchar p1 = 0x33; uchar p2 = 0xCC; - for (int i = 0; i <= 7; i ++) { + for (int i = 0; i <= 7; i++) { fPatternLeft.data[i] = p1; fPatternRight.data[i] = p2; if ((i / 2) % 2 == 0) diff --git a/src/apps/showimage/ShowImageApp.cpp b/src/apps/showimage/ShowImageApp.cpp index 00b45a1533..c3147da98e 100644 --- a/src/apps/showimage/ShowImageApp.cpp +++ b/src/apps/showimage/ShowImageApp.cpp @@ -207,7 +207,7 @@ void ShowImageApp::_BroadcastToWindows(BMessage* message) { const int32 count = CountWindows(); - for (int32 i = 0; i < count; i ++) { + for (int32 i = 0; i < count; i++) { // BMessenger checks for us if BWindow is still a valid object BMessenger messenger(WindowAt(i)); messenger.SendMessage(message); diff --git a/src/apps/showimage/ShowImageUndo.cpp b/src/apps/showimage/ShowImageUndo.cpp index 31a9073a68..d4c2ad7cf8 100644 --- a/src/apps/showimage/ShowImageUndo.cpp +++ b/src/apps/showimage/ShowImageUndo.cpp @@ -64,7 +64,7 @@ ShowImageUndo::SendUndoStateMessage(bool bCanUndo) void -ShowImageUndo::SetTo(BRect rect, BBitmap *restore, BBitmap *selection) +ShowImageUndo::SetTo(BRect rect, BBitmap* restore, BBitmap* selection) { // NOTE: THIS FUNCTION DOES NOT MAKE COPIES OF THE BITMAPS PASSED TO IT InternalClear(); @@ -79,7 +79,7 @@ ShowImageUndo::SetTo(BRect rect, BBitmap *restore, BBitmap *selection) void -ShowImageUndo::Undo(BRect rect, BBitmap *restore, BBitmap *selection) +ShowImageUndo::Undo(BRect rect, BBitmap* restore, BBitmap* selection) { // NOTE: THIS FUNCTION DOES NOT MAKE COPIES OF THE BITMAPS PASSED TO IT fUndoType = UNDO_REDO; diff --git a/src/apps/showimage/ShowImageView.cpp b/src/apps/showimage/ShowImageView.cpp index 22e14a4c52..86b3ee4c8a 100644 --- a/src/apps/showimage/ShowImageView.cpp +++ b/src/apps/showimage/ShowImageView.cpp @@ -90,8 +90,8 @@ ShowImageView::fTransformation[ImageProcessor::kNumberOfAffineTransformations] {k0V, k90V, k0H, k270V, k0, k90, k180, k270} }; -const rgb_color kAlphaLow = (rgb_color){ 0xbb, 0xbb, 0xbb, 0xff }; -const rgb_color kAlphaHigh = (rgb_color){ 0xe0, 0xe0, 0xe0, 0xff }; +const rgb_color kAlphaLow = (rgb_color) { 0xbb, 0xbb, 0xbb, 0xff }; +const rgb_color kAlphaHigh = (rgb_color) { 0xe0, 0xe0, 0xe0, 0xff }; const uint32 kMsgPopUpMenuClosed = 'pmcl'; @@ -129,17 +129,16 @@ compose_checker_background(const BBitmap* bitmap) p[3] = 255; alpha = 255 - alpha; if (x % 10 >= 5) { - if (i % 10 >= 5) { + if (i % 10 >= 5) blend_colors(p, kAlphaLow.red, kAlphaLow.green, kAlphaLow.blue, alpha); - } else { + else blend_colors(p, kAlphaHigh.red, kAlphaHigh.green, kAlphaHigh.blue, alpha); - } + } else { - if (i % 10 >= 5) { + if (i % 10 >= 5) blend_colors(p, kAlphaHigh.red, kAlphaHigh.green, kAlphaHigh.blue, alpha); - } else { + else blend_colors(p, kAlphaLow.red, kAlphaLow.green, kAlphaLow.blue, alpha); - } } } p += 4; @@ -171,7 +170,7 @@ PopUpMenu::~PopUpMenu() // #pragma mark - -ShowImageView::ShowImageView(BRect rect, const char *name, uint32 resizingMode, +ShowImageView::ShowImageView(BRect rect, const char* name, uint32 resizingMode, uint32 flags) : BView(rect, name, resizingMode, flags), @@ -249,9 +248,8 @@ ShowImageView::Pulse() BPoint mousePos; uint32 buttons; GetMouse(&mousePos, &buttons, false); - if (Bounds().Contains(mousePos)) { + if (Bounds().Contains(mousePos)) be_app->ObscureCursor(); - } } else fHideCursorCountDown--; } @@ -263,7 +261,7 @@ ShowImageView::Pulse() void -ShowImageView::_SendMessageToWindow(BMessage *message) +ShowImageView::_SendMessageToWindow(BMessage* message) { BMessenger target(Window()); target.SendMessage(message); @@ -605,18 +603,18 @@ ShowImageView::_DrawBackground(BRect border) { BRect bounds(Bounds()); // top - FillRect(BRect(0, 0, bounds.right, border.top-1), B_SOLID_LOW); + FillRect(BRect(0, 0, bounds.right, border.top - 1), B_SOLID_LOW); // left - FillRect(BRect(0, border.top, border.left-1, border.bottom), B_SOLID_LOW); + FillRect(BRect(0, border.top, border.left - 1, border.bottom), B_SOLID_LOW); // right - FillRect(BRect(border.right+1, border.top, bounds.right, border.bottom), B_SOLID_LOW); + FillRect(BRect(border.right + 1, border.top, bounds.right, border.bottom), B_SOLID_LOW); // bottom - FillRect(BRect(0, border.bottom+1, bounds.right, bounds.bottom), B_SOLID_LOW); + FillRect(BRect(0, border.bottom + 1, bounds.right, bounds.bottom), B_SOLID_LOW); } void -ShowImageView::_LayoutCaption(BFont &font, BPoint &pos, BRect &rect) +ShowImageView::_LayoutCaption(BFont& font, BPoint& pos, BRect& rect) { font_height fontHeight; float width, height; @@ -790,7 +788,7 @@ ShowImageView::_CopySelection(uchar alpha, bool imageSize) bool ShowImageView::_AddSupportedTypes(BMessage* msg, BBitmap* bitmap) { - BTranslatorRoster *roster = BTranslatorRoster::Default(); + BTranslatorRoster* roster = BTranslatorRoster::Default(); if (roster == NULL) return false; @@ -812,9 +810,9 @@ ShowImageView::_AddSupportedTypes(BMessage* msg, BBitmap* bitmap) int32 count; roster->GetOutputFormats(info[i].translator, &formats, &count); for (int32 j = 0; j < count; j++) { - if (fMimeType == formats[j].MIME) { + if (fMimeType == formats[j].MIME) foundCurrent = true; - } else if (strcmp(formats[j].MIME, "image/x-be-bitmap") != 0) { + else if (strcmp(formats[j].MIME, "image/x-be-bitmap") != 0) { foundOther = true; // needed to send data in message msg->AddString("be:types", formats[j].MIME); @@ -932,7 +930,7 @@ ShowImageView::SaveToFile(BDirectory* dir, const char* name, BBitmap* bitmap, bool loop = true; while (loop) { - BTranslatorRoster *roster = BTranslatorRoster::Default(); + BTranslatorRoster* roster = BTranslatorRoster::Default(); if (!roster) break; // write data @@ -954,7 +952,7 @@ ShowImageView::SaveToFile(BDirectory* dir, const char* name, BBitmap* bitmap, char buffer[512]; snprintf(buffer, sizeof(buffer), B_TRANSLATE("The file '%s' could not " "be written."), name); - BAlert *palert = new BAlert("", buffer, B_TRANSLATE("OK")); + BAlert* palert = new BAlert("", buffer, B_TRANSLATE("OK")); palert->Go(); } @@ -965,14 +963,16 @@ ShowImageView::SaveToFile(BDirectory* dir, const char* name, BBitmap* bitmap, void -ShowImageView::_SendInMessage(BMessage* msg, BBitmap* bitmap, translation_format* format) +ShowImageView::_SendInMessage(BMessage* msg, BBitmap* bitmap, + translation_format* format) { BMessage reply(B_MIME_DATA); BBitmapStream stream(bitmap); // destructor deletes bitmap - BTranslatorRoster *roster = BTranslatorRoster::Default(); + BTranslatorRoster* roster = BTranslatorRoster::Default(); BMallocIO memStream; if (roster->Translate(&stream, NULL, NULL, &memStream, format->type) == B_OK) { - reply.AddData(format->MIME, B_MIME_TYPE, memStream.Buffer(), memStream.BufferLength()); + reply.AddData(format->MIME, B_MIME_TYPE, memStream.Buffer(), + memStream.BufferLength()); msg->SendReply(&reply); } } @@ -1335,7 +1335,7 @@ ShowImageView::KeyDown(const char* bytes, int32 numBytes) void -ShowImageView::_MouseWheelChanged(BMessage *msg) +ShowImageView::_MouseWheelChanged(BMessage* msg) { // The BeOS driver does not currently support // X wheel scrolling, therefore, dx is zero. @@ -1379,14 +1379,14 @@ void ShowImageView::_ShowPopUpMenu(BPoint screen) { if (!fShowingPopUpMenu) { - PopUpMenu* menu = new PopUpMenu("PopUpMenu", this); + PopUpMenu* menu = new PopUpMenu("PopUpMenu", this); - ShowImageWindow* window = dynamic_cast(Window()); - if (window != NULL) - window->BuildContextMenu(menu); + ShowImageWindow* window = dynamic_cast(Window()); + if (window != NULL) + window->BuildContextMenu(menu); - menu->Go(screen, true, true, true); - fShowingPopUpMenu = true; + menu->Go(screen, true, true, true); + fShowingPopUpMenu = true; } } @@ -1430,18 +1430,18 @@ ShowImageView::FixupScrollBar(orientation o, float bitmapLength, float viewLength) { float prop, range; - BScrollBar *psb; + BScrollBar* psb; psb = ScrollBar(o); if (psb) { range = bitmapLength - viewLength; - if (range < 0.0) { + if (range < 0.0) range = 0.0; - } + prop = viewLength / bitmapLength; - if (prop > 1.0) { + if (prop > 1.0) prop = 1.0; - } + psb->SetRange(0, range); psb->SetProportion(prop); psb->SetSteps(10, 100); @@ -1481,22 +1481,23 @@ ShowImageView::Undo() // backup current selection BRect undoneSelRect; - BBitmap *undoneSelection; + BBitmap* undoneSelection; undoneSelRect = fSelectionBox.Bounds(); undoneSelection = _CopySelection(); if (undoType == UNDO_UNDO) { - BBitmap *undoRestore; + BBitmap* undoRestore; undoRestore = fUndo.GetRestoreBitmap(); if (undoRestore) _MergeWithBitmap(undoRestore, fUndo.GetRect()); } // restore previous image/selection - BBitmap *undoSelection; + BBitmap* undoSelection; undoSelection = fUndo.GetSelectionBitmap(); // NOTE: ShowImageView is responsible for deleting this bitmap - // (Which it will, as it would with a fSelectionBitmap that it allocated itself) + // (Which it will, as it would with a fSelectionBitmap that it + // allocated itself) if (!undoSelection) _SetHasSelection(false); else { @@ -1683,10 +1684,14 @@ ShowImageView::_DoImageOperation(ImageProcessor::operation op, bool quiet) // update orientation state if (op != ImageProcessor::kInvert) { // Note: If one of these fails, check its definition in class ImageProcessor. -// ASSERT(ImageProcessor::kRotateClockwise < ImageProcessor::kNumberOfAffineTransformations); -// ASSERT(ImageProcessor::kRotateCounterClockwise < ImageProcessor::kNumberOfAffineTransformations); -// ASSERT(ImageProcessor::kFlipLeftToRight < ImageProcessor::kNumberOfAffineTransformations); -// ASSERT(ImageProcessor::kFlipTopToBottom < ImageProcessor::kNumberOfAffineTransformations); +// ASSERT(ImageProcessor::kRotateClockwise < +// ImageProcessor::kNumberOfAffineTransformations); +// ASSERT(ImageProcessor::kRotateCounterClockwise < +// ImageProcessor::kNumberOfAffineTransformations); +// ASSERT(ImageProcessor::kFlipLeftToRight < +// ImageProcessor::kNumberOfAffineTransformations); +// ASSERT(ImageProcessor::kFlipTopToBottom < +// ImageProcessor::kNumberOfAffineTransformations); fImageOrientation = fTransformation[op][fImageOrientation]; } @@ -1697,9 +1702,8 @@ ShowImageView::_DoImageOperation(ImageProcessor::operation op, bool quiet) if (orientation != k0) { node.WriteAttr(SHOW_IMAGE_ORIENTATION_ATTRIBUTE, B_INT32_TYPE, 0, &orientation, sizeof(orientation)); - } else { + } else node.RemoveAttr(SHOW_IMAGE_ORIENTATION_ATTRIBUTE); - } } // set new bitmap @@ -1749,7 +1753,7 @@ ShowImageView::ResizeImage(int w, int h) if (fBitmap == NULL || w < 1 || h < 1) return; - Scaler scaler(fBitmap, BRect(0, 0, w-1, h-1), BMessenger(), 0, false); + Scaler scaler(fBitmap, BRect(0, 0, w - 1, h - 1), BMessenger(), 0, false); scaler.Start(false); BBitmap* scaled = scaler.DetachBitmap(); if (scaled == NULL) { @@ -1784,17 +1788,17 @@ ShowImageView::_SetIcon(bool clear, icon_size which) BRect rect(fBitmap->Bounds()); float s; - s = size / (rect.Width()+1.0); + s = size / (rect.Width() + 1.0); - if (s * (rect.Height()+1.0) <= size) { - rect.right = size-1; - rect.bottom = static_cast(s * (rect.Height()+1.0))-1; + if (s * (rect.Height() + 1.0) <= size) { + rect.right = size - 1; + rect.bottom = static_cast(s * (rect.Height() + 1.0)) - 1; // center vertically rect.OffsetBy(0, (size - rect.IntegerHeight()) / 2); } else { - s = size / (rect.Height()+1.0); - rect.right = static_cast(s * (rect.Width()+1.0))-1; - rect.bottom = size-1; + s = size / (rect.Height() + 1.0); + rect.right = static_cast(s * (rect.Width() + 1.0)) - 1; + rect.bottom = size - 1; // center horizontally rect.OffsetBy((size - rect.IntegerWidth()) / 2, 0); } @@ -1806,7 +1810,7 @@ ShowImageView::_SetIcon(bool clear, icon_size which) scaler.Start(false); ASSERT(thumbnail->ColorSpace() == B_CMAP8); // create icon from thumbnail - BBitmap icon(BRect(0, 0, size-1, size-1), B_CMAP8); + BBitmap icon(BRect(0, 0, size - 1, size - 1), B_CMAP8); memset(icon.Bits(), B_TRANSPARENT_MAGIC_CMAP8, icon.BitsLength()); BScreen screen; const uchar* src = (uchar*)thumbnail->Bits(); @@ -1816,10 +1820,10 @@ ShowImageView::_SetIcon(bool clear, icon_size which) const int32 dx = (int32)rect.left; const int32 dy = (int32)rect.top; - for (int32 y = 0; y <= rect.IntegerHeight(); y ++) { - for (int32 x = 0; x <= rect.IntegerWidth(); x ++) { + for (int32 y = 0; y <= rect.IntegerHeight(); y++) { + for (int32 x = 0; x <= rect.IntegerWidth(); x++) { const uchar* s = src + y * srcBPR + x; - uchar* d = dest + (y+dy) * destBPR + (x+dx); + uchar* d = dest + (y + dy) * destBPR + (x + dx); *d = *s; } } diff --git a/src/apps/showimage/ShowImageView.h b/src/apps/showimage/ShowImageView.h index b72be7d104..b14985b028 100644 --- a/src/apps/showimage/ShowImageView.h +++ b/src/apps/showimage/ShowImageView.h @@ -104,20 +104,20 @@ public: private: enum image_orientation { - k0, // 0 - k90, // 1 - k180, // 2 - k270, // 3 - k0V, // 4 - k90V, // 5 - k0H, // 6 - k270V, // 7 + k0, // 0 + k90, // 1 + k180, // 2 + k270, // 3 + k0V, // 4 + k90V, // 5 + k0H, // 6 + k270V, // 7 kNumberOfOrientations, }; void _SetHasSelection(bool bHasSelection); void _AnimateSelection(bool a); - void _SendMessageToWindow(BMessage *message); + void _SendMessageToWindow(BMessage* message); void _SendMessageToWindow(uint32 code); void _Notify(); void _UpdateStatusText(); diff --git a/src/apps/showimage/ShowImageWindow.cpp b/src/apps/showimage/ShowImageWindow.cpp index 1fad14f560..c6cabd2253 100644 --- a/src/apps/showimage/ShowImageWindow.cpp +++ b/src/apps/showimage/ShowImageWindow.cpp @@ -990,7 +990,8 @@ ShowImageWindow::MessageReceived(BMessage* message) backgroundsMessage.AddRef("refs", fImageView->Image()); // This is used in the Backgrounds code for scaled placement backgroundsMessage.AddInt32("placement", 'scpl'); - be_roster->Launch("application/x-vnd.haiku-backgrounds", &backgroundsMessage); + be_roster->Launch("application/x-vnd.haiku-backgrounds", + &backgroundsMessage); break; } @@ -1050,9 +1051,9 @@ ShowImageWindow::MessageReceived(BMessage* message) if (message->FindFloat("offset", &offset) == B_OK && message->FindBool("show", &show) == B_OK) { // Compensate rounding errors with the final placement - if (show) { + if (show) fToolBarView->MoveTo(fToolBarView->Frame().left, 0); - } else { + else { fToolBarView->MoveTo(fToolBarView->Frame().left, offset); fToolBarView->Hide(); } @@ -1174,7 +1175,8 @@ ShowImageWindow::_SaveToFile(BMessage* message) int32 i; for (i = 0; i < outCount; i++) { - if (outFormat[i].group == B_TRANSLATOR_BITMAP && outFormat[i].type == outType) + if (outFormat[i].group == B_TRANSLATOR_BITMAP && outFormat[i].type + == outType) break; } if (i == outCount) @@ -1271,8 +1273,8 @@ ShowImageWindow::_ToggleFullScreen() BScreen screen; fWindowFrame = Frame(); frame = screen.Frame(); - frame.top -= fBar->Bounds().Height()+1; - frame.right += B_V_SCROLL_BAR_WIDTH-1; + frame.top -= fBar->Bounds().Height() + 1; + frame.right += B_V_SCROLL_BAR_WIDTH - 1; frame.bottom += B_H_SCROLL_BAR_HEIGHT; frame.InsetBy(-1, -1); // PEN_SIZE in ShowImageView @@ -1414,7 +1416,7 @@ ShowImageWindow::_Print(BMessage* msg) float width; switch (fPrintOptions.Option()) { case PrintOptions::kFitToPage: { - float w1 = printableRect.Width()+1; + float w1 = printableRect.Width() + 1; float w2 = imageWidth * (printableRect.Height() + 1) / imageHeight; if (w2 < w1) diff --git a/src/apps/showimage/ToolBarView.cpp b/src/apps/showimage/ToolBarView.cpp index e1c2714ffa..a1ec2e20d1 100644 --- a/src/apps/showimage/ToolBarView.cpp +++ b/src/apps/showimage/ToolBarView.cpp @@ -51,8 +51,8 @@ ToolBarView::AddAction(uint32 command, BHandler* target, const BBitmap* icon, void -ToolBarView::AddAction(BMessage* message, BHandler* target, const BBitmap* icon, - const char* toolTipText) +ToolBarView::AddAction(BMessage* message, BHandler* target, + const BBitmap* icon, const char* toolTipText) { BIconButton* button = new BIconButton(NULL, NULL, message, target); button->SetIcon(icon); From 67eb2a041e44de49f3987a49469fea9b549aae79 Mon Sep 17 00:00:00 2001 From: Humdinger Date: Sun, 24 Jun 2012 20:58:18 +0200 Subject: [PATCH 084/349] Reverting hrev44253. Didn't fix the issue, see #8648. --- src/apps/showimage/ShowImageWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/showimage/ShowImageWindow.cpp b/src/apps/showimage/ShowImageWindow.cpp index c6cabd2253..6430c23d39 100644 --- a/src/apps/showimage/ShowImageWindow.cpp +++ b/src/apps/showimage/ShowImageWindow.cpp @@ -1274,7 +1274,7 @@ ShowImageWindow::_ToggleFullScreen() fWindowFrame = Frame(); frame = screen.Frame(); frame.top -= fBar->Bounds().Height() + 1; - frame.right += B_V_SCROLL_BAR_WIDTH - 1; + frame.right += B_V_SCROLL_BAR_WIDTH; frame.bottom += B_H_SCROLL_BAR_HEIGHT; frame.InsetBy(-1, -1); // PEN_SIZE in ShowImageView From 43ae7728689f08eaea882bd20f8e8d2afe3bec84 Mon Sep 17 00:00:00 2001 From: Humdinger Date: Sun, 24 Jun 2012 21:01:17 +0200 Subject: [PATCH 085/349] Style-fix I missed before. Thanks aldeck. --- src/apps/showimage/Filter.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/apps/showimage/Filter.cpp b/src/apps/showimage/Filter.cpp index b6a8702471..6c5769abdd 100644 --- a/src/apps/showimage/Filter.cpp +++ b/src/apps/showimage/Filter.cpp @@ -23,7 +23,8 @@ // Implementation of FilterThread FilterThread::FilterThread(Filter* filter, int32 i, int32 n, bool runInCurrentThread) - : fFilter(filter), + : + fFilter(filter), fI(i), fN(n) { From 2804cb332fca17a37d42fc3cb10e2255ebddb834 Mon Sep 17 00:00:00 2001 From: Ryan Leavengood Date: Sun, 24 Jun 2012 16:42:12 -0400 Subject: [PATCH 086/349] Fix off-by-one error which caused scrolling artifacts. Based on printf debugging the correct left value is actually -1, not 0, but instead of hard-coding numbers it makes more sense to use the existing value. I'm not sure if a -1 left value makes much sense, but overall this seems to work and does not have the scrolling artifacts. But overall I think ShowImage needs more layout management. Doing all this moving and resizing manually is error prone. Fixes #8648. --- src/apps/showimage/ShowImageWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/showimage/ShowImageWindow.cpp b/src/apps/showimage/ShowImageWindow.cpp index 6430c23d39..6aa6e9f613 100644 --- a/src/apps/showimage/ShowImageWindow.cpp +++ b/src/apps/showimage/ShowImageWindow.cpp @@ -1059,7 +1059,7 @@ ShowImageWindow::MessageReceived(BMessage* message) } BRect frame = fToolBarView->Parent()->Bounds(); frame.top = fToolBarView->Frame().bottom + 1; - fScrollView->MoveTo(0, frame.top); + fScrollView->MoveTo(fScrollView->Frame().left, frame.top); fScrollView->ResizeTo(fScrollView->Bounds().Width(), frame.Height() - B_H_SCROLL_BAR_HEIGHT + 1); fVerticalScrollBar->MoveTo( From 4dea247ceeec0a4022010cf476acf4ee23e390cb Mon Sep 17 00:00:00 2001 From: Philippe Saint-Pierre Date: Sun, 24 Jun 2012 20:47:39 -0400 Subject: [PATCH 087/349] ffmpeg: implement Copyright() (resolves TODO) + typo fix --- .../media/plugins/ffmpeg/AVFormatReader.cpp | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp b/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp index 9b3de2d213..bb12197dfc 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp +++ b/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp @@ -17,10 +17,13 @@ #include #include #include +#include +#include extern "C" { #include "avcodec.h" #include "avformat.h" + #include "dict.h" } #include "DemuxerTable.h" @@ -1478,12 +1481,14 @@ AVFormatReader::~AVFormatReader() const char* AVFormatReader::Copyright() { -// TODO: Could not find the equivalent in libavformat >= version 53. -// Use metadata API instead! -// if (fStreams != NULL && fStreams[0] != NULL) -// return fStreams[0]->Context()->copyright; - // TODO: Return copyright of the file instead! - return "Copyright 2009, Stephan Aßmus"; + BMessage* message = new BMessage(); + if (GetMetaData(message) == B_OK) { + const char* copyright; + if (message->FindString("copyright", ©right) == B_OK) + return copyright; + } + delete message; + return ""; } @@ -1638,9 +1643,9 @@ AVFormatReader::GetMetaData(BMessage* _data) // Add program info for (unsigned i = 0; i < context->nb_programs; i++) { - BMessage progamData; - avdictionary_to_message(context->programs[i]->metadata, &progamData); - _data->AddMessage("be:program", &progamData); + BMessage programData; + avdictionary_to_message(context->programs[i]->metadata, &programData); + _data->AddMessage("be:program", &programData); } return B_OK; From c589e68f4299a767a6d3d87423caa157fe9459d3 Mon Sep 17 00:00:00 2001 From: Philippe Saint-Pierre Date: Sun, 24 Jun 2012 20:49:34 -0400 Subject: [PATCH 088/349] MediaPlayer InfoWindow: Add Bitrate info, fix duration display * The duration minutes didn't include a leading zero when necessary * Added Bitrate info (#7782) --- src/apps/mediaplayer/InfoWin.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/apps/mediaplayer/InfoWin.cpp b/src/apps/mediaplayer/InfoWin.cpp index a98f3ceac4..d179add82e 100644 --- a/src/apps/mediaplayer/InfoWin.cpp +++ b/src/apps/mediaplayer/InfoWin.cpp @@ -405,6 +405,16 @@ printf("InfoWin::Update(0x%08lx)\n", which); rateString.ReplaceFirst("%d", "??"); s << rateString; } + if (format.type == B_MEDIA_ENCODED_AUDIO) { + float br = format.u.encoded_audio.bit_rate; + if (br > 0.0) { + char rateString[20]; + snprintf(rateString, sizeof(rateString), B_TRANSLATE(", %.0f kbps"), + br / 1000); + s << rateString; + } + } + s << "\n\n"; fContentsView->Insert(s.String()); } @@ -430,6 +440,8 @@ printf("InfoWin::Update(0x%08lx)\n", which); d = d % (60 * 1000); s << v << ":"; v = d / 1000; + if (v < 10) + s << '0'; s << v; if (hours) s << " " << B_TRANSLATE_COMMENT("h", "Hours"); From 9741d697e80af3e3023d59243bb61f6029eb9c37 Mon Sep 17 00:00:00 2001 From: Philippe Saint-Pierre Date: Mon, 25 Jun 2012 11:05:01 -0400 Subject: [PATCH 089/349] FFMPEG Copyright(): Fix memory leak Fix a memory leak I introduced. Followed Stippi's suggestion. Thanks! --- .../media/plugins/ffmpeg/AVFormatReader.cpp | 14 ++++++-------- src/add-ons/media/plugins/ffmpeg/AVFormatReader.h | 2 ++ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp b/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp index bb12197dfc..7b2d164525 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp +++ b/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp @@ -18,7 +18,6 @@ #include #include #include -#include extern "C" { #include "avcodec.h" @@ -1453,6 +1452,7 @@ AVFormatReader::Stream::Seek(uint32 flags, int64* frame, bigtime_t* time) AVFormatReader::AVFormatReader() : + fCopyright(""), fStreams(NULL), fSourceLock("source I/O lock") { @@ -1481,14 +1481,12 @@ AVFormatReader::~AVFormatReader() const char* AVFormatReader::Copyright() { - BMessage* message = new BMessage(); - if (GetMetaData(message) == B_OK) { - const char* copyright; - if (message->FindString("copyright", ©right) == B_OK) - return copyright; + if (fCopyright.Length() <= 0) { + BMessage message; + if (GetMetaData(&message) == B_OK) + message.FindString("copyright", &fCopyright); } - delete message; - return ""; + return fCopyright.String(); } diff --git a/src/add-ons/media/plugins/ffmpeg/AVFormatReader.h b/src/add-ons/media/plugins/ffmpeg/AVFormatReader.h index 256ee50429..9ffa4570dd 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVFormatReader.h +++ b/src/add-ons/media/plugins/ffmpeg/AVFormatReader.h @@ -7,6 +7,7 @@ #include +#include #include "ReaderPlugin.h" @@ -48,6 +49,7 @@ public: private: class Stream; + BString fCopyright; Stream** fStreams; BLocker fSourceLock; }; From 8d87f2b43afbba4bdeb052163cee6b70dba8974d Mon Sep 17 00:00:00 2001 From: Philippe Saint-Pierre Date: Mon, 25 Jun 2012 13:29:22 -0400 Subject: [PATCH 090/349] StringForRate() Introduce a function to generate the string representation of a bitrate (kbps, mbps, gbps, etc..) * Factor out the code from MediaPlayer InfoWindow * Allow different bases (/1000 or /1024) --- headers/private/shared/StringForRate.h | 24 ++++++++++ src/apps/mediaplayer/InfoWin.cpp | 11 ++--- src/kits/shared/Jamfile | 1 + src/kits/shared/StringForRate.cpp | 61 ++++++++++++++++++++++++++ 4 files changed, 90 insertions(+), 7 deletions(-) create mode 100644 headers/private/shared/StringForRate.h create mode 100644 src/kits/shared/StringForRate.cpp diff --git a/headers/private/shared/StringForRate.h b/headers/private/shared/StringForRate.h new file mode 100644 index 0000000000..bd1a0bd8d7 --- /dev/null +++ b/headers/private/shared/StringForRate.h @@ -0,0 +1,24 @@ +/* + * Copyright 2010 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef STRING_FOR_RATE_H +#define STRING_FOR_RATE_H + +#include + + +namespace BPrivate { + + +const char* string_for_rate(double rate, char* string, size_t stringSize, + double base = 1024.0f); + + +} // namespace BPrivate + + +using BPrivate::string_for_rate; + + +#endif // COLOR_QUANTIZER_H diff --git a/src/apps/mediaplayer/InfoWin.cpp b/src/apps/mediaplayer/InfoWin.cpp index d179add82e..e6508b07fe 100644 --- a/src/apps/mediaplayer/InfoWin.cpp +++ b/src/apps/mediaplayer/InfoWin.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -407,14 +408,10 @@ printf("InfoWin::Update(0x%08lx)\n", which); } if (format.type == B_MEDIA_ENCODED_AUDIO) { float br = format.u.encoded_audio.bit_rate; - if (br > 0.0) { - char rateString[20]; - snprintf(rateString, sizeof(rateString), B_TRANSLATE(", %.0f kbps"), - br / 1000); - s << rateString; - } + char string[20] = ""; + if (br > 0.0) + s << ", " << string_for_rate(br, string, 20, 1000.0); } - s << "\n\n"; fContentsView->Insert(s.String()); } diff --git a/src/kits/shared/Jamfile b/src/kits/shared/Jamfile index 109df80924..d56a8b6fe2 100644 --- a/src/kits/shared/Jamfile +++ b/src/kits/shared/Jamfile @@ -29,6 +29,7 @@ StaticLibrary libshared.a : RWLockManager.cpp SHA256.cpp ShakeTrackingFilter.cpp + StringForRate.cpp StringForSize.cpp Variant.cpp ; diff --git a/src/kits/shared/StringForRate.cpp b/src/kits/shared/StringForRate.cpp new file mode 100644 index 0000000000..4f0c163526 --- /dev/null +++ b/src/kits/shared/StringForRate.cpp @@ -0,0 +1,61 @@ +/* + * Copyright 2012 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#include "StringForRate.h" + +#include + +#include + +using BPrivate::gSystemCatalog; + + +#undef B_TRANSLATION_CONTEXT +#define B_TRANSLATION_CONTEXT "StringForRate" + + +namespace BPrivate { + + +const char* +string_for_rate(double rate, char* string, size_t stringSize, double base) +{ + double kbps = rate / base; + if (kbps < 1.0) { + const char* trKey = B_TRANSLATE_MARK("%.0f bps"); + snprintf(string, stringSize, gSystemCatalog.GetString(trKey, + B_TRANSLATION_CONTEXT), (int)rate); + return string; + } + double mbps = kbps / base; + if (mbps < 1.0) { + const char* trKey = B_TRANSLATE_MARK("%.0f kbps"); + snprintf(string, stringSize, gSystemCatalog.GetString(trKey, + B_TRANSLATION_CONTEXT), kbps); + return string; + } + double gbps = mbps / base; + if (gbps < 1.0) { + const char* trKey = B_TRANSLATE_MARK("%.0f mbps"); + snprintf(string, stringSize, gSystemCatalog.GetString(trKey, + B_TRANSLATION_CONTEXT), mbps); + return string; + } + double tbps = gbps / base; + if (tbps < 1.0) { + const char* trKey = B_TRANSLATE_MARK("%.0f gbps"); + snprintf(string, stringSize, gSystemCatalog.GetString(trKey, + B_TRANSLATION_CONTEXT), gbps); + return string; + } + const char* trKey = B_TRANSLATE_MARK("%.0f tbps"); + snprintf(string, stringSize, gSystemCatalog.GetString(trKey, + B_TRANSLATION_CONTEXT), tbps); + return string; +} + + +} // namespace BPrivate + From 36784bbc2c3faad776d9d12481a0ed9a6aabb646 Mon Sep 17 00:00:00 2001 From: Philippe Saint-Pierre Date: Mon, 25 Jun 2012 13:43:53 -0400 Subject: [PATCH 091/349] StringForRate(): adjustments * Make 1000.0f the default base * Also use sizeof() in MediaPlayer to get the string size rather than hardcode. Thanks Marcus --- headers/private/shared/StringForRate.h | 2 +- src/apps/mediaplayer/InfoWin.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/headers/private/shared/StringForRate.h b/headers/private/shared/StringForRate.h index bd1a0bd8d7..65e17407da 100644 --- a/headers/private/shared/StringForRate.h +++ b/headers/private/shared/StringForRate.h @@ -12,7 +12,7 @@ namespace BPrivate { const char* string_for_rate(double rate, char* string, size_t stringSize, - double base = 1024.0f); + double base = 1000.0f); } // namespace BPrivate diff --git a/src/apps/mediaplayer/InfoWin.cpp b/src/apps/mediaplayer/InfoWin.cpp index e6508b07fe..2316481d6f 100644 --- a/src/apps/mediaplayer/InfoWin.cpp +++ b/src/apps/mediaplayer/InfoWin.cpp @@ -410,7 +410,7 @@ printf("InfoWin::Update(0x%08lx)\n", which); float br = format.u.encoded_audio.bit_rate; char string[20] = ""; if (br > 0.0) - s << ", " << string_for_rate(br, string, 20, 1000.0); + s << ", " << string_for_rate(br, string, sizeof(string)); } s << "\n\n"; fContentsView->Insert(s.String()); From c4e5472a71bd1b62643effe55abf6ac674b3255b Mon Sep 17 00:00:00 2001 From: Philippe Saint-Pierre Date: Mon, 25 Jun 2012 13:52:31 -0400 Subject: [PATCH 092/349] FFMPEG: Remove unnecessary #include statements They were included because of earlier tests. Thanks Korli for the heads-up! (and sorry for the noise..) --- src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp b/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp index 7b2d164525..23b0b66815 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp +++ b/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp @@ -17,12 +17,10 @@ #include #include #include -#include extern "C" { #include "avcodec.h" #include "avformat.h" - #include "dict.h" } #include "DemuxerTable.h" From d1556a0e0f26d07d7b2d8c40fc5c6be0f879b514 Mon Sep 17 00:00:00 2001 From: Scott McCreary Date: Sat, 16 Jun 2012 00:12:29 +0000 Subject: [PATCH 093/349] Updated optional packages for curl, freetype, libxml2, mercurial, openssl, p7zip, sqlite and tar. --- build/jam/OptionalBuildFeatures | 12 +++---- build/jam/OptionalLibPackages | 44 +++++++++++++------------- build/jam/OptionalPackages | 56 ++++++++++++++++----------------- 3 files changed, 56 insertions(+), 56 deletions(-) diff --git a/build/jam/OptionalBuildFeatures b/build/jam/OptionalBuildFeatures index 789c4e908e..dc4da0a0cb 100644 --- a/build/jam/OptionalBuildFeatures +++ b/build/jam/OptionalBuildFeatures @@ -12,9 +12,9 @@ if [ IsOptionalHaikuImagePackageAdded OpenSSL ] { } if $(HAIKU_GCC_VERSION[1]) >= 4 { - HAIKU_OPENSSL_PACKAGE = openssl-1.0.0e-x86-gcc4-2011-09-08.zip ; + HAIKU_OPENSSL_PACKAGE = openssl-1.0.0j-x86-gcc4-2012-06-01.zip ; } else { - HAIKU_OPENSSL_PACKAGE = openssl-1.0.0e-x86-gcc2-2011-09-09.zip ; + HAIKU_OPENSSL_PACKAGE = openssl-1.0.0j-x86-gcc2-2012-06-15.zip ; } local baseURL = http://haiku-files.org/files/optional-packages ; @@ -339,9 +339,9 @@ if $(TARGET_ARCH) = ppc || $(TARGET_ARCH) = x86 { if $(TARGET_ARCH) = ppc { HAIKU_FREETYPE_FILE = freetype-2.4.6-ppc-gcc4-2012-03-17.zip ; } else if $(HAIKU_GCC_VERSION[1]) >= 4 { - HAIKU_FREETYPE_FILE = freetype-2.4.6-x86-gcc4-2012-03-15.zip ; + HAIKU_FREETYPE_FILE = freetype-2.4.9-x86-gcc4-2012-06-15.zip ; } else { - HAIKU_FREETYPE_FILE = freetype-2.4.6-x86-gcc2-2012-03-15.zip ; + HAIKU_FREETYPE_FILE = freetype-2.4.9-x86-gcc2-2012-06-15.zip ; } local freetypeZipFile = [ DownloadFile $(HAIKU_FREETYPE_FILE) @@ -361,7 +361,7 @@ if $(TARGET_ARCH) = ppc || $(TARGET_ARCH) = x86 { : extracted-freetype ] ; HAIKU_FREETYPE_CURRENT_LIB = [ ExtractArchive $(HAIKU_FREETYPE_DIR) : - common/lib/libfreetype.so.6.7.1 + common/lib/libfreetype.so.6.8.1 : $(freetypeZipFile) : extracted-freetype ] ; Depends $(HAIKU_FREETYPE_LIB) $(HAIKU_FREETYPE_CURRENT_LIB) : $(HAIKU_FREETYPE_HEADERS_DEPENDENCY) ; @@ -385,7 +385,7 @@ if [ IsOptionalHaikuImagePackageAdded TagLib ] { } local baseURL = http://haiku-files.org/files/optional-packages ; -HAIKU_TAGLIB_PACKAGE = taglib-1.6.3-r1a2-x86-gcc2-2010-04-25.zip ; +HAIKU_TAGLIB_PACKAGE = taglib-1.7.2-x86-gcc2-2012-06-15.zip ; HAIKU_TAGLIB_URL = $(baseURL)/$(HAIKU_TAGLIB_PACKAGE) ; if $(HAIKU_BUILD_FEATURE_TAGLIB) { diff --git a/build/jam/OptionalLibPackages b/build/jam/OptionalLibPackages index 82042787c3..941fee38ff 100644 --- a/build/jam/OptionalLibPackages +++ b/build/jam/OptionalLibPackages @@ -227,41 +227,41 @@ if [ IsOptionalHaikuImagePackageAdded SDLLibs ] { Echo "No optional package SDLLibs available for $(TARGET_ARCH)" ; } else if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - libsdl-1.2-hg-r1a3-x86-gcc4-2011-05-29.zip - : $(baseURL)/lib/libsdl-1.2-hg-r1a3-x86-gcc4-2011-05-29.zip ; + libsdl-1.2.15-x86-gcc4-2012-05-31.zip + : $(baseURL)/lib/libsdl-1.2.15-x86-gcc4-2012-05-31.zip ; InstallOptionalHaikuImagePackage - guilib-1.2.1-r1a3-x86-gcc4-2011-05-26.zip - : $(baseURL)/lib/guilib-1.2.1-r1a3-x86-gcc4-2011-05-26.zip ; + guilib-1.2.1-x86-gcc4-2012-05-31.zip + : $(baseURL)/lib/guilib-1.2.1-x86-gcc4-2012-05-31.zip ; InstallOptionalHaikuImagePackage - sdl-gfx-2.0.22-r1a3-x86-gcc4-2011-05-26.zip - : $(baseURL)/lib/sdl-gfx-2.0.22-r1a3-x86-gcc4-2011-05-26.zip ; + sdl-gfx-2.0.23-x86-gcc4-2011-05-31.zip + : $(baseURL)/lib/sdl-gfx-2.0.23-x86-gcc4-2012-05-31.zip ; InstallOptionalHaikuImagePackage - sdl-image-1.2.10-r1a3-x86-gcc4-2011-05-26.zip - : $(baseURL)/lib/sdl-image-1.2.10-r1a3-x86-gcc4-2011-05-26.zip ; + sdl-image-1.2.12-x86-gcc4-2012-05-31.zip + : $(baseURL)/lib/sdl-image-1.2.12-x86-gcc4-2011-05-31.zip ; InstallOptionalHaikuImagePackage - sdl-mixer-1.2.11-r1a3-x86-gcc4-2011-05-26.zip - : $(baseURL)/lib/sdl-mixer-1.2.11-r1a3-x86-gcc4-2011-05-26.zip ; + sdl-mixer-1.2.11-x86-gcc4-2012-05-31.zip + : $(baseURL)/lib/sdl-mixer-1.2.11-x86-gcc4-2012-05-31.zip ; InstallOptionalHaikuImagePackage - sdl-net-1.2.7-r1a3-x86-gcc4-2011-05-26.zip - : $(baseURL)/lib/sdl-net-1.2.7-r1a3-x86-gcc4-2011-05-26.zip ; + sdl-net-1.2.8-x86-gcc4-2012-05-31.zip + : $(baseURL)/lib/sdl-net-1.2.8-x86-gcc4-2012-05-31.zip ; InstallOptionalHaikuImagePackage - sdl-sound-1.0.3-r1a3-x86-gcc4-2011-05-26.zip - : $(baseURL)/lib/sdl-sound-1.0.3-r1a3-x86-gcc4-2011-05-26.zip ; + sdl-sound-1.0.3-x86-gcc4-2012-05-31.zip + : $(baseURL)/lib/sdl-sound-1.0.3-x86-gcc4-2012-05-31.zip ; InstallOptionalHaikuImagePackage sdl-rtf-0.1.0-r1a3-x86-gcc4-2011-05-26.zip : $(baseURL)/lib/sdl-rtf-0.1.0-r1a3-x86-gcc4-2011-05-26.zip ; InstallOptionalHaikuImagePackage - sdl-ttf-2.0.10-r1a3-x86-gcc4-2011-05-26.zip - : $(baseURL)/lib/sdl-ttf-2.0.10-r1a3-x86-gcc4-2011-05-26.zip ; + sdl-ttf-2.0.11-x86-gcc4-2012-05-31.zip + : $(baseURL)/lib/sdl-ttf-2.0.11-x86-gcc4-2012-05-31.zip ; InstallOptionalHaikuImagePackage - sge-030809-r1a3-x86-gcc4-2011-05-26.zip - : $(baseURL)/lib/sge-030809-r1a3-x86-gcc4-2011-05-26.zip ; + sge-030809-x86-gcc4-2012-05-31.zip + : $(baseURL)/lib/sge-030809-x86-gcc4-2012-05-31.zip ; InstallOptionalHaikuImagePackage - smjpeg-0.2.1-r1a3-x86-gcc4-2011-05-26.zip - : $(baseURL)/lib/smjpeg-0.2.1-r1a3-x86-gcc4-2011-05-26.zip ; + smjpeg-0.2.1-x86-gcc4-2012-05-31.zip + : $(baseURL)/lib/smjpeg-0.2.1-x86-gcc4-2012-05-31.zip ; InstallOptionalHaikuImagePackage - smpeg-0.4.5-r1a3-x86-gcc4-2011-05-26.zip - : $(baseURL)/lib/smpeg-0.4.5-r1a3-x86-gcc4-2011-05-26.zip ; + smpeg-0.4.5-x86-gcc4-2011-05-31.zip + : $(baseURL)/lib/smpeg-0.4.5-x86-gcc4-2012-05-31.zip ; } else { InstallOptionalHaikuImagePackage libsdl-1.2-hg-r1a3-x86-gcc2-2011-05-29.zip diff --git a/build/jam/OptionalPackages b/build/jam/OptionalPackages index 533fd73bcb..8737a0f92d 100644 --- a/build/jam/OptionalPackages +++ b/build/jam/OptionalPackages @@ -532,11 +532,11 @@ if [ IsOptionalHaikuImagePackageAdded Curl ] { if $(TARGET_ARCH) != x86 { Echo "No optional package Curl available for $(TARGET_ARCH)" ; } else if $(HAIKU_GCC_VERSION[1]) >= 4 { - InstallOptionalHaikuImagePackage curl-7.21.7-x86-gcc4-2012-02-18.zip - : $(baseURL)/curl-7.21.7-x86-gcc4-2012-02-18.zip ; + InstallOptionalHaikuImagePackage curl-7.26.0-x86-gcc4-2012-06-15.zip + : $(baseURL)/curl-7.26.0-x86-gcc4-2012-06-15.zip ; } else { - InstallOptionalHaikuImagePackage curl-7.21.7-x86-gcc2-2012-02-18.zip - : $(baseURL)/curl-7.21.7-x86-gcc2-2012-02-18.zip ; + InstallOptionalHaikuImagePackage curl-7.26.0-x86-gcc2-2012-06-15.zip + : $(baseURL)/curl-7.26.0-x86-gcc2-2012-06-15.zip ; } } @@ -1185,12 +1185,12 @@ if [ IsOptionalHaikuImagePackageAdded LibXML2 ] { } else { if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - libxml2-2.7.8-r1a3-x86-gcc4-2011-05-24.zip - : $(baseURL)/libxml2-2.7.8-r1a3-x86-gcc4-2011-05-24.zip ; + libxml2-2.8.0-x86-gcc4-2012-06-15.zip + : $(baseURL)/libxml2-2.8.0-x86-gcc4-2012-06-15.zip ; } else { InstallOptionalHaikuImagePackage - libxml2-2.7.8-r1a3-x86-gcc2-2011-05-18.zip - : $(baseURL)/libxml2-2.7.8-r1a3-x86-gcc2-2011-05-18.zip ; + libxml2-2.8.0-x86-gcc2-2012-06-15.zip + : $(baseURL)/libxml2-2.8.0-x86-gcc2-2012-06-15.zip ; } } } @@ -1277,13 +1277,13 @@ if [ IsOptionalHaikuImagePackageAdded Mercurial ] { } else { if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - mercurial-1.8.3-r1a3-x86-gcc4-2011-05-24.zip - : $(baseURL)/mercurial-1.8.3-r1a3-x86-gcc4-2011-05-24.zip + mercurial-2.2.2-x86-gcc4-2012-06-15.zip + : $(baseURL)/mercurial-2.2.2-x86-gcc4-2012-06-15.zip : : true ; } else { InstallOptionalHaikuImagePackage - mercurial-1.8.3-r1a3-x86-gcc2-2011-05-17.zip - : $(baseURL)/mercurial-1.8.3-r1a3-x86-gcc2-2011-05-17.zip + mercurial-2.2.2-x86-gcc2-2012-06-15.zip + : $(baseURL)/mercurial-2.2.2-x86-gcc2-2012-06-15.zip : : true ; } } @@ -1449,12 +1449,12 @@ if [ IsOptionalHaikuImagePackageAdded P7zip ] { } else { if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - p7zip-9.13-r1a3-x86-gcc4-2011-05-24.zip - : $(baseURL)/p7zip-9.13-r1a3-x86-gcc4-2011-05-24.zip ; + p7zip-9.20.1-x86-gcc4-2012-06-15.zip + : $(baseURL)/p7zip-9.20.1-x86-gcc4-2011-06-15.zip ; } else { InstallOptionalHaikuImagePackage - p7zip-9.13-r1a3-x86-gcc2-2011-05-18.zip - : $(baseURL)/p7zip-9.13-r1a3-x86-gcc2-2011-05-18.zip ; + p7zip-9.20.1-x86-gcc2-2012-06-15.zip + : $(baseURL)/p7zip-9.20.1-x86-gcc2-2012-06-15.zip ; } AddExpanderRuleToHaikuImage "application/x-7z-compressed" : .7z : "7za l \\0045s" @@ -1664,12 +1664,12 @@ if [ IsOptionalHaikuImagePackageAdded TagLib ] { Echo "No optional package TagLib available for $(TARGET_ARCH)" ; } else if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - taglib-1.6.3-r1r3-x86-gcc4-2011-05-24.zip - : $(baseURL)/taglib-1.6.3-r1r3-x86-gcc4-2011-05-24.zip ; + taglib-1.7.2-x86-gcc4-2012-06-15.zip + : $(baseURL)/taglib-1.7.2-x86-gcc4-2012-06-15.zip ; } else { InstallOptionalHaikuImagePackage - taglib-1.6.3-r1a3-x86-gcc2-2011-05-20.zip - : $(baseURL)/taglib-1.6.3-r1a3-x86-gcc2-2011-05-20.zip ; + taglib-1.7.2-x86-gcc2-2012-06-15.zip + : $(baseURL)/taglib-1.7.2-x86-gcc2-2012-06-15.zip ; } } @@ -1681,12 +1681,12 @@ if [ IsOptionalHaikuImagePackageAdded Tar ] { } else { if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - tar-1.25-r1a3-x86-gcc4-2011-05-24.zip - : $(baseURL)/tar-1.25-r1a3-x86-gcc4-2011-05-24.zip ; + tar-1.26-x86-gcc4-2012-06-15.zip + : $(baseURL)/tar-1.26-x86-gcc4-2012-06-15.zip ; } else { InstallOptionalHaikuImagePackage - tar-1.25-r1a3-x86-gcc2-2011-05-20.zip - : $(baseURL)/tar-1.25-r1a3-x86-gcc2-2011-05-20.zip ; + tar-1.26-x86-gcc2-2012-06-15.zip + : $(baseURL)/tar-1.26-x86-gcc2-2012-06-15.zip ; } } } @@ -1973,11 +1973,11 @@ if [ IsOptionalHaikuImagePackageAdded Yasm ] { Echo "No optional package Yasm available for $(TARGET_ARCH)" ; } else if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - yasm-1.1.0-r1a3-x86-gcc4-2011-05-24.zip - : $(baseURL)/yasm-1.1.0-r1a3-x86-gcc4-2011-05-24.zip ; + yasm-1.2.0-x86-gcc4-2012-06-15.zip + : $(baseURL)/yasm-1.2.0-x86-gcc4-2012-06-15.zip ; } else { InstallOptionalHaikuImagePackage - yasm-1.1.0-r1a3-x86-gcc2-2011-05-17.zip - : $(baseURL)/yasm-1.1.0-r1a3-x86-gcc2-2011-05-17.zip ; + yasm-1.2.0-x86-gcc2-2012-06-15.zip + : $(baseURL)/yasm-1.2.0-x86-gcc2-2012-06-15.zip ; } } From cc41587c17d8ee3e3a23c02ef94e847ad2d08383 Mon Sep 17 00:00:00 2001 From: Scott McCreary Date: Wed, 20 Jun 2012 22:29:26 +0000 Subject: [PATCH 094/349] Updated optionalpackages for apr, apr-util, curl,subversion, git, mercurial, openssh, sqlite, cdrtools, man, p7zip, tar, libxml2, and yasm. --- build/jam/OptionalPackages | 129 +++++++++++++++++++++---------------- 1 file changed, 75 insertions(+), 54 deletions(-) diff --git a/build/jam/OptionalPackages b/build/jam/OptionalPackages index 8737a0f92d..e00b4587d6 100644 --- a/build/jam/OptionalPackages +++ b/build/jam/OptionalPackages @@ -50,6 +50,7 @@ if $(HAIKU_ADD_ALTERNATIVE_GCC_LIBS) = 1 # friss - RSS/ATOM/... feeds reader # GetText - a framework to help produce multi-lingual messages. # Git - the distributed version control system +# GitDoc - documentation for the distributed version control system # GPerf - the perfect hash function generator. # Groff - text formatter used for man pages # ICU-devel - the headers and lib-links for ICU (for development) @@ -122,13 +123,13 @@ if [ IsOptionalHaikuImagePackageAdded APR ] { Echo "No optional package APR available for $(TARGET_ARCH)" ; } else if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - apr-1.4.5-x86-gcc4-2011-08-03.zip - : $(baseURL)/apr-1.4.5-x86-gcc4-2011-08-03.zip + apr-1.4.6-x86-gcc4-2012-06-19.zip + : $(baseURL)/apr-1.4.6-x86-gcc4-2012-06-19.zip : : true ; } else { InstallOptionalHaikuImagePackage - apr-1.4.5-x86-gcc2-2011-08-02.zip - : $(baseURL)/apr-1.4.5-x86-gcc2-2011-08-02.zip + apr-1.4.6-x86-gcc2-2012-06-20.zip + : $(baseURL)/apr-1.4.6-x86-gcc2-2012-06-20.zip : : true ; } } @@ -140,13 +141,13 @@ if [ IsOptionalHaikuImagePackageAdded APR-util ] { Echo "No optional package APR-util available for $(TARGET_ARCH)" ; } else if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - apr-util-1.3.12-x86-gcc4-2011-08-03.zip - : $(baseURL)/apr-util-1.3.12-x86-gcc4-2011-08-03.zip + apr-util-1.4.1-x86-gcc4-2012-06-19.zip + : $(baseURL)/apr-util-1.4.1-x86-gcc4-2012-06-19.zip : : true ; } else { InstallOptionalHaikuImagePackage - apr-util-1.3.12-x86-gcc2-2011-08-02.zip - : $(baseURL)/apr-util-1.3.12-x86-gcc2-2011-08-02.zip + apr-util-1.4.1-x86-gcc2-2012-06-20.zip + : $(baseURL)/apr-util-1.4.1-x86-gcc2-2012-06-20.zip : : true ; } } @@ -408,12 +409,12 @@ if [ IsOptionalHaikuImagePackageAdded CDRecord ] { Echo "No optional package CDRecord available for $(TARGET_ARCH)" ; } else if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - cdrtools-3.01a01-r1a3-x86-gcc4-2011-05-23.zip - : $(baseURL)/cdrtools-3.01a01-r1a3-x86-gcc4-2011-05-23.zip ; + cdrtools-3.01a06-x86-gcc4-2012-06-19.zip + : $(baseURL)/cdrtools-3.01a06-x86-gcc4-2012-06-19.zip ; } else { InstallOptionalHaikuImagePackage - cdrtools-3.01a01-r1a3-x86-gcc2-2011-05-17.zip - : $(baseURL)/cdrtools-3.01a01-r1a3-x86-gcc2-2011-05-17.zip ; + cdrtools-3.01a06-x86-gcc2-2012-06-20.zip + : $(baseURL)/cdrtools-3.01a06-x86-gcc2-2012-06-20.zip ; } } @@ -532,11 +533,11 @@ if [ IsOptionalHaikuImagePackageAdded Curl ] { if $(TARGET_ARCH) != x86 { Echo "No optional package Curl available for $(TARGET_ARCH)" ; } else if $(HAIKU_GCC_VERSION[1]) >= 4 { - InstallOptionalHaikuImagePackage curl-7.26.0-x86-gcc4-2012-06-15.zip - : $(baseURL)/curl-7.26.0-x86-gcc4-2012-06-15.zip ; + InstallOptionalHaikuImagePackage curl-7.26.0-x86-gcc4-2012-06-20.zip + : $(baseURL)/curl-7.26.0-x86-gcc4-2012-06-20.zip ; } else { - InstallOptionalHaikuImagePackage curl-7.26.0-x86-gcc2-2012-06-15.zip - : $(baseURL)/curl-7.26.0-x86-gcc2-2012-06-15.zip ; + InstallOptionalHaikuImagePackage curl-7.26.0-x86-gcc2-2012-06-20.zip + : $(baseURL)/curl-7.26.0-x86-gcc2-2012-06-20.zip ; } } @@ -548,13 +549,13 @@ if [ IsOptionalHaikuImagePackageAdded CVS ] { } else { if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - cvs-1.12.13.1-r1a3-x86-gcc4-2011-05-24.zip - : $(baseURL)/cvs-1.12.13.1-r1a3-x86-gcc4-2011-05-24.zip + cvs-1.12.13.1-x86-gcc4-2012-06-19.zip + : $(baseURL)/cvs-1.12.13.1-x86-gcc4-2012-06-19.zip : : true ; } else { InstallOptionalHaikuImagePackage - cvs-1.12.13.1-r1a3-x86-gcc2-2011-05-18.zip - : $(baseURL)/cvs-1.12.13.1-r1a3-x86-gcc2-2011-05-18.zip + cvs-1.12.13.1-r1a3-x86-gcc2-2012-06-20.zip + : $(baseURL)/cvs-1.12.13.1-r1a3-x86-gcc2-2012-06-20.zip : : true ; } } @@ -983,13 +984,33 @@ if [ IsOptionalHaikuImagePackageAdded Git ] { } else { if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - git-1.7.7.2-x86-gcc4-2011-11-04.zip - : $(baseURL)/git-1.7.7.2-x86-gcc4-2011-11-04.zip + git-1.7.10.2-x86-gcc4-2012-06-20.zip + : $(baseURL)/git-1.7.10.2-x86-gcc4-2012-06-20.zip : : true ; } else { InstallOptionalHaikuImagePackage - git-1.7.7.2-x86-gcc2-2011-11-04.zip - : $(baseURL)/git-1.7.7.2-x86-gcc2-2011-11-04.zip + git-1.7.10.2-x86-gcc2-2012-06-20.zip + : $(baseURL)/git-1.7.10.2-x86-gcc2-2012-06-20.zip + : : true ; + } + } +} + + +# GitDoc +if [ IsOptionalHaikuImagePackageAdded GitDoc ] { + if $(TARGET_ARCH) != x86 { + Echo "No optional package GitDoc available for $(TARGET_ARCH)" ; + } else { + if $(HAIKU_GCC_VERSION[1]) >= 4 { + InstallOptionalHaikuImagePackage + gitdoc-1.7.10.2-x86-gcc4-2012-06-20.zip + : $(baseURL)/gitdoc-1.7.10.2-x86-gcc4-2012-06-20.zip + : : true ; + } else { + InstallOptionalHaikuImagePackage + gitdoc-1.7.10.2-x86-gcc2-2012-06-20.zip + : $(baseURL)/gitdoc-1.7.10.2-x86-gcc2-2012-06-20.zip : : true ; } } @@ -1185,8 +1206,8 @@ if [ IsOptionalHaikuImagePackageAdded LibXML2 ] { } else { if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - libxml2-2.8.0-x86-gcc4-2012-06-15.zip - : $(baseURL)/libxml2-2.8.0-x86-gcc4-2012-06-15.zip ; + libxml2-2.8.0-x86-gcc4-2012-06-18.zip + : $(baseURL)/libxml2-2.8.0-x86-gcc4-2012-06-18.zip ; } else { InstallOptionalHaikuImagePackage libxml2-2.8.0-x86-gcc2-2012-06-15.zip @@ -1254,12 +1275,12 @@ if [ IsOptionalHaikuImagePackageAdded Man ] { Echo "No optional package Man available for $(TARGET_ARCH)" ; } else if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - man-1.6f-r1a3-x86-gcc4-2011-05-24.zip - : $(baseURL)/man-1.6f-r1a3-x86-gcc4-2011-05-24.zip ; + man-1.6g-x86-gcc4-2012-06-19.zip + : $(baseURL)/man-1.6g-x86-gcc4-2012-06-19.zip ; } else { InstallOptionalHaikuImagePackage - man-1.6f-r1a3-x86-gcc2-2011-05-18.zip - : $(baseURL)/man-1.6f-r1a3-x86-gcc2-2011-05-18.zip ; + man-1.6g-x86-gcc2-2012-06-20.zip + : $(baseURL)/man-1.6g-x86-gcc2-2012-06-20.zip ; } } @@ -1277,8 +1298,8 @@ if [ IsOptionalHaikuImagePackageAdded Mercurial ] { } else { if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - mercurial-2.2.2-x86-gcc4-2012-06-15.zip - : $(baseURL)/mercurial-2.2.2-x86-gcc4-2012-06-15.zip + mercurial-2.2.2-x86-gcc4-2012-06-19.zip + : $(baseURL)/mercurial-2.2.2-x86-gcc4-2012-06-19.zip : : true ; } else { InstallOptionalHaikuImagePackage @@ -1315,12 +1336,12 @@ if [ IsOptionalHaikuImagePackageAdded Neon ] { } else { if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - neon-0.29.6-r1a3-x86-gcc4-2011-05-24.zip - : $(baseURL)/neon-0.29.6-r1a3-x86-gcc4-2011-05-24.zip ; + neon-0.29.6-x86-gcc4-2012-06-19.zip + : $(baseURL)/neon-0.29.6-x86-gcc4-2012-06-19.zip ; } else { InstallOptionalHaikuImagePackage - neon-0.29.6-r1a3-x86-gcc2-2011-05-18.zip - : $(baseURL)/neon-0.29.6-r1a3-x86-gcc2-2011-05-18.zip ; + neon-0.29.6-x86-gcc2-2012-06-19.zip + : $(baseURL)/neon-0.29.6-x86-gcc2-2012-06-19.zip ; } } } @@ -1412,12 +1433,12 @@ if [ IsOptionalHaikuImagePackageAdded OpenSSH ] { if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - openssh-5.9p1-x86-gcc4-2011-11-30.zip - : $(baseURL)/openssh-5.9p1-x86-gcc4-2011-11-30.zip ; + openssh-6.0p1-x86-gcc4-2012-06-20.zip + : $(baseURL)/openssh-6.0p1-x86-gcc4-2012-06-20.zip ; } else { InstallOptionalHaikuImagePackage - openssh-5.9p1-x86-gcc2-2011-11-30.zip - : $(baseURL)/openssh-5.9p1-x86-gcc2-2011-11-30.zip ; + openssh-6.0p1-x86-gcc2-2012-06-20.zip + : $(baseURL)/openssh-6.0p1-x86-gcc2-2012-06-20.zip ; } AddUserToHaikuImage sshd : 1001 : 100 : /var/empty : /bin/true @@ -1449,8 +1470,8 @@ if [ IsOptionalHaikuImagePackageAdded P7zip ] { } else { if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - p7zip-9.20.1-x86-gcc4-2012-06-15.zip - : $(baseURL)/p7zip-9.20.1-x86-gcc4-2011-06-15.zip ; + p7zip-9.20.1-x86-gcc4-2012-06-19.zip + : $(baseURL)/p7zip-9.20.1-x86-gcc4-2011-06-19.zip ; } else { InstallOptionalHaikuImagePackage p7zip-9.20.1-x86-gcc2-2012-06-15.zip @@ -1627,12 +1648,12 @@ if [ IsOptionalHaikuImagePackageAdded SQLite ] { } else { if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - sqlite-3.7.7.1-x86-gcc4-2012-03-30.zip - : $(baseURL)/sqlite-3.7.7.1-x86-gcc4-2012-03-30.zip ; + sqlite-3.7.13-x86-gcc4-2012-06-19.zip + : $(baseURL)/sqlite-3.7.13-x86-gcc4-2012-06-19.zip ; } else { InstallOptionalHaikuImagePackage - sqlite-3.7.7.1-x86-gcc2-2012-03-31.zip - : $(baseURL)/sqlite-3.7.7.1-x86-gcc2-2012-03-31.zip ; + sqlite-3.7.13-x86-gcc2-2012-06-20.zip + : $(baseURL)/sqlite-3.7.13-x86-gcc2-2012-06-20.zip ; } } } @@ -1645,13 +1666,13 @@ if [ IsOptionalHaikuImagePackageAdded Subversion ] { } else { if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - subversion-1.6.17-x86-gcc4-2011-08-03.zip - : $(baseURL)/subversion-1.6.17-x86-gcc4-2011-08-03.zip + subversion-1.6.18-x86-gcc4-2012-06-19.zip + : $(baseURL)/subversion-1.6.18-x86-gcc4-2012-06-19.zip : : true ; } else { InstallOptionalHaikuImagePackage - subversion-1.6.17-x86-gcc2-2011-08-02.zip - : $(baseURL)/subversion-1.6.17-x86-gcc2-2011-08-02.zip + subversion-1.6.18-x86-gcc2-2012-06-20.zip + : $(baseURL)/subversion-1.6.18-x86-gcc2-2012-06-20.zip : : true ; } } @@ -1681,8 +1702,8 @@ if [ IsOptionalHaikuImagePackageAdded Tar ] { } else { if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - tar-1.26-x86-gcc4-2012-06-15.zip - : $(baseURL)/tar-1.26-x86-gcc4-2012-06-15.zip ; + tar-1.26-x86-gcc4-2012-06-19.zip + : $(baseURL)/tar-1.26-x86-gcc4-2012-06-19.zip ; } else { InstallOptionalHaikuImagePackage tar-1.26-x86-gcc2-2012-06-15.zip @@ -1973,8 +1994,8 @@ if [ IsOptionalHaikuImagePackageAdded Yasm ] { Echo "No optional package Yasm available for $(TARGET_ARCH)" ; } else if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - yasm-1.2.0-x86-gcc4-2012-06-15.zip - : $(baseURL)/yasm-1.2.0-x86-gcc4-2012-06-15.zip ; + yasm-1.2.0-x86-gcc4-2012-06-18.zip + : $(baseURL)/yasm-1.2.0-x86-gcc4-2012-06-18.zip ; } else { InstallOptionalHaikuImagePackage yasm-1.2.0-x86-gcc2-2012-06-15.zip From 893996e358a7cbd68558c5c7ae38381758fb6dca Mon Sep 17 00:00:00 2001 From: Scott McCreary Date: Thu, 21 Jun 2012 22:01:52 +0000 Subject: [PATCH 095/349] Updated gcc2 packages for p7zip, mercurial, expat, cvs, curl, bzr, apr, and apr-util --- build/jam/OptionalPackageDependencies | 1 + build/jam/OptionalPackages | 36 +++++++++++++-------------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/build/jam/OptionalPackageDependencies b/build/jam/OptionalPackageDependencies index a706c5387f..92d475d54d 100644 --- a/build/jam/OptionalPackageDependencies +++ b/build/jam/OptionalPackageDependencies @@ -17,6 +17,7 @@ OptionalPackageDependencies Development : DevelopmentBase Perl ; OptionalPackageDependencies DevelopmentPowerPC : DevelopmentMin ; OptionalPackageDependencies GetText : LibIconv ; OptionalPackageDependencies Git : Expat Curl OpenSSL LibIconv ; +OptionalPackageDependencies GitDoc : Man Git ; OptionalPackageDependencies ICU-devel : DevelopmentBase ; OptionalPackageDependencies LibLayout : DevelopmentBase ; OptionalPackageDependencies Man : Groff ; diff --git a/build/jam/OptionalPackages b/build/jam/OptionalPackages index e00b4587d6..ed55cdb1d9 100644 --- a/build/jam/OptionalPackages +++ b/build/jam/OptionalPackages @@ -128,8 +128,8 @@ if [ IsOptionalHaikuImagePackageAdded APR ] { : : true ; } else { InstallOptionalHaikuImagePackage - apr-1.4.6-x86-gcc2-2012-06-20.zip - : $(baseURL)/apr-1.4.6-x86-gcc2-2012-06-20.zip + apr-1.4.6-x86-gcc2-2012-06-19.zip + : $(baseURL)/apr-1.4.6-x86-gcc2-2012-06-19.zip : : true ; } } @@ -146,8 +146,8 @@ if [ IsOptionalHaikuImagePackageAdded APR-util ] { : : true ; } else { InstallOptionalHaikuImagePackage - apr-util-1.4.1-x86-gcc2-2012-06-20.zip - : $(baseURL)/apr-util-1.4.1-x86-gcc2-2012-06-20.zip + apr-util-1.4.1-x86-gcc2-2012-06-19.zip + : $(baseURL)/apr-util-1.4.1-x86-gcc2-2012-06-19.zip : : true ; } } @@ -174,11 +174,11 @@ if [ IsOptionalHaikuImagePackageAdded Bazaar ] { if $(TARGET_ARCH) != x86 { Echo "No optional package Bazaar available for $(TARGET_ARCH)" ; } else if $(HAIKU_GCC_VERSION[1]) >= 4 { - InstallOptionalHaikuImagePackage bzr-2.6b1-x86-gcc4-2012-03-30.zip - : $(baseURL)/bzr-2.6b1-x86-gcc4-2012-03-30.zip ; + InstallOptionalHaikuImagePackage bzr-2.5.1-x86-gcc4-2012-06-21.zip + : $(baseURL)/bzr-2.5.1-x86-gcc4-2012-06-21.zip ; } else { - InstallOptionalHaikuImagePackage bzr-2.6b1-x86-gcc2-2012-03-31.zip - : $(baseURL)/bzr-2.6b1-x86-gcc2-2012-03-31.zip ; + InstallOptionalHaikuImagePackage bzr-2.5.1-x86-gcc2-2012-06-21.zip + : $(baseURL)/bzr-2.5.1-x86-gcc2-2012-06-21.zip ; } } @@ -536,8 +536,8 @@ if [ IsOptionalHaikuImagePackageAdded Curl ] { InstallOptionalHaikuImagePackage curl-7.26.0-x86-gcc4-2012-06-20.zip : $(baseURL)/curl-7.26.0-x86-gcc4-2012-06-20.zip ; } else { - InstallOptionalHaikuImagePackage curl-7.26.0-x86-gcc2-2012-06-20.zip - : $(baseURL)/curl-7.26.0-x86-gcc2-2012-06-20.zip ; + InstallOptionalHaikuImagePackage curl-7.26.0-x86-gcc2-2012-06-21.zip + : $(baseURL)/curl-7.26.0-x86-gcc2-2012-06-21.zip ; } } @@ -554,8 +554,8 @@ if [ IsOptionalHaikuImagePackageAdded CVS ] { : : true ; } else { InstallOptionalHaikuImagePackage - cvs-1.12.13.1-r1a3-x86-gcc2-2012-06-20.zip - : $(baseURL)/cvs-1.12.13.1-r1a3-x86-gcc2-2012-06-20.zip + cvs-1.12.13.1-x86-gcc2-2012-06-20.zip + : $(baseURL)/cvs-1.12.13.1-gcc2-2012-06-20.zip : : true ; } } @@ -913,8 +913,8 @@ if [ IsOptionalHaikuImagePackageAdded Expat ] { : : true ; } else { InstallOptionalHaikuImagePackage - expat-2.0.1-r1a3-x86-gcc2-2011-05-20.zip - : $(baseURL)/expat-2.0.1-r1a3-x86-gcc2-2011-05-20.zip + expat-2.0.1-x86-gcc2-2012-06-20.zip + : $(baseURL)/expat-2.0.1-x86-gcc2-2012-06-20.zip : : true ; } } @@ -1303,8 +1303,8 @@ if [ IsOptionalHaikuImagePackageAdded Mercurial ] { : : true ; } else { InstallOptionalHaikuImagePackage - mercurial-2.2.2-x86-gcc2-2012-06-15.zip - : $(baseURL)/mercurial-2.2.2-x86-gcc2-2012-06-15.zip + mercurial-2.2.2-x86-gcc2-2012-06-20.zip + : $(baseURL)/mercurial-2.2.2-x86-gcc2-2012-06-20.zip : : true ; } } @@ -1474,8 +1474,8 @@ if [ IsOptionalHaikuImagePackageAdded P7zip ] { : $(baseURL)/p7zip-9.20.1-x86-gcc4-2011-06-19.zip ; } else { InstallOptionalHaikuImagePackage - p7zip-9.20.1-x86-gcc2-2012-06-15.zip - : $(baseURL)/p7zip-9.20.1-x86-gcc2-2012-06-15.zip ; + p7zip-9.20.1-x86-gcc2-2012-06-21.zip + : $(baseURL)/p7zip-9.20.1-x86-gcc2-2012-06-21.zip ; } AddExpanderRuleToHaikuImage "application/x-7z-compressed" : .7z : "7za l \\0045s" From 6ccbb9012fd80f09aa991ecd163a3c9b8bcd97b7 Mon Sep 17 00:00:00 2001 From: Scott McCreary Date: Thu, 21 Jun 2012 23:19:04 +0000 Subject: [PATCH 096/349] Fixed urls for a few gcc2 OptionalPacakges. Changing talib back to 1.6.3 as 1.7.2 is failing to build with gcc4. --- build/jam/OptionalPackages | 44 +++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/build/jam/OptionalPackages b/build/jam/OptionalPackages index ed55cdb1d9..238dd06293 100644 --- a/build/jam/OptionalPackages +++ b/build/jam/OptionalPackages @@ -555,7 +555,7 @@ if [ IsOptionalHaikuImagePackageAdded CVS ] { } else { InstallOptionalHaikuImagePackage cvs-1.12.13.1-x86-gcc2-2012-06-20.zip - : $(baseURL)/cvs-1.12.13.1-gcc2-2012-06-20.zip + : $(baseURL)/cvs-1.12.13.1-x86-gcc2-2012-06-20.zip : : true ; } } @@ -984,8 +984,8 @@ if [ IsOptionalHaikuImagePackageAdded Git ] { } else { if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - git-1.7.10.2-x86-gcc4-2012-06-20.zip - : $(baseURL)/git-1.7.10.2-x86-gcc4-2012-06-20.zip + git-1.7.10.2-x86-gcc4-2012-06-19.zip + : $(baseURL)/git-1.7.10.2-x86-gcc4-2012-06-19.zip : : true ; } else { InstallOptionalHaikuImagePackage @@ -1210,8 +1210,8 @@ if [ IsOptionalHaikuImagePackageAdded LibXML2 ] { : $(baseURL)/libxml2-2.8.0-x86-gcc4-2012-06-18.zip ; } else { InstallOptionalHaikuImagePackage - libxml2-2.8.0-x86-gcc2-2012-06-15.zip - : $(baseURL)/libxml2-2.8.0-x86-gcc2-2012-06-15.zip ; + libxml2-2.8.0-x86-gcc2-2012-06-21.zip + : $(baseURL)/libxml2-2.8.0-x86-gcc2-2012-06-21.zip ; } } } @@ -1279,8 +1279,8 @@ if [ IsOptionalHaikuImagePackageAdded Man ] { : $(baseURL)/man-1.6g-x86-gcc4-2012-06-19.zip ; } else { InstallOptionalHaikuImagePackage - man-1.6g-x86-gcc2-2012-06-20.zip - : $(baseURL)/man-1.6g-x86-gcc2-2012-06-20.zip ; + man-1.6g-x86-gcc2-2012-06-21.zip + : $(baseURL)/man-1.6g-x86-gcc2-2012-06-21.zip ; } } @@ -1340,8 +1340,8 @@ if [ IsOptionalHaikuImagePackageAdded Neon ] { : $(baseURL)/neon-0.29.6-x86-gcc4-2012-06-19.zip ; } else { InstallOptionalHaikuImagePackage - neon-0.29.6-x86-gcc2-2012-06-19.zip - : $(baseURL)/neon-0.29.6-x86-gcc2-2012-06-19.zip ; + neon-0.29.6-x86-gcc2-2012-06-21.zip + : $(baseURL)/neon-0.29.6-x86-gcc2-2012-06-21.zip ; } } } @@ -1437,8 +1437,8 @@ if [ IsOptionalHaikuImagePackageAdded OpenSSH ] { : $(baseURL)/openssh-6.0p1-x86-gcc4-2012-06-20.zip ; } else { InstallOptionalHaikuImagePackage - openssh-6.0p1-x86-gcc2-2012-06-20.zip - : $(baseURL)/openssh-6.0p1-x86-gcc2-2012-06-20.zip ; + openssh-6.0p1-x86-gcc2-2012-06-21.zip + : $(baseURL)/openssh-6.0p1-x86-gcc2-2012-06-21.zip ; } AddUserToHaikuImage sshd : 1001 : 100 : /var/empty : /bin/true @@ -1471,7 +1471,7 @@ if [ IsOptionalHaikuImagePackageAdded P7zip ] { if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage p7zip-9.20.1-x86-gcc4-2012-06-19.zip - : $(baseURL)/p7zip-9.20.1-x86-gcc4-2011-06-19.zip ; + : $(baseURL)/p7zip-9.20.1-x86-gcc4-2012-06-19.zip ; } else { InstallOptionalHaikuImagePackage p7zip-9.20.1-x86-gcc2-2012-06-21.zip @@ -1671,8 +1671,8 @@ if [ IsOptionalHaikuImagePackageAdded Subversion ] { : : true ; } else { InstallOptionalHaikuImagePackage - subversion-1.6.18-x86-gcc2-2012-06-20.zip - : $(baseURL)/subversion-1.6.18-x86-gcc2-2012-06-20.zip + subversion-1.6.18-x86-gcc2-2012-06-21.zip + : $(baseURL)/subversion-1.6.18-x86-gcc2-2012-06-21.zip : : true ; } } @@ -1685,12 +1685,12 @@ if [ IsOptionalHaikuImagePackageAdded TagLib ] { Echo "No optional package TagLib available for $(TARGET_ARCH)" ; } else if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - taglib-1.7.2-x86-gcc4-2012-06-15.zip - : $(baseURL)/taglib-1.7.2-x86-gcc4-2012-06-15.zip ; + taglib-1.6.3-r1a3-x86-gcc4-2011-05-24.zip + : $(baseURL)/taglib-1.6.3-r1a3-x86-gcc4-2011-05-24.zip ; } else { InstallOptionalHaikuImagePackage - taglib-1.7.2-x86-gcc2-2012-06-15.zip - : $(baseURL)/taglib-1.7.2-x86-gcc2-2012-06-15.zip ; + taglib-1.6.3-r1a3-x86-gcc2-2011-05-20.zip + : $(baseURL)/taglib-1.6.3-r1a3-x86-gcc2-2011-05-20.zip ; } } @@ -1706,8 +1706,8 @@ if [ IsOptionalHaikuImagePackageAdded Tar ] { : $(baseURL)/tar-1.26-x86-gcc4-2012-06-19.zip ; } else { InstallOptionalHaikuImagePackage - tar-1.26-x86-gcc2-2012-06-15.zip - : $(baseURL)/tar-1.26-x86-gcc2-2012-06-15.zip ; + tar-1.26-x86-gcc2-2012-06-21.zip + : $(baseURL)/tar-1.26-x86-gcc2-2012-06-21.zip ; } } } @@ -1998,7 +1998,7 @@ if [ IsOptionalHaikuImagePackageAdded Yasm ] { : $(baseURL)/yasm-1.2.0-x86-gcc4-2012-06-18.zip ; } else { InstallOptionalHaikuImagePackage - yasm-1.2.0-x86-gcc2-2012-06-15.zip - : $(baseURL)/yasm-1.2.0-x86-gcc2-2012-06-15.zip ; + yasm-1.2.0-x86-gcc2-2012-06-19.zip + : $(baseURL)/yasm-1.2.0-x86-gcc2-2012-06-19.zip ; } } From 4daad1e10580026ccb543ca5dbb73078a6307e3e Mon Sep 17 00:00:00 2001 From: Scott McCreary Date: Fri, 22 Jun 2012 18:37:05 +0000 Subject: [PATCH 097/349] Fixed url dates for gcc4 packages for bzr and cvs. Updated taglib gcc4 package name to match typo from alpha3 release. --- build/jam/OptionalPackages | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/build/jam/OptionalPackages b/build/jam/OptionalPackages index 238dd06293..c1639dfb28 100644 --- a/build/jam/OptionalPackages +++ b/build/jam/OptionalPackages @@ -174,11 +174,11 @@ if [ IsOptionalHaikuImagePackageAdded Bazaar ] { if $(TARGET_ARCH) != x86 { Echo "No optional package Bazaar available for $(TARGET_ARCH)" ; } else if $(HAIKU_GCC_VERSION[1]) >= 4 { - InstallOptionalHaikuImagePackage bzr-2.5.1-x86-gcc4-2012-06-21.zip - : $(baseURL)/bzr-2.5.1-x86-gcc4-2012-06-21.zip ; + InstallOptionalHaikuImagePackage bzr-2.5.1-x86-gcc4-2012-06-22.zip + : $(baseURL)/bzr-2.5.1-x86-gcc4-2012-06-22.zip ; } else { - InstallOptionalHaikuImagePackage bzr-2.5.1-x86-gcc2-2012-06-21.zip - : $(baseURL)/bzr-2.5.1-x86-gcc2-2012-06-21.zip ; + InstallOptionalHaikuImagePackage bzr-2.5.1-x86-gcc2-2012-06-22.zip + : $(baseURL)/bzr-2.5.1-x86-gcc2-2012-06-22.zip ; } } @@ -549,8 +549,8 @@ if [ IsOptionalHaikuImagePackageAdded CVS ] { } else { if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - cvs-1.12.13.1-x86-gcc4-2012-06-19.zip - : $(baseURL)/cvs-1.12.13.1-x86-gcc4-2012-06-19.zip + cvs-1.12.13.1-x86-gcc4-2012-06-22.zip + : $(baseURL)/cvs-1.12.13.1-x86-gcc4-2012-06-22.zip : : true ; } else { InstallOptionalHaikuImagePackage @@ -1685,8 +1685,8 @@ if [ IsOptionalHaikuImagePackageAdded TagLib ] { Echo "No optional package TagLib available for $(TARGET_ARCH)" ; } else if $(HAIKU_GCC_VERSION[1]) >= 4 { InstallOptionalHaikuImagePackage - taglib-1.6.3-r1a3-x86-gcc4-2011-05-24.zip - : $(baseURL)/taglib-1.6.3-r1a3-x86-gcc4-2011-05-24.zip ; + taglib-1.6.3-r1r3-x86-gcc4-2011-05-24.zip + : $(baseURL)/taglib-1.6.3-r1r3-x86-gcc4-2011-05-24.zip ; } else { InstallOptionalHaikuImagePackage taglib-1.6.3-r1a3-x86-gcc2-2011-05-20.zip From 1ed63ff99d44b0d703e9bbf68c89772cfffa0207 Mon Sep 17 00:00:00 2001 From: Scott McCreary Date: Fri, 22 Jun 2012 20:13:46 +0000 Subject: [PATCH 098/349] Updated filename for taglib --- build/jam/OptionalBuildFeatures | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/jam/OptionalBuildFeatures b/build/jam/OptionalBuildFeatures index dc4da0a0cb..65e1ca68f3 100644 --- a/build/jam/OptionalBuildFeatures +++ b/build/jam/OptionalBuildFeatures @@ -385,7 +385,7 @@ if [ IsOptionalHaikuImagePackageAdded TagLib ] { } local baseURL = http://haiku-files.org/files/optional-packages ; -HAIKU_TAGLIB_PACKAGE = taglib-1.7.2-x86-gcc2-2012-06-15.zip ; +HAIKU_TAGLIB_PACKAGE = taglib-1.6.3-r1a3-x86-gcc2-2011-05-20.zip ; HAIKU_TAGLIB_URL = $(baseURL)/$(HAIKU_TAGLIB_PACKAGE) ; if $(HAIKU_BUILD_FEATURE_TAGLIB) { From a420070eceb9b514a62acac3838dd346aca19874 Mon Sep 17 00:00:00 2001 From: Scott McCreary Date: Sat, 23 Jun 2012 18:48:31 +0000 Subject: [PATCH 099/349] Updated gcc2 packages for sdl and related libraries. --- build/jam/OptionalLibPackages | 44 +++++++++++++++++------------------ 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/build/jam/OptionalLibPackages b/build/jam/OptionalLibPackages index 941fee38ff..a8c6d2a620 100644 --- a/build/jam/OptionalLibPackages +++ b/build/jam/OptionalLibPackages @@ -264,41 +264,41 @@ if [ IsOptionalHaikuImagePackageAdded SDLLibs ] { : $(baseURL)/lib/smpeg-0.4.5-x86-gcc4-2012-05-31.zip ; } else { InstallOptionalHaikuImagePackage - libsdl-1.2-hg-r1a3-x86-gcc2-2011-05-29.zip - : $(baseURL)/lib/libsdl-1.2-hg-r1a3-x86-gcc2-2011-05-29.zip ; + libsdl-1.2.15-x86-gcc2-2012-06-24.zip + : $(baseURL)/lib/libsdl-1.2.15-x86-gcc2-2012-06-24.zip ; InstallOptionalHaikuImagePackage - guilib-1.2.1-r1a3-x86-gcc2-2011-05-19.zip - : $(baseURL)/lib/guilib-1.2.1-r1a3-x86-gcc2-2011-05-19.zip ; + guilib-1.2.1-x86-gcc2-2012-06-24.zip + : $(baseURL)/lib/guilib-1.2.1-x86-gcc2-2012-06-24.zip ; InstallOptionalHaikuImagePackage - sdl-gfx-2.0.22-r1a3-x86-gcc2-2011-05-19.zip - : $(baseURL)/lib/sdl-gfx-2.0.22-r1a3-x86-gcc2-2011-05-19.zip ; + sdl-gfx-2.0.23-x86-gcc2-2012-06-24.zip + : $(baseURL)/lib/sdl-gfx-2.0.23-x86-gcc2-2012-06-24.zip ; InstallOptionalHaikuImagePackage - sdl-image-1.2.10-x86-r1a3-x86-gcc2-2011-05-19.zip - : $(baseURL)/lib/sdl-image-1.2.10-r1a3-x86-gcc2-2011-05-19.zip ; + sdl-image-1.2.12-x86-x86-gcc2-2012-06-24.zip + : $(baseURL)/lib/sdl-image-1.2.12-x86-gcc2-2012-06-24.zip ; InstallOptionalHaikuImagePackage - sdl-mixer-1.2.11-r1a3-x86-gcc2-2011-05-19.zip - : $(baseURL)/lib/sdl-mixer-1.2.11-r1a3-x86-gcc2-2011-05-19.zip ; + sdl-mixer-1.2.11-x86-gcc2-2012-06-25.zip + : $(baseURL)/lib/sdl-mixer-1.2.11-x86-gcc2-2012-06-25.zip ; InstallOptionalHaikuImagePackage - sdl-net-1.2.7-r1a3-x86-gcc2-2011-05-19.zip - : $(baseURL)/lib/sdl-net-1.2.7-r1a3-x86-gcc2-2011-05-19.zip ; + sdl-net-1.2.8-x86-gcc2-2012-06-24.zip + : $(baseURL)/lib/sdl-net-1.2.8-x86-gcc2-2012-06-25.zip ; InstallOptionalHaikuImagePackage - sdl-sound-1.0.3-r1a3-x86-gcc2-2011-05-19.zip - : $(baseURL)/lib/sdl-sound-1.0.3-r1a3-x86-gcc2-2011-05-19.zip ; + sdl-sound-1.0.3-x86-gcc2-2012-06-24.zip + : $(baseURL)/lib/sdl-sound-1.0.3-x86-gcc2-2012-06-25.zip ; InstallOptionalHaikuImagePackage sdl-rtf-0.1.0-r1a3-x86-gcc2-2011-05-20.zip : $(baseURL)/lib/sdl-rtf-0.1.0-r1a3-x86-gcc2-2011-05-20.zip ; InstallOptionalHaikuImagePackage - sdl-ttf-2.0.10-r1a3-x86-gcc2-2011-05-19.zip - : $(baseURL)/lib/sdl-ttf-2.0.10-r1a3-x86-gcc2-2011-05-19.zip ; + sdl-ttf-2.0.11-x86-gcc2-2012-06-24.zip + : $(baseURL)/lib/sdl-ttf-2.0.11-x86-gcc2-2012-06-24.zip ; InstallOptionalHaikuImagePackage - sge-030809-r1a3-x86-gcc2-2011-05-19.zip - : $(baseURL)/lib/sge-030809-r1a3-x86-gcc2-2011-05-19.zip ; + sge-030809-x86-gcc2-2012-06-24.zip + : $(baseURL)/lib/sge-030809-x86-gcc2-2012-06-24.zip ; InstallOptionalHaikuImagePackage - smjpeg-0.2.1-r1a3-x86-gcc2-2011-05-19.zip - : $(baseURL)/lib/smjpeg-0.2.1-r1a3-x86-gcc2-2011-05-19.zip ; + smjpeg-0.2.1-x86-gcc2-2012-06-24.zip + : $(baseURL)/lib/smjpeg-0.2.1-x86-gcc2-2012-06-24.zip ; InstallOptionalHaikuImagePackage - smpeg-0.4.5-r1a3-x86-gcc2-2011-05-20.zip - : $(baseURL)/lib/smpeg-0.4.5-r1a3-x86-gcc2-2011-05-20.zip ; + smpeg-0.4.5-x86-gcc2-2012-06-24.zip + : $(baseURL)/lib/smpeg-0.4.5-x86-gcc2-2012-06-24.zip ; } } From 14fc8a0138e0478a40c8908beb0b9bc266b0be11 Mon Sep 17 00:00:00 2001 From: Scott McCreary Date: Mon, 25 Jun 2012 21:09:05 +0000 Subject: [PATCH 100/349] Corrected build dates for gcc2 builds of sdl-sound and sdl-net --- build/jam/OptionalLibPackages | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/jam/OptionalLibPackages b/build/jam/OptionalLibPackages index a8c6d2a620..e2f58aa5e4 100644 --- a/build/jam/OptionalLibPackages +++ b/build/jam/OptionalLibPackages @@ -280,10 +280,10 @@ if [ IsOptionalHaikuImagePackageAdded SDLLibs ] { : $(baseURL)/lib/sdl-mixer-1.2.11-x86-gcc2-2012-06-25.zip ; InstallOptionalHaikuImagePackage sdl-net-1.2.8-x86-gcc2-2012-06-24.zip - : $(baseURL)/lib/sdl-net-1.2.8-x86-gcc2-2012-06-25.zip ; + : $(baseURL)/lib/sdl-net-1.2.8-x86-gcc2-2012-06-24.zip ; InstallOptionalHaikuImagePackage sdl-sound-1.0.3-x86-gcc2-2012-06-24.zip - : $(baseURL)/lib/sdl-sound-1.0.3-x86-gcc2-2012-06-25.zip ; + : $(baseURL)/lib/sdl-sound-1.0.3-x86-gcc2-2012-06-24.zip ; InstallOptionalHaikuImagePackage sdl-rtf-0.1.0-r1a3-x86-gcc2-2011-05-20.zip : $(baseURL)/lib/sdl-rtf-0.1.0-r1a3-x86-gcc2-2011-05-20.zip ; From b271ff3f4e54e2ddf5b54aba6538c9173e52a08d Mon Sep 17 00:00:00 2001 From: Philippe Saint-Pierre Date: Mon, 25 Jun 2012 18:28:16 -0400 Subject: [PATCH 101/349] SoundRecorder: UI fixes * Remove several hard-coded colors * Reduce slightly the font size in the file info panel (#6909). * Don't hardcode the font height, compute it * Fix a bug where deploying the bottom panel makes the current window width the new minimum width * Don't hardcode the bottom panel's height, compute it (allows better font size tolerance). --- src/apps/soundrecorder/RecorderWindow.cpp | 89 +++++++++++++++-------- src/apps/soundrecorder/RecorderWindow.h | 2 + src/apps/soundrecorder/SoundListView.cpp | 10 +-- 3 files changed, 66 insertions(+), 35 deletions(-) diff --git a/src/apps/soundrecorder/RecorderWindow.cpp b/src/apps/soundrecorder/RecorderWindow.cpp index f5c6e7ceaf..11b5a92997 100644 --- a/src/apps/soundrecorder/RecorderWindow.cpp +++ b/src/apps/soundrecorder/RecorderWindow.cpp @@ -62,7 +62,7 @@ // default window positioning static const float MIN_WIDTH = 400.0f; -static const float MIN_HEIGHT = 336.0f; +static const float MIN_HEIGHT = 175.0f; static const float XPOS = 100.0f; static const float YPOS = 200.0f; @@ -364,7 +364,7 @@ RecorderWindow::InitWindow() fSoundList = new SoundListView(r, B_TRANSLATE("Sound List"), B_FOLLOW_ALL); fSoundList->SetSelectionMessage(new BMessage(SOUND_SELECTED)); - fSoundList->SetViewColor(216, 216, 216); + fSoundList->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); BScrollView *scroller = new BScrollView("scroller", fSoundList, B_FOLLOW_ALL, 0, false, true, B_FANCY_BORDER); fBottomBox->AddChild(scroller); @@ -374,43 +374,75 @@ RecorderWindow::InitWindow() r.bottom -= 25; r.InsetBy(10, 8); r.top -= 1; - fFileInfoBox = new BBox(r, "fileinfo", B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); + fFileInfoBox = new BBox(r, "fileinfo", B_FOLLOW_LEFT); fFileInfoBox->SetLabel(B_TRANSLATE("File info")); + fFileInfoBox->SetHighColor(ui_color(B_PANEL_TEXT_COLOR)); + + BFont font = be_plain_font; + font.SetSize(font.Size() * 0.92f); + font_height height; + font.GetHeight(&height); + float fontHeight = height.ascent + height.leading + height.descent; + r = fFileInfoBox->Bounds(); r.left = 8; - r.top = 13; - r.bottom = r.top + 15; + r.top = fontHeight + 6; + r.bottom = r.top + fontHeight + 3; r.right -= 10; fFilename = new BStringView(r, "filename", B_TRANSLATE("File name:")); fFileInfoBox->AddChild(fFilename); - r.top += 13; - r.bottom = r.top + 15; + fFilename->SetFont(&font, B_FONT_SIZE); + fFilename->SetHighColor(ui_color(B_PANEL_TEXT_COLOR)); + + r.top += fontHeight; + r.bottom = r.top + fontHeight + 3; fFormat = new BStringView(r, "format", B_TRANSLATE("Format:")); fFileInfoBox->AddChild(fFormat); - r.top += 13; - r.bottom = r.top + 15; + fFormat->SetFont(&font, B_FONT_SIZE); + fFormat->SetHighColor(ui_color(B_PANEL_TEXT_COLOR)); + + r.top += fontHeight; + r.bottom = r.top + fontHeight + 3; fCompression = new BStringView(r, "compression", B_TRANSLATE("Compression:")); fFileInfoBox->AddChild(fCompression); - r.top += 13; - r.bottom = r.top + 15; + fCompression->SetFont(&font, B_FONT_SIZE); + fCompression->SetHighColor(ui_color(B_PANEL_TEXT_COLOR)); + + r.top += fontHeight; + r.bottom = r.top + fontHeight + 3; fChannels = new BStringView(r, "channels", B_TRANSLATE("Channels:")); fFileInfoBox->AddChild(fChannels); - r.top += 13; - r.bottom = r.top + 15; + fChannels->SetFont(&font, B_FONT_SIZE); + fChannels->SetHighColor(ui_color(B_PANEL_TEXT_COLOR)); + + r.top += fontHeight; + r.bottom = r.top + fontHeight + 3; fSampleSize = new BStringView(r, "samplesize", B_TRANSLATE("Sample size:")); fFileInfoBox->AddChild(fSampleSize); - r.top += 13; - r.bottom = r.top + 15; + fSampleSize->SetFont(&font, B_FONT_SIZE); + fSampleSize->SetHighColor(ui_color(B_PANEL_TEXT_COLOR)); + + r.top += fontHeight; + r.bottom = r.top + fontHeight + 3; fSampleRate = new BStringView(r, "samplerate", B_TRANSLATE("Sample rate:")); fFileInfoBox->AddChild(fSampleRate); - r.top += 13; - r.bottom = r.top + 15; + fSampleRate->SetFont(&font, B_FONT_SIZE); + fSampleRate->SetHighColor(ui_color(B_PANEL_TEXT_COLOR)); + + r.top += fontHeight; + r.bottom = r.top + fontHeight + 3; fDuration = new BStringView(r, "duration", B_TRANSLATE("Duration:")); fFileInfoBox->AddChild(fDuration); + fDuration->SetFont(&font, B_FONT_SIZE); + fDuration->SetHighColor(ui_color(B_PANEL_TEXT_COLOR)); + + fFileInfoBox->ResizeTo(fFileInfoBox->Frame().Width(), + r.bottom + fontHeight / 2.0f); + fDeployedHeight = MIN_HEIGHT + fFileInfoBox->Bounds().Height() + 40.0f; // Input selection lists all available physical inputs that produce // buffers with B_MEDIA_RAW_AUDIO format data. @@ -451,12 +483,10 @@ RecorderWindow::InitWindow() } // Create the actual widget - BRect frame(fBottomBox->Bounds()); - r = frame; - r.left = 42; - r.right = (r.left + r.right) / 2; - r.InsetBy(10,10); - r.top = r.bottom - 18; + r = fFileInfoBox->Bounds(); + r.top = r.bottom + 2; + r.bottom = r.top + 18; + r.InsetBy(10, 10); fInputField = new BMenuField(r, "Input", B_TRANSLATE("Input:"), popup); fInputField->SetDivider(fInputField->StringWidth(B_TRANSLATE("Input:")) + 4.0f); @@ -465,9 +495,8 @@ RecorderWindow::InitWindow() fBottomBox->AddChild(fFileInfoBox); fBottomBox->Hide(); - CalcSizes(Frame().Width(), MIN_HEIGHT-161); - ResizeTo(Frame().Width(), MIN_HEIGHT-161); - + CalcSizes(MIN_WIDTH, MIN_HEIGHT); + ResizeTo(Frame().Width(), MIN_HEIGHT); popup->Superitem()->SetLabel(selected_name); @@ -551,12 +580,12 @@ RecorderWindow::MessageReceived(BMessage * message) case VIEW_LIST: if (fUpDownButton->Value() == B_CONTROL_ON) { fBottomBox->Show(); - CalcSizes(Frame().Width(), MIN_HEIGHT); - ResizeTo(Frame().Width(), MIN_HEIGHT); + CalcSizes(MIN_WIDTH, fDeployedHeight); + ResizeTo(Frame().Width(), fDeployedHeight); } else { fBottomBox->Hide(); - CalcSizes(Frame().Width(), MIN_HEIGHT-161); - ResizeTo(Frame().Width(), MIN_HEIGHT-161); + CalcSizes(MIN_WIDTH, MIN_HEIGHT); + ResizeTo(Frame().Width(), MIN_HEIGHT); } break; diff --git a/src/apps/soundrecorder/RecorderWindow.h b/src/apps/soundrecorder/RecorderWindow.h index 34dec3a226..63f6b01c4b 100644 --- a/src/apps/soundrecorder/RecorderWindow.h +++ b/src/apps/soundrecorder/RecorderWindow.h @@ -94,6 +94,8 @@ private: BDirectory fTempDir; int fTempCount; + float fDeployedHeight; + BBox * fBottomBox; BBox * fFileInfoBox; BStringView *fFilename; diff --git a/src/apps/soundrecorder/SoundListView.cpp b/src/apps/soundrecorder/SoundListView.cpp index bd3bcab293..42cab62d92 100644 --- a/src/apps/soundrecorder/SoundListView.cpp +++ b/src/apps/soundrecorder/SoundListView.cpp @@ -34,12 +34,11 @@ void SoundListView::Draw(BRect updateRect) { if (IsEmpty()) { - SetHighColor(235,235,235); - FillRect(Bounds()); + SetLowColor(ViewColor()); + FillRect(Bounds(), B_SOLID_LOW); - SetHighColor(0,0,0); + SetHighColor(ui_color(B_PANEL_TEXT_COLOR)); BFont font(be_bold_font); - font.SetSize(12.0); SetFont(&font); font_height height; font.GetHeight(&height); @@ -58,7 +57,8 @@ void SoundListView::AttachedToWindow() { BListView::AttachedToWindow(); - SetViewColor(255,255,255); + SetViewColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), + B_LIGHTEN_1_TINT)); } From 234eed6b0da64f3d7c9f37b15fda172d27489fbb Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Mon, 25 Jun 2012 18:38:25 -0400 Subject: [PATCH 102/349] Fix build. gcc2 freetype package's name was wrong, and the uploaded package was in the wrong subdir. --- build/jam/OptionalBuildFeatures | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/jam/OptionalBuildFeatures b/build/jam/OptionalBuildFeatures index 65e1ca68f3..9e5958f1c7 100644 --- a/build/jam/OptionalBuildFeatures +++ b/build/jam/OptionalBuildFeatures @@ -341,7 +341,7 @@ if $(TARGET_ARCH) = ppc || $(TARGET_ARCH) = x86 { } else if $(HAIKU_GCC_VERSION[1]) >= 4 { HAIKU_FREETYPE_FILE = freetype-2.4.9-x86-gcc4-2012-06-15.zip ; } else { - HAIKU_FREETYPE_FILE = freetype-2.4.9-x86-gcc2-2012-06-15.zip ; + HAIKU_FREETYPE_FILE = freetype-2.4.9-x86-gcc2-2012-06-19.zip ; } local freetypeZipFile = [ DownloadFile $(HAIKU_FREETYPE_FILE) From d6f3ff4030295af0bf6dc52632943f4444ff8482 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Mon, 25 Jun 2012 19:31:40 -0400 Subject: [PATCH 103/349] Another build fix. Incorrect URLs for SSL optional packages. --- build/jam/OptionalBuildFeatures | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/jam/OptionalBuildFeatures b/build/jam/OptionalBuildFeatures index 9e5958f1c7..9b25819355 100644 --- a/build/jam/OptionalBuildFeatures +++ b/build/jam/OptionalBuildFeatures @@ -12,9 +12,9 @@ if [ IsOptionalHaikuImagePackageAdded OpenSSL ] { } if $(HAIKU_GCC_VERSION[1]) >= 4 { - HAIKU_OPENSSL_PACKAGE = openssl-1.0.0j-x86-gcc4-2012-06-01.zip ; + HAIKU_OPENSSL_PACKAGE = openssl-1.0.0j-x86-gcc4-2012-06-19.zip ; } else { - HAIKU_OPENSSL_PACKAGE = openssl-1.0.0j-x86-gcc2-2012-06-15.zip ; + HAIKU_OPENSSL_PACKAGE = openssl-1.0.0j-x86-gcc2-2012-06-19.zip ; } local baseURL = http://haiku-files.org/files/optional-packages ; From b78760b964a5be4a9453a02c74ba742f87150908 Mon Sep 17 00:00:00 2001 From: Philippe Saint-Pierre Date: Mon, 25 Jun 2012 21:09:55 -0400 Subject: [PATCH 104/349] Replace several hard-coded paths with find_directory calls --- src/apps/codycam/CodyCam.cpp | 8 +++++++- src/apps/icon-o-matic/IconEditorApp.cpp | 12 ++++++++++-- src/apps/mediaconverter/MediaConverterWindow.cpp | 10 +++++++--- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/apps/codycam/CodyCam.cpp b/src/apps/codycam/CodyCam.cpp index 2a68bce107..0df1c060a6 100644 --- a/src/apps/codycam/CodyCam.cpp +++ b/src/apps/codycam/CodyCam.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -22,6 +23,7 @@ #include #include +#include #undef B_TRANSLATION_CONTEXT #define B_TRANSLATION_CONTEXT "CodyCam" @@ -169,7 +171,11 @@ CodyCam::CodyCam() kUploadClients[index++] = B_TRANSLATE("SFTP"); kUploadClients[index++] = B_TRANSLATE("Local"); - chdir("/boot/home"); + BPath homeDir; + if (find_directory(B_USER_DIRECTORY, &homeDir) != B_OK) + homeDir.SetTo("/boot/home"); + + chdir(homeDir.Path()); } diff --git a/src/apps/icon-o-matic/IconEditorApp.cpp b/src/apps/icon-o-matic/IconEditorApp.cpp index 65c48b8610..27f73a9484 100644 --- a/src/apps/icon-o-matic/IconEditorApp.cpp +++ b/src/apps/icon-o-matic/IconEditorApp.cpp @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include "support_settings.h" @@ -329,8 +331,14 @@ IconEditorApp::_LastFilePath(path_kind which) path = fLastOpenPath.String(); break; } - if (!path) - path = "/boot/home"; + if (!path) { + + BPath homePath; + if (find_directory(B_USER_DIRECTORY, &homePath) == B_OK) + path = homePath.Path(); + else + path = "/boot/home"; + } return path; } diff --git a/src/apps/mediaconverter/MediaConverterWindow.cpp b/src/apps/mediaconverter/MediaConverterWindow.cpp index 2d1cc7e8cf..d97dcb1b0e 100644 --- a/src/apps/mediaconverter/MediaConverterWindow.cpp +++ b/src/apps/mediaconverter/MediaConverterWindow.cpp @@ -31,6 +31,8 @@ #include #include +#include + #include "MediaFileInfoView.h" #include "MediaFileListView.h" #include "MessageConstants.h" @@ -122,8 +124,10 @@ MediaConverterWindow::MediaConverterWindow(BRect frame) fConverting(false), fCancelling(false) { - const char* defaultDirectory = "/boot/home"; - fOutputDir.SetTo(defaultDirectory); + BPath outputDir; + if (find_directory(B_USER_DIRECTORY, &outputDir) != B_OK) + outputDir.SetTo("/boot/home"); + fOutputDir.SetTo(outputDir.Path()); fMenuBar = new BMenuBar("menubar"); _CreateMenu(); @@ -165,7 +169,7 @@ MediaConverterWindow::MediaConverterWindow(BRect frame) fDestButton = new BButton(B_TRANSLATE("Output folder"), new BMessage(OUTPUT_FOLDER_MESSAGE)); BAlignment labelAlignment(be_control_look->DefaultLabelAlignment()); - fOutputFolder = new BStringView(NULL, defaultDirectory); + fOutputFolder = new BStringView(NULL, outputDir.Path()); fOutputFolder->SetExplicitAlignment(labelAlignment); // start/end duration From ff09c7bfdfc0ba76fa9fee6e1ba7207cca53420a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 26 Jun 2012 23:46:51 +0200 Subject: [PATCH 105/349] Now is transparent on the desktop as other replicants. --- src/apps/networkstatus/NetworkStatusView.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/apps/networkstatus/NetworkStatusView.cpp b/src/apps/networkstatus/NetworkStatusView.cpp index 69d149567c..f3490d9bb5 100644 --- a/src/apps/networkstatus/NetworkStatusView.cpp +++ b/src/apps/networkstatus/NetworkStatusView.cpp @@ -243,9 +243,12 @@ void NetworkStatusView::AttachedToWindow() { BView::AttachedToWindow(); - if (Parent()) - SetViewColor(Parent()->ViewColor()); - else + if (Parent() != NULL) { + if ((Parent()->Flags() & B_DRAW_ON_CHILDREN) != 0) + SetViewColor(B_TRANSPARENT_COLOR); + else + SetViewColor(Parent()->ViewColor()); + } else SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); SetLowColor(ViewColor()); From 342e3b2c1b43a755a32645f97032a551e29ec5bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Wed, 27 Jun 2012 00:07:10 +0200 Subject: [PATCH 106/349] Updated optional package for Freetype ppc. * Fix the PPC build. --- build/jam/OptionalBuildFeatures | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/jam/OptionalBuildFeatures b/build/jam/OptionalBuildFeatures index 9b25819355..8cdc51972b 100644 --- a/build/jam/OptionalBuildFeatures +++ b/build/jam/OptionalBuildFeatures @@ -337,7 +337,7 @@ if $(TARGET_ARCH) = x86 { local freetypeBaseURL = http://haiku-files.org/files/optional-packages/lib ; if $(TARGET_ARCH) = ppc || $(TARGET_ARCH) = x86 { if $(TARGET_ARCH) = ppc { - HAIKU_FREETYPE_FILE = freetype-2.4.6-ppc-gcc4-2012-03-17.zip ; + HAIKU_FREETYPE_FILE = freetype-2.4.9-ppc-gcc4-2012-06-26.zip ; } else if $(HAIKU_GCC_VERSION[1]) >= 4 { HAIKU_FREETYPE_FILE = freetype-2.4.9-x86-gcc4-2012-06-15.zip ; } else { From 06e8742063e6bd56b6b4c0d75f1129034feec6a0 Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Fri, 29 Jun 2012 00:24:49 +0200 Subject: [PATCH 107/349] Fix #8643: AVLTreeMap strategy Auto discards const Signed-off-by: Ingo Weinhold --- headers/private/kernel/util/AVLTreeMap.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/headers/private/kernel/util/AVLTreeMap.h b/headers/private/kernel/util/AVLTreeMap.h index 2405bb79b8..ea436be3c1 100644 --- a/headers/private/kernel/util/AVLTreeMap.h +++ b/headers/private/kernel/util/AVLTreeMap.h @@ -26,7 +26,7 @@ namespace AVLTreeMapStrategy { typename Node; inline Node* Allocate(const Key& key, const Value& value) inline void Free(Node* node) - inline Key GetKey(Node* node) const + inline const Key GetKey(const Node* node) const inline Value& GetValue(Node* node) const inline AVLTreeNode* GetAVLTreeNode(Node* node) const inline Node* GetNode(AVLTreeNode* node) const @@ -622,7 +622,7 @@ public: fAllocator.Deallocate(node); } - inline Key& GetKey(Node* node) const + inline const Key& GetKey(const Node* node) const { return node->key; } From 191b137a318e10f987c0c7713b09d4e9f9ef6d68 Mon Sep 17 00:00:00 2001 From: Matt Madia Date: Sat, 30 Jun 2012 18:51:26 -0400 Subject: [PATCH 108/349] Updated VL-Gothic fonts to version 20120629. Fixes #8662. --- .../data/fonts/ttfonts/VL-Gothic-Regular.ttf | Bin 3816268 -> 3816416 bytes .../data/fonts/ttfonts/VL-PGothic-Regular.ttf | Bin 3946376 -> 3946424 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/data/system/data/fonts/ttfonts/VL-Gothic-Regular.ttf b/data/system/data/fonts/ttfonts/VL-Gothic-Regular.ttf index 016461965c245227f45fe0cf2a82980f1e7f1285..f880d709e7cffab4e8af7b3748c0fb3d122dcfa8 100644 GIT binary patch delta 129447 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 delta 129900 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 L;9Sg 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 t!(Jwal5 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 TmO*Cr?6_@K$bH6;Ge7=+ymhR6 delta 65460 zcmXt=e_Uka8}~mu=ggclGv~~lGeQUiz=e`SeQGqeWI&c5dLyy?*=oKjy1UsZ1-rWC)Blj*-*6k`V z?UlucCPxUePp!G&lovu3FUdHfP`fN_t3G*g)!%a8S_$r<=i?o%a$zetVy3$;J8fInM)Vf*Y3G!!CAyN6Oei4;-x1qeR9SKDnX^z2j^WtpB^iKWrnZKC7JQ=J*34JuZTOA5VBzYFZJzgy zKehJiRKeyECJR^F`(G4Yu*d4A!#_8TIULnTzZ$|3yCLs{%NhOE11D@2Sg`5pRAqR5 z*3Rnb3!e!SnSMi0({m)&T>kS0EZ13GdFL~061Q2M+5J{v!G^169{9&)ow0hR|Na1z zoYfsq-w|H0&gz1fo{X|yfA!qxH~xaHSEs(X*;tUhy8i12jRia0ko8@1!DcsfeYeTF zbIKviLp%p|hOJr0mrs26#KdX%7tR6 zfeyfzSFOO#1yBx+fNkedm{VYv94GsA*xv@?_Mcavn6VhG1FB$Dfdf52>!1qgN-9u-p@gJ^DRgiXOe=5*O&sdLnvr#B z0W`q40*B=S$%nNma5xPf&irul4##%{T1S)vu}4fOP)6~xE*OGI1&+jjB=EDsVi($JYZzj~@VhC*%OdPQZ2oIw$5r1N19U zX+j0Cu0&%opUC1OsDWMuPV#`}k|z;x5&=sx0HGx`Qk4mHK*v?{3Y<*h$sG!uBA~HT zT3}p(Qz>#PMNh4OW*AnW+J=0nhIYVq8pTdS4buuNqlsm#mr-!pgaWnrYgyOgKa1S6N`d*= z%+Jn;1|aX8OwRwDMxcSZY~UlQ<5M`-hGH0iaRtsJ@w_ak0Gc?j7ii?XDFx2Yff{Iq zK?UmbfcXVzT+jkNFb4AqT!_YnCD07SUX;w{M@oTg05zMjRy!`Gpj%g4Yc$ta4r68@n1Wkz;!fwT^5u;Ep!8$S&;@5TTu<@ zt{7FI)rL%UU>px_O?K*wzex6w=+^BZaM zrUsZ);AUdlX{4RTZo#&SyjAT$@moEh@U1fnbc`u*TP;xI_BFr%cho7+iStemniRMz z7YMqWB6s&I&^4gIJuM2{n*oU5*R4QzxdQjIzQ0R>2grMXoCj*5Pk{%qKS+E}77Quy zze1Q);2~@e^C>)>QlPgiAGc@qbr~=Ox0poM{1}Qd3L(ilCJn=6S!?*%3mcq0GL+zaZO9Z`? zQsCuA1zyRADFucJezjA9*UA)lonj+tFs#5E_}&~+;H_>2Mzeupqm@9Dqlk_6!#K<- z@OC=nLpjt#JD~gaqyq2Qz-Hbl<^12NV}kP?cKc3Bfp<+n{9ShaZY{JyKTIev=0E|| zKnKvw*t7!gr31~pR}WplC-6Qx@8?1Vw88*PDeyrCp#4E33~~M+%qlQW!Er>#5gi{< z;6n!rfd)S8gE<90DggW+(ac8__z1C&De`e9;QP27*v!Wi`?v>&VN!t!K?dYO2~;ca zNsa=a7Af#q66a^>fb+9bsDWlc;IlEHa0-74f2sl+fhJNT3Ve?3b8S_%9#2WhfoWpdR{UEGU9u83D#X6ZFHB z3?l29q!=Bh!R5$bvj5f-Ct!sf1c+gjV3=-lP`>VH8p@BV$v62bquyg-{BWPz#OF3Z2jkgD?sy zn31uWz=KT4g+k7Mvr;CNPz#OF3Z2jkgD?syn30hs@E{X%p%6-;5^A9lTA>qqVGu?k z1v4@>7kH2fxlqXYZ(hoz5^A9lTA>qqVGu?k1v4_X5O|OYxljnDPzklr2(8cwy)X!) zkb)T*TM9hLgj^`({I@KHN~ncKXoXJbg+UmF)c+$}GP3i5Gu^5JILocmfce&(@zy;s zBV(IfD1}q!*5#-u{q5^ZVvbV#CtuQ8II}b?St_=oYQpWa< zj9lhB@T<227o8n*p$dk8iwn<$#!fVumjQ_HoDMXziwPCb4aDtQ3o|nEn`G=pY;re5 zcW;!jM;72HCD#JP~9g|jjiQFPI?j6K_7LPlXR49nOHvAt~=m9YYrcm?gw7>48}p zRoQ@MRXd<}vJLq_{>f7^PAP}vw2V^`IkjI#HG)&aXOu!J}l#m z5@-b)uBirumgYhSU^}xB#$_xkhh7=A4z$3CjI+=@s|L_H+XnKIXE!k+;T#O-6az_h z8Bhi6>f9n|0AkK70L0E0U^{EiVxVrr z80UX6K^N1>#Z}M=h+e|_l3M7c!*n1xIVz(u4|-%=ng(^y3TxIhdRaCgd|5l7v7Ba? zR|AbKpOewVx(UrDn!FsH%bS7wKjZRw8CR46MXsRWmCT#jVe^2Ds|saY?Lh;~%D84y z22Vl8wRJMC%agGJTGM5$B<6Z@u20FhfxNa388=ekCVV%uvGze3x6s6@E*ZCyb1QKj z?J{mlHp;l2uI|9tnJweaLK%0NGVU&y(N!no9=JDO#(g<5y770<%D5jMn2_-x&Gd}Q zc!>CiW@J1(B;yepd6aQAd3|Lv9?OMZ8IP0uI88i({u5I&`YHZo6`$%;O){P)aDbp^ z#$-I(DdRbko|};|$WC~8FkZ-#@nRYfGeqH+MrFJ_BIA{M8N&z;&&hZd!PiP_%lL}?uV!R?L*r9rFfM}| zP-D74#t$Zt^CK}ouKE4{sYS+29`wujIUOkSGvYrZ@JlI>_$v+k%KXCsR4lBXdCoG|CKQL%&SJgH9NcX)@=g(=-QU2J@j;W+)AsU`D1@ z2*Wb%Qka$*Zk3sgkPw-Z8J&{pRKciBw*g3qwabjx0Kpzj_{@Fg2@0;&Ei(=O+K8=V z%3K%H%Ve%c?)t=RkO{|AFnH%%{Z*JVfWL{=wBMiyhBpVRf zRKR*O60*vH1~zX7;~G~%%*U5m&~m)p;zYC#BV(;bDM6NIT_F|bK54F+fjV` zB4~k>%-kH9NXpy+;|>JxKodK50^?3qFefvw4yI-9OanVl$lRqs=B^~}Iw&)rLirss zcgunSnY(+?C36qPJ;*D_0E+Wg)Lb|wb5RY9$lQ}!h2$1a%G@hS;NEG_EOVa{Ah3wB zXiDb3BoX^8{=s%*#Bn4rrp1B79Sti_2y54QZa#FLOzW%&KhYmU(h55O+!q%ya&y zVywnl-6iuh#?x&WlX(WhHCcez(qWlr766ScBd)ed=2^u+GiTGpIe9Yc(t-K86gziB z=6N)5UP|WqZ8Gce)nmJ$M&^b2FfQ|=A(;*Jod3l|GB5D}v1Gr@##WiUdNVI&SC>u5 zT;43RsX^xDl`^l$fmxYX64zWI^QtsJ=xTh|Fuw+kmL8ecw#&SZ2Co~HxnfLaYp=|e z#IGdx`VN^lRLgA3lX+v(`O%3xaNqlm2Tli61w^RaZ9kCXH`O+C>hv!7y5+Q9m$7MV|1$Q&SM zU{K~Wt0lrVE@fl-^Mm|UDi%QP_%Pbg@IoTldt2~)s)7jUpGQVk*ImPD^u3a*2F-EsxfOB7s>*!3AVz?bCu9L$(eaKj-5 zc~lN=44H!pZi2{WCZrV1now|aY+JJ4a#F!;a=6q6w`SaiF{e+#Z5g-Eg;@o6kb*l> zV5epU^STt=8UHR6-!)so{5%DB!^bm6aF22&g9SJiHYm8LTfset6)YrSuPO!iZc%U_ zd_~On#lIgS`%fx(fT!Srj)Dg<9z?N&5j}*$hs-Nj%6J$#hZBDUT1Vz6cyy+M<#h@k zgY8&~ABVr9UBTlSPbf_)cw&Kqm8}Xcu2%3QcDZCs!KxVrPwrFjlqLmFEmN?XnA2=X zDR>5P+;#_-jw^WPtb)r16s(<4@a%L2&jBt(!E@ofd)*~*j%gN)pUOi-M4rOUd#MCnpx4K;7S_0zCpno zMijh}@g{O_#(qncf~)!z?8sB_Hni@bfzB}n?;`$girrHRqYB=e4YLZ~*Gv=Lxe9h8 zbbqgc576O*H4641&@->#|K=2Y2;alC3icw-wITRuIv}>XO~F2R4Bz7>3@i9Vr-J=7 z^klVyPt_^-G`@jp1)nK^E(M=;fZXRs6&yrou#NK{#PEC-q!fIi5=eLvfgysq*$lok zqu?ur&fL@sU;q->{)a!8h^0B_Q`Lv_@MLd^;Oh zzmvoHzniPzn5W=-4vZ`K{-}Zl6-;F5vJp$A13jRRw zkCO`iG@#&2vw}YtEBK3}AUC1G*)*6^@OKLR(W&5^4dndE_$T9EbqfBS3F8XR*C_Z8 z+W%1O-zEkBD_2Ox3N7eXC@`mxnWs?FtYVT+wXpd%v3c3|q*ssu{N`>|$ZqFHo_9}omh4!ZSJ}n9rQDk4@_8U@Y ze>98HJYY(pgEAE=DOc#=DuoVdRj4$XqtIa_A5Op#h#r}x&{5e69o?o-`KUt2Q2e+& zg(^roAw!`P`xIJC;geDdEy1>AR-r0vCzmL63UQ}U#bqxxg3+It^ej!XNR6n861qfcqjxOp`sDWKw zoKlECR)&(~G&U-9DLc9h|MD4ynrPy3d{?l6D~AzXMmC3{wakXq;W1_p@$k2dU!~o-fTes5&VzP_@k8yt>@QH{#VVlTAsf)+E+_O-F`&iW zPUvOyUcvSX4G$M8^eV+)9a8AEWH~=(6nec|p^*`V-WXQs%|30r{VD?m{sV*0zl`ZY9ROHJm^SS?+vlisY3gpW&Y*{Ar zV6LoCfh_*yV%g2I!Y#5QJ+h)xNm=fgtXLk5$ci`0@(A|2WN`~+B}!$j#X7B0*4imq z>l8x2taVFZLRNaKtn~zluAeDugA5pwm4SW3QCZwkS^Pc0%0wfR^(MozHXV?)8Twg8 zvNlf=xCMgTR$1BUPy;ivwyK9ISzA{FN!w%ru{j>p!lk#cEv#c_GQoxE>Ff6OQnDak|ZjPbTV{>3k)^T;RD$;;v zDiAn+K-LMlzp;J~(vPITX63@hNCW*^PT!vsR30#`3v#_0A28f+gFRLy`*12i2&a;6XoKO7u z`09zNpOSUKw5$u8WnGjF9kO`UYBkWn#r?8)t7=`+%bBCu$h;9-lGmu#W$D0Tc_B>7 z;x(ytd5f$o@?lukm4mXHO91h!m|uSykgU!= zS$ERRT~)H~X6(w8bx#_M%euE!)_pmEMmHMw7s+}c1MofABCCh^|CxZsL#47F&fxqX zo|e@+BI}U>S&!DqT3rDXvieAR9C2QoT2BSrhY#5~z3>nVhv&VpH413j{yX_56T zdC%nmHr||C&lC3oc`u}7y-3UuF)y(Zz7MRIXJqmA)EZ8bFigO!{jy%8``4>wjiken ztT)DGy*VxGtu|Ss_}{LQ^$xywu)W(PYb*`MWW6^j>-|nyAHaCCtPhF*C{NbMrYx@a z*2JhRuJzWZH1%1ztQ5Y_+05tUCco&D_2q=DuX1I5O~TiReKRC$s!i6n1bj!*_jR(S zdu9DVgFmv9pWtT)24($HBkR{PS+nH-M*eST{XQk@k7-$Ry+$m24wRx(cX4M_I5P7{k-fQ9N9aj$=<0(c3vUO z%HFw0_AWG>PyTKtvUew^fVhGg*$ancFB+A-C%J`_viC}2+$TeJ5dlRQ_REsZ717>* zT6Qra2Nugds8V)Gi|m6tWgnUjZIC?Cjs zn7oIH??vYkbRU_J{V3Oe`_Vbss|oBQ;4vH6(c_3ckquL_``ctcnGW5upQ@1kbS7Zu z!ec*E1>`?V(PtT-V;n4oaoNw;$$mjVb1z~a%78A}FICEZxnA}wc^us(_!ge;y zC>-urm?z_Kv_xSCyECA$OKz-2;dqn69vXfwq!dncD7;py!aNCw*G_gSybj{)W+|MW zqwsp3!t1YLL}6|u!x?=FZ;1FtByhzFXHsAj3T#3no8sGST;VL@Ht$k+3u3lp&g;4G zR@k@6S2!nA;cd$m-mXmH?OEsA3h%&t$7+Rl!k)~_P#;YH&L@0n6~FB;ryKw<9d!uzn^mzez!-M>cR;wps?XjJ&X7KIP0Q@Es0 z;e*LP6#Y_a9mWO@Z&vsSd}U=yhL5C+qw*9!n$F706h4N;V+lA8@d|cyJe-)XaAm2& zi)rj6{7d>3t{PSN6i?w($*o5Cv>cdM_zVivR4crcPhwdn%qV;o>$Ax_XG-C^UWLzP zejc3PpH%n)DSRPKG$3*@U0u?{$1<*Pc5?E4-5U>zTLFSX&7Yf1?e}3g5&ha1**W(?ENL!na_*CE26!Dhk|+ z;H@}2*!67%fY|Nb3g6MGaA%>ycam^dsls?4jFBj$%eh7F94s(+eeq>bP)ikoY5?CkuDAw1n@MHNfpz!02-0_5;s1yHDL#x71 zWGlej#@Uznj4-z{_?DN=Oa9~p57s(mwRrsZLgn0U)Cx-iG32SuPFRA8sCsVRjKf| zY3E!ars!{8J`ODLgZ#@Xs9z|AG(?sNq?Bzj-jH@b7$De>5mO zhwV=a|CIr=3ja;ce6Pa);QO~(;s2TxQKcdaav`Ni01Pm@6bUA)6$uq8VpS?)XDJf4 zVOWs}MCTQ8rWJ7q6^V^167NyO>sG|CRwR+3$Xb~&rAXRMDoNCKP!Xe{Y#0k6?e4xYeVI^wIF+ z1vLCblOp}|iagb?$Uvqd&$KD>?35zBpO3tdp~#D+iVP9_a-|}#v?}tdqX-Wwk=N%G zc>{qrdlVUMR^%Q0W9>i_@0A1g_iGgSAPXosUJUp?>{8^TTtz;%VUY9ZZB*owe8BnX zgd(3!E0UtX=Z%VdfxwsbicBK-RiPqZS1IyMgCbLie><WK{m`k%k2F0){4eDF zg8x?&(4Iwmc3P3&Y9Xb_?-f8U@022c@cu6{*QdyznJ}QpUpW6l=x?0!6q_gE9}4`N z1A~hE$M|2jqAE~yK|XXT8pwbFMU4iSQPgZzlz)B^4fZM;>QK}wR@5$4G;BhXqLE6N zRy0bSlg#7Cu%d2@qA`-<9*isMH7e?7!-S%Vl%i|ZE1HJT+Bu4@gU~uNimpr1bi~%H zQ*?dC4bq`s(Tp}lH>B`JRf=w0plD_qP-BxpMK=@7E4n$pEvTK`vQW|N3`Ms>bZh3@ zR4SSS+g2#L9Sv-cEw@O~9U2wgu}RULXe6&$(Vdy^(xvFG6yx_kx*Pu8hZHTa6atQqjr==vQ=cF0h-EN)%mU0}WLnb~4SJOuwnDRwEsmrf|k#U;8N-*RkCh+J+%gQ7fIMXw<5O2nHp zU|7+s%3)5?tNE0#senmETRIiJHWT{Lzm5j3n^1HGAN>jfTk8~EiRj8{MXzVPp$MiF zZ9}w;25%(pM&fSjR`g~>xJX6YTNS+}AG#D>)uQOFIY8qb#Behcy*&$vyQ3UN6zwGb zPKw_(&H3Nmp=ei?qW9z~dT$0yD|#QvJX%HXN9+L#K8Qe%qv-!A@=%GQ57YF+G|@|e zN63A&LebSZiuTb^ANI$vKTh1^Q;I&(t7w0tqED77`c$Q&PYWg#9iX9SQk?&@lZtZp z5`CTm&y)N@i=r=^iy=u3l&zC57lD-DVc*DCsIm!hu?Df&7&Z=?afH`^3_3*Ts! zqHov3yrS{be7<%s!|9+pM{NI@^O=*6S=VFd_T=r^s^!$`13+Vzerc~ z%X~#A>lFQ}ThVVy6rCdY+e$^h%TVj-4kb+$o0} z5ht3GZp1XztM`r=SRkUD%M6v#0>r!JcJ6 zU?Bl}6~m;Qy@%xNQ!S?m!F@gGm$P4uoc)O{PM324%^kP~gb!+zQ<5*|;A|lG5Ht@( ziwl)=Sh<|T@g316r))sZk_&8Nl%$T_`9&KXm3mKMo56W=m4mr;NxAE%a>T6{bKIcH}< zr<`*t<|pUm-D|qISo}6DiIloeXcfHQV!qLc+>O!91H zxw|*X-J?WqL9yJ0$yT|Gy5;UUDz|V#?%w%w_rbO=e5jyJZfULD!|LT8?!m0wBSz$w!I3m{RGHkP)1XssvYalC zDV2L{CXC5Fj_xW*su-4gJdK@DE%(G67?)ewBX@C^T<(zElP2XZL7)m>6^)-_0w4FO z4RWiqpik~;jdD*fkb4Hc8fq-9gekda*2-O$3ta!*+Ge?DInXNiY!8Ozp3^P2u3hfA za9*L@^Yi4^lTc3+7u3kT2*HcyKSZ*VEmzK!AEEA^WE+@WeMDFDs za<3?rdnLQRlGtW+ud0xHHUIwKy@tS+8M)U^%3VQXE8?xKa#uFWy}nKE4FtC}$i1;r z?oCBHa__`{S0)U|y_@E`(7h)|?!D!5 zd5`RNuj%@JPwoTh&?omngnMe`a;M`yMB>AYy>)UQA@NZ}R?~eS;*TNn*sR>gN98`z zD7U{r})dsn*RmgoEfstIfZ;<$An%uW+px7wMZ+FXmhw)wV_{RwD7>&G7-1`*Zg5-`9 z_aWjRRm%N18>Zz>Ov?SFSMH~Maz7(3h5rkO^Z&9)F3)!^&v)+E8FIgAl>4m-^K!qV z(D!w6r)lnoEV(}t`xAmQZE}A}m-{R8Unk_w&dB|3T<#y4Kr?@m|L3sWzbN*1wcPn0 zx&OewBXa+1R!mijEhtqike^h{$W_d2R4gRuR?M1G%pOuKlBQU64TFj~od+GUEZQ>@s!9g3x6Tc6ks`V`AZDYoITVjJfH^G&K1+q6Ql z&Ds^qO3o{``G8_uO0jGNwklF=YsPI5%3<7=#O-<&+rCq=+-}8q^%C20MzOq1#dfYy zY!}wMwkVcQ%x-Op?Ll6_gkplNeoJa!rD|31Q)hhNq1*WGJ`_WYFCu}p_iv2vJ*sqm}@#mD-Z)1x6 z!A|Dp6#L6l?C*ZX{wYxG-wq(|zedHC4x@@MXiz+0L%-riIm{|<_9`B1S3JbO|BG8S zirZ<>1T%_N`>g#w#S_JfuayPZ(}-KUO7V5j zTxU-4b(<7VuU34$0>#%Cptr%e;u%wlZ^-}tH@?xZ;v07=o=MUs1Z>i-_@*?q83|d1 zif?YhfZ|)UD841)*%>gY_*U4qCTE)l#dC5M-?l`UZ zPWbXDzVo=^yG$s)D{=WrI@>J+Xo4Gq_#XK{Z~;46*sl1ZA;tHsRh(BSaqbV|d(A1n zH}-uHF3JQN*|$aU{b+_%@nb6$KMr37g2y|GpFn{VGZe2xbTR9b za$!#KC4Gulp?5MxPQiXEan+2c6)S!^w$mpSKLfoQbeA%o*}?g96A-WMRQ#+a#n0|m z{2Uy01e^=!btry*yW;gjieG^5LdJ_I(tz*cdc`k6lOd!i?h0_^u-N>R!dKftG5;uPx#HuM_kuzM@6(R#@4p`1Q?--+)LPi8ppCeiNcM z4=COaw@fR(YDDo{$?0fN{5IlmC;pBK#XIvAzjIjeyD8e0rT9H*ir>rpzGB6@D;2*V z-vhIXKRB=W|MC=nC|RKR!ww+YJE8carHZevQoN6(J^~+O$B&crL`w1gLB*eJQT!c;?DE>i#;^VoBf7qb-NAPi(;uAFaNweag z)++v4kK(Cr#Xlcb{0kcV5{*gpzC!z}8O6WJSA42Z@o#DDyAH*_A5i=UQ}G{p{)_*V zuJ}xr;y>Gp^KcRWm7=pXivLET->Vh>gZZDt{8g&>-;IjTWBZ2&{;gH~zZ!Y!l((Rd z|BJ0$d1jhC9xS{NcB@;S-7YUYDlalEFFGsF&6F2Q2i9J;Jij_AFVQG(tyXzyz4F#Z zXq_2(>(0wtZ$RGq*f!{rmx0iR{qi>Ikhd|m%yD^}%*or#lb2N@Z*vN6F(EIT2DU1c zw>3>|L;ki|^0sS}w>{*NyQ3{{r*wIFweofzl(#GI|Gj*IcSCUZQF(i$-?bRZ77LA@mJbxAO_^XI_KEm~5@-86eqB?mERq`$d{+jAF5_2grmyOC>J}B?< zOnFxn%e%5$N$)BaS69lrre0o4i@a+|SV2N-pS+bRdDlLd z--qFG3{OnTd$LL1QxozA%H%!ME$_KBd4mW&KP&G=Y%k@>dnH5OFipPZ$a{TE9$(Ae zTi8b_`c8+uu@ZUjoAN&BlgDGZ_YpA@UGhFjgK2r6R=|Y3&pPF$k}N(?m-ht;Uku3m zvQFM4fnUMb6!@CJZ}=3ZXy)5?dHni#d_8;9@WZUUpU9u7l=pLkykBVaS3cI+JbAxm z%ljRTKN#nT`Lj{pU+_2i|6uzU-+y`XlPZ?KAYXohy1nDU`BpgyZp6V)}fe+v@1EB1N(_OlV&DqsHAHjK*OhWMOT z`Py*E9h5TKL zv+@gB@XpWQo38dr$uF9bzn>|8e+qD$>>o%HU#0#*)ACEIA2T5TSOky7 z##gU@T$lU`1dgYvyucE+J*sdOte@(6YmSXwW!gVxxU6=e7#I)wXg#48)@~Y&L+tT3`A^Vkf4}@EN8~?6k*BBRKa&B(^77Gtj?M?kc>&=U zX5_y};h`bmjqK2DcE(Ev2?3A_H(hGF@i;Y(G@=OM!XoCdzAlg}S1{4eL^PqxeFVZ#3! zoo@={Pi4sewp#vokEQZ|lKdGO;VVDs|BS#d6Y_uUmOtAl|2Kqx zFPHxZ0dwgvFaIwG80RbG|1&E8-z;c`Y5D(^z_b!-;{Qg~gDxck4)iNwlqq3iGkcT> z7QvtrA;!?C5>`2I{t3HYiEs%_C=qE^BANwlN;o+%q=eg~L@Xch$6J)}5b*kx@UbTl zNsKA6Rw2wOkyZ^;O03@$rCqI2wiS@`|KOOp&*q|7aBT8hHD6ydfByH57 z#Kr}HNM@%Jn^Y*VsSOm_jPA3lmDrqOn-3_lMXeHBGS3$DD8Y?KVyhV?w(d}3n<^!8 z(g4kEE0x$T1MqD>s6;M>b7^J==E)r!l-Ma3Xe1Ajo%3N@iCub?*tJH9d=G|{*sV^9 z-3yf1!vUHpm{Ve5zY>dRXwOU~3Td)%Qi;9BmDsyQiG66GCPgPc(_k z8kAVxq(oDu65KW=E+1FoiWViV>{p_hoU2UeRO0F)C9c7L&5#l;G;?jf64${Bv|0<5 zSSg^P>&d@?X4=@mjgY)4TZx;~m1wt>xP|#D1aBqy)|3(*6uPZl32v_vcho4+iP)W) zO5ByB#NEVp5ql5wdkd7fkNo>4mFVtO;{IwS9w<@bL3Dc7K+*rfLsLpTJf}qOm=ce) zDDh|(=l|%u61*l!a0N^}29MV$@dQPlm{Fpi^^+A!a1~5E-Jrw(zGrCY*&-#L%U5EM zBF`5p@j{gnFJ=Kde2MX8Y_Fg(?7^%OuMR8mTB{PT)7S{jzLBfMoA8#&`M))z#3YFPHd;WG;7|jBz{cxDe)7+Gqp-^5106b0>3iOmMHNX z{7&IN(v_H_+duP__>1Jf5dC{ZiFq3MhunV!tpDrRT7m_$S}Op?sMa#;wN@}!YlZT) zmX)Wq?Egd283)8Nwo&|t5JK$i?(FXD?(FXD?p#6$A%xH+gb+dqA%qZOLkJ;+5JIjH zx`Yry2qAnJ$o{ie^Y}`)9lUIpnlMy_+J9#z}A-@sN<~?|}sK>LV zj0#HeY?X^=Yl&?w&NkC{w#~z{T|b`foA4Bs@L>ZnVHC7kmIZBNj-Hhj$20S&YJytkw0?+Zi zcxvT!LJgi1Rew@u3QwI5PRYY_s=BSO!gE?Np3{XhB-|jOGnG3FLEN(k@idO%Ij0-X zxt(~lt@1QY<2ip(=Te;JVmueh^r9I&Ey`aao_0{4RyBXQOt0v`b7do*Hs!8TBblpp za7`jQ2Nv)=ScK=HN<0q>{pEO8>i_@K^GG$GM->>5 z$YWD@9+$`yi+G+i@jO+G=jjSOLo$0t$Imw6c}_yZYV7$XJTEFfqS}|#)GHRA(KbA< zO7FEgJg@6`tPjr{b9mm$#iJJ-p0~w)XAsZ3YVbW1&jd@w zj^`KgepP-!^WQ4*{I2njHav?nc>YrSZ_Sr7BY6H%;J+LU1~66;Rx>fOYA{xB#8{&X zBU|&eYBAQI>D~2(I;T^;9S7Vs-7{OAE&^U%Qg%O^? zh>CAFV8rGy63rNn^fJj_jI@E_mSAj@jj^%jo0MT}I)afelg%Zzg^mkUyp@W!)^TAu z#l~-WwH;i#W z85yHu8si`lDoZgAS;RQB9^)_x95#wkrPUwafT2svII<9M%~O#W#K*Z*3j0+1eE|y74gU~0;V_edUacL9AWhH`mt<}N;#^wDOSIG3r z35=^$bJaA))sq<4h|^w)ajp2*>C?nwhiOkS&Z)%F}`2I z_(2*!PGbC2hcWL6Ll{4|V*FAnNK2QYv5<%Hn{vNP^N#|IMd|#h-~WuiT#UbqF_sLB ze;P3UZO8b}66*1iEA--BrBs;2yJ`#G)#~tO*+Mto)pLXqyt+)iYnI^6Ry=zg?^=y` z*R}-Ju2U;aD-UQzDGwpbDi-bPB8w}yyFkjF=Vc?N~N24)_*V}~G zSAo|rGyf!BQ%&eG>9$RHx62Va@NSCCp z@eCz%2JxPv zno}F_*6aT7J*^S%=`uM(#50!go@wDdD_78J&Mp-e@HTehJ*Nuqx#f7ztHG-ql=u8L zyce|V97?FUAMb?{y~xFTaUR|lQ;^mri+C?p?lSROON4p6mk;2*Lfk8*mubtv+ct;y zDh02ez!lczrqEjxxMANbm-U-8hT)raru#O?Yos!?$D!GP-pNZ`T-J zy*2UPuKGK4+^zaM^$FZ1jl0F`$-#S%g?B|U-g`CPtH1x@?N#A@61;yH?*l6C)2bgF z#QRVW-iHP_c3uE7oHf!JE+)`GJ2{7@6+NA3D3w>`vvcF zwRneJyw4ZneW4ofi<*y!_fj3+muqzXU+Km>+K%^C8ENC-eLWBFST5c-G`?x#eM?2- zI(}QZcWk`xN^C;&i6y-6tL6hOU~&%cM-JYPWiqAOsTsVVYK5O=3Cd5;;{9Bo$`>Pe zzZ}9lBmP%9{yL+?tb_MkgfYC|b>RKJ8Sk9PKeXc2UCsNG;`3@ycQo%WMRp!gvJpOqyH;tNmWi^x2xW4jYyO#6Rdd>o%6vNMA(Ie{;&hSDM}%f`1+ z9lnh_@a6U5+oT2GrZxCBtHPJxh;Q=>d|M3T+fv*D32!ZpZA$PJs=iRMZKv^Vr?E&H zJE(5QZhYFL_=*+ZMNRFRi?2lQ|9!hv;@f=~-ySkA?ZUTQo$aaPGOcp&Vto53zwZ#f z{Zyd$xxW3CJ75Igfm-!J;vU?Lud)x{A*wyJ2Va#|eRwUtBV=^sD8A}>d`FGpJEjO< zO%uLj#XU~BTJW8aG4Y+KZuC;YS0}>BZTL=6vfjpbnhZ~`!goe9zJ?BbXG-iW6`w7f zQ-beYanCEp*EERld>LQRtMfUA??TmHRE_Uq#adK%iA*n5&1H-DE-%A(MGd|yrPoX{8p3zm1istF?Jmc6XB)n| z!Pn#9yGPBg&?j=Q8oDnB-~Ea`ps`Q92W9w>@(-8b>o3N)QsX0f|LfCE#5XX5?{SGg zp~PSjz9$uX+Q2tt;d@3!&vxN^ZV2D7R`7yyFD~I55nj&2_evGMQQ=h?ye6a9g)uep zhVW)9zPIY}jSu5{Tc6%L{rKK(!8g%{@4ZHR@9Y2n!#Al8KP*aX^fJ@;yG$3gFkPCyzdGLFN9N)jv|1Z;of0cUttB&AbZ3utXJpMJx@vm8o zKYJAaT9f$K(LARH|GL6@UHEe~ZfN1xp5O1S!0(&EZx-SY^y3fC;DjsX zVFkjeQi7iX<7f4K(lz$r)7Ixy_ZXAD+ z%yt;VzmxdI65Cm^U9<6*wBz4B3;!NP_)8b??>T_KtO5VtZTRk;d3 z%*TIDjv&IhGC5BsO^P>7;XhyV3uKa!ShI{TEEE>;>oM!USp1ej{Flh|vRpy)R^jq~ z{8#kizp@Q~+W`KnhVWnAivOAx{O#@dukFNtT_gVMGj;eo3h?XKP5+Hqg3LNA@!wp9 z|CU1hw`L0xzsJj@t~@6u@xM2s^Z$M~{tsj}xrF~C8GJ1AC*c3I68~p1n4ZJ``8577B{VaD|0@-L zt%ko@#Q$vr{_lG6e=oB+Y5Z7$|ECfB^UD1qvtPwuQ0?zU`2Xm@zc`EkuPXe1%VVh< z|3Bk8|NrXW0iyy_k41B}GR&-IOg$0JHKsAMOEA~c@jCUGIm4KG3YzOTVCD{BZdi%w z8N~GFV)|6)*W8p=unyBI$BblS+KR;u%tSk863mq1>26F{yp5VLH`e~o+(ZR>s+pVV zINuf)FgNeV+@cF}%NEQ66>KdrJ>AT0hA|73+g6w$OxGS%G;-5$2&_9;T+MBwn?IdAOQ6q7m~*)m1x! zYLA-2Jh~6FM%-f!GUjo)n8%G{9zTLv+k$yQ1E#KL^CSt^bz`2~iFt~|>Lpq~k9oQ{ zXUt$~mu#LjirHvmo-3T!CWzOh+VhpWAYZF1#%z{;^AP5R)tDDGV_sZ|*`o0hSD4FS zUMh2KkImLn%*(Z+%Qe?)GV@BIZ4&cpiCrzjYo;;VXECqs#=Ndd|8|@qEMj&nVBUzJ z@un%v&SA`(HQu6JmsWn88n{h$x^&HM)!f;Lc~>pw-Nl$anR3i~9LyCK=DiZ>ZNR** z9`pVV%m?~0`!s)0^M^_?AFjddZ^c}xkM9vdPfl|{c&r=qaT)53x%p%P=2In@Ps?mb zpU5-Kn9sIg>e4lbW%_(I<_i^=FDf=7{me__m@hA2jvAP+s@vC^Fvkip-;mIo8sDnI z9B;sUyA$)BUd)Ls%=Z*~U#s{)vB??Ck6g@;)x;+@=BH}xvpLMq#ra|w^Go3?#lKbq z-%MeC+kyF=#yNTYp#8u3lL$Y{OyASZgYD+rmj`d@@ED+dC zCYwntU-`{*g?R#7ED6WB#HnO!>xlvESg%_6XSE`dGNnQjh&vF>Q3Ctb6WG6lzyVbRDpXrBPT)Z49n?+W;6VbF(m14%z@cRX4l5NF2^@|v zK;VdG0!QlK{|Qu!a8w(Cqq_(k(?Xy|V#g|W+!%r5MXXi)gjoV7O7tXs3U$hztm9K; ze5yq1+Xm?v;%5rMO0c6L62Mnh2S+*|_Zl@n;HCUCxT7bt$gf>y8lf1r7i zz(o#$iz^7UbP%{?h`^;PYBhyf0#~S^D|-pFO%S*`hrl&zpuL~KwaQ&LN1!8HSR!zv z_&3R<(;{$-P2g5>y42|Hs=1?{KzAvDJC(mHkHFo91bW1|C(}S+#R7p|2;8S8?$;;K zS3=-HjSq{U>pie?hQOow1O~)?Oier??w|yp>>}{AxI@Z6qo$tiC-9uKo>%Mz)s0jW zc-a+(3B1xwU{vu})#Pgqf!7ruE7B+MMlpdm)zw?VxJ2KsB=AlceOi1KC6}~S4 z{cWber10T1fsa)VGi|2> zf6f#5tB%0mmLTIL)h>+__($VEBLx0c&3`4rBtgmvu7c1>aMdDVp5ST&8G>0g1Xs@! z6j-B;;F`t40>SJqf@>MVD8aSs2(DuZeFSql2(H^gaJ>?O>*oq11anolfv}-X(4&}V zjG)m@P_OQSKGpeV3Hrq|r5UIu7%U|il9rXx#9Aa6mS{wQXca+Q#jzoRaTzBX2|CIp zn+T?A38wQ2x)R&SBDk?bFwZ2oNg2US>j`ewLomOe;N}H_G`GwqSfKn?s@-au;MU4- zQ!FeIESw;?Z7addb}qr~l-z!pV3CS7oF}LaMDVB?f=AC0)CMAWtc;Em zju&cOLHQF43F^B*uue56tM(L)r&bcIm*Hs!L46Mho>4`xp_Aa5LpuLwiFEb|!A6;# zGeq#bT7peu1kaz<$0M<36<^py@S-k)7k3bBnIw3LpnXHI)gpMgxL0NoY?Js^Z3M3t zu924R5y9(<30~h#utT~x2sbLGJwov2Y=XBq1aHl>5bT;KczX%KJ7m;7Ozb?5!bqpXLu}m3=(~A5?P>O%UvFB)C%CN2>@9lo5Qam!S3n!6#(&WCg*e zbo{iq+QJ8)9V9p`o#*=qzNp4V2DCukAcC(*=+$z9uPHF*5PYMS;F~Jc{UG>`^6zSV zuY}+S*#vbD2!5O=NMx#$;3p#lKb6_EV$;pSB*D)cggJs=v=aO>UsxbG(?Ren#lO<= z*WCoak;kn5`=8)!FF|bzg5Qbwor=Gg*<3lnA0+srA&e9JN%?v4ewN`cGWoTQ;KC@u z-(>!~8vR4#pW^-{j`j<|e+miy+d}X^ix8cJRxKp7S{W zHrojWstDY$@%6JYkB^ zRyy8VwYm?4wrL?$Xc5X3DzUAEw^QNv3KrE7+Cd-J4l>`djnGaq-f5graVw#nWwHx| zcKttOS|Y*S#M!-w&>k|^z9CdPOlY}cdrExIX+nExURFV9Z|UrlEesOcS9;|Og!UUJ z6WU)Q2S}j8CUjt~Fh}TMQ=u+ zCG(?Z2^~E`=op#TD1K}uq2p=@9k04t2%TUFlY~y3Aav3wp*rcF+^O?_N;#oZMLJc& zrxg-9U5%WPPpCl!XJ!c!JzL#3<`FuliqN^8gw7iybiQKetLFcwusKJVCv;H>p^K%} zB7;jbzjTg}?hzqTNxSP=PO@v<1{Dm1pFE$by zDb@LZNkuPB5qf!q&@1hPM#~AkD&yA_e?5!Pm?g;gO_$JH5+5%h^tNJeOZ1&SLfWW= zCRG34BBA#u2z}5)Xj0>c8b6lVRF0thC!>TuZ6@?tDWPfUex5BX==^_a5}Hw9W{}WV zU4*_aCiIPrW(x^@n@{LFM_3^Ay$t7M_`?vPAJynj4TR=L2>skc=$A1lS0Jr*Zv8tlTcF4f?S>U>PM?-XbiYjpetnOlbyG8&a*M zF$g-EPVnQMtE8`SkC6!DGX$iaaSj!~3Q6JXEV_2IMVr?qn&2+rE@>_Ib zZP|@gFp0Hw16E-b*0ya}+YMoDKY&#xJFDqk#NBlPYqv72-K9~Apt{m= ztmVyQtUYD0rwsR!c$tpNrm^V%LIEv92h> zYRkvEss>9p4C|U1toAyrYb9{)G}d(sSRJMyu^TF}^d-c)QH!`q$DO&tJl4%Jy`@}O z!n#$tt`4l*O0jMiH=~<~b;l%Dw~X)9YVJ}Kcei8psGvv1_Y7jK=)=0V8LKx>n8LcR z73=;stOu&G`tq?JEWvuHP*Cl|!&v>wtt=K~_-K|ei#4F*$L6peSHn+?V+~3}UtluU zQv+B}*I*4bU_DcT^=v8Db5&TweOS+TV7*X_^u-?kY8Xv%Vdlc(kHSn(L-jl}%I-ab?`mhV@qhYL%hjsp^MzB6vz|xJu znpWZGIaptmV0|gk8HsMG&uaFUS*!&U>o@WL zP}7T@SbwUCzhZzQ9<3c{NV6W&xJ`4Zh+ zLR&((Ky_OQTMrU0EF`?`0O9SGFB&4eV=>{K`Un@#65d5Q?G?hiHB~9cm->l z2%peQ_(X}ER6w{ci}1;&AhA=_{i(x*>w5^FCY;_v_zdwIB%qg&;WOt5pC!)O8XF~i zj=1M`6F#q_bZxe2p#vK~(lY0_ zd;R_w{=p*rV=LjGB>rs{|H=--ZbPp~64r3I8eHUsZ(v?j^i5NBCbg`Ckzc zdWo!>MPxODNLCM#HL{7Usd#oHk+mVRPCb#FF(T`g63JC=gEAr;4iYhx^Jbce_&SOB zCx`?@2#yd5Ef5Kp6N!uxv2%&UR1ohVl2{~?lyGW*NP3RQvO*#oseWVCY*I{Q(=H^9g)mVlSFn_aF-S$yUIY%>B#Q0 zL`o&HTmpNJ5h*JnvbTixEhbW4O=Lgi52zwiF-YXV1tJGG5;>%n$f1f?6%sjITy4!G z)iXqnR=lQ_$Z@4aj+fSnGCoQ3lN*TW37U!2tE^P)m@oSq)oi51iiYCT$4+rUA$`* zzfSY(CW&0%MWmyO$PGqDe~b~iv5Ck{T3Kfuk(+HIxBMTAM7mUXTNaVqONrc}Tz7$> z2JRdua+gHzZX?no<9pQT3dMUZBKMUOxxbUh1Fb~*lzVWH$iu4d*Me3S5_v>;w1vpP zD3Ql9i$tDqhz!d7NfkUTfgzbZGfm_=3qwTo1dO~?L*!*O@`{W{)x>Mc zzg|gXY=X#}eMH_GAu>KoAQ~0d&LJAhA{y6RyWgmz^B+wbL{oW0(=|lhR-zk;w2_SRB)ExU zo3;_%Ovvvhy7?s0EhVnqZ*=Q?qT5sw)nygkc9`gPvqXy&+d)P&u9Cj1s+3b^0b>B)CGwy*APNDv91dPqa_O2iu4~qz3zQh_37)`p7WR0dXFyAo_R%(I*Cp zK4}tts+Q=}(t1WsK9^5)xQeLukkJ>$iH;N#eW{h`%Q7F;_*wzc*Xwou$0V*Vm(jNx ziH@uI9TiPf5`905=m#Qy=n(x#CR3$EKUM5A2~Rf@{X)%rSxa=Lo9Nf7|E7%S>>|L7Mj z9ro%Y*lXrtXHQ_S-G{x-9QJy-*z3<=Z%~izDa1Awuzl^=W+`?s8#~m49d@vzI<_aV z#tEAB>MZ!F#>;$$`*#?Dt@^DgWybFd2}ytNYBXuhrD+cjYqRb%fU zv7KaCJc_+b7Pj_u_HIMiyGy)O`Mq51GKua}g1xV5_mj^4%2lYrgZi;6Yp@TQ!9J`P z`|xt?BWAIy_4j}6qa}KbCdZCoAK!v~LLK%=ik&QhQ!B7f)BFs@&+NoLdmQ^537n@- zihq$-d9jV%VhZ!vm#Y3U1sQGsN{%c<= zp=%ehudBhnK3nL=?#Rc!Axmh-zEPjbjUCuGl?&t8dM#t$Ea97Huy2vbt}!<2yRByUVffR3mpTVBa-@efKc-J*r#bVBedI-K&M&m#M+NUk48iU_S`BgfZ;LB>H$Y_7f5vRDMvoCtI+eD#de!zJvG#hX%oN;RLz;8WqV9_;B}?9VlRF^&D@1h%$b_SXjXH>KFK)!5(m zVSlIiTt4;>uFn6D#n?YJVb8Z?|E%I)IzV@zq_&j(fDsO z_J0$^R&j(`Vyku$TTSzHA{$P7Z6*kQJ5pP_6V_cbe!V~s#&*%*n0Z= z|FQK(iLKvFELX`5gbh21d6YD2iFxydMPfd|KTOQ*BNmt@78I;(V&Mj25sBHo#Nw)r z>p0O$%rS)lVoBvwY9yT_v=ehHh%Ix7ZDa^)YU7NA^2Ug5(n)O7CSsep!X&Z$abjDj zXbT;0IZCWxh}hP)ut;nh<+d#&wtW_{qDo>rN^B=Jtgljo1;2A6ZMRT87nq#E#Npj;t);_@f$2+H!63NNvtzR zm?w7g9I;zvdg~yuu0CS7jS{=Plh_??#JU%V-6`X{guA8H(?jf@j5=N+^1Y43daH=t zS3&H489X3^KE)nvAofrve1F-8Nzq%D>k^?EM*HA1o64Q2CE)iG8e9O?49cG?&WR%t>)TnK|L+x?Qv*NL5&Kc1KTQ(*S%SZm68p88*n(oejS>4@ zW{V}n{;VbTS0%B(dx$Mf5&Kty|8){aSk)lDS|#zUDdKAs5MQ&Ncy=}MwQb_-^blWH z<9g-9*KZ)6yF`3Lz5kDUW{G=ei0k!9+#Dw!G>M1WiEHB+kJJ;l`-#Upgn8nLcH)jj zJXu0Kr7_h=Je?(ov^Tf9pBVHh$zM93i z(iSVel^WQ(hWIwFpw0_NiEBd{-)?~T_A1ijH@-s!@g2q4QN=rHzSA7>Vl}0oWa7JM z#k*D!*UvHW-CBw7-cEcE%}d2wE{#2v-%Ind3F3QC6W>RieHAM&Bc9o>miYeN#19xD zULhQ05&lI(;EgO{miU{hc}uGpZzHbzLj0Xl;_qe)5}r`( zJ;mOy66T11&_aB&miULZphbSvNBm>yPc;$$q(JBYlQH6-iu{=?%o3j-CjPlZzEJE- zHSwilGtLUKNgmv?X&lVB?R>I$D{7$CdD>i2l{~=EpC$9TQTwhG%^98~jaqTPO zzqAwowUqdRY8Ix5|JFnNcm4N2@!#i({~^-i5b-~&i2o(R-*v>7Dv1B1f`9vn|JO|d zVU-RNtGdECiPhRjWR;Luy@7-_9Emk^NMz>!w`h6sF zrL#c|i4AQMo{T}l(19^X!YlY1N%&=8O3<7m5l}4HPeM1Ogw;wSEVD=@iKt1!7GinA z5{dXQi9{C(r;S8%f<&r?L|P_pDT!qWYG9*T5*v$~w@6|WVbc*3na!$5Z##)C zDoJdq6%_m*GS`hMv9$`f=_R3?Qes;PZl?yeFDFsdN@9m05<52pu0OR2Psq$`Yij4M^e`#cE1O z91Dr#vV{c_$B&Sx6;2q*kT|i0#7S)=>O?xZl*B0#JhhrceG`e(nn|2qM&b;aHc0r) zJQ8Qg`0N1^jWRfAg2cH)B+lz3(KJQk`~?yhNVwS$W=LEl(~G7_v^autm%1b_YawxY z7Ktn5d1Ypv#8o0+EyC5aB(51F(LPS%I!lnCHX4Z=gd5ewO=_-FK;&*7?t(rS$NZc*syQSTu`3fDc(DA(^Bzo1%{nB|r=6#xH9#oOOS||E*Nvu@j zk!li;Hjx<6_*gTE$Gb^9QAJ`Vb4NDMELcwU?rEfOO| zBwiXO@$wvrR}>$W{%iRpUYGt@C5bm`NW9ra;;k{A|F^S9yd(2>D@aTT@5%Iim&6Am zPU`q0NPJvKVoJrIl#}?>5f({I7nAtBgTxmym{IJj5)xlmllVp&v+X3lZ6xtsJ&Eu8 zNzBRYN9BL2BQf7e;^#>czh;wIDA)P_ZI;9zGF%k-&v6oZQIIAw=WaZ$jUWT(qBhH$2IN1X@Yg;($l;Y%6;pmHnv)%;G`hz&Rs@YIA9>J?R zpZNYx9J3WCP>&PLbl_N7IN@BJh>H`Iu-%6f6DdA}pRD@G3?ToHh zXIHJDWFBWXCHAPpDILODK83Sa4Nh4P&OS2RSG@8noc$_s_AkacpcSX03+F%yAJl@Q zOVgT;ZG=5VeZ$l&NrmD4eabE8&xlSFP-r?;rf zTXo!}?r(Q+?hvP2(Ei=IyBMdZ4d)&m_h#YTXX4!7g!8~4PTvyFL*hL=fU~k1M=z?J zfjpeYlzXBOXRsINN!2~AEvPvX3x z*ju$YZ-evBG|q&C-dn`^Kq4QO;(VNqGu4grX$8(_;^^vdK3C&kRN{QugEKRV^R-ia$>v6q7pndu9bYWnmN}A_%#yrxl;mYPzT75xh3cuCwY^`oAXKDBGFqXNp?+{~94#RE>LAJ2WjZF# z8;ZZFPh;FB`F118cce8@O7gu9lJAd@oXjHmp>#eLf2xb*rv}N-N=Qy;RQUM>$uDL} z>Q!0tYc(>fTyuuhS{0<$);y<=RA#*rQn|&XHs~ki$suJFkn(nr z@)waZn@I)cNQJsdg(VnKQB2&pMyHKba*9;Cl$1M3YNIhyd4r@jmELAUq&BZ5wWUR> zK)J0|TbNC1J85sPd6C8<@psUF|CQRYlGIK)!YHX?8SSk3E)w0fk5q|_c2g6(my_B9 zVVcx(ahGcqdk&D=ODJn2wRZ=pePpt4E2;8!Qu}GXzZP`BFsTD&d{7ywgBwUyPLMjJ zN>GD`){r`^B15VwOAzt!UQ+sYn>sRIkWuw4siQgVU zRjcs?%}NSQ7w3^`k$^6*)Fq>&E*0mp0aC54 zq%K#(S7?5vjM{2RUDZtLYT=rBQrBh+s<}R&REIM0SQt|T>7P3oCeQqT5~8dhw0p49U* zq+To{HPT7yWtY?|Eu==U9Z?=~$Ov>dj$N<7)2ha#HVzJE7cr6Qn+n{$xL? z55@nul+-6SsZW*rtb)|Ee*Z~*K1k||Nm5^qllsaa^|gv-CGu@MsqY3z&DD_lVV=}a zip_VE`gw-buO_L5DpJ2mHH;*o{*`fF;f55lKO9!^eW|~SF=cGjgwx( zA-!fV>9sVjQ$l)Oo&WUu)ucB-s1jyKZ`e=TqqxyR+B-nnubf#*Ixs~#*hV@eo>faa z+(kOlNIF_X+O8oTs~{cMm~cru4(Vhi>6AF>A=0j}Y?}1O7U{fJ(wmHs-gKUHCf_E# zc{S-RWK@ttdaDA`Tg#--Aib?jx0@whR7-ltEYig$>75nZrI&O`t}sD*H?3;-InsM9 zkzQUzdQWNX)j_&!l=R+;?ORB?TutsL&HdX+>j9RoQ2Zd5v>srYbmb!HLn}xh)=c_v znI2J3`bfo&8Y6vlfuK&0DG?S(*U0!-agUuKeVpRQD}MYu=~@|_fS{TarE`)g^pVzA zy7b9~q)(CAsab-!+Eb=at0jGUzM$WK(r2i%28o_oN%|~{^x4^h#2Z^lpQG5h!g-FM zSW`Xe^9zIp(z-O$8Pzqbrg@mOo_y(xRD01P>5Dr^x8#w&M7c{QNnfhQ^nN+rYLmWP z#+T2NzM_Tnl^GG*6l|L&eN`W6U90J9WY8|d_5sq@Hj=*15L9q|C+Utd(l->7zA;Bo z>?WCYs_terb4x$zTboFCwUNH9lJxE3-%%kfk?t1f&UVswm5{z$o;?U%TEIOWq*v6F zzPFroZxLy|fKK19p+`*8kJ_XM8c9D^P5Nv7O}{14@n+I*SCW25P3h%R`rQ%I6Ro7*6Zid6(jT~_ zC$oh)(jVmr8mBaVl1KVeji1hv{%l(3e|n7c7YckaM|!4~^j8x8dYJS#GMb$r{cRuV z?^;NIUrl#MuU8@dv?N;1%dU12a zSr0+u`m?wjWZ`aDgX?L+)jK5DJB;g7&aYe`2RE3F8!E!JRAbHKMl_Es;o7CRu@c-& zycjppkLxIyas`px0^DUL?naHc8#m+TNqm!X+)Z0>H*3e;ybN~>iEgRm0vT?dkGo9+ zZs8Q}cJsJJGTxyIcgIfLVjb&|?(U-6UF&g6dT@8^#oc`fcMtvk7}FP-jfD!fBQ-7UCxj^f@e)1D68 zdlqn42)(tq_f6tHVB_}9;Xc%j+pnhjCvaEJ<36&8`{)erV+FX6tFb4<*Cy9}vIF-i zafWhnpHXe*S^e=`EADU~?(@^QFSg;1i12b2?kif|s}AmK5*P#bjXB&ms|E4iQq8zl zF+PU-c0cYry}0j6d_wv6RP%n0Fo^p>8}4L1?uV{0h5M24u^OLJ{F6GJ|4*}VKb^<@ zYyfv!#Lv5NzbMB2Qt>aBaA&lNuexx*miRX{xU*%r-dE_i~GX}?vG=* zKS_9ACO>!L{?dy3t2Ff+lKY$Hzc=Il(Sy6F2L6=i-#I$}e`~U&psq>xUkUuz&9YS- zmaSUCvegP$mSwVR^=x5*Wou@!EL*v?6kA)lwdYy3&J4@et!LSKV=P-=^9?MPZJ5V0 zk4B@KW!gMtIm_%`mc=EWsAQQl!2im67l5d$ zHEj6VGu#>O!~G(6n7#MR?3umyfXW?IR8&+{QZ!Rayd{AJ$%Lz3=nBYp=c5de@p^v}Ce8s|uFv zPFTcjSR|%$5iC~1Mj3k@EJ`yhjzh3;>9(k+V9}Ea=3T7Mq4AsnSaNG&nNHamyI`5w z21_36^BZ9)U|C@dEbgKjSc+Re1j~gWMqt@71j|L_zqkjMOFCg`VA;;Yuv~fsmdm=`urxArc^@oS zFx^GMT{Lzjm9Ap`>V8<724T6T29`aQur!;AF5Mp$m8Y&&^6Xy-Ow-`)+&9fx4q&;6g}&cm?WMZ&u&&^ZdrJx5`= zmqxg&wR8=`@<2H(4_3p{y#6a}pH#x~SuQNYbnFY> zkuRHIIdL48uW93(Bd~m%4$F5ZU>W85Z~2~tKX$?LlLE`nJ+S=3R-7b$-4DxeeX#t_ zvQxbNgK~ckz%ov!CaPia5T|!R1i`&sfXx$45EKE#K218C`3~$#Gpoq z!DeCvV#q;=p{xtbc0&yJBgP;`P|4f{F|re4R0G6l62v4x{q z5R-Z!P9te@9mJFhhzz~OG|HrF5Hn2)lbNM1=&7 z4v0>AsWR10LUaLQPCCR~DsudaGa4c0`4Qs~3rJc>V?~rNJ_5016k_QB#Il1BXEB{U z2yxB{h;u_B&hvsezX4)J6T}59Uw8^)CG{7VL0nP`(Y^E##Hu!k9Jk_fR<59dvtl5w z+yQabafmfT5ZBO|vq`d+#@5LY*H=QUJqGbSGsF#D5I54$rgDgzTOn>uhIoDpL=Hu9 zdo#ofdLVKbiWiw6Ud+Zekmu5Dh?gCPcsc+6OT2VkMb z3Gb)Q1BW3#*b1?`6XHXa5Fe(|17>0b;z5=@QUvi)>OFcK;$uS)4^j5<9T1;LC&=}r z`v}Ay3O>~a@#!Xry{zop1@Rdf;B_11x_%Vt9RSofY9z>37k#E0RP){)G(jOAX=)%74YWuWKQG z!@7}Hh~LuScSR8Y-3f7&+}|_(VG!aN?fpdApF`RIzc6z$6ymRC5Pu`l@64ZKyHz0j%fJESV@9 z)B}kTv&7|D3M+>cUI{6p6_UBr4JncW(Ikpl3n{h@QoJ9e1d=9pK}w=RGOttmAf*mK zN>7HAL9)!lkg`J|Sx6)vg~SM1vJ$pkkd!t^jE*IhdK#U`F+<9wBQwawQ!lB2a)sn6 zN+;aikcu^e6(v+Cm5Jk!%9h)t!*sXYGfyvLDi_AxJe_ zAgx{tX${k}b0MuY6ZCqWi8u~vJ)Ny>fOM`#j6gb%#2b1b)lqljVMv?0AZ@0RE%lJL z?t*lF1*C1Ykm{2mZTBOnbHO;I3yB@WkS_LuTe|oJqy~Dllf;)cLAvY^q{c=_msdi% zf<*2-NV{n8$`(jhwL-eO6H?Ovq}?=p4IOA^-QFTd+)hi^QMZM4`&f1Z^;;E4H?D=m zc|p4QAf#KeA>GP+`%y@@@%r{6_WvCxAl=yp=`I%BH3sQ!3U>BEx`()TKcxGJu6juK z*FbuJ>4SBUx=Hv@7o>-qAswJY2U{UMLOe?H$23TXLLoiw2k8kfNKX z45^QD&vZa~);$R6xgJQ*v*HEbt{1mJ>TiMc63bsc0%?HduTq&iW9jvykOqe#z1axq ztp-R#yCA(ynRfx{2<6@*-e=th)IHh*>BBro|D+suz|u!2A^pn)>39O9Pud`TM!C=F znEQ)bNGHsY7-CD`uwaCqeR~|zcO#HS`yu^M4(UgdjL{IoY3Uc%{YshN#vq+4gTyde z`b&W{Q3c6!6f#;M8$ux)PeS(YhU}veEcZPK*>4wQ|4zsOW}**rAU}U2n~ER@HA4=L zfgECj9Lh9|1Yx6)!v`Qou+H2DIg$iXOt~z}F=dcrNfJ8*Iqn4Hc%}@e<-``qNn0Ru zS(dph%PAUh3UcZQGDG*Tq*KLgLo#~^Q`Qa#DG(iX;r`#RH{(i`Ju_br!g4{`td)gr1OWbz^a@TRl_m4q- zFc)$+4LwBT2Y7vua*r_oXg6do$MWOc|H)5OL4J}R^|U}{*epLy#XfrZ4DoCzWQNW1 z;ZDfU)A$P{e(?n4mst05E#y}YK^|ZkcgynYm5>J;A-{1L@|(kuhms+`Ekk~X++1?y zBWoeQ*8%x`)*aO#|Dzi6hn)XqF17MUH1shAj{`DKsN_%S)Mx#WhsPm*(FFO+{g6)_ zg#5J$@;AwlM`|E{I|TVV){n+O{=OXY54#|b@tTpe{PQs6li84erTlL!`@J6WDeC`8 zJAdUu=7v|EpsxFLBdq9wRTzWSxC>UVHdwufVD;^W)xQSTfKFJsj9N{nU=8+zl|$6Z zA!-fV0&935tPw|GHTT0Bc^KBHld#4puyPf(#_^h~s5S8*tkbBMTn%eVJ*=t2u%?&8 znnAmn{Qg&K76~j}uu7q@$`r76z-l`NtC9z+gT|dy&=gqp9#~yRVa)}s)9J(v*5{dF zztFYa>caHqw)D|urBa|bzv>6i~3<*oDA!d1~;rr zX?&RmE2Cd)bp@x zw>H4KEgRPD>9AhV2kQ>%T(k?;iz$D}D6BgNV7;sh)<*JNQ3k7LG*Lx_mmxiwMg0+RpT+OUE(EA&6VZDj+ZF#WX(g|yOGOQgtV7;B`9W=O~M(#QY zYbVL?q27Iz?;_U&CRiV=fVKNLtPfNE0OcMjg7wiJI`J4YkCXgKGps!gus#h~d;4L1 zrV-ZXnqYmt64n>k+J5F=qQWc853v5V7+7CtJpLL4C}iGVP#-xeZLvj zqs)KU0_#6d!TJ%M{+K++t6}}*B&?tH!TLEr|8M=$1nY@TSih$5H{Gyub7=jJN~6qw z-vR3n1F(+e!uqoxtiR9!E!15!9j7r*7i_43O&EdAm<^j(9cTM@u7Pb0_0Oj4*{5K0pOXyR zI$}K)YtvynmxSk0V8edc>RMsjSOME65^a`Y+rpM^HNkd1%eGa*R!_s*t6{r<`3sru zVE&>y*e*T<+a+{(ryp#W=E8Ov9ld-lY*)0<;BnZl%!chMmS4@!f7qHxw3}XC(+%66 z5!jkZ)Z7KzUXtw{hK+HZ?K&E0Az8~HY}YftkIMT_!FI!8*jjnr%Ih0x^d^m<4EKMw zwg%X4*#XRT_JZEqHwpw!wbb-k{E#U9i110NW5r-|mC$ohI1crOc7zu)Rl}_lXaPe^kNt zp$ywUD_}cDJ@-d6@UH~ej;F)+NgZsTHo!LQ2OIZxwl7HfC7t_9fsOk*+X&Nd+hF@Q zWk*T={V~{n=!WgbQ?UI+`JYa}_A?#&r4zQ3<*@xqL%)v0_8aSeKMLEa4%q&n+@E={ z{l&V!#@PSkW3X{wXY0_{C40hoZ>_$J>xft2KkHGFT0K4B7*!}xq4@`#LbO`pK zao9uZU=O8CSQ+f$3c>n_YS_(Hutyfb9wieeVUIovdrULzj2G>3ekiiTwPh zogWsmCnpdzn#wdS2KICfcCJwNOcH02IGf6rTG&MzlnA*Jb}J3p=!l(q3JD#DVRzC2 zEfjX0@{AMhIU}%7=k*Mxc~!9I_rYG64tr4@>?MA%mvRxXmvzHF+Y9zNtei`sd9AQl z(DMa@urDfteQ`PLOGs8lkC)SlY6bR{*|66zt)bD?)L9cljKjXx4Es66x;)s|6ScXp zpG%!{S$7^$S3!_>qXzpX!o8W^Y~jV$4%p96CXT|s?HKI!!?153fc=7#uwTfs9Ye5R zbO`o~J7K@18}^3%u{rlPcOC4zsB`5J*smgZjAL&afqgf* z_LvBk?G1(fTAu&guOnd#aeX7~`?kP-!+zLX`(eLv5cZoX)TY6HOFitj_Q2jjL$}GW z-`)!Q9hBKmr|uks{q9QGJ8AqL@^IC&cd-Evgu?zH`MSyX5V;Oe_mL{tAElkgPQm_o z6YNjcvj3k-fc@!Ru=nM`{;Uc1=O}!*4)*7%{6ZV-FH(@71G2x=4g1S9{K_HN2Wa3m z%Dyhc&X~{s2Fu=xfqke9_P1MLe`gr>BXs6HKZ5D|1F#=0hy5R2uz#3MjKcm;${geR zZ~y2p>>rQ8ew+lKkn~d$e8%g~j>107R)1ax`xjLDf=0h2*@+t1zp8-!YX$aiLWz^G zkBq?n?I7&m9f$qjCtx2X=l9*P|Ii2fk92NqKkPp-{h8dq(20{Q|FxN2^&5$PPasag z{)ZWMeuBaNR}JjrET3qEox{?8`Y05PLot}37;~X`5#AaUpDHN6bx{1Oq4+Zmpqwck zN>DPC;5;ZH*-%0$6UO@RCMXd-P$CncL{T=n6-o@h|3!&C2qmr$N`ed}k-|wkpd@=i zNhyMoS`H4R*jewOEMrB5+cZTVfa2N$K`Bm#Qo{I8DN~@#BGH^JQ0B659*HaVLs>||MMt14E`qYO z63Q|vu1JScT>)h!Wmi$Q#tdaOon1}+HA7I&ZiKS76UsRUp{%QivYxWF)IC>$a-Ixj z1NAo?hf;SG%EnPBo7}@twp2mcN@E;;$~L0D2+DR6UqF%zo1pC24~5$=*-Pr}@ZYp=yLAj?9 z%Dt4ik7Zp$Q0^av@&M%@JPG9?KzW#42b!Q9WcNP8`bWp0JWkywTA=i7f%3GO{ohN4 zzCkF@Q0cjPD2KA~LV1}&FSGoWVJNRE1Y7YM`*V;aZ)i~7tcLOy4ZQ6I<()Pt z@76*&vIEL{bng9KP(J8@a`Z5i52^dlTqwsV|4}8BkLkd_jzBqng8l!=DJY+nK^dm8 z&ksTQVgSmQV^B`eiLaRQR74qJ`M1pfo2?r4gYta^lpko|$37@y$D#aO1cj@fa*{H? z(fIGJP)@N?e;k4GS2~n&a!;_#GXe)>ID{%V42R$_x=+I4-3^D&ARK-sIQ;j+5zq%m z;1M{2C>T5n2ZxX&tQn5*Q*fAfz!5nBM|3hAF^zD<4#N?j07pUx9Es$bRu2akGDm6~ z9O>lC=z=4YT-l*;SjZ(&UuK|=nI980naTd8( zX>c$Ab*!PiwSI7%(+9`;dbl0u*1@rX1agVwmdlMS-zbP zTu=|kgIKJ*jd0v-Cc5EhtAOK{GB|D}aXX#tNQdLLJUDJA zA-7wO{Up0{6pp*I;pl9Fn-XIt52B1^ejvvsG|B*9OPo6L9cc(DC9CI9^%{$14eNyb3s8 zBl+u;d!r1FHxI!vR1U}6G>)WaE>4ri1XoY5MbF%@veHp0oZ!I@x!GjT1PNkedQZE&VgHkIXRV{m3v z!sh04&Y|&g%FJzobG{#(6}fOOXn}K4C7hKFa4uo} zQl?eZS)Ksr3UXCb_pC8ESB1h^lMUx;+B=)NYpHvV`!JmAWjJeh!FgUCoErw<+{knj z(=9CDdI-*K6s{-H_8~YKjyZW8=e#%_&P#T{*+98V%iz4M6VA&uIIkd&n+EyRJFhwh zXOkD4yKCXRrW?*?Uhk#uwWr{0Vg2<7DZ7t^tvztwq`=9i-g(PfINQ_V?AQz~=qQ|rSpWD4oKKRk zhg^KPoxQy7I|1jjt#BSLg7f)K_Wz53v!7nQbR5oCV&EL8g!8ooIA8CB^Nl(<-(vj` z4ZM8}&UdTee6I%156a*?dKAtNx4_B61?NXyaQ@2+&g10xl=Z_VI6v=)^UH&9ezgnE zZ_42u8G!TOEFW!z^9RcQ*aYWKT>qWFFvF+W`P*7Je?J80A58ybI^F`OhXzj%Llugk z8pfb{?T6|;4%N36s((GyKpCp(FjO91t07Fo{h&s)L5<9V8l4U`hGlU~s41vR@5s(1vd+ym8ShRO|v>a2mPW<%A=pz3R(x@a(`1!`^u)ak67 zQ3Z8oBh);S=99eODAXbvFQ$A+E!5IMsI!=#O^!L#DW~k*gHY#dP%Bu!fI170L3LNM za`AqsOU9vA$xxS(csU(fF$DE260A&yx~c|h4Gpc{1$9j~)U&C`a|3lo38>r4pg|-{1FYT|1NE*tsCOTOdJnJf<@J3hq2AB;f7Ay$pmv*}KE%R@4?{gj zB}OaiV}4K%RY84x4C<44Q27+APw~3925KM4pH-kf*9!IUIMf$vp}yD&^(E@Qd>HBg zIbS^m_4N}_xjk3kBG(X|dYjI?+XVH!gHZVpt4G~5^x;~l$C&x(IMjbNK>dXIPme+! zPJsG3$-bf?s)fd|T(gxyvmb@Vuv~MJPi=vw zk<;Y|jWLFnI|6M6*MDs$h4W3&3Ywu6F)i+dR!SpfRN$1WF)Y{0Ni?q#+WanP3lwMz zhoDtbZb>e*s&r_}Nw$JcRkMC2>sRfEwpxa^W)Rw1I(E)5wDsgUSA%xm321f9Z>oZ} zx!MhFOCPkY6grbZhFR|j4Y-j_Ap}j^AIqhnL z6ns;L_7>~jrqDZ0(2mgXdyUXOpd&|zpncc|?HCPzd=%Po8u_FZ+NZ>4`=Jf9?(-IC zUvxk_;Ro$21=`olkI>GyZy1MOR|9<` z$v2h}6xc|mjYGsq=$jG-%9=S zc~{OqOwh?~yxw*Udc7af1ARNsfA#G&zP*V!M6mJ#5?(-}3(EuSzG#!|l0#)p6)oljCYPNv`f7#-TT{psA6d6T3|W9pmb!??G-55$Nig3ULom-7PQQ`YH`Ws5xrq+l z#PXZEi6hW&29ZZJu>Wr+`ORa{+vrtWB|-AGLFl)bi2cxSttJ|XHewihJM-;b&^sv4 zcfa(GL&PZb+bW1Ag1Wbd5=BG{L7hA52pZo{o&DtD)=j^&is0Y>>WpmlyJ@tu5&AtE zK?C>Dz&$6R-%C&L%_UfOFAd$xvisH&G<07dF#?_YJ-w@(*iW#mYYh7REW4iu?r$az zLw~@FkcoQYAaMlxg9_p11%nU0n}iRA5)^ufWDjj2T8Mt)B=m5<`2>K&TA2|s9Q5t@%?>hgyhZ?ElAE@OTX|0{w{w zqLZM~lOS@59RwA7Vu&NqpJMq_3eiK*v8VHhdZG_{FY9`%2s+Zsx;~BAMGO(lKO+;J z(4Qsmv&=s?+5d-=p&vd5{duM>F!UGOp!a7JEPsi{U#^7yN(?aueV`Hgt9{U4 zYlZ$g9e=%np#1AJ`uYHI0{WmAL9W3vqLyePx`+XS4SmBzC7074uW-WvhGdRF^<#U$|dTE4q}jCONK}`L}!LrHpH^GDff06K_|H_*Walo znuuf2-z_IjK|fMQxJRMCM?>$?(0kp)5cK!y-TN$ipRIbI${(Z?6$E8I=p(3nG=|6} zwh*1fATb90AC&zEW&hDYbV2`+G9Mm+{!f{p1OGe<{a7|ZosY=j{^$_&kIM-f`d0_^ z<0Lpvp--58vLE`VAX*95e^yBhKp$R9bV2_-lxTteg+d&H{$({mM@}$3L5{B)h*9WY zHxtzR#*3&Y`k*rw&_^cwe}n?xQs7&r-%;q_wFH$%Y2r&(`WU_c ziS<8qLI0UDKes{uC7n11{bUF9UlWKP=)cj}?=eIx^iz~O#RmOB!++4(KUw}~6Z`+q zG3b945i~GfMv!zOl-LE`L!#3r;t*U2CCZ5wVi+!=hUg~7;4-8W)kFtz3@)P|kxQ`N zD}kVnH)Xu*i4$=7$V4aM9)Zi3M7~YL5xD#)?AJz+)PD!j2Uh?U0~(2OxB|zHPLRhPPJ`iV2?|CO5mbuc zwOJ$Rl=&1~kt~ZGg)6ERu4ocPGao$!R}6JyXgr2QF?24Lq&%{5#U3P%!xcv-<0^<| zf`;S$2=c~LhdW|dJm3FwC9oiYgb6)xC6X|a!ijVsaTKm3DkRZhQX6p?u4$~F)(2NI z9ZO*gc@E@C*-wx>m9nYn1RIfBLo^UHk~#!ennI8xjlAi+PCrBp!m3nj>Hqn^#(&tDX@XA_mg7NU({x&1hC3ND3CDU{(>%H`;T%gI(c>xeP9R1&GR zL>F<4pqxghw1aTzW`epp%UlX^h!}?}hdenuh#t5~a!8U(lH7V?h!}xudKuA7jKVd8 z*E4E~T?8GPN#&WtaODlamG4Ki?I~JnB)ocymU_D#?boGyWe57E<@{DVZ?4hs`|s`7 zE;lB+?S?>nVl==AM5xhe_S$*#SP8xi{P=#LaNSg$FCb8r|5V|+xoc|s*VL9ya{Nw7 z14=2^^>xDY#emvvW8bV{_3 zFMsSpv@0jg$2TiY&vNDHQ)O8hKE9EzoXo78sL9F*B04KFCo0Rwmx?~#6q=Mx(bIgH zMny+O`$ncks*&Ej_RY-E-D%{>Nuj=vkRvo%#iy7BBZp88ToTJPEPB{(`}eSVs6uJDHkD zDjR+L&rX`{ZJcXaQegC(nQsh?PWBI9wmGP1e);sm@Sv#N#L!gdf`pBN;2BRYu*%uj zUg%EEXn9*NOA~G=$VjeBnSE(qR%)@~Y)@lAj=|THxALygK-XDma!Ro|IKdDX9pP1) zA@a^IO}imKz}s-P{jZFyw&WCX=F1A|fSHox1ZW0-y3U-ue_>jZEQ_p5o)15@rrIq-N<+PFKFb zvM?WEwlL_)6$Y0~Y!nK7SXLP(U>KiN1-FQw}kSDid z)<=sL?VX=FUntp`o)wyu=xHt7(Bd4ZtsQV?r+dziPcr)$i@bco@^2B&pRwm)b#U*& z>X3&*m-%yWZ#90zhv{rSI=eZUU5^`a3vNR}I5%qy*sV>X05lh2;u%9*6|RU zDXsR$Q?gZe^4A<+iw%ZY-=NP8yA5W8At88XXlSZ$RBDhh#V2m1Wxc=sZu!=%U7Heu zJ~9Y~#BIIAGzj11hef7(ZVL^VF)c0N&vh}Dd@ZH0 zWYI<9d1Yzl$jIrD2^$_YCub!`8WPXny7jTGTen8Lg941D$rg*rH^~?p?Gt8rX0Eq6 zaD%}Z=o?}7JQLv4WvE&b5)u|5B!xJp8JyGV$(uuZlQ)Mxw=**M^n=D< zj4Hp_K9hf!X5*>r3>38oPY+6Hf4eO;B2-8TOY!Eo&T^d@tL+QE4vlg5M+W9(Wcqn` zWk=NT%SCnD>V4MBmSku6$0ys0vg@9TOVSG$M+=XB^Nr`2u*q|)=iO2s`B=<(4#Lz^lNQFGsYi!ni0eYCZ&rFnlE9}aQa!VT z@NrCu%%HHU`xx6l|0Il0qY!3t-?`y+%XizdOQQDuA^-C#&#RwKlY(L$3BqlH7%e1U zdc%^~%_&)&sgg7yWMY1LLd2c!g;UK<5(7hX{Nh%6K3``jaL!Mkk?OID>vGlUp87od zV%I{0^I})-th+tG2?6&n$tiZ1WKWAQ6#Khoq{c)AZI89(PEJNCVp7T7DPs7h08auN z{Sv2w>CV{Y!n!Agk7!gGLwU6aH}$_XOu* z3$8^g=lEz<_cgP9MrWbm($Cxu7hBI>=d?08sc=q7ntihhgvp7;%n7DYphPeS ztR$pz;I=2dp~iaWP%-n?pTkn!XI9+83>Sc>2K3^sk$u&ZxuW#6sv!Y`By}fqy6KTXaMm|h#{_!? z_!v!rp;39J3)^FV2{ZWwr*5cEJiqtwzOd;tm8Xoa8xy7`^gx6mn*Xg*8VXQ`d8ov4 z?7*dbEcLX==t(ec@orCWF5uM1j+uIxr!J#2 zBF#x&GXpBx@-nE1r7><9OUd#95> z!Tu2u$)T2Oa(oQNxn8CKbLypKjk$?|rb`R$t8gc;JbPVZucM;aAA_invs0sjqWl6(G3on+C(d)$_-Ub4#o{7H+qcC)$fwJz5?9py9q{T1cS(j8I2ZcX(FiQ=VT_g~WvEC4#X2 z4bL|T6%|)Wkwu=-V(X>rmsL3Ct=w7cD!AZmN6D%s*i#l9(_0oCyKU59%4~n?&)BM< z+171g=j4^ttO`E+teL%0f5qP2kYYj%=;ob=34XR?ae=ei*ZMcXJ=WblrUioEA zv^&!Gf1~TPDBi7{$TQ*hnMg2fD&qV9hJ#aa{N&@v34#;L{~N{sy}X>!&zTAZCl~tv zjnQLtTSR_{pu1%zbBlun!>Ym=n&IK)@!^}7CEfMWvbwo3**p6@KX?a5M}7B6V9ePU z`TLx*8vOj%Ce86SR@-VMA=J<7CSyQka?J60bI%Ehot_ja#x38vGVOA2Z-eJVQkg2+ z_FrR9z2o2ci?W4*g7EN^^HUe?os8EF;hBXC66Od=S?;{@gwlzhpD+c)MBaNq6MUEN z4GvOQWr-=pg>kVlrCAKm4NKB)DDVjoiW%ew`rD7k=9*^tg}wOHxzU23uXlE&(QA?K zcWGf=3E5ex_Plv(CRSyuS9|*ir8CoWUAdhpro_uH79I9$vDja9u%u;nw=RLbY;Mt>?R@t#@Y4&e-VC zb;qXk*;#jPZCQS9+@>0@?8_&s^5ASC*z34zd^b4Q+xAT2MgIA|2tM6we9lt-#fweMQghP0xhZV#Oi4t~q{O=Edit4(h~aTmh=Ie&7~H;Q*Ru-?qp!`+Os$IC+*E&5 zHhTHQsI!Cs&;5uxF}K;W<5Pm_cMBVWoHzhn>%CHH9wAAzc4Ph_@ZJtK~9Lysh_x@ z+gW=zO)xLYw7K+ ziLPMxWtSS?g87SzPJ%LV7OxMfws%1bUe;P34U zleL(T`*TW4a*B&<+=6i5Q<;Xa@I?teIi_HPXSuiVZ(eR2r3> z-XNU6X3d*Ur{{F$HF+z1XLyOOEy5kHLjKH}bx~pAMTMRRQ`DlE8OiZE`Qf=@?DT@* z+}>@z>5We$C!X%(U7R^}7bO(^-yPrNFy({Y{@97Y1a}1Qz|?J;8qt%(nE{vJ5{5m= z!tg{!(v#Ic3bC;f6~W;K?}>jz#TvqV<82Gh7tWg-Sg>)O zGNUr9yr{-qV%vB2l9c?+bN0p-g?X;Zu`hK=Nm)VRf?;`tSLmh>HcW1)NUiw^^e0m3i1etpVCr?5y$Cd4s_n7kA=iHGU={31CXg^(*7VFN+)F-zOQ$6A1 ztEVvdO3}v((x=^V$1BwauXuy+B?FH1!=~lIZIZ0hhWym`odz(o?lF1*}Y|60oK$xGm;aM z{UZe93g3Y8-Ua63Z9y^9{mmA+bQ4Ktd!FIRnCiP+Fq|WJ&7Pj>RHcOVf2xzOJ)UV6 zLhSWSlfJpTG6+$pyNvf6#s3cYXimnJ>$tJlg!9h~cKys?kDN@6k$i-S$?11; z<8Wq*o(yHx_8Yt7;@mtR$~qI<@-$;INK=Jy@5K1TWUr+7ETweu|Gmz1W~$lm z$Aky|ohHoxMtwk%s$H&ylC(&Y_U7d5Nq$KpWWw5;{F3dq_^m#OWB55{%;T+#Mg_yq zD$bDLjw&T1h0QmsQ}HFEBnFsiKGA6rljk5)ds9ATQ+rZAa8q|Jg2y9V<9Md>-}8?t zQCHaHZA*)EWwhV;s4dDJmL~k_d0Lp~`A&!w)_R#tCdEG}HnYePnfj{nO2P2LZL#rb zt~9?o@97z}rQsp>e0rzx`M4A>FCpMt`%_9!ZrR%zfq_qJqksBkrZ1SDEqpdH&AB8a ziBHKBY0i`q?oKYO&h5w-u8gW`wj`&gD@jplg0R}MWKdY)7has77^Y_EzDA3d7Zscz z=XoeBSc@sxwai*`-H_%o810W2ScO~SR-7yTQ@pb=HGN0TU8b2{L2;$2^0_N7ymS2X zJ!7BP2s@z=4#L?x_KEt-tVHqjQ^v!_pueBP|Lmy>r?&ZMA37FPSaoKjloK(vJ2F&H z?tQrXx#xd&KP#tpKg*_eKU@E^`|%4gOnhLdo%o6`A!1_n|L%S^weR^TC}rArdc1#$ zUvQLkyFn^mmv>&?M!)B8lG>gSe3Y%L?X`Q}P1kzgP1iqm&GSR{>HCc@8E0d1QjA0_ zw|*)7?&&7r%w{9Xd$OCOIX80m#=V=7114*-8~;uPeR8;PP_$opIxE6G+2NBXU;jD& z;_h(jz-%h!nF?+ucZJg?&(eaq`4c!xai5;WnET9f!3oSGMQ%06$cA7;Y?yqzU&Ush{T|5vjjoOWAG@j|a9 z?u5wM;n9MrDl9TFDJXPCY($LFJ3BgWVX1kB*Om>|NSm^(A%1OX$*k1G3v zPd3`_P8YH~A5FqzFs9^0Mdg&UKaD#tAJ`XTc!t@WErw?Yc>WN43^TKmr`h8Z z4C~fYUP&2X`M&TeUcF!)&2~rw!$yGv|fQE?gVKk!p&6$dDmBee4#`OSuJ_<&)mS|8i{z zOqLmw_w!^dp6^O!@NCS^L(nrz*<|F3i1x6Bjmq>3ds!$ngzei`;yHCgbkK!D zoKPtQu3Bnnn(1Too;$}-5N3)}g;-&>H6%E`C}p;jT> zm**?a%|?E!REYRk~JKtXE$cV>gz1sYN@=W|`-eh8jfK6~^spX`Fm4|Guk&@A0RmrzAe{s+OD_uqZRZW}7+9H!skZ5?$u77dx_J zV`tR5)RZ*7qnML3U5ty2y42zo65tgaA8O4A^Y`^H;oAwT_(ra2RZ@|EfZ>8P(@g)Y zq+jb(!)&4EOy7`0UL1|9J@<_Yg7Blsojc8tC-AJ@JI`R)l)u|MJfJo|Fe#u={P5ak zYWX~$jjIB}l||bM5`_*&T6FXGA<2GgDz7-;nK)I{pcUus4Ngzb5N6Dtd39t$a%TPm zR&nqA&0Yltz3jq*1?KssVTKIV5f&8T6CUsBbLIawdv@M}1s)}O{!-JzC9(4s8$v4f zIDd2zIlaywbI*Pt+{Nb=%g?>w!j0R`Pj=cAr)$rBw@fEy^xk*N% Date: Sat, 30 Jun 2012 22:01:48 +0200 Subject: [PATCH 109/349] Import qrencode-3.3.0 source to be used for QR encoding in KDL. --- .../kernel/debugger/qrencode/bitstream.c | 238 +++ .../kernel/debugger/qrencode/bitstream.h | 38 + src/add-ons/kernel/debugger/qrencode/config.h | 5 + src/add-ons/kernel/debugger/qrencode/mask.c | 330 ++++ src/add-ons/kernel/debugger/qrencode/mask.h | 37 + src/add-ons/kernel/debugger/qrencode/mmask.c | 177 ++ src/add-ons/kernel/debugger/qrencode/mmask.h | 34 + .../kernel/debugger/qrencode/mqrspec.c | 280 +++ .../kernel/debugger/qrencode/mqrspec.h | 157 ++ .../kernel/debugger/qrencode/qrencode.c | 929 +++++++++ .../kernel/debugger/qrencode/qrencode.h | 565 ++++++ .../kernel/debugger/qrencode/qrencode_inner.h | 88 + .../kernel/debugger/qrencode/qrinput.c | 1724 +++++++++++++++++ .../kernel/debugger/qrencode/qrinput.h | 123 ++ src/add-ons/kernel/debugger/qrencode/qrspec.c | 562 ++++++ src/add-ons/kernel/debugger/qrencode/qrspec.h | 181 ++ src/add-ons/kernel/debugger/qrencode/rscode.c | 327 ++++ src/add-ons/kernel/debugger/qrencode/rscode.h | 41 + src/add-ons/kernel/debugger/qrencode/split.c | 311 +++ src/add-ons/kernel/debugger/qrencode/split.h | 47 + 20 files changed, 6194 insertions(+) create mode 100644 src/add-ons/kernel/debugger/qrencode/bitstream.c create mode 100644 src/add-ons/kernel/debugger/qrencode/bitstream.h create mode 100644 src/add-ons/kernel/debugger/qrencode/config.h create mode 100644 src/add-ons/kernel/debugger/qrencode/mask.c create mode 100644 src/add-ons/kernel/debugger/qrencode/mask.h create mode 100644 src/add-ons/kernel/debugger/qrencode/mmask.c create mode 100644 src/add-ons/kernel/debugger/qrencode/mmask.h create mode 100644 src/add-ons/kernel/debugger/qrencode/mqrspec.c create mode 100644 src/add-ons/kernel/debugger/qrencode/mqrspec.h create mode 100644 src/add-ons/kernel/debugger/qrencode/qrencode.c create mode 100644 src/add-ons/kernel/debugger/qrencode/qrencode.h create mode 100644 src/add-ons/kernel/debugger/qrencode/qrencode_inner.h create mode 100644 src/add-ons/kernel/debugger/qrencode/qrinput.c create mode 100644 src/add-ons/kernel/debugger/qrencode/qrinput.h create mode 100644 src/add-ons/kernel/debugger/qrencode/qrspec.c create mode 100644 src/add-ons/kernel/debugger/qrencode/qrspec.h create mode 100644 src/add-ons/kernel/debugger/qrencode/rscode.c create mode 100644 src/add-ons/kernel/debugger/qrencode/rscode.h create mode 100644 src/add-ons/kernel/debugger/qrencode/split.c create mode 100644 src/add-ons/kernel/debugger/qrencode/split.h diff --git a/src/add-ons/kernel/debugger/qrencode/bitstream.c b/src/add-ons/kernel/debugger/qrencode/bitstream.c new file mode 100644 index 0000000000..a0b9283cb0 --- /dev/null +++ b/src/add-ons/kernel/debugger/qrencode/bitstream.c @@ -0,0 +1,238 @@ +/* + * qrencode - QR Code encoder + * + * Binary sequence class. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include + +#include "bitstream.h" + +BitStream *BitStream_new(void) +{ + BitStream *bstream; + + bstream = (BitStream *)malloc(sizeof(BitStream)); + if(bstream == NULL) return NULL; + + bstream->length = 0; + bstream->data = NULL; + + return bstream; +} + +static int BitStream_allocate(BitStream *bstream, int length) +{ + unsigned char *data; + + if(bstream == NULL) { + return -1; + } + + data = (unsigned char *)malloc(length); + if(data == NULL) { + return -1; + } + + if(bstream->data) { + free(bstream->data); + } + bstream->length = length; + bstream->data = data; + + return 0; +} + +static BitStream *BitStream_newFromNum(int bits, unsigned int num) +{ + unsigned int mask; + int i; + unsigned char *p; + BitStream *bstream; + + bstream = BitStream_new(); + if(bstream == NULL) return NULL; + + if(BitStream_allocate(bstream, bits)) { + BitStream_free(bstream); + return NULL; + } + + p = bstream->data; + mask = 1 << (bits - 1); + for(i=0; i> 1; + } + + return bstream; +} + +static BitStream *BitStream_newFromBytes(int size, unsigned char *data) +{ + unsigned char mask; + int i, j; + unsigned char *p; + BitStream *bstream; + + bstream = BitStream_new(); + if(bstream == NULL) return NULL; + + if(BitStream_allocate(bstream, size * 8)) { + BitStream_free(bstream); + return NULL; + } + + p = bstream->data; + for(i=0; i> 1; + } + } + + return bstream; +} + +int BitStream_append(BitStream *bstream, BitStream *arg) +{ + unsigned char *data; + + if(arg == NULL) { + return -1; + } + if(arg->length == 0) { + return 0; + } + if(bstream->length == 0) { + if(BitStream_allocate(bstream, arg->length)) { + return -1; + } + memcpy(bstream->data, arg->data, arg->length); + return 0; + } + + data = (unsigned char *)malloc(bstream->length + arg->length); + if(data == NULL) { + return -1; + } + memcpy(data, bstream->data, bstream->length); + memcpy(data + bstream->length, arg->data, arg->length); + + free(bstream->data); + bstream->length += arg->length; + bstream->data = data; + + return 0; +} + +int BitStream_appendNum(BitStream *bstream, int bits, unsigned int num) +{ + BitStream *b; + int ret; + + if(bits == 0) return 0; + + b = BitStream_newFromNum(bits, num); + if(b == NULL) return -1; + + ret = BitStream_append(bstream, b); + BitStream_free(b); + + return ret; +} + +int BitStream_appendBytes(BitStream *bstream, int size, unsigned char *data) +{ + BitStream *b; + int ret; + + if(size == 0) return 0; + + b = BitStream_newFromBytes(size, data); + if(b == NULL) return -1; + + ret = BitStream_append(bstream, b); + BitStream_free(b); + + return ret; +} + +unsigned char *BitStream_toByte(BitStream *bstream) +{ + int i, j, size, bytes; + unsigned char *data, v; + unsigned char *p; + + size = BitStream_size(bstream); + if(size == 0) { + return NULL; + } + data = (unsigned char *)malloc((size + 7) / 8); + if(data == NULL) { + return NULL; + } + + bytes = size / 8; + + p = bstream->data; + for(i=0; idata); + free(bstream); + } +} diff --git a/src/add-ons/kernel/debugger/qrencode/bitstream.h b/src/add-ons/kernel/debugger/qrencode/bitstream.h new file mode 100644 index 0000000000..ffe743c5e0 --- /dev/null +++ b/src/add-ons/kernel/debugger/qrencode/bitstream.h @@ -0,0 +1,38 @@ +/* + * qrencode - QR Code encoder + * + * Binary sequence class. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __BITSTREAM_H__ +#define __BITSTREAM_H__ + +typedef struct { + int length; + unsigned char *data; +} BitStream; + +extern BitStream *BitStream_new(void); +extern int BitStream_append(BitStream *bstream, BitStream *arg); +extern int BitStream_appendNum(BitStream *bstream, int bits, unsigned int num); +extern int BitStream_appendBytes(BitStream *bstream, int size, unsigned char *data); +#define BitStream_size(__bstream__) (__bstream__->length) +extern unsigned char *BitStream_toByte(BitStream *bstream); +extern void BitStream_free(BitStream *bstream); + +#endif /* __BITSTREAM_H__ */ diff --git a/src/add-ons/kernel/debugger/qrencode/config.h b/src/add-ons/kernel/debugger/qrencode/config.h new file mode 100644 index 0000000000..20515db864 --- /dev/null +++ b/src/add-ons/kernel/debugger/qrencode/config.h @@ -0,0 +1,5 @@ +#define MAJOR_VERSION 3 +#define MINOR_VERSION 3 +#define MICRO_VERSION 0 +#define VERSION "3.3.0" +#define __STATIC static diff --git a/src/add-ons/kernel/debugger/qrencode/mask.c b/src/add-ons/kernel/debugger/qrencode/mask.c new file mode 100644 index 0000000000..47c658ca0e --- /dev/null +++ b/src/add-ons/kernel/debugger/qrencode/mask.c @@ -0,0 +1,330 @@ +/* + * qrencode - QR Code encoder + * + * Masking. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include + +#include "qrencode.h" +#include "qrspec.h" +#include "mask.h" + +__STATIC int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level) +{ + unsigned int format; + unsigned char v; + int i; + int blacks = 0; + + format = QRspec_getFormatInfo(mask, level); + + for(i=0; i<8; i++) { + if(format & 1) { + blacks += 2; + v = 0x85; + } else { + v = 0x84; + } + frame[width * 8 + width - 1 - i] = v; + if(i < 6) { + frame[width * i + 8] = v; + } else { + frame[width * (i + 1) + 8] = v; + } + format= format >> 1; + } + for(i=0; i<7; i++) { + if(format & 1) { + blacks += 2; + v = 0x85; + } else { + v = 0x84; + } + frame[width * (width - 7 + i) + 8] = v; + if(i == 0) { + frame[width * 8 + 7] = v; + } else { + frame[width * 8 + 6 - i] = v; + } + format= format >> 1; + } + + return blacks; +} + +/** + * Demerit coefficients. + * See Section 8.8.2, pp.45, JIS X0510:2004. + */ +#define N1 (3) +#define N2 (3) +#define N3 (40) +#define N4 (10) + +#define MASKMAKER(__exp__) \ + int x, y;\ + int b = 0;\ +\ + for(y=0; y= maskNum) { + errno = EINVAL; + return NULL; + } + + masked = (unsigned char *)malloc(width * width); + if(masked == NULL) return NULL; + + maskMakers[mask](width, frame, masked); + Mask_writeFormatInformation(width, masked, mask, level); + + return masked; +} + + +//static int n1; +//static int n2; +//static int n3; +//static int n4; + +__STATIC int Mask_calcN1N3(int length, int *runLength) +{ + int i; + int demerit = 0; + int fact; + + for(i=0; i= 5) { + demerit += N1 + (runLength[i] - 5); + //n1 += N1 + (runLength[i] - 5); + } + if((i & 1)) { + if(i >= 3 && i < length-2 && (runLength[i] % 3) == 0) { + fact = runLength[i] / 3; + if(runLength[i-2] == fact && + runLength[i-1] == fact && + runLength[i+1] == fact && + runLength[i+2] == fact) { + if(i == 3 || runLength[i-3] >= 4 * fact) { + demerit += N3; + //n3 += N3; + } else if(i+4 >= length || runLength[i+3] >= 4 * fact) { + demerit += N3; + //n3 += N3; + } + } + } + } + } + + return demerit; +} + +__STATIC int Mask_calcN2(int width, unsigned char *frame) +{ + int x, y; + unsigned char *p; + unsigned char b22, w22; + int demerit = 0; + + p = frame + width + 1; + for(y=1; y + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MASK_H__ +#define __MASK_H__ + +extern unsigned char *Mask_makeMask(int width, unsigned char *frame, int mask, QRecLevel level); +extern unsigned char *Mask_mask(int width, unsigned char *frame, QRecLevel level); + +#ifdef WITH_TESTS +extern int Mask_calcN2(int width, unsigned char *frame); +extern int Mask_calcN1N3(int length, int *runLength); +extern int Mask_calcRunLength(int width, unsigned char *frame, int dir, int *runLength); +extern int Mask_evaluateSymbol(int width, unsigned char *frame); +extern int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level); +extern unsigned char *Mask_makeMaskedFrame(int width, unsigned char *frame, int mask); +#endif + +#endif /* __MASK_H__ */ diff --git a/src/add-ons/kernel/debugger/qrencode/mmask.c b/src/add-ons/kernel/debugger/qrencode/mmask.c new file mode 100644 index 0000000000..99470f2008 --- /dev/null +++ b/src/add-ons/kernel/debugger/qrencode/mmask.c @@ -0,0 +1,177 @@ +/* + * qrencode - QR Code encoder + * + * Masking for Micro QR Code. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include + +#include "qrencode.h" +#include "mqrspec.h" +#include "mmask.h" + +__STATIC void MMask_writeFormatInformation(int version, int width, unsigned char *frame, int mask, QRecLevel level) +{ + unsigned int format; + unsigned char v; + int i; + + format = MQRspec_getFormatInfo(mask, version, level); + + for(i=0; i<8; i++) { + v = 0x84 | (format & 1); + frame[width * (i + 1) + 8] = v; + format = format >> 1; + } + for(i=0; i<7; i++) { + v = 0x84 | (format & 1); + frame[width * 8 + 7 - i] = v; + format = format >> 1; + } +} + +#define MASKMAKER(__exp__) \ + int x, y;\ +\ + for(y=0; y= maskNum) { + errno = EINVAL; + return NULL; + } + + width = MQRspec_getWidth(version); + masked = (unsigned char *)malloc(width * width); + if(masked == NULL) return NULL; + + maskMakers[mask](width, frame, masked); + MMask_writeFormatInformation(version, width, masked, mask, level); + + return masked; +} + +__STATIC int MMask_evaluateSymbol(int width, unsigned char *frame) +{ + int x, y; + unsigned char *p; + int sum1 = 0, sum2 = 0; + + p = frame + width * (width - 1); + for(x=1; x maxScore) { + maxScore = score; + free(bestMask); + bestMask = mask; + mask = (unsigned char *)malloc(width * width); + if(mask == NULL) break; + } + } + free(mask); + return bestMask; +} diff --git a/src/add-ons/kernel/debugger/qrencode/mmask.h b/src/add-ons/kernel/debugger/qrencode/mmask.h new file mode 100644 index 0000000000..f6556e877d --- /dev/null +++ b/src/add-ons/kernel/debugger/qrencode/mmask.h @@ -0,0 +1,34 @@ +/* + * qrencode - QR Code encoder + * + * Masking for Micro QR Code. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MMASK_H__ +#define __MMASK_H__ + +extern unsigned char *MMask_makeMask(int version, unsigned char *frame, int mask, QRecLevel level); +extern unsigned char *MMask_mask(int version, unsigned char *frame, QRecLevel level); + +#ifdef WITH_TESTS +extern int MMask_evaluateSymbol(int width, unsigned char *frame); +extern void MMask_writeFormatInformation(int version, int width, unsigned char *frame, int mask, QRecLevel level); +extern unsigned char *MMask_makeMaskedFrame(int width, unsigned char *frame, int mask); +#endif + +#endif /* __MMASK_H__ */ diff --git a/src/add-ons/kernel/debugger/qrencode/mqrspec.c b/src/add-ons/kernel/debugger/qrencode/mqrspec.c new file mode 100644 index 0000000000..76d2d261a6 --- /dev/null +++ b/src/add-ons/kernel/debugger/qrencode/mqrspec.c @@ -0,0 +1,280 @@ +/* + * qrencode - QR Code encoder + * + * Micor QR Code specification in convenient format. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * The following data / specifications are taken from + * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) + * or + * "Automatic identification and data capture techniques -- + * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include +#ifdef HAVE_LIBPTHREAD +#include +#endif + +#include "mqrspec.h" + +/****************************************************************************** + * Version and capacity + *****************************************************************************/ + +typedef struct { + int width; //< Edge length of the symbol + int ec[4]; //< Number of ECC code (bytes) +} MQRspec_Capacity; + +/** + * Table of the capacity of symbols + * See Table 1 (pp.106) and Table 8 (pp.113) of Appendix 1, JIS X0510:2004. + */ +static const MQRspec_Capacity mqrspecCapacity[MQRSPEC_VERSION_MAX + 1] = { + { 0, {0, 0, 0, 0}}, + { 11, {2, 0, 0, 0}}, + { 13, {5, 6, 0, 0}}, + { 15, {6, 8, 0, 0}}, + { 17, {8, 10, 14, 0}} +}; + +int MQRspec_getDataLengthBit(int version, QRecLevel level) +{ + int w; + int ecc; + + w = mqrspecCapacity[version].width - 1; + ecc = mqrspecCapacity[version].ec[level]; + if(ecc == 0) return 0; + return w * w - 64 - ecc * 8; +} + +int MQRspec_getDataLength(int version, QRecLevel level) +{ + return (MQRspec_getDataLengthBit(version, level) + 4) / 8; +} + +int MQRspec_getECCLength(int version, QRecLevel level) +{ + return mqrspecCapacity[version].ec[level]; +} + +int MQRspec_getWidth(int version) +{ + return mqrspecCapacity[version].width; +} + +/****************************************************************************** + * Length indicator + *****************************************************************************/ + +/** + * See Table 3 (pp.107) of Appendix 1, JIS X0510:2004. + */ +static const int lengthTableBits[4][4] = { + { 3, 4, 5, 6}, + { 0, 3, 4, 5}, + { 0, 0, 4, 5}, + { 0, 0, 3, 4} +}; + +int MQRspec_lengthIndicator(QRencodeMode mode, int version) +{ + return lengthTableBits[mode][version - 1]; +} + +int MQRspec_maximumWords(QRencodeMode mode, int version) +{ + int bits; + int words; + + bits = lengthTableBits[mode][version - 1]; + words = (1 << bits) - 1; + if(mode == QR_MODE_KANJI) { + words *= 2; // the number of bytes is required + } + + return words; +} + +/****************************************************************************** + * Format information + *****************************************************************************/ + +/* See calcFormatInfo in tests/test_mqrspec.c */ +static const unsigned int formatInfo[4][8] = { + {0x4445, 0x55ae, 0x6793, 0x7678, 0x06de, 0x1735, 0x2508, 0x34e3}, + {0x4172, 0x5099, 0x62a4, 0x734f, 0x03e9, 0x1202, 0x203f, 0x31d4}, + {0x4e2b, 0x5fc0, 0x6dfd, 0x7c16, 0x0cb0, 0x1d5b, 0x2f66, 0x3e8d}, + {0x4b1c, 0x5af7, 0x68ca, 0x7921, 0x0987, 0x186c, 0x2a51, 0x3bba} +}; + +/* See Table 10 of Appendix 1. (pp.115) */ +static const int typeTable[MQRSPEC_VERSION_MAX + 1][3] = { + {-1, -1, -1}, + { 0, -1, -1}, + { 1, 2, -1}, + { 3, 4, -1}, + { 5, 6, 7} +}; + +unsigned int MQRspec_getFormatInfo(int mask, int version, QRecLevel level) +{ + int type; + + if(mask < 0 || mask > 3) return 0; + if(version <= 0 || version > MQRSPEC_VERSION_MAX) return 0; + if(level == QR_ECLEVEL_H) return 0; + type = typeTable[version][level]; + if(type < 0) return 0; + + return formatInfo[mask][type]; +} + +/****************************************************************************** + * Frame + *****************************************************************************/ + +/** + * Cache of initial frames. + */ +/* C99 says that static storage shall be initialized to a null pointer + * by compiler. */ +static unsigned char *frames[MQRSPEC_VERSION_MAX + 1]; +#ifdef HAVE_LIBPTHREAD +static pthread_mutex_t frames_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif + +/** + * Put a finder pattern. + * @param frame + * @param width + * @param ox,oy upper-left coordinate of the pattern + */ +static void putFinderPattern(unsigned char *frame, int width, int ox, int oy) +{ + static const unsigned char finder[] = { + 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, + 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, + 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, + }; + int x, y; + const unsigned char *s; + + frame += oy * width + ox; + s = finder; + for(y=0; y<7; y++) { + for(x=0; x<7; x++) { + frame[x] = s[x]; + } + frame += width; + s += 7; + } +} + +static unsigned char *MQRspec_createFrame(int version) +{ + unsigned char *frame, *p, *q; + int width; + int x, y; + + width = mqrspecCapacity[version].width; + frame = (unsigned char *)malloc(width * width); + if(frame == NULL) return NULL; + + memset(frame, 0, width * width); + /* Finder pattern */ + putFinderPattern(frame, width, 0, 0); + /* Separator */ + p = frame; + for(y=0; y<7; y++) { + p[7] = 0xc0; + p += width; + } + memset(frame + width * 7, 0xc0, 8); + /* Mask format information area */ + memset(frame + width * 8 + 1, 0x84, 8); + p = frame + width + 8; + for(y=0; y<7; y++) { + *p = 0x84; + p += width; + } + /* Timing pattern */ + p = frame + 8; + q = frame + width * 8; + for(x=1; x MQRSPEC_VERSION_MAX) return NULL; + +#ifdef HAVE_LIBPTHREAD + pthread_mutex_lock(&frames_mutex); +#endif + if(frames[version] == NULL) { + frames[version] = MQRspec_createFrame(version); + } +#ifdef HAVE_LIBPTHREAD + pthread_mutex_unlock(&frames_mutex); +#endif + if(frames[version] == NULL) return NULL; + + width = mqrspecCapacity[version].width; + frame = (unsigned char *)malloc(width * width); + if(frame == NULL) return NULL; + memcpy(frame, frames[version], width * width); + + return frame; +} + +void MQRspec_clearCache(void) +{ + int i; + +#ifdef HAVE_LIBPTHREAD + pthread_mutex_lock(&frames_mutex); +#endif + for(i=1; i<=MQRSPEC_VERSION_MAX; i++) { + free(frames[i]); + frames[i] = NULL; + } +#ifdef HAVE_LIBPTHREAD + pthread_mutex_unlock(&frames_mutex); +#endif +} diff --git a/src/add-ons/kernel/debugger/qrencode/mqrspec.h b/src/add-ons/kernel/debugger/qrencode/mqrspec.h new file mode 100644 index 0000000000..2d4b90d281 --- /dev/null +++ b/src/add-ons/kernel/debugger/qrencode/mqrspec.h @@ -0,0 +1,157 @@ +/* + * qrencode - QR Code encoder + * + * Micro QR Code specification in convenient format. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MQRSPEC_H__ +#define __MQRSPEC_H__ + +#include "qrencode.h" + +/****************************************************************************** + * Version and capacity + *****************************************************************************/ + +/** + * Maximum width of a symbol + */ +#define MQRSPEC_WIDTH_MAX 17 + +/** + * Return maximum data code length (bits) for the version. + * @param version + * @param level + * @return maximum size (bits) + */ +extern int MQRspec_getDataLengthBit(int version, QRecLevel level); + +/** + * Return maximum data code length (bytes) for the version. + * @param version + * @param level + * @return maximum size (bytes) + */ +extern int MQRspec_getDataLength(int version, QRecLevel level); + +/** + * Return maximum error correction code length (bytes) for the version. + * @param version + * @param level + * @return ECC size (bytes) + */ +extern int MQRspec_getECCLength(int version, QRecLevel level); + +/** + * Return a version number that satisfies the input code length. + * @param size input code length (byte) + * @param level + * @return version number + */ +extern int MQRspec_getMinimumVersion(int size, QRecLevel level); + +/** + * Return the width of the symbol for the version. + * @param version + * @return width + */ +extern int MQRspec_getWidth(int version); + +/** + * Return the numer of remainder bits. + * @param version + * @return number of remainder bits + */ +extern int MQRspec_getRemainder(int version); + +/****************************************************************************** + * Length indicator + *****************************************************************************/ + +/** + * Return the size of lenght indicator for the mode and version. + * @param mode + * @param version + * @return the size of the appropriate length indicator (bits). + */ +extern int MQRspec_lengthIndicator(QRencodeMode mode, int version); + +/** + * Return the maximum length for the mode and version. + * @param mode + * @param version + * @return the maximum length (bytes) + */ +extern int MQRspec_maximumWords(QRencodeMode mode, int version); + +/****************************************************************************** + * Version information pattern + *****************************************************************************/ + +/** + * Return BCH encoded version information pattern that is used for the symbol + * of version 7 or greater. Use lower 18 bits. + * @param version + * @return BCH encoded version information pattern + */ +extern unsigned int MQRspec_getVersionPattern(int version); + +/****************************************************************************** + * Format information + *****************************************************************************/ + +/** + * Return BCH encoded format information pattern. + * @param mask + * @param version + * @param level + * @return BCH encoded format information pattern + */ +extern unsigned int MQRspec_getFormatInfo(int mask, int version, QRecLevel level); + +/****************************************************************************** + * Frame + *****************************************************************************/ + +/** + * Return a copy of initialized frame. + * When the same version is requested twice or more, a copy of cached frame + * is returned. + * @param version + * @return Array of unsigned char. You can free it by free(). + */ +extern unsigned char *MQRspec_newFrame(int version); + +/** + * Clear the frame cache. Typically for debug. + */ +extern void MQRspec_clearCache(void); + +/****************************************************************************** + * Mode indicator + *****************************************************************************/ + +/** + * Mode indicator. See Table 2 in Appendix 1 of JIS X0510:2004, pp.107. + */ +#define MQRSPEC_MODEID_NUM 0 +#define MQRSPEC_MODEID_AN 1 +#define MQRSPEC_MODEID_8 2 +#define MQRSPEC_MODEID_KANJI 3 + +#endif /* __MQRSPEC_H__ */ diff --git a/src/add-ons/kernel/debugger/qrencode/qrencode.c b/src/add-ons/kernel/debugger/qrencode/qrencode.c new file mode 100644 index 0000000000..d166a24812 --- /dev/null +++ b/src/add-ons/kernel/debugger/qrencode/qrencode.c @@ -0,0 +1,929 @@ +/* + * qrencode - QR Code encoder + * + * Copyright (C) 2006-2012 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include + +#include "qrencode.h" +#include "qrspec.h" +#include "mqrspec.h" +#include "bitstream.h" +#include "qrinput.h" +#include "rscode.h" +#include "split.h" +#include "mask.h" +#include "mmask.h" + +/****************************************************************************** + * Raw code + *****************************************************************************/ + +typedef struct { + int dataLength; + unsigned char *data; + int eccLength; + unsigned char *ecc; +} RSblock; + +typedef struct { + int version; + int dataLength; + int eccLength; + unsigned char *datacode; + unsigned char *ecccode; + int b1; + int blocks; + RSblock *rsblock; + int count; +} QRRawCode; + +static void RSblock_initBlock(RSblock *block, int dl, unsigned char *data, int el, unsigned char *ecc, RS *rs) +{ + block->dataLength = dl; + block->data = data; + block->eccLength = el; + block->ecc = ecc; + + encode_rs_char(rs, data, ecc); +} + +static int RSblock_init(RSblock *blocks, int spec[5], unsigned char *data, unsigned char *ecc) +{ + int i; + RSblock *block; + unsigned char *dp, *ep; + RS *rs; + int el, dl; + + dl = QRspec_rsDataCodes1(spec); + el = QRspec_rsEccCodes1(spec); + rs = init_rs(8, 0x11d, 0, 1, el, 255 - dl - el); + if(rs == NULL) return -1; + + block = blocks; + dp = data; + ep = ecc; + for(i=0; idatacode = QRinput_getByteStream(input); + if(raw->datacode == NULL) { + free(raw); + return NULL; + } + + QRspec_getEccSpec(input->version, input->level, spec); + + raw->version = input->version; + raw->b1 = QRspec_rsBlockNum1(spec); + raw->dataLength = QRspec_rsDataLength(spec); + raw->eccLength = QRspec_rsEccLength(spec); + raw->ecccode = (unsigned char *)malloc(raw->eccLength); + if(raw->ecccode == NULL) { + free(raw->datacode); + free(raw); + return NULL; + } + + raw->blocks = QRspec_rsBlockNum(spec); + raw->rsblock = (RSblock *)calloc(sizeof(RSblock), raw->blocks); + if(raw->rsblock == NULL) { + QRraw_free(raw); + return NULL; + } + ret = RSblock_init(raw->rsblock, spec, raw->datacode, raw->ecccode); + if(ret < 0) { + QRraw_free(raw); + return NULL; + } + + raw->count = 0; + + return raw; +} + +/** + * Return a code (byte). + * This function can be called iteratively. + * @param raw raw code. + * @return code + */ +__STATIC unsigned char QRraw_getCode(QRRawCode *raw) +{ + int col, row; + unsigned char ret; + + if(raw->count < raw->dataLength) { + row = raw->count % raw->blocks; + col = raw->count / raw->blocks; + if(col >= raw->rsblock[0].dataLength) { + row += raw->b1; + } + ret = raw->rsblock[row].data[col]; + } else if(raw->count < raw->dataLength + raw->eccLength) { + row = (raw->count - raw->dataLength) % raw->blocks; + col = (raw->count - raw->dataLength) / raw->blocks; + ret = raw->rsblock[row].ecc[col]; + } else { + return 0; + } + raw->count++; + return ret; +} + +__STATIC void QRraw_free(QRRawCode *raw) +{ + if(raw != NULL) { + free(raw->datacode); + free(raw->ecccode); + free(raw->rsblock); + free(raw); + } +} + +/****************************************************************************** + * Raw code for Micro QR Code + *****************************************************************************/ + +typedef struct { + int version; + int dataLength; + int eccLength; + unsigned char *datacode; + unsigned char *ecccode; + RSblock *rsblock; + int oddbits; + int count; +} MQRRawCode; + +__STATIC void MQRraw_free(MQRRawCode *raw); +__STATIC MQRRawCode *MQRraw_new(QRinput *input) +{ + MQRRawCode *raw; + RS *rs; + + raw = (MQRRawCode *)malloc(sizeof(MQRRawCode)); + if(raw == NULL) return NULL; + + raw->version = input->version; + raw->dataLength = MQRspec_getDataLength(input->version, input->level); + raw->eccLength = MQRspec_getECCLength(input->version, input->level); + raw->oddbits = raw->dataLength * 8 - MQRspec_getDataLengthBit(input->version, input->level); + raw->datacode = QRinput_getByteStream(input); + if(raw->datacode == NULL) { + free(raw); + return NULL; + } + raw->ecccode = (unsigned char *)malloc(raw->eccLength); + if(raw->ecccode == NULL) { + free(raw->datacode); + free(raw); + return NULL; + } + + raw->rsblock = (RSblock *)calloc(sizeof(RSblock), 1); + if(raw->rsblock == NULL) { + MQRraw_free(raw); + return NULL; + } + + rs = init_rs(8, 0x11d, 0, 1, raw->eccLength, 255 - raw->dataLength - raw->eccLength); + if(rs == NULL) { + MQRraw_free(raw); + return NULL; + } + + RSblock_initBlock(raw->rsblock, raw->dataLength, raw->datacode, raw->eccLength, raw->ecccode, rs); + + raw->count = 0; + + return raw; +} + +/** + * Return a code (byte). + * This function can be called iteratively. + * @param raw raw code. + * @return code + */ +__STATIC unsigned char MQRraw_getCode(MQRRawCode *raw) +{ + unsigned char ret; + + if(raw->count < raw->dataLength) { + ret = raw->datacode[raw->count]; + } else if(raw->count < raw->dataLength + raw->eccLength) { + ret = raw->ecccode[raw->count - raw->dataLength]; + } else { + return 0; + } + raw->count++; + return ret; +} + +__STATIC void MQRraw_free(MQRRawCode *raw) +{ + if(raw != NULL) { + free(raw->datacode); + free(raw->ecccode); + free(raw->rsblock); + free(raw); + } +} + + +/****************************************************************************** + * Frame filling + *****************************************************************************/ + +typedef struct { + int width; + unsigned char *frame; + int x, y; + int dir; + int bit; + int mqr; +} FrameFiller; + +static FrameFiller *FrameFiller_new(int width, unsigned char *frame, int mqr) +{ + FrameFiller *filler; + + filler = (FrameFiller *)malloc(sizeof(FrameFiller)); + if(filler == NULL) return NULL; + filler->width = width; + filler->frame = frame; + filler->x = width - 1; + filler->y = width - 1; + filler->dir = -1; + filler->bit = -1; + filler->mqr = mqr; + + return filler; +} + +static unsigned char *FrameFiller_next(FrameFiller *filler) +{ + unsigned char *p; + int x, y, w; + + if(filler->bit == -1) { + filler->bit = 0; + return filler->frame + filler->y * filler->width + filler->x; + } + + x = filler->x; + y = filler->y; + p = filler->frame; + w = filler->width; + + if(filler->bit == 0) { + x--; + filler->bit++; + } else { + x++; + y += filler->dir; + filler->bit--; + } + + if(filler->dir < 0) { + if(y < 0) { + y = 0; + x -= 2; + filler->dir = 1; + if(!filler->mqr && x == 6) { + x--; + y = 9; + } + } + } else { + if(y == w) { + y = w - 1; + x -= 2; + filler->dir = -1; + if(!filler->mqr && x == 6) { + x--; + y -= 8; + } + } + } + if(x < 0 || y < 0) return NULL; + + filler->x = x; + filler->y = y; + + if(p[y * w + x] & 0x80) { + // This tail recursion could be optimized. + return FrameFiller_next(filler); + } + return &p[y * w + x]; +} + +#ifdef WITH_TESTS +extern unsigned char *FrameFiller_test(int version) +{ + int width; + unsigned char *frame, *p; + FrameFiller *filler; + int i, length; + + width = QRspec_getWidth(version); + frame = QRspec_newFrame(version); + if(frame == NULL) return NULL; + filler = FrameFiller_new(width, frame, 0); + if(filler == NULL) { + free(frame); + return NULL; + } + length = QRspec_getDataLength(version, QR_ECLEVEL_L) * 8 + + QRspec_getECCLength(version, QR_ECLEVEL_L) * 8 + + QRspec_getRemainder(version); + for(i=0; iversion = version; + qrcode->width = width; + qrcode->data = data; + + return qrcode; +} + +void QRcode_free(QRcode *qrcode) +{ + if(qrcode != NULL) { + free(qrcode->data); + free(qrcode); + } +} + +__STATIC QRcode *QRcode_encodeMask(QRinput *input, int mask) +{ + int width, version; + QRRawCode *raw; + unsigned char *frame, *masked, *p, code, bit; + FrameFiller *filler; + int i, j; + QRcode *qrcode = NULL; + + if(input->mqr) { + errno = EINVAL; + return NULL; + } + if(input->version < 0 || input->version > QRSPEC_VERSION_MAX) { + errno = EINVAL; + return NULL; + } + if(input->level > QR_ECLEVEL_H) { + errno = EINVAL; + return NULL; + } + + raw = QRraw_new(input); + if(raw == NULL) return NULL; + + version = raw->version; + width = QRspec_getWidth(version); + frame = QRspec_newFrame(version); + if(frame == NULL) { + QRraw_free(raw); + return NULL; + } + filler = FrameFiller_new(width, frame, 0); + if(filler == NULL) { + QRraw_free(raw); + free(frame); + return NULL; + } + + /* inteleaved data and ecc codes */ + for(i=0; idataLength + raw->eccLength; i++) { + code = QRraw_getCode(raw); + bit = 0x80; + for(j=0; j<8; j++) { + p = FrameFiller_next(filler); + if(p == NULL) goto EXIT; + *p = 0x02 | ((bit & code) != 0); + bit = bit >> 1; + } + } + QRraw_free(raw); + raw = NULL; + /* remainder bits */ + j = QRspec_getRemainder(version); + for(i=0; ilevel); + } else { + masked = Mask_makeMask(width, frame, mask, input->level); + } + if(masked == NULL) { + goto EXIT; + } + qrcode = QRcode_new(version, width, masked); + +EXIT: + QRraw_free(raw); + free(filler); + free(frame); + return qrcode; +} + +__STATIC QRcode *QRcode_encodeMaskMQR(QRinput *input, int mask) +{ + int width, version; + MQRRawCode *raw; + unsigned char *frame, *masked, *p, code, bit; + FrameFiller *filler; + int i, j; + QRcode *qrcode = NULL; + + if(!input->mqr) { + errno = EINVAL; + return NULL; + } + if(input->version <= 0 || input->version > MQRSPEC_VERSION_MAX) { + errno = EINVAL; + return NULL; + } + if(input->level > QR_ECLEVEL_Q) { + errno = EINVAL; + return NULL; + } + + raw = MQRraw_new(input); + if(raw == NULL) return NULL; + + version = raw->version; + width = MQRspec_getWidth(version); + frame = MQRspec_newFrame(version); + if(frame == NULL) { + MQRraw_free(raw); + return NULL; + } + filler = FrameFiller_new(width, frame, 1); + if(filler == NULL) { + MQRraw_free(raw); + free(frame); + return NULL; + } + + /* inteleaved data and ecc codes */ + for(i=0; idataLength + raw->eccLength; i++) { + code = MQRraw_getCode(raw); + if(raw->oddbits && i == raw->dataLength - 1) { + bit = 1 << raw->oddbits; + for(j=0; joddbits; j++) { + p = FrameFiller_next(filler); + if(p == NULL) goto EXIT; + *p = 0x02 | ((bit & code) != 0); + bit = bit >> 1; + } + } else { + bit = 0x80; + for(j=0; j<8; j++) { + p = FrameFiller_next(filler); + if(p == NULL) goto EXIT; + *p = 0x02 | ((bit & code) != 0); + bit = bit >> 1; + } + } + } + MQRraw_free(raw); + raw = NULL; + + /* masking */ + if(mask < 0) { + masked = MMask_mask(version, frame, input->level); + } else { + masked = MMask_makeMask(version, frame, mask, input->level); + } + if(masked == NULL) { + goto EXIT; + } + + qrcode = QRcode_new(version, width, masked); + +EXIT: + MQRraw_free(raw); + free(filler); + free(frame); + return qrcode; +} + +QRcode *QRcode_encodeInput(QRinput *input) +{ + if(input->mqr) { + return QRcode_encodeMaskMQR(input, -1); + } else { + return QRcode_encodeMask(input, -1); + } +} + +static QRcode *QRcode_encodeStringReal(const char *string, int version, QRecLevel level, int mqr, QRencodeMode hint, int casesensitive) +{ + QRinput *input; + QRcode *code; + int ret; + + if(string == NULL) { + errno = EINVAL; + return NULL; + } + if(hint != QR_MODE_8 && hint != QR_MODE_KANJI) { + errno = EINVAL; + return NULL; + } + + if(mqr) { + input = QRinput_newMQR(version, level); + } else { + input = QRinput_new2(version, level); + } + if(input == NULL) return NULL; + + ret = Split_splitStringToQRinput(string, input, hint, casesensitive); + if(ret < 0) { + QRinput_free(input); + return NULL; + } + code = QRcode_encodeInput(input); + QRinput_free(input); + + return code; +} + +QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive) +{ + return QRcode_encodeStringReal(string, version, level, 0, hint, casesensitive); +} + +QRcode *QRcode_encodeStringMQR(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive) +{ + return QRcode_encodeStringReal(string, version, level, 1, hint, casesensitive); +} + +static QRcode *QRcode_encodeDataReal(const unsigned char *data, int length, int version, QRecLevel level, int mqr) +{ + QRinput *input; + QRcode *code; + int ret; + + if(data == NULL || length == 0) { + errno = EINVAL; + return NULL; + } + + if(mqr) { + input = QRinput_newMQR(version, level); + } else { + input = QRinput_new2(version, level); + } + if(input == NULL) return NULL; + + ret = QRinput_append(input, QR_MODE_8, length, data); + if(ret < 0) { + QRinput_free(input); + return NULL; + } + code = QRcode_encodeInput(input); + QRinput_free(input); + + return code; +} + +QRcode *QRcode_encodeData(int size, const unsigned char *data, int version, QRecLevel level) +{ + return QRcode_encodeDataReal(data, size, version, level, 0); +} + +QRcode *QRcode_encodeString8bit(const char *string, int version, QRecLevel level) +{ + if(string == NULL) { + errno = EINVAL; + return NULL; + } + return QRcode_encodeDataReal((unsigned char *)string, strlen(string), version, level, 0); +} + +QRcode *QRcode_encodeDataMQR(int size, const unsigned char *data, int version, QRecLevel level) +{ + return QRcode_encodeDataReal(data, size, version, level, 1); +} + +QRcode *QRcode_encodeString8bitMQR(const char *string, int version, QRecLevel level) +{ + if(string == NULL) { + errno = EINVAL; + return NULL; + } + return QRcode_encodeDataReal((unsigned char *)string, strlen(string), version, level, 1); +} + + +/****************************************************************************** + * Structured QR-code encoding + *****************************************************************************/ + +static QRcode_List *QRcode_List_newEntry(void) +{ + QRcode_List *entry; + + entry = (QRcode_List *)malloc(sizeof(QRcode_List)); + if(entry == NULL) return NULL; + + entry->next = NULL; + entry->code = NULL; + + return entry; +} + +static void QRcode_List_freeEntry(QRcode_List *entry) +{ + if(entry != NULL) { + QRcode_free(entry->code); + free(entry); + } +} + +void QRcode_List_free(QRcode_List *qrlist) +{ + QRcode_List *list = qrlist, *next; + + while(list != NULL) { + next = list->next; + QRcode_List_freeEntry(list); + list = next; + } +} + +int QRcode_List_size(QRcode_List *qrlist) +{ + QRcode_List *list = qrlist; + int size = 0; + + while(list != NULL) { + size++; + list = list->next; + } + + return size; +} + +#if 0 +static unsigned char QRcode_parity(const char *str, int size) +{ + unsigned char parity = 0; + int i; + + for(i=0; ihead; + + while(list != NULL) { + if(head == NULL) { + entry = QRcode_List_newEntry(); + if(entry == NULL) goto ABORT; + head = entry; + tail = head; + } else { + entry = QRcode_List_newEntry(); + if(entry == NULL) goto ABORT; + tail->next = entry; + tail = tail->next; + } + tail->code = QRcode_encodeInput(list->input); + if(tail->code == NULL) { + goto ABORT; + } + list = list->next; + } + + return head; +ABORT: + QRcode_List_free(head); + return NULL; +} + +static QRcode_List *QRcode_encodeInputToStructured(QRinput *input) +{ + QRinput_Struct *s; + QRcode_List *codes; + + s = QRinput_splitQRinputToStruct(input); + if(s == NULL) return NULL; + + codes = QRcode_encodeInputStructured(s); + QRinput_Struct_free(s); + + return codes; +} + +static QRcode_List *QRcode_encodeDataStructuredReal( + int size, const unsigned char *data, + int version, QRecLevel level, + int eightbit, QRencodeMode hint, int casesensitive) +{ + QRinput *input; + QRcode_List *codes; + int ret; + + if(version <= 0) { + errno = EINVAL; + return NULL; + } + if(!eightbit && (hint != QR_MODE_8 && hint != QR_MODE_KANJI)) { + errno = EINVAL; + return NULL; + } + + input = QRinput_new2(version, level); + if(input == NULL) return NULL; + + if(eightbit) { + ret = QRinput_append(input, QR_MODE_8, size, data); + } else { + ret = Split_splitStringToQRinput((char *)data, input, hint, casesensitive); + } + if(ret < 0) { + QRinput_free(input); + return NULL; + } + codes = QRcode_encodeInputToStructured(input); + QRinput_free(input); + + return codes; +} + +QRcode_List *QRcode_encodeDataStructured(int size, const unsigned char *data, int version, QRecLevel level) { + return QRcode_encodeDataStructuredReal(size, data, version, level, 1, QR_MODE_NUL, 0); +} + +QRcode_List *QRcode_encodeString8bitStructured(const char *string, int version, QRecLevel level) { + if(string == NULL) { + errno = EINVAL; + return NULL; + } + return QRcode_encodeDataStructured(strlen(string), (unsigned char *)string, version, level); +} + +QRcode_List *QRcode_encodeStringStructured(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive) +{ + if(string == NULL) { + errno = EINVAL; + return NULL; + } + return QRcode_encodeDataStructuredReal(strlen(string), (unsigned char *)string, version, level, 0, hint, casesensitive); +} + +/****************************************************************************** + * System utilities + *****************************************************************************/ + +void QRcode_APIVersion(int *major_version, int *minor_version, int *micro_version) +{ + if(major_version != NULL) { + *major_version = MAJOR_VERSION; + } + if(minor_version != NULL) { + *minor_version = MINOR_VERSION; + } + if(micro_version != NULL) { + *micro_version = MICRO_VERSION; + } +} + +char *QRcode_APIVersionString(void) +{ + return VERSION; +} + +void QRcode_clearCache(void) +{ + QRspec_clearCache(); + MQRspec_clearCache(); + free_rs_cache(); +} diff --git a/src/add-ons/kernel/debugger/qrencode/qrencode.h b/src/add-ons/kernel/debugger/qrencode/qrencode.h new file mode 100644 index 0000000000..fa53e364d5 --- /dev/null +++ b/src/add-ons/kernel/debugger/qrencode/qrencode.h @@ -0,0 +1,565 @@ +/** + * qrencode - QR Code encoder + * + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** \mainpage + * Libqrencode is a library for encoding data in a QR Code symbol, a kind of 2D + * symbology. + * + * \section encoding Encoding + * + * There are two ways to encode data: encoding a string or + * encoding a structured data. + * + * \subsection encoding-string Encoding a string + * You can encode a string by calling QRcode_encodeString(). + * The given string is parsed automatically and encoded. If you want to encode + * data that can be represented as a C string style (NUL terminated), you can + * simply use this way. + * + * If the input data contains Kanji (Shift-JIS) characters and you want to + * encode them as Kanji in QR Code, you should give QR_MODE_KANJI as a hint. + * Otherwise, all of non-alphanumeric characters are encoded as 8 bit data. + * If you want to encode a whole string in 8 bit mode, use + * QRcode_encodeString8bit() instead. + * + * Please note that a C string can not contain NUL character. If your data + * contains NUL, you should chose the second way. + * + * \subsection encoding-input Encoding a structured data + * You can construct a structured input data manually. If the structure of the + * input data is known, you can use this way. + * At first, create a ::QRinput object by QRinput_new(). Then add input data + * to the QRinput object by QRinput_append(). Finally call QRcode_encodeInput() + * to encode the QRinput data. + * You can reuse the QRinput data again to encode it in other symbols with + * different parameters. + * + * \section result Result + * The encoded symbol is resulted as a ::QRcode object. It will contain + * its version number, width of the symbol and an array represents the symbol. + * See ::QRcode for the details. You can free the object by QRcode_free(). + * + * Please note that the version of the result may be larger than specified. + * In such cases, the input data would be too large to be encoded in a + * symbol of the specified version. + * + * \section structured Structured append + * Libqrencode can generate "Structured-appended" symbols that enables to split + * a large data set into mulitple QR codes. A QR code reader concatenates + * multiple QR code symbols into a string. + * Just like QRcode_encodeString(), you can use QRcode_encodeStringStructured() + * to generate structured-appended symbols. This functions returns an instance + * of ::QRcode_List. The returned list is a singly-linked list of QRcode: you + * can retrieve each QR code in this way: + * + * \code + * QRcode_List *qrcodes; + * QRcode_List *entry; + * QRcode *qrcode; + * + * qrcodes = QRcode_encodeStringStructured(...); + * entry = qrcodes; + * while(entry != NULL) { + * qrcode = entry->code; + * // do something + * entry = entry->next; + * } + * QRcode_List_free(entry); + * \endcode + * + * Instead of using auto-parsing functions, you can construct your own + * structured input. At first, instantiate an object of ::QRinput_Struct + * by calling QRinput_Struct_new(). This object can hold multiple ::QRinput, + * and one QR code is generated for a ::QRinput. + * QRinput_Struct_appendInput() appends a ::QRinput to a ::QRinput_Struct + * object. In order to generate structured-appended symbols, it is required to + * embed headers to each symbol. You can use + * QRinput_Struct_insertStructuredAppendHeaders() to insert appropriate + * headers to each symbol. You should call this function just once before + * encoding symbols. + */ + +#ifndef __QRENCODE_H__ +#define __QRENCODE_H__ + +#if defined(__cplusplus) +extern "C" { +#endif + +/** + * Encoding mode. + */ +typedef enum { + QR_MODE_NUL = -1, ///< Terminator (NUL character). Internal use only + QR_MODE_NUM = 0, ///< Numeric mode + QR_MODE_AN, ///< Alphabet-numeric mode + QR_MODE_8, ///< 8-bit data mode + QR_MODE_KANJI, ///< Kanji (shift-jis) mode + QR_MODE_STRUCTURE, ///< Internal use only + QR_MODE_ECI, ///< ECI mode + QR_MODE_FNC1FIRST, ///< FNC1, first position + QR_MODE_FNC1SECOND, ///< FNC1, second position +} QRencodeMode; + +/** + * Level of error correction. + */ +typedef enum { + QR_ECLEVEL_L = 0, ///< lowest + QR_ECLEVEL_M, + QR_ECLEVEL_Q, + QR_ECLEVEL_H ///< highest +} QRecLevel; + +/** + * Maximum version (size) of QR-code symbol. + */ +#define QRSPEC_VERSION_MAX 40 + +/** + * Maximum version (size) of QR-code symbol. + */ +#define MQRSPEC_VERSION_MAX 4 + + +/****************************************************************************** + * Input data (qrinput.c) + *****************************************************************************/ + +/** + * Singly linked list to contain input strings. An instance of this class + * contains its version and error correction level too. It is required to + * set them by QRinput_setVersion() and QRinput_setErrorCorrectionLevel(), + * or use QRinput_new2() to instantiate an object. + */ +typedef struct _QRinput QRinput; + +/** + * Instantiate an input data object. The version is set to 0 (auto-select) + * and the error correction level is set to QR_ECLEVEL_L. + * @return an input object (initialized). On error, NULL is returned and errno + * is set to indicate the error. + * @throw ENOMEM unable to allocate memory. + */ +extern QRinput *QRinput_new(void); + +/** + * Instantiate an input data object. + * @param version version number. + * @param level Error correction level. + * @return an input object (initialized). On error, NULL is returned and errno + * is set to indicate the error. + * @throw ENOMEM unable to allocate memory for input objects. + * @throw EINVAL invalid arguments. + */ +extern QRinput *QRinput_new2(int version, QRecLevel level); + +/** + * Instantiate an input data object. Object's Micro QR Code flag is set. + * Unlike with full-sized QR Code, version number must be specified (>0). + * @param version version number (1--4). + * @param level Error correction level. + * @return an input object (initialized). On error, NULL is returned and errno + * is set to indicate the error. + * @throw ENOMEM unable to allocate memory for input objects. + * @throw EINVAL invalid arguments. + */ +extern QRinput *QRinput_newMQR(int version, QRecLevel level); + +/** + * Append data to an input object. + * The data is copied and appended to the input object. + * @param input input object. + * @param mode encoding mode. + * @param size size of data (byte). + * @param data a pointer to the memory area of the input data. + * @retval 0 success. + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + * @throw EINVAL input data is invalid. + * + */ +extern int QRinput_append(QRinput *input, QRencodeMode mode, int size, const unsigned char *data); + +/** + * Append ECI header. + * @param input input object. + * @param ecinum ECI indicator number (0 - 999999) + * @retval 0 success. + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + * @throw EINVAL input data is invalid. + * + */ +extern int QRinput_appendECIheader(QRinput *input, unsigned int ecinum); + +/** + * Get current version. + * @param input input object. + * @return current version. + */ +extern int QRinput_getVersion(QRinput *input); + +/** + * Set version of the QR code that is to be encoded. + * This function cannot be applied to Micro QR Code. + * @param input input object. + * @param version version number (0 = auto) + * @retval 0 success. + * @retval -1 invalid argument. + */ +extern int QRinput_setVersion(QRinput *input, int version); + +/** + * Get current error correction level. + * @param input input object. + * @return Current error correcntion level. + */ +extern QRecLevel QRinput_getErrorCorrectionLevel(QRinput *input); + +/** + * Set error correction level of the QR code that is to be encoded. + * This function cannot be applied to Micro QR Code. + * @param input input object. + * @param level Error correction level. + * @retval 0 success. + * @retval -1 invalid argument. + */ +extern int QRinput_setErrorCorrectionLevel(QRinput *input, QRecLevel level); + +/** + * Set version and error correction level of the QR code at once. + * This function is recommened for Micro QR Code. + * @param input input object. + * @param version version number (0 = auto) + * @param level Error correction level. + * @retval 0 success. + * @retval -1 invalid argument. + */ +extern int QRinput_setVersionAndErrorCorrectionLevel(QRinput *input, int version, QRecLevel level); + +/** + * Free the input object. + * All of data chunks in the input object are freed too. + * @param input input object. + */ +extern void QRinput_free(QRinput *input); + +/** + * Validate the input data. + * @param mode encoding mode. + * @param size size of data (byte). + * @param data a pointer to the memory area of the input data. + * @retval 0 success. + * @retval -1 invalid arguments. + */ +extern int QRinput_check(QRencodeMode mode, int size, const unsigned char *data); + +/** + * Set of QRinput for structured symbols. + */ +typedef struct _QRinput_Struct QRinput_Struct; + +/** + * Instantiate a set of input data object. + * @return an instance of QRinput_Struct. On error, NULL is returned and errno + * is set to indicate the error. + * @throw ENOMEM unable to allocate memory. + */ +extern QRinput_Struct *QRinput_Struct_new(void); + +/** + * Set parity of structured symbols. + * @param s structured input object. + * @param parity parity of s. + */ +extern void QRinput_Struct_setParity(QRinput_Struct *s, unsigned char parity); + +/** + * Append a QRinput object to the set. QRinput created by QRinput_newMQR() + * will be rejected. + * @warning never append the same QRinput object twice or more. + * @param s structured input object. + * @param input an input object. + * @retval >0 number of input objects in the structure. + * @retval -1 an error occurred. See Exceptions for the details. + * @throw ENOMEM unable to allocate memory. + * @throw EINVAL invalid arguments. + */ +extern int QRinput_Struct_appendInput(QRinput_Struct *s, QRinput *input); + +/** + * Free all of QRinput in the set. + * @param s a structured input object. + */ +extern void QRinput_Struct_free(QRinput_Struct *s); + +/** + * Split a QRinput to QRinput_Struct. It calculates a parity, set it, then + * insert structured-append headers. QRinput created by QRinput_newMQR() will + * be rejected. + * @param input input object. Version number and error correction level must be + * set. + * @return a set of input data. On error, NULL is returned, and errno is set + * to indicate the error. See Exceptions for the details. + * @throw ERANGE input data is too large. + * @throw EINVAL invalid input data. + * @throw ENOMEM unable to allocate memory. + */ +extern QRinput_Struct *QRinput_splitQRinputToStruct(QRinput *input); + +/** + * Insert structured-append headers to the input structure. It calculates + * a parity and set it if the parity is not set yet. + * @param s input structure + * @retval 0 success. + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw EINVAL invalid input object. + * @throw ENOMEM unable to allocate memory. + */ +extern int QRinput_Struct_insertStructuredAppendHeaders(QRinput_Struct *s); + +/** + * Set FNC1-1st position flag. + */ +extern int QRinput_setFNC1First(QRinput *input); + +/** + * Set FNC1-2nd position flag and application identifier. + */ +extern int QRinput_setFNC1Second(QRinput *input, unsigned char appid); + +/****************************************************************************** + * QRcode output (qrencode.c) + *****************************************************************************/ + +/** + * QRcode class. + * Symbol data is represented as an array contains width*width uchars. + * Each uchar represents a module (dot). If the less significant bit of + * the uchar is 1, the corresponding module is black. The other bits are + * meaningless for usual applications, but here its specification is described. + * + *

    + * MSB 76543210 LSB
    + *     |||||||`- 1=black/0=white
    + *     ||||||`-- data and ecc code area
    + *     |||||`--- format information
    + *     ||||`---- version information
    + *     |||`----- timing pattern
    + *     ||`------ alignment pattern
    + *     |`------- finder pattern and separator
    + *     `-------- non-data modules (format, timing, etc.)
    + * 
    + */ +typedef struct { + int version; ///< version of the symbol + int width; ///< width of the symbol + unsigned char *data; ///< symbol data +} QRcode; + +/** + * Singly-linked list of QRcode. Used to represent a structured symbols. + * A list is terminated with NULL. + */ +typedef struct _QRcode_List QRcode_List; + +struct _QRcode_List { + QRcode *code; + QRcode_List *next; +}; + +/** + * Create a symbol from the input data. + * @warning This function is THREAD UNSAFE when pthread is disabled. + * @param input input data. + * @return an instance of QRcode class. The version of the result QRcode may + * be larger than the designated version. On error, NULL is returned, + * and errno is set to indicate the error. See Exceptions for the + * details. + * @throw EINVAL invalid input object. + * @throw ENOMEM unable to allocate memory for input objects. + */ +extern QRcode *QRcode_encodeInput(QRinput *input); + +/** + * Create a symbol from the string. The library automatically parses the input + * string and encodes in a QR Code symbol. + * @warning This function is THREAD UNSAFE when pthread is disabled. + * @param string input string. It must be NUL terminated. + * @param version version of the symbol. If 0, the library chooses the minimum + * version for the given input data. + * @param level error correction level. + * @param hint tell the library how non-alphanumerical characters should be + * encoded. If QR_MODE_KANJI is given, kanji characters will be + * encoded as Shif-JIS characters. If QR_MODE_8 is given, all of + * non-alphanumerical characters will be encoded as is. If you want + * to embed UTF-8 string, choose this. + * @param casesensitive case-sensitive(1) or not(0). + * @return an instance of QRcode class. The version of the result QRcode may + * be larger than the designated version. On error, NULL is returned, + * and errno is set to indicate the error. See Exceptions for the + * details. + * @throw EINVAL invalid input object. + * @throw ENOMEM unable to allocate memory for input objects. + * @throw ERANGE input data is too large. + */ +extern QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive); + +/** + * Same to QRcode_encodeString(), but encode whole data in 8-bit mode. + * @warning This function is THREAD UNSAFE when pthread is disabled. + */ +extern QRcode *QRcode_encodeString8bit(const char *string, int version, QRecLevel level); + +/** + * Micro QR Code version of QRcode_encodeString(). + * @warning This function is THREAD UNSAFE when pthread is disabled. + */ +extern QRcode *QRcode_encodeStringMQR(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive); + +/** + * Micro QR Code version of QRcode_encodeString8bit(). + * @warning This function is THREAD UNSAFE when pthread is disabled. + */ +extern QRcode *QRcode_encodeString8bitMQR(const char *string, int version, QRecLevel level); + +/** + * Encode byte stream (may include '\0') in 8-bit mode. + * @warning This function is THREAD UNSAFE when pthread is disabled. + * @param size size of the input data. + * @param data input data. + * @param version version of the symbol. If 0, the library chooses the minimum + * version for the given input data. + * @param level error correction level. + * @throw EINVAL invalid input object. + * @throw ENOMEM unable to allocate memory for input objects. + * @throw ERANGE input data is too large. + */ +extern QRcode *QRcode_encodeData(int size, const unsigned char *data, int version, QRecLevel level); + +/** + * Micro QR Code version of QRcode_encodeData(). + * @warning This function is THREAD UNSAFE when pthread is disabled. + */ +extern QRcode *QRcode_encodeDataMQR(int size, const unsigned char *data, int version, QRecLevel level); + +/** + * Free the instance of QRcode class. + * @param qrcode an instance of QRcode class. + */ +extern void QRcode_free(QRcode *qrcode); + +/** + * Create structured symbols from the input data. + * @warning This function is THREAD UNSAFE when pthread is disabled. + * @param s + * @return a singly-linked list of QRcode. + */ +extern QRcode_List *QRcode_encodeInputStructured(QRinput_Struct *s); + +/** + * Create structured symbols from the string. The library automatically parses + * the input string and encodes in a QR Code symbol. + * @warning This function is THREAD UNSAFE when pthread is disabled. + * @param string input string. It must be NUL terminated. + * @param version version of the symbol. + * @param level error correction level. + * @param hint tell the library how non-alphanumerical characters should be + * encoded. If QR_MODE_KANJI is given, kanji characters will be + * encoded as Shif-JIS characters. If QR_MODE_8 is given, all of + * non-alphanumerical characters will be encoded as is. If you want + * to embed UTF-8 string, choose this. + * @param casesensitive case-sensitive(1) or not(0). + * @return a singly-linked list of QRcode. On error, NULL is returned, and + * errno is set to indicate the error. See Exceptions for the details. + * @throw EINVAL invalid input object. + * @throw ENOMEM unable to allocate memory for input objects. + */ +extern QRcode_List *QRcode_encodeStringStructured(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive); + +/** + * Same to QRcode_encodeStringStructured(), but encode whole data in 8-bit mode. + * @warning This function is THREAD UNSAFE when pthread is disabled. + */ +extern QRcode_List *QRcode_encodeString8bitStructured(const char *string, int version, QRecLevel level); + +/** + * Create structured symbols from byte stream (may include '\0'). Wholde data + * are encoded in 8-bit mode. + * @warning This function is THREAD UNSAFE when pthread is disabled. + * @param size size of the input data. + * @param data input dat. + * @param version version of the symbol. + * @param level error correction level. + * @return a singly-linked list of QRcode. On error, NULL is returned, and + * errno is set to indicate the error. See Exceptions for the details. + * @throw EINVAL invalid input object. + * @throw ENOMEM unable to allocate memory for input objects. + */ +extern QRcode_List *QRcode_encodeDataStructured(int size, const unsigned char *data, int version, QRecLevel level); + +/** + * Return the number of symbols included in a QRcode_List. + * @param qrlist a head entry of a QRcode_List. + * @return number of symbols in the list. + */ +extern int QRcode_List_size(QRcode_List *qrlist); + +/** + * Free the QRcode_List. + * @param qrlist a head entry of a QRcode_List. + */ +extern void QRcode_List_free(QRcode_List *qrlist); + + +/****************************************************************************** + * System utilities + *****************************************************************************/ + +/** + * Return a string that identifies the library version. + * @param major_version + * @param minor_version + * @param micro_version + */ +extern void QRcode_APIVersion(int *major_version, int *minor_version, int *micro_version); + +/** + * Return a string that identifies the library version. + * @return a string identifies the library version. The string is held by the + * library. Do NOT free it. + */ +extern char *QRcode_APIVersionString(void); + +/** + * Clear all caches. This is only for debug purpose. If you are attacking a + * complicated memory leak bug, try this to reduce the reachable blocks record. + */ +extern void QRcode_clearCache(void); + +#if defined(__cplusplus) +} +#endif + +#endif /* __QRENCODE_H__ */ diff --git a/src/add-ons/kernel/debugger/qrencode/qrencode_inner.h b/src/add-ons/kernel/debugger/qrencode/qrencode_inner.h new file mode 100644 index 0000000000..3c40d0622a --- /dev/null +++ b/src/add-ons/kernel/debugger/qrencode/qrencode_inner.h @@ -0,0 +1,88 @@ +/** + * qrencode - QR Code encoder + * + * Header for test use + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __QRENCODE_INNER_H__ +#define __QRENCODE_INNER_H__ + +/** + * This header file includes definitions for test use. + */ + +/****************************************************************************** + * Raw code + *****************************************************************************/ + +typedef struct { + int dataLength; + unsigned char *data; + int eccLength; + unsigned char *ecc; +} RSblock; + +typedef struct { + int version; + int dataLength; + int eccLength; + unsigned char *datacode; + unsigned char *ecccode; + int b1; + int blocks; + RSblock *rsblock; + int count; +} QRRawCode; + +extern QRRawCode *QRraw_new(QRinput *input); +extern unsigned char QRraw_getCode(QRRawCode *raw); +extern void QRraw_free(QRRawCode *raw); + +/****************************************************************************** + * Raw code for Micro QR Code + *****************************************************************************/ + +typedef struct { + int version; + int dataLength; + int eccLength; + unsigned char *datacode; + unsigned char *ecccode; + RSblock *rsblock; + int oddbits; + int count; +} MQRRawCode; + +extern MQRRawCode *MQRraw_new(QRinput *input); +extern unsigned char MQRraw_getCode(MQRRawCode *raw); +extern void MQRraw_free(MQRRawCode *raw); + +/****************************************************************************** + * Frame filling + *****************************************************************************/ +extern unsigned char *FrameFiller_test(int version); +extern unsigned char *FrameFiller_testMQR(int version); + +/****************************************************************************** + * QR-code encoding + *****************************************************************************/ +extern QRcode *QRcode_encodeMask(QRinput *input, int mask); +extern QRcode *QRcode_encodeMaskMQR(QRinput *input, int mask); +extern QRcode *QRcode_new(int version, int width, unsigned char *data); + +#endif /* __QRENCODE_INNER_H__ */ diff --git a/src/add-ons/kernel/debugger/qrencode/qrinput.c b/src/add-ons/kernel/debugger/qrencode/qrinput.c new file mode 100644 index 0000000000..5dcacf8aa2 --- /dev/null +++ b/src/add-ons/kernel/debugger/qrencode/qrinput.c @@ -0,0 +1,1724 @@ +/* + * qrencode - QR Code encoder + * + * Input data chunk class + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include + +#include "qrencode.h" +#include "qrspec.h" +#include "mqrspec.h" +#include "bitstream.h" +#include "qrinput.h" + +/****************************************************************************** + * Utilities + *****************************************************************************/ +int QRinput_isSplittableMode(QRencodeMode mode) +{ + return (mode >= QR_MODE_NUM && mode <= QR_MODE_KANJI); +} + +/****************************************************************************** + * Entry of input data + *****************************************************************************/ + +static QRinput_List *QRinput_List_newEntry(QRencodeMode mode, int size, const unsigned char *data) +{ + QRinput_List *entry; + + if(QRinput_check(mode, size, data)) { + errno = EINVAL; + return NULL; + } + + entry = (QRinput_List *)malloc(sizeof(QRinput_List)); + if(entry == NULL) return NULL; + + entry->mode = mode; + entry->size = size; + if(size > 0) { + entry->data = (unsigned char *)malloc(size); + if(entry->data == NULL) { + free(entry); + return NULL; + } + memcpy(entry->data, data, size); + } + entry->bstream = NULL; + entry->next = NULL; + + return entry; +} + +static void QRinput_List_freeEntry(QRinput_List *entry) +{ + if(entry != NULL) { + free(entry->data); + BitStream_free(entry->bstream); + free(entry); + } +} + +static QRinput_List *QRinput_List_dup(QRinput_List *entry) +{ + QRinput_List *n; + + n = (QRinput_List *)malloc(sizeof(QRinput_List)); + if(n == NULL) return NULL; + + n->mode = entry->mode; + n->size = entry->size; + n->data = (unsigned char *)malloc(n->size); + if(n->data == NULL) { + free(n); + return NULL; + } + memcpy(n->data, entry->data, entry->size); + n->bstream = NULL; + n->next = NULL; + + return n; +} + +/****************************************************************************** + * Input Data + *****************************************************************************/ + +QRinput *QRinput_new(void) +{ + return QRinput_new2(0, QR_ECLEVEL_L); +} + +QRinput *QRinput_new2(int version, QRecLevel level) +{ + QRinput *input; + + if(version < 0 || version > QRSPEC_VERSION_MAX || level > QR_ECLEVEL_H) { + errno = EINVAL; + return NULL; + } + + input = (QRinput *)malloc(sizeof(QRinput)); + if(input == NULL) return NULL; + + input->head = NULL; + input->tail = NULL; + input->version = version; + input->level = level; + input->mqr = 0; + input->fnc1 = 0; + + return input; +} + +QRinput *QRinput_newMQR(int version, QRecLevel level) +{ + QRinput *input; + + if(version <= 0 || version > MQRSPEC_VERSION_MAX) goto INVALID; + if((MQRspec_getECCLength(version, level) == 0)) goto INVALID; + + input = QRinput_new2(version, level); + if(input == NULL) return NULL; + + input->mqr = 1; + + return input; + +INVALID: + errno = EINVAL; + return NULL; +} + +int QRinput_getVersion(QRinput *input) +{ + return input->version; +} + +int QRinput_setVersion(QRinput *input, int version) +{ + if(input->mqr || version < 0 || version > QRSPEC_VERSION_MAX) { + errno = EINVAL; + return -1; + } + + input->version = version; + + return 0; +} + +QRecLevel QRinput_getErrorCorrectionLevel(QRinput *input) +{ + return input->level; +} + +int QRinput_setErrorCorrectionLevel(QRinput *input, QRecLevel level) +{ + if(input->mqr || level > QR_ECLEVEL_H) { + errno = EINVAL; + return -1; + } + + input->level = level; + + return 0; +} + +int QRinput_setVersionAndErrorCorrectionLevel(QRinput *input, int version, QRecLevel level) +{ + if(input->mqr) { + if(version <= 0 || version > MQRSPEC_VERSION_MAX) goto INVALID; + if((MQRspec_getECCLength(version, level) == 0)) goto INVALID; + } else { + if(version < 0 || version > QRSPEC_VERSION_MAX) goto INVALID; + if(level > QR_ECLEVEL_H) goto INVALID; + } + + input->version = version; + input->level = level; + + return 0; + +INVALID: + errno = EINVAL; + return -1; +} + +static void QRinput_appendEntry(QRinput *input, QRinput_List *entry) +{ + if(input->tail == NULL) { + input->head = entry; + input->tail = entry; + } else { + input->tail->next = entry; + input->tail = entry; + } + entry->next = NULL; +} + +int QRinput_append(QRinput *input, QRencodeMode mode, int size, const unsigned char *data) +{ + QRinput_List *entry; + + entry = QRinput_List_newEntry(mode, size, data); + if(entry == NULL) { + return -1; + } + + QRinput_appendEntry(input, entry); + + return 0; +} + +/** + * Insert a structured-append header to the head of the input data. + * @param input input data. + * @param size number of structured symbols. + * @param index index number of the symbol. (1 <= index <= size) + * @param parity parity among input data. (NOTE: each symbol of a set of structured symbols has the same parity data) + * @retval 0 success. + * @retval -1 error occurred and errno is set to indeicate the error. See Execptions for the details. + * @throw EINVAL invalid parameter. + * @throw ENOMEM unable to allocate memory. + */ +__STATIC int QRinput_insertStructuredAppendHeader(QRinput *input, int size, int index, unsigned char parity) +{ + QRinput_List *entry; + unsigned char buf[3]; + + if(size > MAX_STRUCTURED_SYMBOLS) { + errno = EINVAL; + return -1; + } + if(index <= 0 || index > MAX_STRUCTURED_SYMBOLS) { + errno = EINVAL; + return -1; + } + + buf[0] = (unsigned char)size; + buf[1] = (unsigned char)index; + buf[2] = parity; + entry = QRinput_List_newEntry(QR_MODE_STRUCTURE, 3, buf); + if(entry == NULL) { + return -1; + } + + entry->next = input->head; + input->head = entry; + + return 0; +} + +int QRinput_appendECIheader(QRinput *input, unsigned int ecinum) +{ + unsigned char data[4]; + + if(ecinum > 999999) { + errno = EINVAL; + return -1; + } + + /* We manually create byte array of ecinum because + (unsigned char *)&ecinum may cause bus error on some architectures, */ + data[0] = ecinum & 0xff; + data[1] = (ecinum >> 8) & 0xff; + data[2] = (ecinum >> 16) & 0xff; + data[3] = (ecinum >> 24) & 0xff; + return QRinput_append(input, QR_MODE_ECI, 4, data); +} + +void QRinput_free(QRinput *input) +{ + QRinput_List *list, *next; + + if(input != NULL) { + list = input->head; + while(list != NULL) { + next = list->next; + QRinput_List_freeEntry(list); + list = next; + } + free(input); + } +} + +static unsigned char QRinput_calcParity(QRinput *input) +{ + unsigned char parity = 0; + QRinput_List *list; + int i; + + list = input->head; + while(list != NULL) { + if(list->mode != QR_MODE_STRUCTURE) { + for(i=list->size-1; i>=0; i--) { + parity ^= list->data[i]; + } + } + list = list->next; + } + + return parity; +} + +QRinput *QRinput_dup(QRinput *input) +{ + QRinput *n; + QRinput_List *list, *e; + + if(input->mqr) { + n = QRinput_newMQR(input->version, input->level); + } else { + n = QRinput_new2(input->version, input->level); + } + if(n == NULL) return NULL; + + list = input->head; + while(list != NULL) { + e = QRinput_List_dup(list); + if(e == NULL) { + QRinput_free(n); + return NULL; + } + QRinput_appendEntry(n, e); + list = list->next; + } + + return n; +} + +/****************************************************************************** + * Numeric data + *****************************************************************************/ + +/** + * Check the input data. + * @param size + * @param data + * @return result + */ +static int QRinput_checkModeNum(int size, const char *data) +{ + int i; + + for(i=0; i '9') + return -1; + } + + return 0; +} + +/** + * Estimates the length of the encoded bit stream of numeric data. + * @param size + * @return number of bits + */ +int QRinput_estimateBitsModeNum(int size) +{ + int w; + int bits; + + w = size / 3; + bits = w * 10; + switch(size - w * 3) { + case 1: + bits += 4; + break; + case 2: + bits += 7; + break; + default: + break; + } + + return bits; +} + +/** + * Convert the number data to a bit stream. + * @param entry + * @param mqr + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + */ +static int QRinput_encodeModeNum(QRinput_List *entry, int version, int mqr) +{ + int words, i, ret; + unsigned int val; + + entry->bstream = BitStream_new(); + if(entry->bstream == NULL) return -1; + + if(mqr) { + if(version > 1) { + ret = BitStream_appendNum(entry->bstream, version - 1, MQRSPEC_MODEID_NUM); + if(ret < 0) goto ABORT; + } + ret = BitStream_appendNum(entry->bstream, MQRspec_lengthIndicator(QR_MODE_NUM, version), entry->size); + if(ret < 0) goto ABORT; + } else { + ret = BitStream_appendNum(entry->bstream, 4, QRSPEC_MODEID_NUM); + if(ret < 0) goto ABORT; + + ret = BitStream_appendNum(entry->bstream, QRspec_lengthIndicator(QR_MODE_NUM, version), entry->size); + if(ret < 0) goto ABORT; + } + + words = entry->size / 3; + for(i=0; idata[i*3 ] - '0') * 100; + val += (entry->data[i*3+1] - '0') * 10; + val += (entry->data[i*3+2] - '0'); + + ret = BitStream_appendNum(entry->bstream, 10, val); + if(ret < 0) goto ABORT; + } + + if(entry->size - words * 3 == 1) { + val = entry->data[words*3] - '0'; + ret = BitStream_appendNum(entry->bstream, 4, val); + if(ret < 0) goto ABORT; + } else if(entry->size - words * 3 == 2) { + val = (entry->data[words*3 ] - '0') * 10; + val += (entry->data[words*3+1] - '0'); + BitStream_appendNum(entry->bstream, 7, val); + if(ret < 0) goto ABORT; + } + + return 0; +ABORT: + BitStream_free(entry->bstream); + entry->bstream = NULL; + return -1; +} + +/****************************************************************************** + * Alphabet-numeric data + *****************************************************************************/ + +const signed char QRinput_anTable[128] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 +}; + +/** + * Check the input data. + * @param size + * @param data + * @return result + */ +static int QRinput_checkModeAn(int size, const char *data) +{ + int i; + + for(i=0; ibstream = BitStream_new(); + if(entry->bstream == NULL) return -1; + + if(mqr) { + if(version < 2) { + errno = EINVAL; + goto ABORT; + } + ret = BitStream_appendNum(entry->bstream, version - 1, MQRSPEC_MODEID_AN); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, MQRspec_lengthIndicator(QR_MODE_AN, version), entry->size); + if(ret < 0) goto ABORT; + } else { + ret = BitStream_appendNum(entry->bstream, 4, QRSPEC_MODEID_AN); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, QRspec_lengthIndicator(QR_MODE_AN, version), entry->size); + if(ret < 0) goto ABORT; + } + + words = entry->size / 2; + for(i=0; idata[i*2 ]) * 45; + val += (unsigned int)QRinput_lookAnTable(entry->data[i*2+1]); + + ret = BitStream_appendNum(entry->bstream, 11, val); + if(ret < 0) goto ABORT; + } + + if(entry->size & 1) { + val = (unsigned int)QRinput_lookAnTable(entry->data[words * 2]); + + ret = BitStream_appendNum(entry->bstream, 6, val); + if(ret < 0) goto ABORT; + } + + return 0; +ABORT: + BitStream_free(entry->bstream); + entry->bstream = NULL; + return -1; +} + +/****************************************************************************** + * 8 bit data + *****************************************************************************/ + +/** + * Estimates the length of the encoded bit stream of 8 bit data. + * @param size + * @return number of bits + */ +int QRinput_estimateBitsMode8(int size) +{ + return size * 8; +} + +/** + * Convert the 8bits data to a bit stream. + * @param entry + * @param mqr + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + */ +static int QRinput_encodeMode8(QRinput_List *entry, int version, int mqr) +{ + int ret; + + entry->bstream = BitStream_new(); + if(entry->bstream == NULL) return -1; + + if(mqr) { + if(version < 3) { + errno = EINVAL; + goto ABORT; + } + ret = BitStream_appendNum(entry->bstream, version - 1, MQRSPEC_MODEID_8); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, MQRspec_lengthIndicator(QR_MODE_8, version), entry->size); + if(ret < 0) goto ABORT; + } else { + ret = BitStream_appendNum(entry->bstream, 4, QRSPEC_MODEID_8); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, QRspec_lengthIndicator(QR_MODE_8, version), entry->size); + if(ret < 0) goto ABORT; + } + + ret = BitStream_appendBytes(entry->bstream, entry->size, entry->data); + if(ret < 0) goto ABORT; + + return 0; +ABORT: + BitStream_free(entry->bstream); + entry->bstream = NULL; + return -1; +} + + +/****************************************************************************** + * Kanji data + *****************************************************************************/ + +/** + * Estimates the length of the encoded bit stream of kanji data. + * @param size + * @return number of bits + */ +int QRinput_estimateBitsModeKanji(int size) +{ + return (size / 2) * 13; +} + +/** + * Check the input data. + * @param size + * @param data + * @return result + */ +static int QRinput_checkModeKanji(int size, const unsigned char *data) +{ + int i; + unsigned int val; + + if(size & 1) + return -1; + + for(i=0; i 0x9ffc && val < 0xe040) || val > 0xebbf) { + return -1; + } + } + + return 0; +} + +/** + * Convert the kanji data to a bit stream. + * @param entry + * @param mqr + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + * @throw EINVAL invalid version. + */ +static int QRinput_encodeModeKanji(QRinput_List *entry, int version, int mqr) +{ + int ret, i; + unsigned int val, h; + + entry->bstream = BitStream_new(); + if(entry->bstream == NULL) return -1; + + if(mqr) { + if(version < 2) { + errno = EINVAL; + goto ABORT; + } + ret = BitStream_appendNum(entry->bstream, version - 1, MQRSPEC_MODEID_KANJI); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, MQRspec_lengthIndicator(QR_MODE_KANJI, version), entry->size/2); + if(ret < 0) goto ABORT; + } else { + ret = BitStream_appendNum(entry->bstream, 4, QRSPEC_MODEID_KANJI); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, QRspec_lengthIndicator(QR_MODE_KANJI, version), entry->size/2); + if(ret < 0) goto ABORT; + } + + for(i=0; isize; i+=2) { + val = ((unsigned int)entry->data[i] << 8) | entry->data[i+1]; + if(val <= 0x9ffc) { + val -= 0x8140; + } else { + val -= 0xc140; + } + h = (val >> 8) * 0xc0; + val = (val & 0xff) + h; + + ret = BitStream_appendNum(entry->bstream, 13, val); + if(ret < 0) goto ABORT; + } + + return 0; +ABORT: + BitStream_free(entry->bstream); + entry->bstream = NULL; + return -1; +} + +/****************************************************************************** + * Structured Symbol + *****************************************************************************/ + +/** + * Convert a structure symbol code to a bit stream. + * @param entry + * @param mqr + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + * @throw EINVAL invalid entry. + */ +static int QRinput_encodeModeStructure(QRinput_List *entry, int mqr) +{ + int ret; + + if(mqr) { + errno = EINVAL; + return -1; + } + entry->bstream = BitStream_new(); + if(entry->bstream == NULL) return -1; + + ret = BitStream_appendNum(entry->bstream, 4, QRSPEC_MODEID_STRUCTURE); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, 4, entry->data[1] - 1); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, 4, entry->data[0] - 1); + if(ret < 0) goto ABORT; + ret = BitStream_appendNum(entry->bstream, 8, entry->data[2]); + if(ret < 0) goto ABORT; + + return 0; +ABORT: + BitStream_free(entry->bstream); + entry->bstream = NULL; + return -1; +} + +/****************************************************************************** + * FNC1 + *****************************************************************************/ + +static int QRinput_checkModeFNC1Second(int size, const unsigned char *data) +{ + if(size != 1) return -1; + + return 0; +} + +static int QRinput_encodeModeFNC1Second(QRinput_List *entry, int version) +{ + int ret; + + entry->bstream = BitStream_new(); + if(entry->bstream == NULL) return -1; + + ret = BitStream_appendNum(entry->bstream, 4, QRSPEC_MODEID_FNC1SECOND); + if(ret < 0) goto ABORT; + + ret = BitStream_appendBytes(entry->bstream, 1, entry->data); + if(ret < 0) goto ABORT; + + return 0; +ABORT: + BitStream_free(entry->bstream); + entry->bstream = NULL; + return -1; +} + +/****************************************************************************** + * ECI header + *****************************************************************************/ +static unsigned int QRinput_decodeECIfromByteArray(unsigned char *data) +{ + int i; + unsigned int ecinum; + + ecinum = 0; + for(i=0; i<4; i++) { + ecinum = ecinum << 8; + ecinum |= data[3-i]; + } + + return ecinum; +} + +int QRinput_estimateBitsModeECI(unsigned char *data) +{ + unsigned int ecinum; + + ecinum = QRinput_decodeECIfromByteArray(data);; + + /* See Table 4 of JISX 0510:2004 pp.17. */ + if(ecinum < 128) { + return MODE_INDICATOR_SIZE + 8; + } else if(ecinum < 16384) { + return MODE_INDICATOR_SIZE + 16; + } else { + return MODE_INDICATOR_SIZE + 24; + } +} + +static int QRinput_encodeModeECI(QRinput_List *entry, int version) +{ + int ret, words; + unsigned int ecinum, code; + + entry->bstream = BitStream_new(); + if(entry->bstream == NULL) return -1; + + ecinum = QRinput_decodeECIfromByteArray(entry->data);; + + /* See Table 4 of JISX 0510:2004 pp.17. */ + if(ecinum < 128) { + words = 1; + code = ecinum; + } else if(ecinum < 16384) { + words = 2; + code = 0x8000 + ecinum; + } else { + words = 3; + code = 0xc0000 + ecinum; + } + + ret = BitStream_appendNum(entry->bstream, 4, QRSPEC_MODEID_ECI); + if(ret < 0) goto ABORT; + + ret = BitStream_appendNum(entry->bstream, words * 8, code); + if(ret < 0) goto ABORT; + + return 0; +ABORT: + BitStream_free(entry->bstream); + entry->bstream = NULL; + return -1; +} + +/****************************************************************************** + * Validation + *****************************************************************************/ + +int QRinput_check(QRencodeMode mode, int size, const unsigned char *data) +{ + if((mode == QR_MODE_FNC1FIRST && size < 0) || size <= 0) return -1; + + switch(mode) { + case QR_MODE_NUM: + return QRinput_checkModeNum(size, (const char *)data); + case QR_MODE_AN: + return QRinput_checkModeAn(size, (const char *)data); + case QR_MODE_KANJI: + return QRinput_checkModeKanji(size, data); + case QR_MODE_8: + return 0; + case QR_MODE_STRUCTURE: + return 0; + case QR_MODE_ECI: + return 0; + case QR_MODE_FNC1FIRST: + return 0; + case QR_MODE_FNC1SECOND: + return QRinput_checkModeFNC1Second(size, data); + case QR_MODE_NUL: + break; + } + + return -1; +} + +/****************************************************************************** + * Estimation of the bit length + *****************************************************************************/ + +/** + * Estimates the length of the encoded bit stream on the current version. + * @param entry + * @param version version of the symbol + * @param mqr + * @return number of bits + */ +static int QRinput_estimateBitStreamSizeOfEntry(QRinput_List *entry, int version, int mqr) +{ + int bits = 0; + int l, m; + int num; + + if(version == 0) version = 1; + + switch(entry->mode) { + case QR_MODE_NUM: + bits = QRinput_estimateBitsModeNum(entry->size); + break; + case QR_MODE_AN: + bits = QRinput_estimateBitsModeAn(entry->size); + break; + case QR_MODE_8: + bits = QRinput_estimateBitsMode8(entry->size); + break; + case QR_MODE_KANJI: + bits = QRinput_estimateBitsModeKanji(entry->size); + break; + case QR_MODE_STRUCTURE: + return STRUCTURE_HEADER_SIZE; + case QR_MODE_ECI: + bits = QRinput_estimateBitsModeECI(entry->data); + break; + case QR_MODE_FNC1FIRST: + return MODE_INDICATOR_SIZE; + break; + case QR_MODE_FNC1SECOND: + return MODE_INDICATOR_SIZE + 8; + default: + return 0; + } + + if(mqr) { + l = QRspec_lengthIndicator(entry->mode, version); + m = version - 1; + bits += l + m; + } else { + l = QRspec_lengthIndicator(entry->mode, version); + m = 1 << l; + num = (entry->size + m - 1) / m; + + bits += num * (MODE_INDICATOR_SIZE + l); + } + + return bits; +} + +/** + * Estimates the length of the encoded bit stream of the data. + * @param input input data + * @param version version of the symbol + * @return number of bits + */ +__STATIC int QRinput_estimateBitStreamSize(QRinput *input, int version) +{ + QRinput_List *list; + int bits = 0; + + list = input->head; + while(list != NULL) { + bits += QRinput_estimateBitStreamSizeOfEntry(list, version, input->mqr); + list = list->next; + } + + return bits; +} + +/** + * Estimates the required version number of the symbol. + * @param input input data + * @return required version number + */ +static int QRinput_estimateVersion(QRinput *input) +{ + int bits; + int version, prev; + + version = 0; + do { + prev = version; + bits = QRinput_estimateBitStreamSize(input, prev); + version = QRspec_getMinimumVersion((bits + 7) / 8, input->level); + if (version < 0) { + return -1; + } + } while (version > prev); + + return version; +} + +/** + * Returns required length in bytes for specified mode, version and bits. + * @param mode + * @param version + * @param bits + * @return required length of code words in bytes. + */ +__STATIC int QRinput_lengthOfCode(QRencodeMode mode, int version, int bits) +{ + int payload, size, chunks, remain, maxsize; + + payload = bits - 4 - QRspec_lengthIndicator(mode, version); + switch(mode) { + case QR_MODE_NUM: + chunks = payload / 10; + remain = payload - chunks * 10; + size = chunks * 3; + if(remain >= 7) { + size += 2; + } else if(remain >= 4) { + size += 1; + } + break; + case QR_MODE_AN: + chunks = payload / 11; + remain = payload - chunks * 11; + size = chunks * 2; + if(remain >= 6) size++; + break; + case QR_MODE_8: + size = payload / 8; + break; + case QR_MODE_KANJI: + size = (payload / 13) * 2; + break; + case QR_MODE_STRUCTURE: + size = payload / 8; + break; + default: + size = 0; + break; + } + maxsize = QRspec_maximumWords(mode, version); + if(size < 0) size = 0; + if(maxsize > 0 && size > maxsize) size = maxsize; + + return size; +} + +/****************************************************************************** + * Data conversion + *****************************************************************************/ + +/** + * Convert the input data in the data chunk to a bit stream. + * @param entry + * @return number of bits (>0) or -1 for failure. + */ +static int QRinput_encodeBitStream(QRinput_List *entry, int version, int mqr) +{ + int words, ret; + QRinput_List *st1 = NULL, *st2 = NULL; + + if(entry->bstream != NULL) { + BitStream_free(entry->bstream); + entry->bstream = NULL; + } + + words = QRspec_maximumWords(entry->mode, version); + if(words != 0 && entry->size > words) { + st1 = QRinput_List_newEntry(entry->mode, words, entry->data); + if(st1 == NULL) goto ABORT; + st2 = QRinput_List_newEntry(entry->mode, entry->size - words, &entry->data[words]); + if(st2 == NULL) goto ABORT; + + ret = QRinput_encodeBitStream(st1, version, mqr); + if(ret < 0) goto ABORT; + ret = QRinput_encodeBitStream(st2, version, mqr); + if(ret < 0) goto ABORT; + entry->bstream = BitStream_new(); + if(entry->bstream == NULL) goto ABORT; + ret = BitStream_append(entry->bstream, st1->bstream); + if(ret < 0) goto ABORT; + ret = BitStream_append(entry->bstream, st2->bstream); + if(ret < 0) goto ABORT; + QRinput_List_freeEntry(st1); + QRinput_List_freeEntry(st2); + } else { + ret = 0; + switch(entry->mode) { + case QR_MODE_NUM: + ret = QRinput_encodeModeNum(entry, version, mqr); + break; + case QR_MODE_AN: + ret = QRinput_encodeModeAn(entry, version, mqr); + break; + case QR_MODE_8: + ret = QRinput_encodeMode8(entry, version, mqr); + break; + case QR_MODE_KANJI: + ret = QRinput_encodeModeKanji(entry, version, mqr); + break; + case QR_MODE_STRUCTURE: + ret = QRinput_encodeModeStructure(entry, mqr); + break; + case QR_MODE_ECI: + ret = QRinput_encodeModeECI(entry, version); + break; + case QR_MODE_FNC1SECOND: + ret = QRinput_encodeModeFNC1Second(entry, version); + default: + break; + } + if(ret < 0) return -1; + } + + return BitStream_size(entry->bstream); +ABORT: + QRinput_List_freeEntry(st1); + QRinput_List_freeEntry(st2); + return -1; +} + +/** + * Convert the input data to a bit stream. + * @param input input data. + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + */ +static int QRinput_createBitStream(QRinput *input) +{ + QRinput_List *list; + int bits, total = 0; + + list = input->head; + while(list != NULL) { + bits = QRinput_encodeBitStream(list, input->version, input->mqr); + if(bits < 0) return -1; + total += bits; + list = list->next; + } + + return total; +} + +/** + * Convert the input data to a bit stream. + * When the version number is given and that is not sufficient, it is increased + * automatically. + * @param input input data. + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + * @throw ERANGE input is too large. + */ +static int QRinput_convertData(QRinput *input) +{ + int bits; + int ver; + + ver = QRinput_estimateVersion(input); + if(ver > QRinput_getVersion(input)) { + QRinput_setVersion(input, ver); + } + + for(;;) { + bits = QRinput_createBitStream(input); + if(bits < 0) return -1; + ver = QRspec_getMinimumVersion((bits + 7) / 8, input->level); + if(ver < 0) { + errno = ERANGE; + return -1; + } else if(ver > QRinput_getVersion(input)) { + QRinput_setVersion(input, ver); + } else { + break; + } + } + + return 0; +} + +/** + * Append padding bits for the input data. + * @param bstream Bitstream to be appended. + * @param input input data. + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ERANGE input data is too large. + * @throw ENOMEM unable to allocate memory. + */ +static int QRinput_appendPaddingBit(BitStream *bstream, QRinput *input) +{ + int bits, maxbits, words, maxwords, i, ret; + BitStream *padding = NULL; + unsigned char *padbuf; + int padlen; + + bits = BitStream_size(bstream); + maxwords = QRspec_getDataLength(input->version, input->level); + maxbits = maxwords * 8; + + if(maxbits < bits) { + errno = ERANGE; + return -1; + } + if(maxbits == bits) { + return 0; + } + + if(maxbits - bits <= 4) { + ret = BitStream_appendNum(bstream, maxbits - bits, 0); + goto DONE; + } + + words = (bits + 4 + 7) / 8; + + padding = BitStream_new(); + if(padding == NULL) return -1; + ret = BitStream_appendNum(padding, words * 8 - bits, 0); + if(ret < 0) goto DONE; + + padlen = maxwords - words; + if(padlen > 0) { + padbuf = (unsigned char *)malloc(padlen); + if(padbuf == NULL) { + ret = -1; + goto DONE; + } + for(i=0; iversion, input->level); + maxwords = maxbits / 8; + + if(maxbits < bits) { + errno = ERANGE; + return -1; + } + if(maxbits == bits) { + return 0; + } + + termbits = input->version * 2 + 1; + + if(maxbits - bits <= termbits) { + ret = BitStream_appendNum(bstream, maxbits - bits, 0); + goto DONE; + } + + bits += termbits; + + words = (bits + 7) / 8; + if(maxbits - words * 8 > 0) { + termbits += words * 8 - bits; + if(words == maxwords) termbits += maxbits - words * 8; + } else { + termbits += words * 8 - bits; + } + padding = BitStream_new(); + if(padding == NULL) return -1; + ret = BitStream_appendNum(padding, termbits, 0); + if(ret < 0) goto DONE; + + padlen = maxwords - words; + if(padlen > 0) { + padbuf = (unsigned char *)malloc(padlen); + if(padbuf == NULL) { + ret = -1; + goto DONE; + } + for(i=0; i 0) { + ret = BitStream_appendNum(padding, termbits, 0); + if(ret < 0) goto DONE; + } + } + + ret = BitStream_append(bstream, padding); + +DONE: + BitStream_free(padding); + return ret; +} + +static int QRinput_insertFNC1Header(QRinput *input) +{ + QRinput_List *entry = NULL; + + if(input->fnc1 == 1) { + entry = QRinput_List_newEntry(QR_MODE_FNC1FIRST, 0, NULL); + } else if(input->fnc1 == 2) { + entry = QRinput_List_newEntry(QR_MODE_FNC1SECOND, 1, &(input->appid)); + } + if(entry == NULL) { + return -1; + } + + if(input->head->mode != QR_MODE_STRUCTURE || input->head->mode != QR_MODE_ECI) { + entry->next = input->head; + input->head = entry; + } else { + entry->next = input->head->next; + input->head->next = entry; + } + + return 0; +} + +/** + * Merge all bit streams in the input data. + * @param input input data. + * @return merged bit stream + */ + +__STATIC BitStream *QRinput_mergeBitStream(QRinput *input) +{ + BitStream *bstream; + QRinput_List *list; + int ret; + + if(input->mqr) { + if(QRinput_createBitStream(input) < 0) { + return NULL; + } + } else { + if(input->fnc1) { + if(QRinput_insertFNC1Header(input) < 0) { + return NULL; + } + } + if(QRinput_convertData(input) < 0) { + return NULL; + } + } + + bstream = BitStream_new(); + if(bstream == NULL) return NULL; + + list = input->head; + while(list != NULL) { + ret = BitStream_append(bstream, list->bstream); + if(ret < 0) { + BitStream_free(bstream); + return NULL; + } + list = list->next; + } + + return bstream; +} + +/** + * Merge all bit streams in the input data and append padding bits + * @param input input data. + * @return padded merged bit stream + */ + +__STATIC BitStream *QRinput_getBitStream(QRinput *input) +{ + BitStream *bstream; + int ret; + + bstream = QRinput_mergeBitStream(input); + if(bstream == NULL) { + return NULL; + } + if(input->mqr) { + ret = QRinput_appendPaddingBitMQR(bstream, input); + } else { + ret = QRinput_appendPaddingBit(bstream, input); + } + if(ret < 0) { + BitStream_free(bstream); + return NULL; + } + + return bstream; +} + +/** + * Pack all bit streams padding bits into a byte array. + * @param input input data. + * @return padded merged byte stream + */ + +unsigned char *QRinput_getByteStream(QRinput *input) +{ + BitStream *bstream; + unsigned char *array; + + bstream = QRinput_getBitStream(input); + if(bstream == NULL) { + return NULL; + } + array = BitStream_toByte(bstream); + BitStream_free(bstream); + + return array; +} + +/****************************************************************************** + * Structured input data + *****************************************************************************/ + +static QRinput_InputList *QRinput_InputList_newEntry(QRinput *input) +{ + QRinput_InputList *entry; + + entry = (QRinput_InputList *)malloc(sizeof(QRinput_InputList)); + if(entry == NULL) return NULL; + + entry->input = input; + entry->next = NULL; + + return entry; +} + +static void QRinput_InputList_freeEntry(QRinput_InputList *entry) +{ + if(entry != NULL) { + QRinput_free(entry->input); + free(entry); + } +} + +QRinput_Struct *QRinput_Struct_new(void) +{ + QRinput_Struct *s; + + s = (QRinput_Struct *)malloc(sizeof(QRinput_Struct)); + if(s == NULL) return NULL; + + s->size = 0; + s->parity = -1; + s->head = NULL; + s->tail = NULL; + + return s; +} + +void QRinput_Struct_setParity(QRinput_Struct *s, unsigned char parity) +{ + s->parity = (int)parity; +} + +int QRinput_Struct_appendInput(QRinput_Struct *s, QRinput *input) +{ + QRinput_InputList *e; + + if(input->mqr) { + errno = EINVAL; + return -1; + } + + e = QRinput_InputList_newEntry(input); + if(e == NULL) return -1; + + s->size++; + if(s->tail == NULL) { + s->head = e; + s->tail = e; + } else { + s->tail->next = e; + s->tail = e; + } + + return s->size; +} + +void QRinput_Struct_free(QRinput_Struct *s) +{ + QRinput_InputList *list, *next; + + if(s != NULL) { + list = s->head; + while(list != NULL) { + next = list->next; + QRinput_InputList_freeEntry(list); + list = next; + } + free(s); + } +} + +static unsigned char QRinput_Struct_calcParity(QRinput_Struct *s) +{ + QRinput_InputList *list; + unsigned char parity = 0; + + list = s->head; + while(list != NULL) { + parity ^= QRinput_calcParity(list->input); + list = list->next; + } + + QRinput_Struct_setParity(s, parity); + + return parity; +} + +static int QRinput_List_shrinkEntry(QRinput_List *entry, int bytes) +{ + unsigned char *data; + + data = (unsigned char *)malloc(bytes); + if(data == NULL) return -1; + + memcpy(data, entry->data, bytes); + free(entry->data); + entry->data = data; + entry->size = bytes; + + return 0; +} + +__STATIC int QRinput_splitEntry(QRinput_List *entry, int bytes) +{ + QRinput_List *e; + int ret; + + e = QRinput_List_newEntry(entry->mode, entry->size - bytes, entry->data + bytes); + if(e == NULL) { + return -1; + } + + ret = QRinput_List_shrinkEntry(entry, bytes); + if(ret < 0) { + QRinput_List_freeEntry(e); + return -1; + } + + e->next = entry->next; + entry->next = e; + + return 0; +} + +QRinput_Struct *QRinput_splitQRinputToStruct(QRinput *input) +{ + QRinput *p; + QRinput_Struct *s; + int bits, maxbits, nextbits, bytes, ret; + QRinput_List *list, *next, *prev; + + if(input->mqr) { + errno = EINVAL; + return NULL; + } + + s = QRinput_Struct_new(); + if(s == NULL) return NULL; + + input = QRinput_dup(input); + if(input == NULL) { + QRinput_Struct_free(s); + return NULL; + } + + QRinput_Struct_setParity(s, QRinput_calcParity(input)); + maxbits = QRspec_getDataLength(input->version, input->level) * 8 - STRUCTURE_HEADER_SIZE; + + if(maxbits <= 0) { + QRinput_Struct_free(s); + QRinput_free(input); + return NULL; + } + + bits = 0; + list = input->head; + prev = NULL; + while(list != NULL) { + nextbits = QRinput_estimateBitStreamSizeOfEntry(list, input->version, input->mqr); + if(bits + nextbits <= maxbits) { + ret = QRinput_encodeBitStream(list, input->version, input->mqr); + if(ret < 0) goto ABORT; + bits += ret; + prev = list; + list = list->next; + } else { + bytes = QRinput_lengthOfCode(list->mode, input->version, maxbits - bits); + if(bytes > 0) { + /* Splits this entry into 2 entries. */ + ret = QRinput_splitEntry(list, bytes); + if(ret < 0) goto ABORT; + /* First half is the tail of the current input. */ + next = list->next; + list->next = NULL; + /* Second half is the head of the next input, p.*/ + p = QRinput_new2(input->version, input->level); + if(p == NULL) goto ABORT; + p->head = next; + /* Renew QRinput.tail. */ + p->tail = input->tail; + input->tail = list; + /* Point to the next entry. */ + prev = list; + list = next; + } else { + /* Current entry will go to the next input. */ + prev->next = NULL; + p = QRinput_new2(input->version, input->level); + if(p == NULL) goto ABORT; + p->head = list; + p->tail = input->tail; + input->tail = prev; + } + ret = QRinput_Struct_appendInput(s, input); + if(ret < 0) goto ABORT; + input = p; + bits = 0; + } + } + QRinput_Struct_appendInput(s, input); + if(s->size > MAX_STRUCTURED_SYMBOLS) { + QRinput_Struct_free(s); + errno = ERANGE; + return NULL; + } + ret = QRinput_Struct_insertStructuredAppendHeaders(s); + if(ret < 0) { + QRinput_Struct_free(s); + return NULL; + } + + return s; + +ABORT: + QRinput_free(input); + QRinput_Struct_free(s); + return NULL; +} + +int QRinput_Struct_insertStructuredAppendHeaders(QRinput_Struct *s) +{ + int num, i; + QRinput_InputList *list; + + if(s->parity < 0) { + QRinput_Struct_calcParity(s); + } + num = 0; + list = s->head; + while(list != NULL) { + num++; + list = list->next; + } + i = 1; + list = s->head; + while(list != NULL) { + if(QRinput_insertStructuredAppendHeader(list->input, num, i, s->parity)) + return -1; + i++; + list = list->next; + } + + return 0; +} + +/****************************************************************************** + * Extended encoding mode (FNC1 and ECI) + *****************************************************************************/ + +int QRinput_setFNC1First(QRinput *input) +{ + if(input->mqr) { + errno = EINVAL; + return -1; + } + input->fnc1 = 1; + + return 0; +} + +int QRinput_setFNC1Second(QRinput *input, unsigned char appid) +{ + if(input->mqr) { + errno = EINVAL; + return -1; + } + input->fnc1 = 2; + input->appid = appid; + + return 0; +} diff --git a/src/add-ons/kernel/debugger/qrencode/qrinput.h b/src/add-ons/kernel/debugger/qrencode/qrinput.h new file mode 100644 index 0000000000..9e6bad625d --- /dev/null +++ b/src/add-ons/kernel/debugger/qrencode/qrinput.h @@ -0,0 +1,123 @@ +/* + * qrencode - QR Code encoder + * + * Input data chunk class + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __QRINPUT_H__ +#define __QRINPUT_H__ + +#include "qrencode.h" +#include "bitstream.h" + +int QRinput_isSplittableMode(QRencodeMode mode); + +/****************************************************************************** + * Entry of input data + *****************************************************************************/ +typedef struct _QRinput_List QRinput_List; + +struct _QRinput_List { + QRencodeMode mode; + int size; ///< Size of data chunk (byte). + unsigned char *data; ///< Data chunk. + BitStream *bstream; + QRinput_List *next; +}; + +/****************************************************************************** + * Input Data + *****************************************************************************/ +struct _QRinput { + int version; + QRecLevel level; + QRinput_List *head; + QRinput_List *tail; + int mqr; + int fnc1; + unsigned char appid; +}; + +/****************************************************************************** + * Structured append input data + *****************************************************************************/ +typedef struct _QRinput_InputList QRinput_InputList; + +struct _QRinput_InputList { + QRinput *input; + QRinput_InputList *next; +}; + +struct _QRinput_Struct { + int size; ///< number of structured symbols + int parity; + QRinput_InputList *head; + QRinput_InputList *tail; +}; + +/** + * Pack all bit streams padding bits into a byte array. + * @param input input data. + * @return padded merged byte stream + */ +extern unsigned char *QRinput_getByteStream(QRinput *input); + + +extern int QRinput_estimateBitsModeNum(int size); +extern int QRinput_estimateBitsModeAn(int size); +extern int QRinput_estimateBitsMode8(int size); +extern int QRinput_estimateBitsModeKanji(int size); + +extern QRinput *QRinput_dup(QRinput *input); + +extern const signed char QRinput_anTable[128]; + +/** + * Look up the alphabet-numeric convesion table (see JIS X0510:2004, pp.19). + * @param __c__ character + * @return value + */ +#define QRinput_lookAnTable(__c__) \ + ((__c__ & 0x80)?-1:QRinput_anTable[(int)__c__]) + +/** + * Length of a standard mode indicator in bits. + */ + +#define MODE_INDICATOR_SIZE 4 + +/** + * Length of a segment of structured-append header. + */ +#define STRUCTURE_HEADER_SIZE 20 + +/** + * Maximum number of symbols in a set of structured-appended symbols. + */ +#define MAX_STRUCTURED_SYMBOLS 16 + +#ifdef WITH_TESTS +extern BitStream *QRinput_mergeBitStream(QRinput *input); +extern BitStream *QRinput_getBitStream(QRinput *input); +extern int QRinput_estimateBitStreamSize(QRinput *input, int version); +extern int QRinput_splitEntry(QRinput_List *entry, int bytes); +extern int QRinput_lengthOfCode(QRencodeMode mode, int version, int bits); +extern int QRinput_insertStructuredAppendHeader(QRinput *input, int size, int index, unsigned char parity); +#endif + +#endif /* __QRINPUT_H__ */ diff --git a/src/add-ons/kernel/debugger/qrencode/qrspec.c b/src/add-ons/kernel/debugger/qrencode/qrspec.c new file mode 100644 index 0000000000..a42706f4b8 --- /dev/null +++ b/src/add-ons/kernel/debugger/qrencode/qrspec.c @@ -0,0 +1,562 @@ +/* + * qrencode - QR Code encoder + * + * QR Code specification in convenient format. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * The following data / specifications are taken from + * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) + * or + * "Automatic identification and data capture techniques -- + * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include +#ifdef HAVE_LIBPTHREAD +#include +#endif + +#include "qrspec.h" +#include "qrinput.h" + +/****************************************************************************** + * Version and capacity + *****************************************************************************/ + +typedef struct { + int width; //< Edge length of the symbol + int words; //< Data capacity (bytes) + int remainder; //< Remainder bit (bits) + int ec[4]; //< Number of ECC code (bytes) +} QRspec_Capacity; + +/** + * Table of the capacity of symbols + * See Table 1 (pp.13) and Table 12-16 (pp.30-36), JIS X0510:2004. + */ +static const QRspec_Capacity qrspecCapacity[QRSPEC_VERSION_MAX + 1] = { + { 0, 0, 0, { 0, 0, 0, 0}}, + { 21, 26, 0, { 7, 10, 13, 17}}, // 1 + { 25, 44, 7, { 10, 16, 22, 28}}, + { 29, 70, 7, { 15, 26, 36, 44}}, + { 33, 100, 7, { 20, 36, 52, 64}}, + { 37, 134, 7, { 26, 48, 72, 88}}, // 5 + { 41, 172, 7, { 36, 64, 96, 112}}, + { 45, 196, 0, { 40, 72, 108, 130}}, + { 49, 242, 0, { 48, 88, 132, 156}}, + { 53, 292, 0, { 60, 110, 160, 192}}, + { 57, 346, 0, { 72, 130, 192, 224}}, //10 + { 61, 404, 0, { 80, 150, 224, 264}}, + { 65, 466, 0, { 96, 176, 260, 308}}, + { 69, 532, 0, { 104, 198, 288, 352}}, + { 73, 581, 3, { 120, 216, 320, 384}}, + { 77, 655, 3, { 132, 240, 360, 432}}, //15 + { 81, 733, 3, { 144, 280, 408, 480}}, + { 85, 815, 3, { 168, 308, 448, 532}}, + { 89, 901, 3, { 180, 338, 504, 588}}, + { 93, 991, 3, { 196, 364, 546, 650}}, + { 97, 1085, 3, { 224, 416, 600, 700}}, //20 + {101, 1156, 4, { 224, 442, 644, 750}}, + {105, 1258, 4, { 252, 476, 690, 816}}, + {109, 1364, 4, { 270, 504, 750, 900}}, + {113, 1474, 4, { 300, 560, 810, 960}}, + {117, 1588, 4, { 312, 588, 870, 1050}}, //25 + {121, 1706, 4, { 336, 644, 952, 1110}}, + {125, 1828, 4, { 360, 700, 1020, 1200}}, + {129, 1921, 3, { 390, 728, 1050, 1260}}, + {133, 2051, 3, { 420, 784, 1140, 1350}}, + {137, 2185, 3, { 450, 812, 1200, 1440}}, //30 + {141, 2323, 3, { 480, 868, 1290, 1530}}, + {145, 2465, 3, { 510, 924, 1350, 1620}}, + {149, 2611, 3, { 540, 980, 1440, 1710}}, + {153, 2761, 3, { 570, 1036, 1530, 1800}}, + {157, 2876, 0, { 570, 1064, 1590, 1890}}, //35 + {161, 3034, 0, { 600, 1120, 1680, 1980}}, + {165, 3196, 0, { 630, 1204, 1770, 2100}}, + {169, 3362, 0, { 660, 1260, 1860, 2220}}, + {173, 3532, 0, { 720, 1316, 1950, 2310}}, + {177, 3706, 0, { 750, 1372, 2040, 2430}} //40 +}; + +int QRspec_getDataLength(int version, QRecLevel level) +{ + return qrspecCapacity[version].words - qrspecCapacity[version].ec[level]; +} + +int QRspec_getECCLength(int version, QRecLevel level) +{ + return qrspecCapacity[version].ec[level]; +} + +int QRspec_getMinimumVersion(int size, QRecLevel level) +{ + int i; + int words; + + for(i=1; i<= QRSPEC_VERSION_MAX; i++) { + words = qrspecCapacity[i].words - qrspecCapacity[i].ec[level]; + if(words >= size) return i; + } + + return -1; +} + +int QRspec_getWidth(int version) +{ + return qrspecCapacity[version].width; +} + +int QRspec_getRemainder(int version) +{ + return qrspecCapacity[version].remainder; +} + +/****************************************************************************** + * Length indicator + *****************************************************************************/ + +static const int lengthTableBits[4][3] = { + {10, 12, 14}, + { 9, 11, 13}, + { 8, 16, 16}, + { 8, 10, 12} +}; + +int QRspec_lengthIndicator(QRencodeMode mode, int version) +{ + int l; + + if(!QRinput_isSplittableMode(mode)) return 0; + if(version <= 9) { + l = 0; + } else if(version <= 26) { + l = 1; + } else { + l = 2; + } + + return lengthTableBits[mode][l]; +} + +int QRspec_maximumWords(QRencodeMode mode, int version) +{ + int l; + int bits; + int words; + + if(!QRinput_isSplittableMode(mode)) return 0; + if(version <= 9) { + l = 0; + } else if(version <= 26) { + l = 1; + } else { + l = 2; + } + + bits = lengthTableBits[mode][l]; + words = (1 << bits) - 1; + if(mode == QR_MODE_KANJI) { + words *= 2; // the number of bytes is required + } + + return words; +} + +/****************************************************************************** + * Error correction code + *****************************************************************************/ + +/** + * Table of the error correction code (Reed-Solomon block) + * See Table 12-16 (pp.30-36), JIS X0510:2004. + */ +static const int eccTable[QRSPEC_VERSION_MAX+1][4][2] = { + {{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}, + {{ 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}}, // 1 + {{ 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}}, + {{ 1, 0}, { 1, 0}, { 2, 0}, { 2, 0}}, + {{ 1, 0}, { 2, 0}, { 2, 0}, { 4, 0}}, + {{ 1, 0}, { 2, 0}, { 2, 2}, { 2, 2}}, // 5 + {{ 2, 0}, { 4, 0}, { 4, 0}, { 4, 0}}, + {{ 2, 0}, { 4, 0}, { 2, 4}, { 4, 1}}, + {{ 2, 0}, { 2, 2}, { 4, 2}, { 4, 2}}, + {{ 2, 0}, { 3, 2}, { 4, 4}, { 4, 4}}, + {{ 2, 2}, { 4, 1}, { 6, 2}, { 6, 2}}, //10 + {{ 4, 0}, { 1, 4}, { 4, 4}, { 3, 8}}, + {{ 2, 2}, { 6, 2}, { 4, 6}, { 7, 4}}, + {{ 4, 0}, { 8, 1}, { 8, 4}, {12, 4}}, + {{ 3, 1}, { 4, 5}, {11, 5}, {11, 5}}, + {{ 5, 1}, { 5, 5}, { 5, 7}, {11, 7}}, //15 + {{ 5, 1}, { 7, 3}, {15, 2}, { 3, 13}}, + {{ 1, 5}, {10, 1}, { 1, 15}, { 2, 17}}, + {{ 5, 1}, { 9, 4}, {17, 1}, { 2, 19}}, + {{ 3, 4}, { 3, 11}, {17, 4}, { 9, 16}}, + {{ 3, 5}, { 3, 13}, {15, 5}, {15, 10}}, //20 + {{ 4, 4}, {17, 0}, {17, 6}, {19, 6}}, + {{ 2, 7}, {17, 0}, { 7, 16}, {34, 0}}, + {{ 4, 5}, { 4, 14}, {11, 14}, {16, 14}}, + {{ 6, 4}, { 6, 14}, {11, 16}, {30, 2}}, + {{ 8, 4}, { 8, 13}, { 7, 22}, {22, 13}}, //25 + {{10, 2}, {19, 4}, {28, 6}, {33, 4}}, + {{ 8, 4}, {22, 3}, { 8, 26}, {12, 28}}, + {{ 3, 10}, { 3, 23}, { 4, 31}, {11, 31}}, + {{ 7, 7}, {21, 7}, { 1, 37}, {19, 26}}, + {{ 5, 10}, {19, 10}, {15, 25}, {23, 25}}, //30 + {{13, 3}, { 2, 29}, {42, 1}, {23, 28}}, + {{17, 0}, {10, 23}, {10, 35}, {19, 35}}, + {{17, 1}, {14, 21}, {29, 19}, {11, 46}}, + {{13, 6}, {14, 23}, {44, 7}, {59, 1}}, + {{12, 7}, {12, 26}, {39, 14}, {22, 41}}, //35 + {{ 6, 14}, { 6, 34}, {46, 10}, { 2, 64}}, + {{17, 4}, {29, 14}, {49, 10}, {24, 46}}, + {{ 4, 18}, {13, 32}, {48, 14}, {42, 32}}, + {{20, 4}, {40, 7}, {43, 22}, {10, 67}}, + {{19, 6}, {18, 31}, {34, 34}, {20, 61}},//40 +}; + +void QRspec_getEccSpec(int version, QRecLevel level, int spec[5]) +{ + int b1, b2; + int data, ecc; + + b1 = eccTable[version][level][0]; + b2 = eccTable[version][level][1]; + data = QRspec_getDataLength(version, level); + ecc = QRspec_getECCLength(version, level); + + if(b2 == 0) { + spec[0] = b1; + spec[1] = data / b1; + spec[2] = ecc / b1; + spec[3] = spec[4] = 0; + } else { + spec[0] = b1; + spec[1] = data / (b1 + b2); + spec[2] = ecc / (b1 + b2); + spec[3] = b2; + spec[4] = spec[1] + 1; + } +} + +/****************************************************************************** + * Alignment pattern + *****************************************************************************/ + +/** + * Positions of alignment patterns. + * This array includes only the second and the third position of the alignment + * patterns. Rest of them can be calculated from the distance between them. + * + * See Table 1 in Appendix E (pp.71) of JIS X0510:2004. + */ +static const int alignmentPattern[QRSPEC_VERSION_MAX+1][2] = { + { 0, 0}, + { 0, 0}, {18, 0}, {22, 0}, {26, 0}, {30, 0}, // 1- 5 + {34, 0}, {22, 38}, {24, 42}, {26, 46}, {28, 50}, // 6-10 + {30, 54}, {32, 58}, {34, 62}, {26, 46}, {26, 48}, //11-15 + {26, 50}, {30, 54}, {30, 56}, {30, 58}, {34, 62}, //16-20 + {28, 50}, {26, 50}, {30, 54}, {28, 54}, {32, 58}, //21-25 + {30, 58}, {34, 62}, {26, 50}, {30, 54}, {26, 52}, //26-30 + {30, 56}, {34, 60}, {30, 58}, {34, 62}, {30, 54}, //31-35 + {24, 50}, {28, 54}, {32, 58}, {26, 54}, {30, 58}, //35-40 +}; + +/** + * Put an alignment marker. + * @param frame + * @param width + * @param ox,oy center coordinate of the pattern + */ +static void QRspec_putAlignmentMarker(unsigned char *frame, int width, int ox, int oy) +{ + static const unsigned char finder[] = { + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa0, 0xa0, 0xa0, 0xa1, + 0xa1, 0xa0, 0xa1, 0xa0, 0xa1, + 0xa1, 0xa0, 0xa0, 0xa0, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + }; + int x, y; + const unsigned char *s; + + frame += (oy - 2) * width + ox - 2; + s = finder; + for(y=0; y<5; y++) { + for(x=0; x<5; x++) { + frame[x] = s[x]; + } + frame += width; + s += 5; + } +} + +static void QRspec_putAlignmentPattern(int version, unsigned char *frame, int width) +{ + int d, w, x, y, cx, cy; + + if(version < 2) return; + + d = alignmentPattern[version][1] - alignmentPattern[version][0]; + if(d < 0) { + w = 2; + } else { + w = (width - alignmentPattern[version][0]) / d + 2; + } + + if(w * w - 3 == 1) { + x = alignmentPattern[version][0]; + y = alignmentPattern[version][0]; + QRspec_putAlignmentMarker(frame, width, x, y); + return; + } + + cx = alignmentPattern[version][0]; + for(x=1; x QRSPEC_VERSION_MAX) return 0; + + return versionPattern[version - 7]; +} + +/****************************************************************************** + * Format information + *****************************************************************************/ + +/* See calcFormatInfo in tests/test_qrspec.c */ +static const unsigned int formatInfo[4][8] = { + {0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976}, + {0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0}, + {0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed}, + {0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b} +}; + +unsigned int QRspec_getFormatInfo(int mask, QRecLevel level) +{ + if(mask < 0 || mask > 7) return 0; + + return formatInfo[level][mask]; +} + +/****************************************************************************** + * Frame + *****************************************************************************/ + +/** + * Cache of initial frames. + */ +/* C99 says that static storage shall be initialized to a null pointer + * by compiler. */ +static unsigned char *frames[QRSPEC_VERSION_MAX + 1]; +#ifdef HAVE_LIBPTHREAD +static pthread_mutex_t frames_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif + +/** + * Put a finder pattern. + * @param frame + * @param width + * @param ox,oy upper-left coordinate of the pattern + */ +static void putFinderPattern(unsigned char *frame, int width, int ox, int oy) +{ + static const unsigned char finder[] = { + 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, + 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, + 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, + }; + int x, y; + const unsigned char *s; + + frame += oy * width + ox; + s = finder; + for(y=0; y<7; y++) { + for(x=0; x<7; x++) { + frame[x] = s[x]; + } + frame += width; + s += 7; + } +} + + +static unsigned char *QRspec_createFrame(int version) +{ + unsigned char *frame, *p, *q; + int width; + int x, y; + unsigned int verinfo, v; + + width = qrspecCapacity[version].width; + frame = (unsigned char *)malloc(width * width); + if(frame == NULL) return NULL; + + memset(frame, 0, width * width); + /* Finder pattern */ + putFinderPattern(frame, width, 0, 0); + putFinderPattern(frame, width, width - 7, 0); + putFinderPattern(frame, width, 0, width - 7); + /* Separator */ + p = frame; + q = frame + width * (width - 7); + for(y=0; y<7; y++) { + p[7] = 0xc0; + p[width - 8] = 0xc0; + q[7] = 0xc0; + p += width; + q += width; + } + memset(frame + width * 7, 0xc0, 8); + memset(frame + width * 8 - 8, 0xc0, 8); + memset(frame + width * (width - 8), 0xc0, 8); + /* Mask format information area */ + memset(frame + width * 8, 0x84, 9); + memset(frame + width * 9 - 8, 0x84, 8); + p = frame + 8; + for(y=0; y<8; y++) { + *p = 0x84; + p += width; + } + p = frame + width * (width - 7) + 8; + for(y=0; y<7; y++) { + *p = 0x84; + p += width; + } + /* Timing pattern */ + p = frame + width * 6 + 8; + q = frame + width * 8 + 6; + for(x=1; x= 7) { + verinfo = QRspec_getVersionPattern(version); + + p = frame + width * (width - 11); + v = verinfo; + for(x=0; x<6; x++) { + for(y=0; y<3; y++) { + p[width * y + x] = 0x88 | (v & 1); + v = v >> 1; + } + } + + p = frame + width - 11; + v = verinfo; + for(y=0; y<6; y++) { + for(x=0; x<3; x++) { + p[x] = 0x88 | (v & 1); + v = v >> 1; + } + p += width; + } + } + /* and a little bit... */ + frame[width * (width - 8) + 8] = 0x81; + + return frame; +} + +unsigned char *QRspec_newFrame(int version) +{ + unsigned char *frame; + int width; + + if(version < 1 || version > QRSPEC_VERSION_MAX) return NULL; + +#ifdef HAVE_LIBPTHREAD + pthread_mutex_lock(&frames_mutex); +#endif + if(frames[version] == NULL) { + frames[version] = QRspec_createFrame(version); + } +#ifdef HAVE_LIBPTHREAD + pthread_mutex_unlock(&frames_mutex); +#endif + if(frames[version] == NULL) return NULL; + + width = qrspecCapacity[version].width; + frame = (unsigned char *)malloc(width * width); + if(frame == NULL) return NULL; + memcpy(frame, frames[version], width * width); + + return frame; +} + +void QRspec_clearCache(void) +{ + int i; + +#ifdef HAVE_LIBPTHREAD + pthread_mutex_lock(&frames_mutex); +#endif + for(i=1; i<=QRSPEC_VERSION_MAX; i++) { + free(frames[i]); + frames[i] = NULL; + } +#ifdef HAVE_LIBPTHREAD + pthread_mutex_unlock(&frames_mutex); +#endif +} diff --git a/src/add-ons/kernel/debugger/qrencode/qrspec.h b/src/add-ons/kernel/debugger/qrencode/qrspec.h new file mode 100644 index 0000000000..54a3d9f09e --- /dev/null +++ b/src/add-ons/kernel/debugger/qrencode/qrspec.h @@ -0,0 +1,181 @@ +/* + * qrencode - QR Code encoder + * + * QR Code specification in convenient format. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __QRSPEC_H__ +#define __QRSPEC_H__ + +#include "qrencode.h" + +/****************************************************************************** + * Version and capacity + *****************************************************************************/ + +/** + * Maximum width of a symbol + */ +#define QRSPEC_WIDTH_MAX 177 + +/** + * Return maximum data code length (bytes) for the version. + * @param version + * @param level + * @return maximum size (bytes) + */ +extern int QRspec_getDataLength(int version, QRecLevel level); + +/** + * Return maximum error correction code length (bytes) for the version. + * @param version + * @param level + * @return ECC size (bytes) + */ +extern int QRspec_getECCLength(int version, QRecLevel level); + +/** + * Return a version number that satisfies the input code length. + * @param size input code length (byte) + * @param level + * @return version number + */ +extern int QRspec_getMinimumVersion(int size, QRecLevel level); + +/** + * Return the width of the symbol for the version. + * @param version + * @return width + */ +extern int QRspec_getWidth(int version); + +/** + * Return the numer of remainder bits. + * @param version + * @return number of remainder bits + */ +extern int QRspec_getRemainder(int version); + +/****************************************************************************** + * Length indicator + *****************************************************************************/ + +/** + * Return the size of lenght indicator for the mode and version. + * @param mode + * @param version + * @return the size of the appropriate length indicator (bits). + */ +extern int QRspec_lengthIndicator(QRencodeMode mode, int version); + +/** + * Return the maximum length for the mode and version. + * @param mode + * @param version + * @return the maximum length (bytes) + */ +extern int QRspec_maximumWords(QRencodeMode mode, int version); + +/****************************************************************************** + * Error correction code + *****************************************************************************/ + +/** + * Return an array of ECC specification. + * @param version + * @param level + * @param spec an array of ECC specification contains as following: + * {# of type1 blocks, # of data code, # of ecc code, + * # of type2 blocks, # of data code} + */ +void QRspec_getEccSpec(int version, QRecLevel level, int spec[5]); + +#define QRspec_rsBlockNum(__spec__) (__spec__[0] + __spec__[3]) +#define QRspec_rsBlockNum1(__spec__) (__spec__[0]) +#define QRspec_rsDataCodes1(__spec__) (__spec__[1]) +#define QRspec_rsEccCodes1(__spec__) (__spec__[2]) +#define QRspec_rsBlockNum2(__spec__) (__spec__[3]) +#define QRspec_rsDataCodes2(__spec__) (__spec__[4]) +#define QRspec_rsEccCodes2(__spec__) (__spec__[2]) + +#define QRspec_rsDataLength(__spec__) \ + ((QRspec_rsBlockNum1(__spec__) * QRspec_rsDataCodes1(__spec__)) + \ + (QRspec_rsBlockNum2(__spec__) * QRspec_rsDataCodes2(__spec__))) +#define QRspec_rsEccLength(__spec__) \ + (QRspec_rsBlockNum(__spec__) * QRspec_rsEccCodes1(__spec__)) + +/****************************************************************************** + * Version information pattern + *****************************************************************************/ + +/** + * Return BCH encoded version information pattern that is used for the symbol + * of version 7 or greater. Use lower 18 bits. + * @param version + * @return BCH encoded version information pattern + */ +extern unsigned int QRspec_getVersionPattern(int version); + +/****************************************************************************** + * Format information + *****************************************************************************/ + +/** + * Return BCH encoded format information pattern. + * @param mask + * @param level + * @return BCH encoded format information pattern + */ +extern unsigned int QRspec_getFormatInfo(int mask, QRecLevel level); + +/****************************************************************************** + * Frame + *****************************************************************************/ + +/** + * Return a copy of initialized frame. + * When the same version is requested twice or more, a copy of cached frame + * is returned. + * @param version + * @return Array of unsigned char. You can free it by free(). + */ +extern unsigned char *QRspec_newFrame(int version); + +/** + * Clear the frame cache. Typically for debug. + */ +extern void QRspec_clearCache(void); + +/****************************************************************************** + * Mode indicator + *****************************************************************************/ + +/** + * Mode indicator. See Table 2 of JIS X0510:2004, pp.16. + */ +#define QRSPEC_MODEID_ECI 7 +#define QRSPEC_MODEID_NUM 1 +#define QRSPEC_MODEID_AN 2 +#define QRSPEC_MODEID_8 4 +#define QRSPEC_MODEID_KANJI 8 +#define QRSPEC_MODEID_FNC1FIRST 5 +#define QRSPEC_MODEID_FNC1SECOND 9 +#define QRSPEC_MODEID_STRUCTURE 3 +#define QRSPEC_MODEID_TERMINATOR 0 + +#endif /* __QRSPEC_H__ */ diff --git a/src/add-ons/kernel/debugger/qrencode/rscode.c b/src/add-ons/kernel/debugger/qrencode/rscode.c new file mode 100644 index 0000000000..edc32e2c92 --- /dev/null +++ b/src/add-ons/kernel/debugger/qrencode/rscode.c @@ -0,0 +1,327 @@ +/* + * qrencode - QR Code encoder + * + * Reed solomon encoder. This code is taken from Phil Karn's libfec then + * editted and packed into a pair of .c and .h files. + * + * Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q + * (libfec is released under the GNU Lesser General Public License.) + * + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#ifdef HAVE_LIBPTHREAD +# include +#endif + +#include "rscode.h" + +/* Stuff specific to the 8-bit symbol version of the general purpose RS codecs + * + */ +typedef unsigned char data_t; + + +/** + * Reed-Solomon codec control block + */ +struct _RS { + int mm; /* Bits per symbol */ + int nn; /* Symbols per block (= (1<= rs->nn) { + x -= rs->nn; + x = (x >> rs->mm) + (x & rs->nn); + } + return x; +} + + +#define MODNN(x) modnn(rs,x) + +#define MM (rs->mm) +#define NN (rs->nn) +#define ALPHA_TO (rs->alpha_to) +#define INDEX_OF (rs->index_of) +#define GENPOLY (rs->genpoly) +#define NROOTS (rs->nroots) +#define FCR (rs->fcr) +#define PRIM (rs->prim) +#define IPRIM (rs->iprim) +#define PAD (rs->pad) +#define A0 (NN) + + +/* Initialize a Reed-Solomon codec + * symsize = symbol size, bits + * gfpoly = Field generator polynomial coefficients + * fcr = first root of RS code generator polynomial, index form + * prim = primitive element to generate polynomial roots + * nroots = RS code generator polynomial degree (number of roots) + * pad = padding bytes at front of shortened block + */ +static RS *init_rs_char(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad) +{ + RS *rs; + + +/* Common code for intializing a Reed-Solomon control block (char or int symbols) + * Copyright 2004 Phil Karn, KA9Q + * May be used under the terms of the GNU Lesser General Public License (LGPL) + */ +//#undef NULL +//#define NULL ((void *)0) + + int i, j, sr,root,iprim; + + rs = NULL; + /* Check parameter ranges */ + if(symsize < 0 || symsize > (int)(8*sizeof(data_t))){ + goto done; + } + + if(fcr < 0 || fcr >= (1<= (1<= (1<= ((1<mm = symsize; + rs->nn = (1<pad = pad; + + rs->alpha_to = (data_t *)malloc(sizeof(data_t)*(rs->nn+1)); + if(rs->alpha_to == NULL){ + free(rs); + rs = NULL; + goto done; + } + rs->index_of = (data_t *)malloc(sizeof(data_t)*(rs->nn+1)); + if(rs->index_of == NULL){ + free(rs->alpha_to); + free(rs); + rs = NULL; + goto done; + } + + /* Generate Galois field lookup tables */ + rs->index_of[0] = A0; /* log(zero) = -inf */ + rs->alpha_to[A0] = 0; /* alpha**-inf = 0 */ + sr = 1; + for(i=0;inn;i++){ + rs->index_of[sr] = i; + rs->alpha_to[i] = sr; + sr <<= 1; + if(sr & (1<nn; + } + if(sr != 1){ + /* field generator polynomial is not primitive! */ + free(rs->alpha_to); + free(rs->index_of); + free(rs); + rs = NULL; + goto done; + } + + /* Form RS code generator polynomial from its roots */ + rs->genpoly = (data_t *)malloc(sizeof(data_t)*(nroots+1)); + if(rs->genpoly == NULL){ + free(rs->alpha_to); + free(rs->index_of); + free(rs); + rs = NULL; + goto done; + } + rs->fcr = fcr; + rs->prim = prim; + rs->nroots = nroots; + rs->gfpoly = gfpoly; + + /* Find prim-th root of 1, used in decoding */ + for(iprim=1;(iprim % prim) != 0;iprim += rs->nn) + ; + rs->iprim = iprim / prim; + + rs->genpoly[0] = 1; + for (i = 0,root=fcr*prim; i < nroots; i++,root += prim) { + rs->genpoly[i+1] = 1; + + /* Multiply rs->genpoly[] by @**(root + x) */ + for (j = i; j > 0; j--){ + if (rs->genpoly[j] != 0) + rs->genpoly[j] = rs->genpoly[j-1] ^ rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[j]] + root)]; + else + rs->genpoly[j] = rs->genpoly[j-1]; + } + /* rs->genpoly[0] can never be zero */ + rs->genpoly[0] = rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[0]] + root)]; + } + /* convert rs->genpoly[] to index form for quicker encoding */ + for (i = 0; i <= nroots; i++) + rs->genpoly[i] = rs->index_of[rs->genpoly[i]]; + done:; + + return rs; +} + +RS *init_rs(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad) +{ + RS *rs; + +#ifdef HAVE_LIBPTHREAD + pthread_mutex_lock(&rslist_mutex); +#endif + for(rs = rslist; rs != NULL; rs = rs->next) { + if(rs->pad != pad) continue; + if(rs->nroots != nroots) continue; + if(rs->mm != symsize) continue; + if(rs->gfpoly != gfpoly) continue; + if(rs->fcr != fcr) continue; + if(rs->prim != prim) continue; + + goto DONE; + } + + rs = init_rs_char(symsize, gfpoly, fcr, prim, nroots, pad); + if(rs == NULL) goto DONE; + rs->next = rslist; + rslist = rs; + +DONE: +#ifdef HAVE_LIBPTHREAD + pthread_mutex_unlock(&rslist_mutex); +#endif + return rs; +} + + +void free_rs_char(RS *rs) +{ + free(rs->alpha_to); + free(rs->index_of); + free(rs->genpoly); + free(rs); +} + +void free_rs_cache(void) +{ + RS *rs, *next; + +#ifdef HAVE_LIBPTHREAD + pthread_mutex_lock(&rslist_mutex); +#endif + rs = rslist; + while(rs != NULL) { + next = rs->next; + free_rs_char(rs); + rs = next; + } + rslist = NULL; +#ifdef HAVE_LIBPTHREAD + pthread_mutex_unlock(&rslist_mutex); +#endif +} + +/* The guts of the Reed-Solomon encoder, meant to be #included + * into a function body with the following typedefs, macros and variables supplied + * according to the code parameters: + + * data_t - a typedef for the data symbol + * data_t data[] - array of NN-NROOTS-PAD and type data_t to be encoded + * data_t parity[] - an array of NROOTS and type data_t to be written with parity symbols + * NROOTS - the number of roots in the RS code generator polynomial, + * which is the same as the number of parity symbols in a block. + Integer variable or literal. + * + * NN - the total number of symbols in a RS block. Integer variable or literal. + * PAD - the number of pad symbols in a block. Integer variable or literal. + * ALPHA_TO - The address of an array of NN elements to convert Galois field + * elements in index (log) form to polynomial form. Read only. + * INDEX_OF - The address of an array of NN elements to convert Galois field + * elements in polynomial form to index (log) form. Read only. + * MODNN - a function to reduce its argument modulo NN. May be inline or a macro. + * GENPOLY - an array of NROOTS+1 elements containing the generator polynomial in index form + + * The memset() and memmove() functions are used. The appropriate header + * file declaring these functions (usually ) must be included by the calling + * program. + + * Copyright 2004, Phil Karn, KA9Q + * May be used under the terms of the GNU Lesser General Public License (LGPL) + */ + +#undef A0 +#define A0 (NN) /* Special reserved value encoding zero in index form */ + +void encode_rs_char(RS *rs, const data_t *data, data_t *parity) +{ + int i, j; + data_t feedback; + + memset(parity,0,NROOTS*sizeof(data_t)); + + for(i=0;i + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __RSCODE_H__ +#define __RSCODE_H__ + +/* + * General purpose RS codec, 8-bit symbols. + */ + +typedef struct _RS RS; + +extern RS *init_rs(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad); +extern void encode_rs_char(RS *rs, const unsigned char *data, unsigned char *parity); +extern void free_rs_char(RS *rs); +extern void free_rs_cache(void); + +#endif /* __RSCODE_H__ */ diff --git a/src/add-ons/kernel/debugger/qrencode/split.c b/src/add-ons/kernel/debugger/qrencode/split.c new file mode 100644 index 0000000000..f53dce5dc4 --- /dev/null +++ b/src/add-ons/kernel/debugger/qrencode/split.c @@ -0,0 +1,311 @@ +/* + * qrencode - QR Code encoder + * + * Input data splitter. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * The following data / specifications are taken from + * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) + * or + * "Automatic identification and data capture techniques -- + * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include "qrencode.h" +#include "qrinput.h" +#include "qrspec.h" +#include "split.h" + +#define isdigit(__c__) ((unsigned char)((signed char)(__c__) - '0') < 10) +#define isalnum(__c__) (QRinput_lookAnTable(__c__) >= 0) + +#if !HAVE_STRDUP +#undef strdup +char *strdup(const char *s) +{ + size_t len = strlen(s) + 1; + void *new = malloc(len); + if(new == NULL) return NULL; + return (char *)memcpy(new, s, len); +} +#endif + +static QRencodeMode Split_identifyMode(const char *string, QRencodeMode hint) +{ + unsigned char c, d; + unsigned int word; + + c = string[0]; + + if(c == '\0') return QR_MODE_NUL; + if(isdigit(c)) { + return QR_MODE_NUM; + } else if(isalnum(c)) { + return QR_MODE_AN; + } else if(hint == QR_MODE_KANJI) { + d = string[1]; + if(d != '\0') { + word = ((unsigned int)c << 8) | d; + if((word >= 0x8140 && word <= 0x9ffc) || (word >= 0xe040 && word <= 0xebbf)) { + return QR_MODE_KANJI; + } + } + } + + return QR_MODE_8; +} + +static int Split_eatNum(const char *string, QRinput *input, QRencodeMode hint); +static int Split_eatAn(const char *string, QRinput *input, QRencodeMode hint); +static int Split_eat8(const char *string, QRinput *input, QRencodeMode hint); +static int Split_eatKanji(const char *string, QRinput *input, QRencodeMode hint); + +static int Split_eatNum(const char *string, QRinput *input,QRencodeMode hint) +{ + const char *p; + int ret; + int run; + int dif; + int ln; + QRencodeMode mode; + + ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version); + + p = string; + while(isdigit(*p)) { + p++; + } + run = p - string; + mode = Split_identifyMode(p, hint); + if(mode == QR_MODE_8) { + dif = QRinput_estimateBitsModeNum(run) + 4 + ln + + QRinput_estimateBitsMode8(1) /* + 4 + l8 */ + - QRinput_estimateBitsMode8(run + 1) /* - 4 - l8 */; + if(dif > 0) { + return Split_eat8(string, input, hint); + } + } + if(mode == QR_MODE_AN) { + dif = QRinput_estimateBitsModeNum(run) + 4 + ln + + QRinput_estimateBitsModeAn(1) /* + 4 + la */ + - QRinput_estimateBitsModeAn(run + 1) /* - 4 - la */; + if(dif > 0) { + return Split_eatAn(string, input, hint); + } + } + + ret = QRinput_append(input, QR_MODE_NUM, run, (unsigned char *)string); + if(ret < 0) return -1; + + return run; +} + +static int Split_eatAn(const char *string, QRinput *input, QRencodeMode hint) +{ + const char *p, *q; + int ret; + int run; + int dif; + int la, ln; + + la = QRspec_lengthIndicator(QR_MODE_AN, input->version); + ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version); + + p = string; + while(isalnum(*p)) { + if(isdigit(*p)) { + q = p; + while(isdigit(*q)) { + q++; + } + dif = QRinput_estimateBitsModeAn(p - string) /* + 4 + la */ + + QRinput_estimateBitsModeNum(q - p) + 4 + ln + - QRinput_estimateBitsModeAn(q - string) /* - 4 - la */; + if(dif < 0) { + break; + } else { + p = q; + } + } else { + p++; + } + } + + run = p - string; + + if(*p && !isalnum(*p)) { + dif = QRinput_estimateBitsModeAn(run) + 4 + la + + QRinput_estimateBitsMode8(1) /* + 4 + l8 */ + - QRinput_estimateBitsMode8(run + 1) /* - 4 - l8 */; + if(dif > 0) { + return Split_eat8(string, input, hint); + } + } + + ret = QRinput_append(input, QR_MODE_AN, run, (unsigned char *)string); + if(ret < 0) return -1; + + return run; +} + +static int Split_eatKanji(const char *string, QRinput *input, QRencodeMode hint) +{ + const char *p; + int ret; + int run; + + p = string; + while(Split_identifyMode(p, hint) == QR_MODE_KANJI) { + p += 2; + } + run = p - string; + ret = QRinput_append(input, QR_MODE_KANJI, run, (unsigned char *)string); + if(ret < 0) return -1; + + return run; +} + +static int Split_eat8(const char *string, QRinput *input, QRencodeMode hint) +{ + const char *p, *q; + QRencodeMode mode; + int ret; + int run; + int dif; + int la, ln; + + la = QRspec_lengthIndicator(QR_MODE_AN, input->version); + ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version); + + p = string + 1; + while(*p != '\0') { + mode = Split_identifyMode(p, hint); + if(mode == QR_MODE_KANJI) { + break; + } + if(mode == QR_MODE_NUM) { + q = p; + while(isdigit(*q)) { + q++; + } + dif = QRinput_estimateBitsMode8(p - string) /* + 4 + l8 */ + + QRinput_estimateBitsModeNum(q - p) + 4 + ln + - QRinput_estimateBitsMode8(q - string) /* - 4 - l8 */; + if(dif < 0) { + break; + } else { + p = q; + } + } else if(mode == QR_MODE_AN) { + q = p; + while(isalnum(*q)) { + q++; + } + dif = QRinput_estimateBitsMode8(p - string) /* + 4 + l8 */ + + QRinput_estimateBitsModeAn(q - p) + 4 + la + - QRinput_estimateBitsMode8(q - string) /* - 4 - l8 */; + if(dif < 0) { + break; + } else { + p = q; + } + } else { + p++; + } + } + + run = p - string; + ret = QRinput_append(input, QR_MODE_8, run, (unsigned char *)string); + if(ret < 0) return -1; + + return run; +} + +static int Split_splitString(const char *string, QRinput *input, + QRencodeMode hint) +{ + int length; + QRencodeMode mode; + + if(*string == '\0') return 0; + + mode = Split_identifyMode(string, hint); + if(mode == QR_MODE_NUM) { + length = Split_eatNum(string, input, hint); + } else if(mode == QR_MODE_AN) { + length = Split_eatAn(string, input, hint); + } else if(mode == QR_MODE_KANJI && hint == QR_MODE_KANJI) { + length = Split_eatKanji(string, input, hint); + } else { + length = Split_eat8(string, input, hint); + } + if(length == 0) return 0; + if(length < 0) return -1; + return Split_splitString(&string[length], input, hint); +} + +static char *dupAndToUpper(const char *str, QRencodeMode hint) +{ + char *newstr, *p; + QRencodeMode mode; + + newstr = strdup(str); + if(newstr == NULL) return NULL; + + p = newstr; + while(*p != '\0') { + mode = Split_identifyMode(p, hint); + if(mode == QR_MODE_KANJI) { + p += 2; + } else { + if (*p >= 'a' && *p <= 'z') { + *p = (char)((int)*p - 32); + } + p++; + } + } + + return newstr; +} + +int Split_splitStringToQRinput(const char *string, QRinput *input, + QRencodeMode hint, int casesensitive) +{ + char *newstr; + int ret; + + if(string == NULL || *string == '\0') { + errno = EINVAL; + return -1; + } + if(!casesensitive) { + newstr = dupAndToUpper(string, hint); + if(newstr == NULL) return -1; + ret = Split_splitString(newstr, input, hint); + free(newstr); + } else { + ret = Split_splitString(string, input, hint); + } + + return ret; +} diff --git a/src/add-ons/kernel/debugger/qrencode/split.h b/src/add-ons/kernel/debugger/qrencode/split.h new file mode 100644 index 0000000000..b2cdbe5468 --- /dev/null +++ b/src/add-ons/kernel/debugger/qrencode/split.h @@ -0,0 +1,47 @@ +/* + * qrencode - QR Code encoder + * + * Input data splitter. + * Copyright (C) 2006-2011 Kentaro Fukuchi + * + * The following data / specifications are taken from + * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) + * or + * "Automatic identification and data capture techniques -- + * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SPLIT_H__ +#define __SPLIT_H__ + +#include "qrencode.h" + +/** + * Split the input string (null terminated) into QRinput. + * @param string input string + * @param hint give QR_MODE_KANJI if the input string contains Kanji character encoded in Shift-JIS. If not, give QR_MODE_8. + * @param casesensitive 0 for case-insensitive encoding (all alphabet characters are replaced to UPPER-CASE CHARACTERS. + * @retval 0 success. + * @retval -1 an error occurred. errno is set to indicate the error. See + * Exceptions for the details. + * @throw EINVAL invalid input object. + * @throw ENOMEM unable to allocate memory for input objects. + */ +extern int Split_splitStringToQRinput(const char *string, QRinput *input, + QRencodeMode hint, int casesensitive); + +#endif /* __SPLIT_H__ */ From fcc4ecb0c7c03ff8ac851150058e0cbbe1f4e08c Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 1 Jul 2012 05:36:45 +0200 Subject: [PATCH 110/349] Add debug_calloc() to the debug_heap. --- headers/private/kernel/debug_heap.h | 1 + src/system/kernel/debug/debug_heap.cpp | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/headers/private/kernel/debug_heap.h b/headers/private/kernel/debug_heap.h index ae110b9840..552a07a8cd 100644 --- a/headers/private/kernel/debug_heap.h +++ b/headers/private/kernel/debug_heap.h @@ -19,6 +19,7 @@ extern "C" { debug_alloc_pool* create_debug_alloc_pool(); void delete_debug_alloc_pool(debug_alloc_pool* pool); void* debug_malloc(size_t size); +void* debug_calloc(size_t num, size_t size); void debug_free(void* address); void debug_heap_init(); diff --git a/src/system/kernel/debug/debug_heap.cpp b/src/system/kernel/debug/debug_heap.cpp index 069e97d6f1..996f5213b9 100644 --- a/src/system/kernel/debug/debug_heap.cpp +++ b/src/system/kernel/debug/debug_heap.cpp @@ -278,6 +278,19 @@ debug_malloc(size_t size) } +void* +debug_calloc(size_t num, size_t size) +{ + size_t allocationSize = num * size; + void* allocation = debug_malloc(allocationSize); + if (allocation == NULL) + return NULL; + + memset(allocation, 0, allocationSize); + return allocation; +} + + void debug_free(void* address) { From 2d37d290b735fe583591f07baaf4a69f37f12e08 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 1 Jul 2012 05:37:14 +0200 Subject: [PATCH 111/349] Make sure that the internal strdup is used. The kernel strdup will still be used, as the local symbol doesn't override that. Since we must not use strdup from within the kernel debugger (as it does malloc from the normal heap), force the use of the internal strdup that gets redirected to debug_malloc. --- src/add-ons/kernel/debugger/qrencode/split.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/add-ons/kernel/debugger/qrencode/split.c b/src/add-ons/kernel/debugger/qrencode/split.c index f53dce5dc4..cf66d0a177 100644 --- a/src/add-ons/kernel/debugger/qrencode/split.c +++ b/src/add-ons/kernel/debugger/qrencode/split.c @@ -41,7 +41,7 @@ #if !HAVE_STRDUP #undef strdup -char *strdup(const char *s) +char *strdup_internal(const char *s) { size_t len = strlen(s) + 1; void *new = malloc(len); @@ -269,7 +269,7 @@ static char *dupAndToUpper(const char *str, QRencodeMode hint) char *newstr, *p; QRencodeMode mode; - newstr = strdup(str); + newstr = strdup_internal(str); if(newstr == NULL) return NULL; p = newstr; From 5521e284150a6f2fcebcfabf1010f1c827224788 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 1 Jul 2012 05:39:46 +0200 Subject: [PATCH 112/349] Reuse two unused lower ASCII chars for block drawing. Characters 17, 18 and 19 (device control 1, 2 and 3) become "full block", "upper filled block" and "lower filled block". Using back- and foreground color inversion these could be reduced to a single "half block", but having them available as idividual chars is more convenient. --- src/system/kernel/debug/font.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/system/kernel/debug/font.h b/src/system/kernel/debug/font.h index 502c77c1ea..9258dd4743 100644 --- a/src/system/kernel/debug/font.h +++ b/src/system/kernel/debug/font.h @@ -46,9 +46,9 @@ static unsigned char FONT[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */ -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */ +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* ' ' */ +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* ' ' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ' ' */ From 0948c0ff50ebdb04a5e60f0ed3ad3f1a9968c7f2 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 1 Jul 2012 06:04:54 +0200 Subject: [PATCH 113/349] Add module code that wraps qrencode and does the printing. * Generates QR codes using the qrencode library functions and prints them using terminal escape sequences and the special "block" characters. * Supplies a static QR buffer that can be used to accumulate output for later conversion into QR codes. * Adds qrencode debugger command that allows to generate QR codes for arbitrary strings. * Adds qrappend, qrflush and qrclear to manipulate the QR buffer. qrappend can be the target of a pipe to accumulate output from other commands. qrflush causes the QR buffer to be encoded and cleared and qrclear only clears the QR buffer. * Adds qrconfig that allows changing the QR code version, determining what size QR codes are to be used. --- .../kernel/debugger/qrencode/module.cpp | 270 ++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 src/add-ons/kernel/debugger/qrencode/module.cpp diff --git a/src/add-ons/kernel/debugger/qrencode/module.cpp b/src/add-ons/kernel/debugger/qrencode/module.cpp new file mode 100644 index 0000000000..58751caa7f --- /dev/null +++ b/src/add-ons/kernel/debugger/qrencode/module.cpp @@ -0,0 +1,270 @@ +/* + * Copyright 2012, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Michael Lotz + */ + + +#include +#include +#include + +extern "C" { +#include "qrencode.h" +#include "qrspec.h" +} + + +static char sStringBuffer[16 * 1024]; +static char sEncodeBuffer[3 * 1024]; +static int sBufferPosition = 0; +static int sQRCodeVersion = 19; +static QRecLevel sQRCodeLevel = QR_ECLEVEL_L; + + +static bool +qrcode_bit(QRcode* qrCode, int x, int y) +{ + if (x >= qrCode->width || y >= qrCode->width) + return false; + + return (qrCode->data[y * qrCode->width + x] & 0x01) == 1; +} + + +static void +move_to_and_clear_line(int line) +{ + kprintf(" \x1b[%dd\x1b[G\x1b[K", line + 1); +} + + +static void +print_qrcode(QRcode* qrCode, bool waitForKey) +{ + move_to_and_clear_line(0); + for (int y = 0; y < qrCode->width; y += 2) { + move_to_and_clear_line(y / 2 + 1); + kputs(" "); + + for (int x = 0; x < qrCode->width; x++) { + bool upper = qrcode_bit(qrCode, x, y); + bool lower = qrcode_bit(qrCode, x, y + 1); + if (upper == lower) + kputs(upper ? "\x11" : " "); + else + kputs(upper ? "\x12" : "\x13"); + } + } + + move_to_and_clear_line(qrCode->width / 2 + 2); + move_to_and_clear_line(qrCode->width / 2 + 3); + + if (waitForKey) { + kputs("press any key to continue...\x1b[1B\x1b[G"); + kgetc(); + } +} + + +static int +qrencode(int argc, char* argv[]) +{ + if (argc > 1 && strcmp(argv[1], "--help") == 0) { + kprintf("%s []\n", argv[0]); + kprintf("If an argument is given, encodes that string as a QR code.\n" + "Otherwise the current QR buffer is encoded as QR codes.\n" + "When encoding from the QR buffer, the buffer is left intact.\n" + "use qrclear to clear the QR buffer or qrflush to encode/clear.\n"); + return 1; + } + + const char* source = NULL; + if (argc < 2) { + sStringBuffer[sBufferPosition] = 0; + source = sStringBuffer; + } else + source = argv[1]; + + int inputLength = strlen(source); + int encodeLength = QRspec_getDataLength(sQRCodeVersion, sQRCodeLevel) - 3; + while (inputLength > 0) { + int copyCount = inputLength < encodeLength ? inputLength : encodeLength; + memcpy(sEncodeBuffer, source, copyCount); + sEncodeBuffer[copyCount] = 0; + + QRcode* qrCode = QRcode_encodeString8bit(sEncodeBuffer, sQRCodeVersion, + sQRCodeLevel); + if (qrCode == NULL) { + kprintf("Failed to encode buffer into qr code\n"); + QRcode_clearCache(); + return 1; + } + + source += copyCount; + inputLength -= copyCount; + + print_qrcode(qrCode, inputLength > 0); + QRcode_free(qrCode); + } + + QRcode_clearCache(); + return 0; +} + + +static int +qrclear(int argc, char* argv[]) +{ + if (argc > 1 && strcmp(argv[1], "--help") == 0) { + kprintf("Clears the current QR buffer.\n"); + return 0; + } + + sBufferPosition = 0; + sStringBuffer[0] = 0; + return 0; +} + + +static int +qrflush(int argc, char* argv[]) +{ + if (argc > 1 && strcmp(argv[1], "--help") == 0) { + kprintf("Flushes the current QR buffer by encoding QR codes from\n" + "the data and then clears the QR buffer.\n"); + return 1; + } + + qrencode(0, NULL); + qrclear(0, NULL); + return 0; +} + + +static int +qrappend(int argc, char* argv[]) +{ + if (argc < 2 || (argc > 1 && strcmp(argv[1], "--help") == 0)) { + kprintf("%s \n", argv[0]); + kprintf("Appends the given string to the QR buffer. Can be used as\n" + "the target of a pipe command to accumulate the output of other\n" + "commands in the QR buffer.\n" + "Note that this command will flush the QR buffer when it runs\n" + "full to make room for the new string. This will cause QR codes\n" + "to be generated while the append command still runs. As these\n" + "implicit flushes only happen to make room in the buffer, the\n" + "strings are afterwards appended aren't flushed, so make sure to\n" + "execute the qrflush command to generate codes for these as\n" + "well.\n"); + return 1; + } + + const char* source = argv[1]; + int length = strlen(source) + 1; + + while (length > 0) { + int copyCount = sizeof(sStringBuffer) - sBufferPosition - 1; + if (copyCount == 0) { + // The buffer is full, we need to flush it. + qrflush(0, NULL); + } + + if (length < copyCount) + copyCount = length; + + memcpy(sStringBuffer + sBufferPosition, source, copyCount); + sBufferPosition += copyCount; + source += copyCount; + length -= copyCount; + } + + // Overwrite the 0 byte that was copied extra with a newline. + if (sBufferPosition > 0) + sStringBuffer[sBufferPosition - 1] = '\n'; + + return 0; +} + + +static int +qrconfig(int argc, char* argv[]) +{ + if (argc < 2 || (argc > 1 && strcmp(argv[1], "--help") == 0)) { + kprintf("%s \n", argv[0]); + kprintf("Sets the QR version to be used. Valid versions range from 1\n" + "to 40 where each version determines the size of the QR code.\n" + "Version 1 is 21x21 in size and each version increments that size\n" + "by 4x4 up to 177x177 for version 40.\n" + "Bigger QR codes can hold more data, so ideally you use a version\n" + "that makes the QR code as big as possible while still fitting on\n" + "your screen.\n" + "You can test the new config by running qrencode\n" + "with a test string.\n" + "Note that due to memory constraints in the kernel debugger, some\n" + "of the higher versions may actually not work. The kernel\n" + "debugger heap size can be adjusted using the KDEBUG_HEAP define\n" + "in the kernel_debug_config.h header\n"); + return 1; + } + + int newVersion = atoi(argv[1]); + if (newVersion <= 0 || newVersion > 40) { + kprintf("Invalid QR code version supplied, " + "must be between 1 and 40.\n"); + return 1; + } + + sQRCodeVersion = newVersion; + return 0; +} + + +static status_t +std_ops(int32 op, ...) +{ + switch (op) { + case B_MODULE_INIT: + add_debugger_command("qrencode", qrencode, + "encodes a string / the current QR buffer"); + add_debugger_command("qrappend", qrappend, + "appends a string to the QR buffer"); + add_debugger_command("qrclear", qrclear, + "clears the current QR buffer"); + add_debugger_command("qrflush", qrflush, + "encodes the current QR buffer and clears it"); + add_debugger_command("qrconfig", qrconfig, + "sets the QR code version to be used"); + return B_OK; + case B_MODULE_UNINIT: + remove_debugger_command("qrencode", qrencode); + remove_debugger_command("qrappend", qrappend); + remove_debugger_command("qrclear", qrclear); + remove_debugger_command("qrflush", qrflush); + remove_debugger_command("qrconfig", qrconfig); + return B_OK; + } + + return B_BAD_VALUE; +} + + +static struct debugger_module_info sModuleInfo = { + { + "debugger/qrencode/v1", + 0, + &std_ops + }, + NULL, + NULL, + NULL, + NULL +}; + +module_info *modules[] = { + (module_info *)&sModuleInfo, + NULL +}; + From ce79b4c428a6d71bb51ffc209dbdb87cc90799b2 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 1 Jul 2012 06:12:59 +0200 Subject: [PATCH 114/349] Add qrencode kernel debugger add-on to the build. The defines in the Jamfile remap the memory allocation functions to use debug heap versions of the corresponding functions. --- src/add-ons/kernel/debugger/Jamfile | 1 + src/add-ons/kernel/debugger/qrencode/Jamfile | 22 ++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 src/add-ons/kernel/debugger/qrencode/Jamfile diff --git a/src/add-ons/kernel/debugger/Jamfile b/src/add-ons/kernel/debugger/Jamfile index dcf3f4a83d..ef05494cf9 100644 --- a/src/add-ons/kernel/debugger/Jamfile +++ b/src/add-ons/kernel/debugger/Jamfile @@ -7,5 +7,6 @@ SubInclude HAIKU_TOP src add-ons kernel debugger disasm ; SubInclude HAIKU_TOP src add-ons kernel debugger hangman ; SubInclude HAIKU_TOP src add-ons kernel debugger invalidate_on_exit ; SubInclude HAIKU_TOP src add-ons kernel debugger laplinkll ; +SubInclude HAIKU_TOP src add-ons kernel debugger qrencode ; SubInclude HAIKU_TOP src add-ons kernel debugger run_on_exit ; SubInclude HAIKU_TOP src add-ons kernel debugger usb_keyboard ; diff --git a/src/add-ons/kernel/debugger/qrencode/Jamfile b/src/add-ons/kernel/debugger/qrencode/Jamfile new file mode 100644 index 0000000000..c196777fbe --- /dev/null +++ b/src/add-ons/kernel/debugger/qrencode/Jamfile @@ -0,0 +1,22 @@ +SubDir HAIKU_TOP src add-ons kernel debugger qrencode ; + +UsePrivateHeaders kernel ; + +DEFINES += HAVE_CONFIG_H ; +DEFINES += malloc=debug_malloc ; +DEFINES += calloc=debug_calloc ; +DEFINES += free=debug_free ; + +KernelAddon qrencode : + bitstream.c + mask.c + mmask.c + mqrspec.c + qrencode.c + qrinput.c + qrspec.c + rscode.c + split.c + + module.cpp + ; From c95456a6990fa9f3dba23c83961617db5a0051f5 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 1 Jul 2012 06:22:01 +0200 Subject: [PATCH 115/349] Add qrencode kernel debugger add-on to the image. --- build/jam/HaikuImage | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/jam/HaikuImage b/build/jam/HaikuImage index ffc8d7ea74..61adf50d76 100644 --- a/build/jam/HaikuImage +++ b/build/jam/HaikuImage @@ -239,7 +239,8 @@ AddFilesToHaikuImage system add-ons kernel busses usb AddFilesToHaikuImage system add-ons kernel console : vga_text ; AddFilesToHaikuImage system add-ons kernel debugger : demangle $(X86_ONLY)disasm hangman - invalidate_on_exit usb_keyboard run_on_exit ; + invalidate_on_exit usb_keyboard qrencode + run_on_exit ; AddFilesToHaikuImage system add-ons kernel file_systems : $(SYSTEM_ADD_ONS_FILE_SYSTEMS) ; AddFilesToHaikuImage system add-ons kernel generic From db744fca35a90986d1c3d061a5b81a803ffa7170 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 1 Jul 2012 06:53:59 +0200 Subject: [PATCH 116/349] Add libqrencode credits to AboutSystem. --- src/apps/aboutsystem/AboutSystem.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/apps/aboutsystem/AboutSystem.cpp b/src/apps/aboutsystem/AboutSystem.cpp index deba9af5e7..ec3303c6ab 100644 --- a/src/apps/aboutsystem/AboutSystem.cpp +++ b/src/apps/aboutsystem/AboutSystem.cpp @@ -1694,6 +1694,12 @@ AboutView::_CreateCreditsView() .SetLicense(B_TRANSLATE("BSD (3-clause)")) .SetURL("http://gtf.sourceforge.net/")); + // libqrencode + _AddPackageCredit(PackageCredit("libqrencode") + .SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2006-2012 Kentaro Fukuchi")) + .SetLicense(B_TRANSLATE("GNU LGPL v2.1")) + .SetURL("http://fukuchi.org/works/qrencode/")); + _AddCopyrightsFromAttribute(); _AddPackageCreditEntries(); From a86c7d0ab32920e70e98ac4437b45f26a63c4b06 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 1 Jul 2012 18:29:11 +0200 Subject: [PATCH 117/349] Add qrwebpost to generate URLs for easier data collection. Using the qrwebpost debugger command one can initialize an id for subsequent QR codes. All QR codes generated following such an invokation produce URL QR codes that link to an online service that concatenates all data with the same id and later allows it to be displayed/downloaded in one piece. This makes collecting larger amounts of data more convenient. Note though that the URL encoding does waste space and therefore reduces data density, causing more QR codes to be generated for the same amount of input data. --- .../kernel/debugger/qrencode/module.cpp | 101 +++++++++++++++++- 1 file changed, 97 insertions(+), 4 deletions(-) diff --git a/src/add-ons/kernel/debugger/qrencode/module.cpp b/src/add-ons/kernel/debugger/qrencode/module.cpp index 58751caa7f..f945a35f87 100644 --- a/src/add-ons/kernel/debugger/qrencode/module.cpp +++ b/src/add-ons/kernel/debugger/qrencode/module.cpp @@ -8,6 +8,7 @@ #include +#include #include #include @@ -17,11 +18,15 @@ extern "C" { } +static const char* kWebPostBaseURL = "http://haiku.mlotz.ch/qrencode/store.php"; + static char sStringBuffer[16 * 1024]; static char sEncodeBuffer[3 * 1024]; static int sBufferPosition = 0; static int sQRCodeVersion = 19; static QRecLevel sQRCodeLevel = QR_ECLEVEL_L; +static char sWebPostId[64]; +static int sWebPostCounter = 0; static bool @@ -69,6 +74,50 @@ print_qrcode(QRcode* qrCode, bool waitForKey) } +static int +encode_url(const char* query, const char* data, int encodeLength, + int inputLength) +{ + sEncodeBuffer[0] = 0; + strlcat(sEncodeBuffer, kWebPostBaseURL, encodeLength + 1); + strlcat(sEncodeBuffer, "?id=", encodeLength + 1); + strlcat(sEncodeBuffer, sWebPostId, encodeLength + 1); + strlcat(sEncodeBuffer, "&", encodeLength + 1); + strlcat(sEncodeBuffer, query, encodeLength + 1); + int position = strlcat(sEncodeBuffer, "=", encodeLength + 1); + if (position > encodeLength) + return -1; + + int copyCount = 0; + while (inputLength > 0 && position < encodeLength) { + char character = data[copyCount]; + if ((character >= 'a' && character <= 'z') + || (character >= 'A' && character <= 'Z') + || (character >= '0' && character <= '9') + || character == '.' || character == '-' || character == '_' + || character == '~') { + sEncodeBuffer[position++] = character; + sEncodeBuffer[position] = 0; + } else { + // Encode to a %xx escape. + if (encodeLength - position < 3) { + // Doesn't fit anymore, we're done. + break; + } + + char escaped[4]; + sprintf(escaped, "%%%.2x", character); + position = strlcat(sEncodeBuffer, escaped, encodeLength + 1); + } + + inputLength--; + copyCount++; + } + + return copyCount; +} + + static int qrencode(int argc, char* argv[]) { @@ -91,14 +140,25 @@ qrencode(int argc, char* argv[]) int inputLength = strlen(source); int encodeLength = QRspec_getDataLength(sQRCodeVersion, sQRCodeLevel) - 3; while (inputLength > 0) { - int copyCount = inputLength < encodeLength ? inputLength : encodeLength; - memcpy(sEncodeBuffer, source, copyCount); - sEncodeBuffer[copyCount] = 0; + int copyCount = 0; + if (sWebPostId[0] != 0) { + copyCount = encode_url(sWebPostCounter++ == 0 ? "clear" : "data", + source, encodeLength, inputLength); + if (copyCount < 0) { + kprintf("Failed to URL encode buffer.\n"); + QRcode_clearCache(); + return 1; + } + } else { + copyCount = inputLength < encodeLength ? inputLength : encodeLength; + memcpy(sEncodeBuffer, source, copyCount); + sEncodeBuffer[copyCount] = 0; + } QRcode* qrCode = QRcode_encodeString8bit(sEncodeBuffer, sQRCodeVersion, sQRCodeLevel); if (qrCode == NULL) { - kprintf("Failed to encode buffer into qr code\n"); + kprintf("Failed to encode buffer into qr code.\n"); QRcode_clearCache(); return 1; } @@ -222,6 +282,36 @@ qrconfig(int argc, char* argv[]) } +static int +qrwebpost(int argc, char* argv[]) +{ + if (argc >= 3 && strcmp(argv[1], "start") == 0) { + strlcpy(sWebPostId, argv[2], sizeof(sWebPostId)); + sWebPostCounter = 0; + + // Generate the clear code. + const char* args[2] = { "", "yes" }; + qrencode(2, (char**)args); + } else if (argc >= 2 && strcmp(argv[1], "stop") == 0) { + sWebPostId[0] = 0; + } else { + kprintf("%s start \n", argv[0]); + kprintf("%s stop\n", argv[0]); + kprintf("Causes the QR codes to be rendered as URLs that resolve to\n" + "a service that allows appending the data of multiple QR codes\n" + "for easier handling.\n" + "An initial QR code is generated that invokes a clear operation\n" + "to prepare the output file on the server.\n" + "Note that there is no logic behind the service, if you and\n" + "someone else use the same id at the same time, they will\n" + "overwrite eachother. Therefore use a reasonably unique name.\n"); + return 1; + } + + return 0; +} + + static status_t std_ops(int32 op, ...) { @@ -237,6 +327,8 @@ std_ops(int32 op, ...) "encodes the current QR buffer and clears it"); add_debugger_command("qrconfig", qrconfig, "sets the QR code version to be used"); + add_debugger_command("qrwebpost", qrwebpost, + "sets up URL encoding for QR codes"); return B_OK; case B_MODULE_UNINIT: remove_debugger_command("qrencode", qrencode); @@ -244,6 +336,7 @@ std_ops(int32 op, ...) remove_debugger_command("qrclear", qrclear); remove_debugger_command("qrflush", qrflush); remove_debugger_command("qrconfig", qrconfig); + remove_debugger_command("qrwebpost", qrwebpost); return B_OK; } From e0ef5b2a972ffaab288c78e04bc9b657ad8badf0 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 1 Jul 2012 18:53:37 +0200 Subject: [PATCH 118/349] Allow aborting the command while QR codes are generated. --- src/add-ons/kernel/debugger/qrencode/module.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/add-ons/kernel/debugger/qrencode/module.cpp b/src/add-ons/kernel/debugger/qrencode/module.cpp index f945a35f87..89470678c8 100644 --- a/src/add-ons/kernel/debugger/qrencode/module.cpp +++ b/src/add-ons/kernel/debugger/qrencode/module.cpp @@ -18,6 +18,11 @@ extern "C" { } +extern "C" { +extern void abort_debugger_command(); +} + + static const char* kWebPostBaseURL = "http://haiku.mlotz.ch/qrencode/store.php"; static char sStringBuffer[16 * 1024]; @@ -68,8 +73,9 @@ print_qrcode(QRcode* qrCode, bool waitForKey) move_to_and_clear_line(qrCode->width / 2 + 3); if (waitForKey) { - kputs("press any key to continue...\x1b[1B\x1b[G"); - kgetc(); + kputs("press q to abort or any other key to continue...\x1b[1B\x1b[G"); + if (kgetc() == 'q') + abort_debugger_command(); } } From 62115b47721b2659d5dd748cbd4d2dbc7900de4d Mon Sep 17 00:00:00 2001 From: Humdinger Date: Sun, 1 Jul 2012 18:58:43 +0200 Subject: [PATCH 119/349] Automatic whitespace cleanup and coding style. --- src/preferences/media/MediaListItem.cpp | 14 +++++++------- src/preferences/media/MediaWindow.cpp | 7 +++---- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/preferences/media/MediaListItem.cpp b/src/preferences/media/MediaListItem.cpp index cfd6f51b09..acf68b6bd2 100644 --- a/src/preferences/media/MediaListItem.cpp +++ b/src/preferences/media/MediaListItem.cpp @@ -2,7 +2,7 @@ // // Copyright (c) 2003, OpenBeOS // -// This software is part of the OpenBeOS distribution and is covered +// This software is part of the OpenBeOS distribution and is covered // by the OpenBeOS license. // // @@ -10,7 +10,7 @@ // Author: Sikosis, Jérôme Duval // Description: Media Preferences // Created : June 25, 2003 -// +// // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ #include "MediaListItem.h" @@ -70,13 +70,13 @@ struct MediaListItem::Renderer { { fDoubleInsets = doubleInset; } - + void Render(BView* onto, BRect frame, bool complete = false) { const rgb_color lowColor = onto->LowColor(); const rgb_color highColor = onto->HighColor(); const rgb_color kBlack = {0, 0, 0, 255}; - + if (fSelected || complete) { if (fSelected) onto->SetLowColor(tint_color(lowColor, B_DARKEN_2_TINT)); @@ -86,7 +86,7 @@ struct MediaListItem::Renderer { frame.left += 4; frame.top += kITEM_MARGIN; BRect iconFrame(MediaIcons::IconRectAt(frame.LeftTop() + BPoint(1, 0))); - + onto->SetDrawingMode(B_OP_OVER); if (fPrimaryIcon && !fDoubleInsets) { onto->DrawBitmap(fPrimaryIcon, iconFrame); @@ -103,7 +103,7 @@ struct MediaListItem::Renderer { onto->SetDrawingMode(B_OP_COPY); onto->SetHighColor(kBlack); - + BFont font = be_plain_font; font_height fontInfo; font.GetHeight(&fontInfo); @@ -130,7 +130,7 @@ struct MediaListItem::Renderer { width += iconSpace; width += 8.0f; // space between icons and text - + width += be_plain_font->StringWidth(fTitle) + 3.0f; return width; } diff --git a/src/preferences/media/MediaWindow.cpp b/src/preferences/media/MediaWindow.cpp index 9d599b8529..a96526e47e 100644 --- a/src/preferences/media/MediaWindow.cpp +++ b/src/preferences/media/MediaWindow.cpp @@ -413,11 +413,10 @@ MediaWindow::InitWindow() // Start the window fInitCheck = InitMedia(true); - if (fInitCheck != B_OK) { + if (fInitCheck != B_OK) PostMessage(B_QUIT_REQUESTED); - } else if (IsHidden()) { + else if (IsHidden()) Show(); - } } @@ -753,7 +752,7 @@ MediaWindow::_MakeEmptyParamView() B_ALIGN_VERTICAL_CENTER); stringView->SetExplicitAlignment(centered); stringView->SetAlignment(B_ALIGN_CENTER); - + fContentLayout->AddView(stringView); fContentLayout->SetVisibleItem(fContentLayout->CountItems() - 1); From f437c10c48325acce0a27524dc34fa352b255074 Mon Sep 17 00:00:00 2001 From: Humdinger Date: Sun, 1 Jul 2012 19:00:26 +0200 Subject: [PATCH 120/349] Small visual changes to left scroll view. Fixes #8659. Fixed width of left scroll view. Added padding to list items. Thanks yourpalal for your hints. --- src/preferences/media/MediaListItem.cpp | 2 +- src/preferences/media/MediaWindow.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/preferences/media/MediaListItem.cpp b/src/preferences/media/MediaListItem.cpp index acf68b6bd2..2e1e508d7e 100644 --- a/src/preferences/media/MediaListItem.cpp +++ b/src/preferences/media/MediaListItem.cpp @@ -131,7 +131,7 @@ struct MediaListItem::Renderer { width += 8.0f; // space between icons and text - width += be_plain_font->StringWidth(fTitle) + 3.0f; + width += be_plain_font->StringWidth(fTitle) + 16.0f; return width; } diff --git a/src/preferences/media/MediaWindow.cpp b/src/preferences/media/MediaWindow.cpp index a96526e47e..a9efbc12ec 100644 --- a/src/preferences/media/MediaWindow.cpp +++ b/src/preferences/media/MediaWindow.cpp @@ -405,7 +405,7 @@ MediaWindow::InitWindow() BLayoutBuilder::Group<>(this, B_HORIZONTAL) .SetInsets(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING) - .Add(scrollView) + .Add(scrollView, 0.0f) .AddGroup(B_VERTICAL) .SetInsets(0, 0, 0, 0) .Add(fTitleView) From 2a80abaa7a912078f5aa4b497c67ab30a9955e81 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 1 Jul 2012 19:34:55 +0200 Subject: [PATCH 121/349] Use a shorter URL and query to maximize payload space. --- src/add-ons/kernel/debugger/qrencode/module.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/add-ons/kernel/debugger/qrencode/module.cpp b/src/add-ons/kernel/debugger/qrencode/module.cpp index 89470678c8..a030e621ab 100644 --- a/src/add-ons/kernel/debugger/qrencode/module.cpp +++ b/src/add-ons/kernel/debugger/qrencode/module.cpp @@ -23,7 +23,7 @@ extern void abort_debugger_command(); } -static const char* kWebPostBaseURL = "http://haiku.mlotz.ch/qrencode/store.php"; +static const char* kWebPostBaseURL = "http://mlotz.ch/q"; static char sStringBuffer[16 * 1024]; static char sEncodeBuffer[3 * 1024]; @@ -86,7 +86,7 @@ encode_url(const char* query, const char* data, int encodeLength, { sEncodeBuffer[0] = 0; strlcat(sEncodeBuffer, kWebPostBaseURL, encodeLength + 1); - strlcat(sEncodeBuffer, "?id=", encodeLength + 1); + strlcat(sEncodeBuffer, "?i=", encodeLength + 1); strlcat(sEncodeBuffer, sWebPostId, encodeLength + 1); strlcat(sEncodeBuffer, "&", encodeLength + 1); strlcat(sEncodeBuffer, query, encodeLength + 1); @@ -148,7 +148,7 @@ qrencode(int argc, char* argv[]) while (inputLength > 0) { int copyCount = 0; if (sWebPostId[0] != 0) { - copyCount = encode_url(sWebPostCounter++ == 0 ? "clear" : "data", + copyCount = encode_url(sWebPostCounter++ == 0 ? "clear" : "d", source, encodeLength, inputLength); if (copyCount < 0) { kprintf("Failed to URL encode buffer.\n"); From 39a26a0aa5e64858a54720432ffd1505cb25259f Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 1 Jul 2012 20:27:35 +0200 Subject: [PATCH 122/349] Ensure that the qrencode caches are cleared when aborting. The caches contain pointers into memory allocated by debug_malloc() that come from a pool that is destroied once the command returns. We therefore have to ensure that all such pointers are cleared in all cases before returning from the command or we will run into errors when executing the next commands. --- src/add-ons/kernel/debugger/qrencode/module.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/add-ons/kernel/debugger/qrencode/module.cpp b/src/add-ons/kernel/debugger/qrencode/module.cpp index a030e621ab..54a52c53b2 100644 --- a/src/add-ons/kernel/debugger/qrencode/module.cpp +++ b/src/add-ons/kernel/debugger/qrencode/module.cpp @@ -51,7 +51,7 @@ move_to_and_clear_line(int line) } -static void +static bool print_qrcode(QRcode* qrCode, bool waitForKey) { move_to_and_clear_line(0); @@ -75,8 +75,10 @@ print_qrcode(QRcode* qrCode, bool waitForKey) if (waitForKey) { kputs("press q to abort or any other key to continue...\x1b[1B\x1b[G"); if (kgetc() == 'q') - abort_debugger_command(); + return false; } + + return true; } @@ -172,8 +174,14 @@ qrencode(int argc, char* argv[]) source += copyCount; inputLength -= copyCount; - print_qrcode(qrCode, inputLength > 0); + bool doContinue = print_qrcode(qrCode, inputLength > 0); QRcode_free(qrCode); + + if (!doContinue) { + QRcode_clearCache(); + abort_debugger_command(); + // Does not return. + } } QRcode_clearCache(); From 5dc5dbbbb464bf4930380313e3e64bd23b7eb5c5 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 1 Jul 2012 20:30:35 +0200 Subject: [PATCH 123/349] Allow more chars to be sent unencoded and encode space as '+'. While this produces not strictly valid query strings, it reduces the encoding overhead significantly. --- src/add-ons/kernel/debugger/qrencode/module.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/add-ons/kernel/debugger/qrencode/module.cpp b/src/add-ons/kernel/debugger/qrencode/module.cpp index 54a52c53b2..b2f215ddce 100644 --- a/src/add-ons/kernel/debugger/qrencode/module.cpp +++ b/src/add-ons/kernel/debugger/qrencode/module.cpp @@ -103,9 +103,21 @@ encode_url(const char* query, const char* data, int encodeLength, || (character >= 'A' && character <= 'Z') || (character >= '0' && character <= '9') || character == '.' || character == '-' || character == '_' - || character == '~') { + || character == '~' + // These aren't strictly valid, but seem to work. + || character == '/' || character == '(' || character == ')' + || character == '=' || character == '^' || character == '?' + || character == '|' || character == '*' || character == '@' + || character == ';' || character == ':' || character == ',' + || character == '{' || character == '}' || character == '[' + || character == ']' || character == '<' || character == '>' + || character == '!' || character == '\\') { sEncodeBuffer[position++] = character; sEncodeBuffer[position] = 0; + } else if (character == ' ') { + // Encode spaces as '+' as that's shorter than %20. + sEncodeBuffer[position++] = '+'; + sEncodeBuffer[position] = 0; } else { // Encode to a %xx escape. if (encodeLength - position < 3) { From fb8447d59586d40fc8987ede4795ebda64354839 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Mon, 2 Jul 2012 02:06:29 -0400 Subject: [PATCH 124/349] Fix ticket #8650. - Replace arch_cpu_user_strlcpy() and arch_cpu_user_memset() with x86 assembly versions. These correctly handle the fault handler, which had broken again on gcc4 for the C versions, causing stack corruption in certain error cases. The other architectures will still need to have corresponding asm variants added in order for them to not run into the same issue though. --- src/system/kernel/arch/x86/arch_cpu.cpp | 60 +------------- src/system/kernel/arch/x86/arch_x86.S | 103 ++++++++++++++++++++++++ src/system/kernel/vm/vm.cpp | 4 +- 3 files changed, 107 insertions(+), 60 deletions(-) diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index 5ebb194bb1..8d44375dbf 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -4,6 +4,7 @@ * * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. * Distributed under the terms of the NewOS License. + * */ @@ -988,65 +989,6 @@ arch_cpu_invalidate_TLB_list(addr_t pages[], int num_pages) } -ssize_t -arch_cpu_user_strlcpy(char *to, const char *from, size_t size, - addr_t *faultHandler) -{ - int fromLength = 0; - addr_t oldFaultHandler = *faultHandler; - - // this check is to trick the gcc4 compiler and have it keep the error label - if (to == NULL && size > 0) - goto error; - - *faultHandler = (addr_t)&&error; - - if (size > 0) { - to[--size] = '\0'; - // copy - for ( ; size; size--, fromLength++, to++, from++) { - if ((*to = *from) == '\0') - break; - } - } - // count any leftover from chars - while (*from++ != '\0') { - fromLength++; - } - - *faultHandler = oldFaultHandler; - return fromLength; - -error: - *faultHandler = oldFaultHandler; - return B_BAD_ADDRESS; -} - - -status_t -arch_cpu_user_memset(void *s, char c, size_t count, addr_t *faultHandler) -{ - char *xs = (char *)s; - addr_t oldFaultHandler = *faultHandler; - - // this check is to trick the gcc4 compiler and have it keep the error label - if (s == NULL) - goto error; - - *faultHandler = (addr_t)&&error; - - while (count--) - *xs++ = c; - - *faultHandler = oldFaultHandler; - return 0; - -error: - *faultHandler = oldFaultHandler; - return B_BAD_ADDRESS; -} - - status_t arch_cpu_shutdown(bool rebootSystem) { diff --git a/src/system/kernel/arch/x86/arch_x86.S b/src/system/kernel/arch/x86/arch_x86.S index 28611fe247..58e20fc8cc 100644 --- a/src/system/kernel/arch/x86/arch_x86.S +++ b/src/system/kernel/arch/x86/arch_x86.S @@ -1,5 +1,6 @@ /* * Copyright 2003-2007, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2012, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. * * Copyright 2001, Travis Geiselbrecht. All rights reserved. @@ -219,6 +220,108 @@ FUNCTION(arch_cpu_user_memcpy): FUNCTION_END(arch_cpu_user_memcpy) +/* status_t arch_cpu_user_memset(void *to, char c, size_t count, addr_t *faultHandler) */ +FUNCTION(arch_cpu_user_memset): + pushl %esi + pushl %edi + movl 12(%esp),%edi /* dest */ + movb 16(%esp),%al /* c */ + movl 20(%esp),%ecx /* count */ + + /* set the fault handler */ + movl 24(%esp),%edx /* fault handler */ + movl (%edx),%esi + movl $.L_user_memset_error, (%edx) + + rep + stosb + + /* restore the old fault handler */ + movl %esi,(%edx) + xor %eax,%eax + + popl %edi + popl %esi + ret + + /* error condition */ +.L_user_memset_error: + /* restore the old fault handler */ + movl %esi,(%edx) + movl $-1,%eax /* return a generic error, the wrapper routine will deal with it */ + popl %edi + popl %esi + ret +FUNCTION_END(arch_cpu_user_memset) + + +/* ssize_t arch_cpu_user_strlcpy(void *to, const void *from, size_t size, addr_t *faultHandler) */ +FUNCTION(arch_cpu_user_strlcpy): + pushl %esi + pushl %edi + pushl %ebx + movl 16(%esp),%edi /* dest */ + movl 20(%esp),%esi /* source */ + movl 24(%esp),%ecx /* count */ + + /* set the fault handler */ + movl 28(%esp),%edx /* fault handler */ + movl (%edx),%ebx + movl $.L_user_strlcpy_error, (%edx) + + /* Check for 0 length */ + cmp $0,%ecx + je .L_user_strlcpy_source_count + + /* Copy at most count - 1 bytes */ + dec %ecx + + /* move data by bytes */ + cld + repnz + movsb + + /* null terminate string */ + movb $0,(%edi) + dec %esi + + /* check if we copied the entire source string */ + cmp $0,%ecx + jne .L_user_strlcpy_source_done + + /* count remaining bytes in src */ +.L_user_strlcpy_source_count: + not %ecx + movb $0,%al + repnz + scasb + +.L_user_strlcpy_source_done: + + movl %esi,%eax + subl 20(%esp),%eax + subl $1,%eax + + /* restore the old fault handler */ + movl %ebx,(%edx) + + popl %ebx + popl %edi + popl %esi + ret + + /* error condition */ +.L_user_strlcpy_error: + /* restore the old fault handler */ + movl %ebx,(%edx) + movl $-1,%eax /* return a generic error, the wrapper routine will deal with it */ + popl %ebx + popl %edi + popl %esi + ret +FUNCTION_END(arch_cpu_user_strlcpy) + + /*! \fn void arch_debug_call_with_fault_handler(cpu_ent* cpu, jmp_buf jumpBuffer, void (*function)(void*), void* parameter) diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index 857bf22808..e289def87f 100644 --- a/src/system/kernel/vm/vm.cpp +++ b/src/system/kernel/vm/vm.cpp @@ -5104,8 +5104,10 @@ user_strlcpy(char* to, const char* from, size_t size) &thread_get_current_thread()->fault_handler); // If we hit the address overflow boundary, fail. - if (result >= 0 && (size_t)result >= maxSize && maxSize < size) + if (result < 0 || (result >= 0 && (size_t)result >= maxSize + && maxSize < size)) { return B_BAD_ADDRESS; + } return result; } From 8695be5049294c32c45ef69f8a500dd759f46079 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Mon, 2 Jul 2012 14:41:31 -0400 Subject: [PATCH 125/349] Fix regressions in arch_cpu_user_strlcpy(). - repnz movsb turns out to not actually be a legal instruction, resulting in various strings being copied incorrectly, leading to random crashes in various places. Rework to use loop instead. Thanks to Alex Smith for helping review changes and offering improvements. - Minor cleanups. - Fixes #8650 properly. --- src/system/kernel/arch/x86/arch_x86.S | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/system/kernel/arch/x86/arch_x86.S b/src/system/kernel/arch/x86/arch_x86.S index 58e20fc8cc..f731299222 100644 --- a/src/system/kernel/arch/x86/arch_x86.S +++ b/src/system/kernel/arch/x86/arch_x86.S @@ -276,19 +276,32 @@ FUNCTION(arch_cpu_user_strlcpy): /* Copy at most count - 1 bytes */ dec %ecx - /* move data by bytes */ + /* If count is now 0, skip straight to null terminating + as our loop will otherwise overflow */ + cmp $0,%ecx + jne .L_user_strlcpy_copy_begin + movb $0,(%edi) + jmp .L_user_strlcpy_source_count + +.L_user_strlcpy_copy_begin: cld - repnz +.L_user_strlcpy_copy_loop: + /* move data by bytes */ movsb + cmpb $0,-1(%esi) + je .L_user_strlcpy_copy_loop_done + loop .L_user_strlcpy_copy_loop - /* null terminate string */ - movb $0,(%edi) - dec %esi - +.L_user_strlcpy_copy_loop_done: /* check if we copied the entire source string */ cmp $0,%ecx jne .L_user_strlcpy_source_done +.L_user_strlcpy_zero_terminate: + /* null terminate string */ + movb $0,(%edi) + dec %esi + /* count remaining bytes in src */ .L_user_strlcpy_source_count: not %ecx @@ -297,11 +310,9 @@ FUNCTION(arch_cpu_user_strlcpy): scasb .L_user_strlcpy_source_done: - movl %esi,%eax subl 20(%esp),%eax subl $1,%eax - /* restore the old fault handler */ movl %ebx,(%edx) From dc5a16bb70c95c64b1203682acf5a67e19b2b882 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Mon, 2 Jul 2012 15:42:38 -0400 Subject: [PATCH 126/349] Add TODO note with respect to needed asm implementations. --- src/system/kernel/arch/arm/arch_cpu.cpp | 2 ++ src/system/kernel/arch/m68k/arch_cpu.cpp | 2 ++ src/system/kernel/arch/ppc/arch_cpu.cpp | 3 +++ 3 files changed, 7 insertions(+) diff --git a/src/system/kernel/arch/arm/arch_cpu.cpp b/src/system/kernel/arch/arm/arch_cpu.cpp index e225f9cef8..65d4795a80 100644 --- a/src/system/kernel/arch/arm/arch_cpu.cpp +++ b/src/system/kernel/arch/arm/arch_cpu.cpp @@ -161,6 +161,8 @@ arch_cpu_user_TLB_invalidate(void) } +// TODO: all functions that use fault handlers need to be implemented +// in assembly due to problems passing in label addresses in gcc4. status_t arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr_t *faultHandler) diff --git a/src/system/kernel/arch/m68k/arch_cpu.cpp b/src/system/kernel/arch/m68k/arch_cpu.cpp index 235c5aabaf..488e905c19 100644 --- a/src/system/kernel/arch/m68k/arch_cpu.cpp +++ b/src/system/kernel/arch/m68k/arch_cpu.cpp @@ -171,6 +171,8 @@ arch_cpu_user_TLB_invalidate(void) } +// TODO: all functions that use fault handlers need to be implemented +// in assembly due to problems passing in label addresses in gcc4. status_t arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr_t *faultHandler) diff --git a/src/system/kernel/arch/ppc/arch_cpu.cpp b/src/system/kernel/arch/ppc/arch_cpu.cpp index 79c62967f0..80a76d4294 100644 --- a/src/system/kernel/arch/ppc/arch_cpu.cpp +++ b/src/system/kernel/arch/ppc/arch_cpu.cpp @@ -172,6 +172,9 @@ arch_cpu_user_TLB_invalidate(void) } +// TODO: all functions that use fault handlers need to be implemented +// in assembly due to problems passing in label addresses in gcc4. + status_t arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr_t *faultHandler) From 29291c8c924ada62bf015aaf70d04616cc2e7314 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Mon, 2 Jul 2012 19:42:20 -0400 Subject: [PATCH 127/349] Cleanups/optimizations. --- src/system/kernel/arch/x86/arch_x86.S | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/system/kernel/arch/x86/arch_x86.S b/src/system/kernel/arch/x86/arch_x86.S index f731299222..d5c51507f7 100644 --- a/src/system/kernel/arch/x86/arch_x86.S +++ b/src/system/kernel/arch/x86/arch_x86.S @@ -278,9 +278,8 @@ FUNCTION(arch_cpu_user_strlcpy): /* If count is now 0, skip straight to null terminating as our loop will otherwise overflow */ - cmp $0,%ecx - jne .L_user_strlcpy_copy_begin - movb $0,(%edi) + jnz .L_user_strlcpy_copy_begin + movb $0,(%edi) jmp .L_user_strlcpy_source_count .L_user_strlcpy_copy_begin: @@ -289,30 +288,24 @@ FUNCTION(arch_cpu_user_strlcpy): /* move data by bytes */ movsb cmpb $0,-1(%esi) - je .L_user_strlcpy_copy_loop_done + je .L_user_strlcpy_source_done loop .L_user_strlcpy_copy_loop -.L_user_strlcpy_copy_loop_done: - /* check if we copied the entire source string */ - cmp $0,%ecx - jne .L_user_strlcpy_source_done - -.L_user_strlcpy_zero_terminate: /* null terminate string */ movb $0,(%edi) - dec %esi + dec %esi /* count remaining bytes in src */ .L_user_strlcpy_source_count: not %ecx - movb $0,%al + xor %al,%al repnz scasb .L_user_strlcpy_source_done: movl %esi,%eax subl 20(%esp),%eax - subl $1,%eax + dec %eax /* restore the old fault handler */ movl %ebx,(%edx) From 7f7b659ec5eb4911c6a62e86af3a379227c3eeb0 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Mon, 2 Jul 2012 20:17:03 -0400 Subject: [PATCH 128/349] Use safer but slower approach to copying the string. --- src/system/kernel/arch/x86/arch_x86.S | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/system/kernel/arch/x86/arch_x86.S b/src/system/kernel/arch/x86/arch_x86.S index d5c51507f7..1ebcae0e82 100644 --- a/src/system/kernel/arch/x86/arch_x86.S +++ b/src/system/kernel/arch/x86/arch_x86.S @@ -286,9 +286,10 @@ FUNCTION(arch_cpu_user_strlcpy): cld .L_user_strlcpy_copy_loop: /* move data by bytes */ - movsb - cmpb $0,-1(%esi) - je .L_user_strlcpy_source_done + lodsb + stosb + test %al,%al + jz .L_user_strlcpy_source_done loop .L_user_strlcpy_copy_loop /* null terminate string */ From 0b355b4e977e1c28512c3c60b9fb143e7a574ea1 Mon Sep 17 00:00:00 2001 From: Alexandre Deckner Date: Tue, 3 Jul 2012 14:58:51 +0200 Subject: [PATCH 129/349] Rename LauncherXXX files to their new WebPositive names Edit history with this rename commit to preserve history as we will git-filter --subdirectory-filter the WebPositive directory. The HaikuLauncher directory was renamed to WebPositive trough the past history with git-filter. --- src/apps/webpositive/{LauncherApp.cpp => BrowserApp.cpp} | 0 src/apps/webpositive/{LauncherApp.h => BrowserApp.h} | 0 src/apps/webpositive/{LauncherWindow.cpp => BrowserWindow.cpp} | 0 src/apps/webpositive/{LauncherWindow.h => BrowserWindow.h} | 0 src/apps/webpositive/{Launcher.rdef => WebPositive.rdef} | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename src/apps/webpositive/{LauncherApp.cpp => BrowserApp.cpp} (100%) rename src/apps/webpositive/{LauncherApp.h => BrowserApp.h} (100%) rename src/apps/webpositive/{LauncherWindow.cpp => BrowserWindow.cpp} (100%) rename src/apps/webpositive/{LauncherWindow.h => BrowserWindow.h} (100%) rename src/apps/webpositive/{Launcher.rdef => WebPositive.rdef} (100%) diff --git a/src/apps/webpositive/LauncherApp.cpp b/src/apps/webpositive/BrowserApp.cpp similarity index 100% rename from src/apps/webpositive/LauncherApp.cpp rename to src/apps/webpositive/BrowserApp.cpp diff --git a/src/apps/webpositive/LauncherApp.h b/src/apps/webpositive/BrowserApp.h similarity index 100% rename from src/apps/webpositive/LauncherApp.h rename to src/apps/webpositive/BrowserApp.h diff --git a/src/apps/webpositive/LauncherWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp similarity index 100% rename from src/apps/webpositive/LauncherWindow.cpp rename to src/apps/webpositive/BrowserWindow.cpp diff --git a/src/apps/webpositive/LauncherWindow.h b/src/apps/webpositive/BrowserWindow.h similarity index 100% rename from src/apps/webpositive/LauncherWindow.h rename to src/apps/webpositive/BrowserWindow.h diff --git a/src/apps/webpositive/Launcher.rdef b/src/apps/webpositive/WebPositive.rdef similarity index 100% rename from src/apps/webpositive/Launcher.rdef rename to src/apps/webpositive/WebPositive.rdef From a3b3ded520bdf755cef087bfdb2323c0a832627d Mon Sep 17 00:00:00 2001 From: Alexandre Deckner Date: Tue, 3 Jul 2012 15:05:29 +0200 Subject: [PATCH 130/349] Manually update to the r238 state, so that we can rebase next commits on top of it Original commit message of r238: Split up WebPositive from HaikuLauncher. HaikuLauncher is back to it's simple self. WebPositive uses a new WebPositive folder in config/settings. Otherwise, everything should be as before. LauncherWindow and LauncherApp have been renamed and cleaned up for the Haiku coding style. --- src/apps/webpositive/BrowserApp.cpp | 351 ++++---- src/apps/webpositive/BrowserApp.h | 54 +- src/apps/webpositive/BrowserWindow.cpp | 997 ++++++++++++----------- src/apps/webpositive/BrowserWindow.h | 134 +-- src/apps/webpositive/BrowsingHistory.cpp | 4 +- src/apps/webpositive/DownloadWindow.cpp | 4 +- src/apps/webpositive/WebPositive.rdef | 6 +- 7 files changed, 833 insertions(+), 717 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 5ebef34120..3dd0d7a25a 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -8,10 +8,10 @@ * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -27,17 +27,16 @@ */ #include "config.h" -#include "LauncherApp.h" +#include "BrowserApp.h" +#include "BrowserWindow.h" #include "DownloadWindow.h" -#include "FrameView.h" -#include "GraphicsContext.h" -#include "LauncherWindow.h" #include "WebPage.h" #include "WebView.h" #include "WebViewConstants.h" #include #include +#include #include #include #include @@ -45,170 +44,187 @@ #include #include -extern const char* kApplicationSignature = "application/x-vnd.RJL-HaikuLauncher"; + +const char* kApplicationSignature = "application/x-vnd.Haiku-WebPositive"; +const char* kApplicationName = "WebPositive"; + + enum { - LOAD_AT_STARTING = 'lost' + LOAD_AT_STARTING = 'lost' }; -LauncherApp::LauncherApp() - : BApplication(kApplicationSignature) - , m_windowCount(0) - , m_lastWindowFrame(100, 100, 700, 750) - , m_launchRefsMessage(0) - , m_initialized(false) - , m_downloadWindow(0) +BrowserApp::BrowserApp() + : BApplication(kApplicationSignature) + , fWindowCount(0) + , fLastWindowFrame(100, 100, 700, 750) + , fLaunchRefsMessage(0) + , fInitialized(false) + , fDownloadWindow(0) { } -LauncherApp::~LauncherApp() + +BrowserApp::~BrowserApp() { - delete m_launchRefsMessage; + delete fLaunchRefsMessage; } -void LauncherApp::AboutRequested() + +void +BrowserApp::AboutRequested() { - BAlert* alert = new BAlert("About HaikuLauncher", - "For testing WebKit...\n\nby Ryan Leavengood", "Sweet!"); - alert->Go(); + BAlert* alert = new BAlert("About WebPositive", + "WebPositive\n\nby Ryan Leavengood, Andrea Anzani, " + "Maxime Simone, Michael Lotz, Rene Gollent and Stephan Aßmus", + "Sweet!"); + alert->Go(); } -void LauncherApp::ArgvReceived(int32 argc, char** argv) + +void +BrowserApp::ArgvReceived(int32 argc, char** argv) { for (int i = 1; i < argc; i++) { const char* url = argv[i]; BEntry entry(argv[i], true); BPath path; if (entry.Exists() && entry.GetPath(&path) == B_OK) - url = path.Path(); - BMessage message(LOAD_AT_STARTING); - message.AddString("url", url); - message.AddBool("new window", m_initialized || i > 1); - PostMessage(&message); + url = path.Path(); + BMessage message(LOAD_AT_STARTING); + message.AddString("url", url); + message.AddBool("new window", fInitialized || i > 1); + PostMessage(&message); } } -void LauncherApp::ReadyToRun() + +void +BrowserApp::ReadyToRun() { // Since we will essentially run the GUI... set_thread_priority(Thread(), B_DISPLAY_PRIORITY); - BWebPage::InitializeOnce(); - BWebPage::SetCacheModel(B_WEBKIT_CACHE_MODEL_WEB_BROWSER); + BWebPage::InitializeOnce(); + BWebPage::SetCacheModel(B_WEBKIT_CACHE_MODEL_WEB_BROWSER); BFile settingsFile; - BRect windowFrameFromSettings = m_lastWindowFrame; + BRect windowFrameFromSettings = fLastWindowFrame; BRect downloadWindowFrame(100, 100, 300, 250); bool showDownloads = false; - if (openSettingsFile(settingsFile, B_READ_ONLY)) { + if (_OpenSettingsFile(settingsFile, B_READ_ONLY)) { BMessage settingsArchive; settingsArchive.Unflatten(&settingsFile); settingsArchive.FindRect("window frame", &windowFrameFromSettings); settingsArchive.FindRect("downloads window frame", &downloadWindowFrame); settingsArchive.FindBool("show downloads", &showDownloads); } - m_lastWindowFrame = windowFrameFromSettings; + fLastWindowFrame = windowFrameFromSettings; - m_downloadWindow = new DownloadWindow(downloadWindowFrame, showDownloads); + fDownloadWindow = new DownloadWindow(downloadWindowFrame, showDownloads); - m_initialized = true; + fInitialized = true; - if (m_launchRefsMessage) { - RefsReceived(m_launchRefsMessage); - delete m_launchRefsMessage; - m_launchRefsMessage = 0; + if (fLaunchRefsMessage) { + RefsReceived(fLaunchRefsMessage); + delete fLaunchRefsMessage; + fLaunchRefsMessage = 0; } else { - LauncherWindow* window = new LauncherWindow(m_lastWindowFrame, - BMessenger(m_downloadWindow)); - window->Show(); + BrowserWindow* window = new BrowserWindow(fLastWindowFrame, + BMessenger(fDownloadWindow)); + window->Show(); } } -void LauncherApp::MessageReceived(BMessage* message) + +void +BrowserApp::MessageReceived(BMessage* message) { - switch (message->what) { - case LOAD_AT_STARTING: { - BString url; - if (message->FindString("url", &url) != B_OK) - break; - bool openNewWindow = false; - message->FindBool("new window", &openNewWindow); - LauncherWindow* webWindow = NULL; - for (int i = 0; BWindow* window = WindowAt(i); i++) { - webWindow = dynamic_cast(window); - if (!webWindow) - continue; - if (!openNewWindow) { - // stop at the first window - break; - } - } - if (webWindow) { - // There should always be at least one window open. If not, maybe we are about - // to quit anyway... - if (openNewWindow) { - // open a new window with an offset to the last window - newWindow(url); - } else { - // load the URL in the first window - webWindow->CurrentWebView()->LoadURL(url.String()); - } - } - break; - } - case B_SILENT_RELAUNCH: - newWindow(""); - break; - case NEW_WINDOW: { + switch (message->what) { + case LOAD_AT_STARTING: { BString url; if (message->FindString("url", &url) != B_OK) break; - newWindow(url); - break; - } - case NEW_TAB: { - LauncherWindow* window; + bool openNewWindow = false; + message->FindBool("new window", &openNewWindow); + BrowserWindow* webWindow = NULL; + for (int i = 0; BWindow* window = WindowAt(i); i++) { + webWindow = dynamic_cast(window); + if (!webWindow) + continue; + if (!openNewWindow) { + // stop at the first window + break; + } + } + if (webWindow) { + // There should always be at least one window open. If not, maybe we are about + // to quit anyway... + if (openNewWindow) { + // open a new window with an offset to the last window + _CreateNewWindow(url); + } else { + // load the URL in the first window + webWindow->CurrentWebView()->LoadURL(url.String()); + } + } + break; + } + case B_SILENT_RELAUNCH: + _CreateNewWindow(""); + break; + case NEW_WINDOW: { + BString url; + if (message->FindString("url", &url) != B_OK) + break; + _CreateNewWindow(url); + break; + } + case NEW_TAB: { + BrowserWindow* window; if (message->FindPointer("window", reinterpret_cast(&window)) != B_OK) break; - BString url; + BString url; message->FindString("url", &url); - bool select = false; + bool select = false; message->FindBool("select", &select); - newTab(window, url, select); - break; - } - case WINDOW_OPENED: - m_windowCount++; - break; - case WINDOW_CLOSED: - m_windowCount--; - message->FindRect("window frame", &m_lastWindowFrame); - if (m_windowCount <= 0) - PostMessage(B_QUIT_REQUESTED); - break; + _CreateNewTab(window, url, select); + break; + } + case WINDOW_OPENED: + fWindowCount++; + break; + case WINDOW_CLOSED: + fWindowCount--; + message->FindRect("window frame", &fLastWindowFrame); + if (fWindowCount <= 0) + PostMessage(B_QUIT_REQUESTED); + break; - case SHOW_DOWNLOAD_WINDOW: { - BAutolock _(m_downloadWindow); - uint32 workspaces; - if (message->FindUInt32("workspaces", &workspaces) == B_OK) - m_downloadWindow->SetWorkspaces(workspaces); - if (m_downloadWindow->IsHidden()) - m_downloadWindow->Show(); - else - m_downloadWindow->Activate(); - } + case SHOW_DOWNLOAD_WINDOW: { + BAutolock _(fDownloadWindow); + uint32 workspaces; + if (message->FindUInt32("workspaces", &workspaces) == B_OK) + fDownloadWindow->SetWorkspaces(workspaces); + if (fDownloadWindow->IsHidden()) + fDownloadWindow->Show(); + else + fDownloadWindow->Activate(); + } - default: - BApplication::MessageReceived(message); - break; - } + default: + BApplication::MessageReceived(message); + break; + } } -void LauncherApp::RefsReceived(BMessage* message) + +void +BrowserApp::RefsReceived(BMessage* message) { - if (!m_initialized) { - delete m_launchRefsMessage; - m_launchRefsMessage = new BMessage(*message); + if (!fInitialized) { + delete fLaunchRefsMessage; + fLaunchRefsMessage = new BMessage(*message); return; } @@ -222,82 +238,97 @@ void LauncherApp::RefsReceived(BMessage* message) continue; BString url; url << path.Path(); - newWindow(url); + _CreateNewWindow(url); } } -bool LauncherApp::QuitRequested() + +bool +BrowserApp::QuitRequested() { - for (int i = 0; BWindow* window = WindowAt(i); i++) { - LauncherWindow* webWindow = dynamic_cast(window); - if (!webWindow) - continue; - if (!webWindow->Lock()) - continue; - if (webWindow->QuitRequested()) { - m_lastWindowFrame = webWindow->Frame(); - webWindow->Quit(); - i--; - } else { - webWindow->Unlock(); - return false; - } - } + for (int i = 0; BWindow* window = WindowAt(i); i++) { + BrowserWindow* webWindow = dynamic_cast(window); + if (!webWindow) + continue; + if (!webWindow->Lock()) + continue; + if (webWindow->QuitRequested()) { + fLastWindowFrame = webWindow->Frame(); + webWindow->Quit(); + i--; + } else { + webWindow->Unlock(); + return false; + } + } BFile settingsFile; - if (openSettingsFile(settingsFile, B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) { + if (_OpenSettingsFile(settingsFile, B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) { BMessage settingsArchive; - settingsArchive.AddRect("window frame", m_lastWindowFrame); - if (m_downloadWindow->Lock()) { - settingsArchive.AddRect("downloads window frame", m_downloadWindow->Frame()); - settingsArchive.AddBool("show downloads", !m_downloadWindow->IsHidden()); - m_downloadWindow->Unlock(); + settingsArchive.AddRect("window frame", fLastWindowFrame); + if (fDownloadWindow->Lock()) { + settingsArchive.AddRect("downloads window frame", fDownloadWindow->Frame()); + settingsArchive.AddBool("show downloads", !fDownloadWindow->IsHidden()); + fDownloadWindow->Unlock(); } settingsArchive.Flatten(&settingsFile); } - return true; + return true; } -bool LauncherApp::openSettingsFile(BFile& file, uint32 mode) + +bool +BrowserApp::_OpenSettingsFile(BFile& file, uint32 mode) { BPath path; if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK - || path.Append("HaikuLauncher") != B_OK) { + || path.Append(kApplicationName) != B_OK + || create_directory(path.Path(), 0777) != B_OK + || path.Append("Application") != B_OK) { return false; } + return file.SetTo(path.Path(), mode) == B_OK; } -void LauncherApp::newWindow(const BString& url) -{ - m_lastWindowFrame.OffsetBy(20, 20); - if (!BScreen().Frame().Contains(m_lastWindowFrame)) - m_lastWindowFrame.OffsetTo(50, 50); - LauncherWindow* window = new LauncherWindow(m_lastWindowFrame, - BMessenger(m_downloadWindow)); +void +BrowserApp::_CreateNewWindow(const BString& url) +{ + fLastWindowFrame.OffsetBy(20, 20); + if (!BScreen().Frame().Contains(fLastWindowFrame)) + fLastWindowFrame.OffsetTo(50, 50); + + BrowserWindow* window = new BrowserWindow(fLastWindowFrame, + BMessenger(fDownloadWindow)); window->Show(); if (url.Length()) - window->CurrentWebView()->LoadURL(url.String()); + window->CurrentWebView()->LoadURL(url.String()); } -void LauncherApp::newTab(LauncherWindow* window, const BString& url, bool select) + +void +BrowserApp::_CreateNewTab(BrowserWindow* window, const BString& url, + bool select) { - if (!window->Lock()) - return; - window->newTab(url, select); - window->Unlock(); + if (!window->Lock()) + return; + window->CreateNewTab(url, select); + window->Unlock(); } + // #pragma mark - -int main(int, char**) -{ - new LauncherApp(); - be_app->Run(); - delete be_app; - return 0; +int +main(int, char**) +{ + new BrowserApp(); + be_app->Run(); + delete be_app; + + return 0; } diff --git a/src/apps/webpositive/BrowserApp.h b/src/apps/webpositive/BrowserApp.h index 15dabba6a2..f834d41f62 100644 --- a/src/apps/webpositive/BrowserApp.h +++ b/src/apps/webpositive/BrowserApp.h @@ -8,10 +8,10 @@ * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. + * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE @@ -25,43 +25,49 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#ifndef BROWSER_APP_H +#define BROWSER_APP_H -#ifndef LauncherApp_h -#define LauncherApp_h #include #include class BFile; class DownloadWindow; -class LauncherWindow; +class BrowserWindow; -class LauncherApp : public BApplication { + +class BrowserApp : public BApplication { public: - LauncherApp(); - virtual ~LauncherApp(); + BrowserApp(); + virtual ~BrowserApp(); - virtual void AboutRequested(); - virtual void ArgvReceived(int32, char**); - virtual void MessageReceived(BMessage*); - virtual void RefsReceived(BMessage*); - virtual void ReadyToRun(); - virtual bool QuitRequested(); + virtual void AboutRequested(); + virtual void ArgvReceived(int32 agrc, char** argv); + virtual void MessageReceived(BMessage* message); + virtual void RefsReceived(BMessage* message); + virtual void ReadyToRun(); + virtual bool QuitRequested(); private: - bool openSettingsFile(BFile& file, uint32 mode); - void newWindow(const BString& url); - void newTab(LauncherWindow* window, const BString& url, bool select); + bool _OpenSettingsFile(BFile& file, uint32 mode); + void _CreateNewWindow(const BString& url); + void _CreateNewTab(BrowserWindow* window, + const BString& url, bool select); - int m_windowCount; - BRect m_lastWindowFrame; - BMessage* m_launchRefsMessage; - bool m_initialized; +private: + int fWindowCount; + BRect fLastWindowFrame; + BMessage* fLaunchRefsMessage; + bool fInitialized; - DownloadWindow* m_downloadWindow; + DownloadWindow* fDownloadWindow; }; + extern const char* kApplicationSignature; +extern const char* kApplicationName; -#endif // LauncherApp_h + +#endif // BROWSER_APP_H diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 37ff504ae6..ee11bf91ac 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -31,12 +31,12 @@ */ #include "config.h" -#include "LauncherWindow.h" +#include "BrowserWindow.h" #include "AuthenticationPanel.h" +#include "BrowserApp.h" #include "BrowsingHistory.h" #include "IconButton.h" -#include "LauncherApp.h" #include "WebPage.h" #include "WebTabView.h" #include "WebView.h" @@ -61,628 +61,687 @@ #include + enum { OPEN_LOCATION = 'open', - GO_BACK = 'goba', - GO_FORWARD = 'gofo', - STOP = 'stop', - GOTO_URL = 'goul', - RELOAD = 'reld', - CLEAR_HISTORY = 'clhs', + GO_BACK = 'goba', + GO_FORWARD = 'gofo', + STOP = 'stop', + GOTO_URL = 'goul', + RELOAD = 'reld', + CLEAR_HISTORY = 'clhs', - TEXT_SIZE_INCREASE = 'tsin', - TEXT_SIZE_DECREASE = 'tsdc', - TEXT_SIZE_RESET = 'tsrs', + TEXT_SIZE_INCREASE = 'tsin', + TEXT_SIZE_DECREASE = 'tsdc', + TEXT_SIZE_RESET = 'tsrs', - TEXT_SHOW_FIND_GROUP = 'sfnd', - TEXT_HIDE_FIND_GROUP = 'hfnd', - TEXT_FIND_NEXT = 'fndn', - TEXT_FIND_PREVIOUS = 'fndp', + TEXT_SHOW_FIND_GROUP = 'sfnd', + TEXT_HIDE_FIND_GROUP = 'hfnd', + TEXT_FIND_NEXT = 'fndn', + TEXT_FIND_PREVIOUS = 'fndp', }; -using namespace WebCore; -static BLayoutItem* layoutItemFor(BView* view) +static BLayoutItem* +layoutItemFor(BView* view) { - BLayout* layout = view->Parent()->GetLayout(); - int32 index = layout->IndexOfView(view); - return layout->ItemAt(index); + BLayout* layout = view->Parent()->GetLayout(); + int32 index = layout->IndexOfView(view); + return layout->ItemAt(index); } -LauncherWindow::LauncherWindow(BRect frame, const BMessenger& downloadListener, - ToolbarPolicy toolbarPolicy) - : BWebWindow(frame, "HaikuLauncher", - B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, - B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) - , m_downloadListener(downloadListener) + +BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, + ToolbarPolicy toolbarPolicy) + : BWebWindow(frame, kApplicationName, + B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, + B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) + , fDownloadListener(downloadListener) { - BMessage* newTabMessage = new BMessage(NEW_TAB); - newTabMessage->AddString("url", ""); - newTabMessage->AddPointer("window", this); - newTabMessage->AddBool("select", true); - m_tabManager = new TabManager(BMessenger(this), newTabMessage); + BMessage* newTabMessage = new BMessage(NEW_TAB); + newTabMessage->AddString("url", ""); + newTabMessage->AddPointer("window", this); + newTabMessage->AddBool("select", true); + fTabManager = new TabManager(BMessenger(this), newTabMessage); - if (toolbarPolicy == HaveToolbar) { - // Menu - m_menuBar = new BMenuBar("Main menu"); - BMenu* menu = new BMenu("Window"); - BMessage* newWindowMessage = new BMessage(NEW_WINDOW); - newWindowMessage->AddString("url", ""); - BMenuItem* newItem = new BMenuItem("New window", newWindowMessage, 'N'); - menu->AddItem(newItem); - newItem->SetTarget(be_app); - newItem = new BMenuItem("New tab", new BMessage(*newTabMessage), 'T'); - menu->AddItem(newItem); - newItem->SetTarget(be_app); - menu->AddItem(new BMenuItem("Open location", new BMessage(OPEN_LOCATION), 'L')); - menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Close window", new BMessage(B_QUIT_REQUESTED), 'W', B_SHIFT_KEY)); - menu->AddItem(new BMenuItem("Close tab", new BMessage(CLOSE_TAB), 'W')); - menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Show downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'J')); - menu->AddSeparatorItem(); - BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); - menu->AddItem(quitItem); - quitItem->SetTarget(be_app); - m_menuBar->AddItem(menu); + if (toolbarPolicy == HaveToolbar) { + // Menu + fMenuBar = new BMenuBar("Main menu"); + BMenu* menu = new BMenu("Window"); + BMessage* newWindowMessage = new BMessage(NEW_WINDOW); + newWindowMessage->AddString("url", ""); + BMenuItem* newItem = new BMenuItem("New window", newWindowMessage, 'N'); + menu->AddItem(newItem); + newItem->SetTarget(be_app); + newItem = new BMenuItem("New tab", new BMessage(*newTabMessage), 'T'); + menu->AddItem(newItem); + newItem->SetTarget(be_app); + menu->AddItem(new BMenuItem("Open location", new BMessage(OPEN_LOCATION), 'L')); + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("Close window", new BMessage(B_QUIT_REQUESTED), 'W', B_SHIFT_KEY)); + menu->AddItem(new BMenuItem("Close tab", new BMessage(CLOSE_TAB), 'W')); + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("Show downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'J')); + menu->AddSeparatorItem(); + BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); + menu->AddItem(quitItem); + quitItem->SetTarget(be_app); + fMenuBar->AddItem(menu); - menu = new BMenu("Text"); - menu->AddItem(new BMenuItem("Find", new BMessage(TEXT_SHOW_FIND_GROUP), 'F')); - menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Increase size", new BMessage(TEXT_SIZE_INCREASE), '+')); - menu->AddItem(new BMenuItem("Decrease size", new BMessage(TEXT_SIZE_DECREASE), '-')); - menu->AddItem(new BMenuItem("Reset size", new BMessage(TEXT_SIZE_RESET), '0')); - m_menuBar->AddItem(menu); + menu = new BMenu("Text"); + menu->AddItem(new BMenuItem("Find", new BMessage(TEXT_SHOW_FIND_GROUP), 'F')); + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("Increase size", new BMessage(TEXT_SIZE_INCREASE), '+')); + menu->AddItem(new BMenuItem("Decrease size", new BMessage(TEXT_SIZE_DECREASE), '-')); + menu->AddItem(new BMenuItem("Reset size", new BMessage(TEXT_SIZE_RESET), '0')); + fMenuBar->AddItem(menu); - m_goMenu = new BMenu("Go"); - m_menuBar->AddItem(m_goMenu); + fGoMenu = new BMenu("Go"); + fMenuBar->AddItem(fGoMenu); - // Back, Forward & Stop - m_BackButton = new IconButton("Back", 0, NULL, new BMessage(GO_BACK)); - m_BackButton->SetIcon(201); - m_BackButton->TrimIcon(); + // Back, Forward & Stop + fBackButton = new IconButton("Back", 0, NULL, new BMessage(GO_BACK)); + fBackButton->SetIcon(201); + fBackButton->TrimIcon(); - m_ForwardButton = new IconButton("Forward", 0, NULL, new BMessage(GO_FORWARD)); - m_ForwardButton->SetIcon(202); - m_ForwardButton->TrimIcon(); + fForwardButton = new IconButton("Forward", 0, NULL, new BMessage(GO_FORWARD)); + fForwardButton->SetIcon(202); + fForwardButton->TrimIcon(); - m_StopButton = new IconButton("Stop", 0, NULL, new BMessage(STOP)); - m_StopButton->SetIcon(204); - m_StopButton->TrimIcon(); + fStopButton = new IconButton("Stop", 0, NULL, new BMessage(STOP)); + fStopButton->SetIcon(204); + fStopButton->TrimIcon(); - // URL - m_url = new BTextControl("url", "", "", NULL); - m_url->SetDivider(50.0); + // URL + fURLTextControl = new BTextControl("url", "", "", NULL); + fURLTextControl->SetDivider(50.0); - // Go - m_goButton = new BButton("", "Go", new BMessage(GOTO_URL)); + // Go + fGoButton = new BButton("", "Go", new BMessage(GOTO_URL)); - // Status Bar - m_statusText = new BStringView("status", ""); - m_statusText->SetAlignment(B_ALIGN_LEFT); - m_statusText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); - m_statusText->SetExplicitMinSize(BSize(150, 12)); - // Prevent the window from growing to fit a long status message... - BFont font(be_plain_font); - font.SetSize(ceilf(font.Size() * 0.8)); - m_statusText->SetFont(&font, B_FONT_SIZE); + // Status Bar + fStatusText = new BStringView("status", ""); + fStatusText->SetAlignment(B_ALIGN_LEFT); + fStatusText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); + fStatusText->SetExplicitMinSize(BSize(150, 12)); + // Prevent the window from growing to fit a long status message... + BFont font(be_plain_font); + font.SetSize(ceilf(font.Size() * 0.8)); + fStatusText->SetFont(&font, B_FONT_SIZE); - // Loading progress bar - m_loadingProgressBar = new BStatusBar("progress"); - m_loadingProgressBar->SetMaxValue(100); - m_loadingProgressBar->Hide(); - m_loadingProgressBar->SetBarHeight(12); + // Loading progress bar + fLoadingProgressBar = new BStatusBar("progress"); + fLoadingProgressBar->SetMaxValue(100); + fLoadingProgressBar->Hide(); + fLoadingProgressBar->SetBarHeight(12); - const float kInsetSpacing = 5; - const float kElementSpacing = 7; + const float kInsetSpacing = 5; + const float kElementSpacing = 7; - m_findTextControl = new BTextControl("find", "Find:", "", - new BMessage(TEXT_FIND_NEXT)); - m_findCaseSensitiveCheckBox = new BCheckBox("Match case"); - BView* findGroup = BGroupLayoutBuilder(B_VERTICAL) - .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) - .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) - .Add(m_findTextControl) - .Add(new BButton("Previous", new BMessage(TEXT_FIND_PREVIOUS))) - .Add(new BButton("Next", new BMessage(TEXT_FIND_NEXT))) - .Add(m_findCaseSensitiveCheckBox) - .Add(BSpaceLayoutItem::CreateGlue()) - .Add(new BButton("Close", new BMessage(TEXT_HIDE_FIND_GROUP))) - .SetInsets(kInsetSpacing, kInsetSpacing, - kInsetSpacing, kInsetSpacing) - ) - ; - // Layout - AddChild(BGroupLayoutBuilder(B_VERTICAL) - .Add(m_menuBar) - .Add(m_tabManager->TabGroup()) - .Add(BGridLayoutBuilder(kElementSpacing, kElementSpacing) - .Add(m_BackButton, 0, 0) - .Add(m_ForwardButton, 1, 0) - .Add(m_StopButton, 2, 0) - .Add(m_url, 3, 0) - .Add(m_goButton, 4, 0) - .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) - ) - .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) - .Add(m_tabManager->ContainerView()) - .Add(findGroup) - .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) - .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) - .Add(m_statusText) - .Add(m_loadingProgressBar, 0.2) - .AddStrut(12 - kElementSpacing) - .SetInsets(kInsetSpacing, 0, kInsetSpacing, 0) - ) - ); + fFindTextControl = new BTextControl("find", "Find:", "", + new BMessage(TEXT_FIND_NEXT)); + fFindCaseSensitiveCheckBox = new BCheckBox("Match case"); + BView* findGroup = BGroupLayoutBuilder(B_VERTICAL) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) + .Add(fFindTextControl) + .Add(new BButton("Previous", new BMessage(TEXT_FIND_PREVIOUS))) + .Add(new BButton("Next", new BMessage(TEXT_FIND_NEXT))) + .Add(fFindCaseSensitiveCheckBox) + .Add(BSpaceLayoutItem::CreateGlue()) + .Add(new BButton("Close", new BMessage(TEXT_HIDE_FIND_GROUP))) + .SetInsets(kInsetSpacing, kInsetSpacing, + kInsetSpacing, kInsetSpacing) + ) + ; + // Layout + AddChild(BGroupLayoutBuilder(B_VERTICAL) + .Add(fMenuBar) + .Add(fTabManager->TabGroup()) + .Add(BGridLayoutBuilder(kElementSpacing, kElementSpacing) + .Add(fBackButton, 0, 0) + .Add(fForwardButton, 1, 0) + .Add(fStopButton, 2, 0) + .Add(fURLTextControl, 3, 0) + .Add(fGoButton, 4, 0) + .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) + ) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(fTabManager->ContainerView()) + .Add(findGroup) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) + .Add(fStatusText) + .Add(fLoadingProgressBar, 0.2) + .AddStrut(12 - kElementSpacing) + .SetInsets(kInsetSpacing, 0, kInsetSpacing, 0) + ) + ); - m_url->MakeFocus(true); + fURLTextControl->MakeFocus(true); - m_findGroup = layoutItemFor(findGroup); - m_tabGroup = layoutItemFor(m_tabManager->TabGroup()); - } else { - m_BackButton = 0; - m_ForwardButton = 0; - m_StopButton = 0; - m_goButton = 0; - m_url = 0; - m_menuBar = 0; - m_statusText = 0; - m_loadingProgressBar = 0; + fFindGroup = layoutItemFor(findGroup); + fTabGroup = layoutItemFor(fTabManager->TabGroup()); + } else { + fBackButton = 0; + fForwardButton = 0; + fStopButton = 0; + fGoButton = 0; + fURLTextControl = 0; + fMenuBar = 0; + fStatusText = 0; + fLoadingProgressBar = 0; - BWebView* webView = new BWebView("web_view"); - SetCurrentWebView(webView); + BWebView* webView = new BWebView("web_view"); + SetCurrentWebView(webView); - AddChild(BGroupLayoutBuilder(B_VERTICAL, 7) - .Add(CurrentWebView()) - ); - } + AddChild(BGroupLayoutBuilder(B_VERTICAL, 7) + .Add(CurrentWebView()) + ); + } - newTab("", true); + CreateNewTab("", true); - m_findGroup->SetVisible(false); + fFindGroup->SetVisible(false); - AddShortcut('G', B_COMMAND_KEY, new BMessage(TEXT_FIND_NEXT)); - AddShortcut('G', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_FIND_PREVIOUS)); - AddShortcut('F', B_COMMAND_KEY, new BMessage(TEXT_SHOW_FIND_GROUP)); - AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_HIDE_FIND_GROUP)); - AddShortcut('R', B_COMMAND_KEY, new BMessage(RELOAD)); + AddShortcut('G', B_COMMAND_KEY, new BMessage(TEXT_FIND_NEXT)); + AddShortcut('G', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_FIND_PREVIOUS)); + AddShortcut('F', B_COMMAND_KEY, new BMessage(TEXT_SHOW_FIND_GROUP)); + AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_HIDE_FIND_GROUP)); + AddShortcut('R', B_COMMAND_KEY, new BMessage(RELOAD)); - be_app->PostMessage(WINDOW_OPENED); + be_app->PostMessage(WINDOW_OPENED); } -LauncherWindow::~LauncherWindow() + +BrowserWindow::~BrowserWindow() { } -void LauncherWindow::DispatchMessage(BMessage* message, BHandler* target) + +void +BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) { - if (m_url && message->what == B_KEY_DOWN && target == m_url->TextView()) { + if (fURLTextControl && message->what == B_KEY_DOWN + && target == fURLTextControl->TextView()) { // Handle B_RETURN in the URL text control. This is the easiest // way to react *only* when the user presses the return key in the // address bar, as opposed to trying to load whatever is in there when // the text control just goes out of focus. - const char* bytes; - if (message->FindString("bytes", &bytes) == B_OK - && bytes[0] == B_RETURN) { - // Do it in such a way that the user sees the Go-button go down. - m_goButton->SetValue(B_CONTROL_ON); - UpdateIfNeeded(); - m_goButton->Invoke(); - snooze(1000); - m_goButton->SetValue(B_CONTROL_OFF); - } + const char* bytes; + if (message->FindString("bytes", &bytes) == B_OK + && bytes[0] == B_RETURN) { + // Do it in such a way that the user sees the Go-button go down. + fGoButton->SetValue(B_CONTROL_ON); + UpdateIfNeeded(); + fGoButton->Invoke(); + snooze(1000); + fGoButton->SetValue(B_CONTROL_OFF); + } } BWebWindow::DispatchMessage(message, target); } -void LauncherWindow::MessageReceived(BMessage* message) + +void +BrowserWindow::MessageReceived(BMessage* message) { - switch (message->what) { - case OPEN_LOCATION: - if (m_url) { - if (m_url->TextView()->IsFocus()) - m_url->TextView()->SelectAll(); - else - m_url->MakeFocus(true); - } - break; - case RELOAD: - CurrentWebView()->Reload(); - break; - case GOTO_URL: { - BString url; - if (message->FindString("url", &url) != B_OK) - url = m_url->Text(); - CurrentWebView()->LoadURL(url.String()); - break; - } - case GO_BACK: - CurrentWebView()->GoBack(); - break; - case GO_FORWARD: - CurrentWebView()->GoForward(); - break; - case STOP: - CurrentWebView()->StopLoading(); - break; + switch (message->what) { + case OPEN_LOCATION: + if (fURLTextControl) { + if (fURLTextControl->TextView()->IsFocus()) + fURLTextControl->TextView()->SelectAll(); + else + fURLTextControl->MakeFocus(true); + } + break; + case RELOAD: + CurrentWebView()->Reload(); + break; + case GOTO_URL: { + BString url; + if (message->FindString("url", &url) != B_OK) + url = fURLTextControl->Text(); + CurrentWebView()->LoadURL(url.String()); + break; + } + case GO_BACK: + CurrentWebView()->GoBack(); + break; + case GO_FORWARD: + CurrentWebView()->GoForward(); + break; + case STOP: + CurrentWebView()->StopLoading(); + break; - case CLEAR_HISTORY: { - BrowsingHistory* history = BrowsingHistory::defaultInstance(); - if (history->countItems() == 0) - break; - BAlert* alert = new BAlert("Confirmation", "Do you really want to clear " - "the browsing history?", "Clear", "Cancel"); - if (alert->Go() == 0) - history->clear(); - break; - } + case CLEAR_HISTORY: { + BrowsingHistory* history = BrowsingHistory::defaultInstance(); + if (history->countItems() == 0) + break; + BAlert* alert = new BAlert("Confirmation", "Do you really want to " + "clear the browsing history?", "Clear", "Cancel"); + if (alert->Go() == 0) + history->clear(); + break; + } - case B_SIMPLE_DATA: { - // User possibly dropped files on this window. - // If there is more than one entry_ref, let the app handle it (open one - // new page per ref). If there is one ref, open it in this window. - type_code type; - int32 countFound; - if (message->GetInfo("refs", &type, &countFound) != B_OK - || type != B_REF_TYPE) { - break; - } - if (countFound > 1) { - message->what = B_REFS_RECEIVED; - be_app->PostMessage(message); - break; - } - entry_ref ref; - if (message->FindRef("refs", &ref) != B_OK) - break; - BEntry entry(&ref, true); - BPath path; - if (!entry.Exists() || entry.GetPath(&path) != B_OK) - break; - CurrentWebView()->LoadURL(path.Path()); - break; - } + case B_SIMPLE_DATA: { + // User possibly dropped files on this window. + // If there is more than one entry_ref, let the app handle it (open one + // new page per ref). If there is one ref, open it in this window. + type_code type; + int32 countFound; + if (message->GetInfo("refs", &type, &countFound) != B_OK + || type != B_REF_TYPE) { + break; + } + if (countFound > 1) { + message->what = B_REFS_RECEIVED; + be_app->PostMessage(message); + break; + } + entry_ref ref; + if (message->FindRef("refs", &ref) != B_OK) + break; + BEntry entry(&ref, true); + BPath path; + if (!entry.Exists() || entry.GetPath(&path) != B_OK) + break; + CurrentWebView()->LoadURL(path.Path()); + break; + } - case TEXT_SIZE_INCREASE: - CurrentWebView()->IncreaseTextSize(); - break; - case TEXT_SIZE_DECREASE: - CurrentWebView()->DecreaseTextSize(); - break; - case TEXT_SIZE_RESET: - CurrentWebView()->ResetTextSize(); - break; + case TEXT_SIZE_INCREASE: + CurrentWebView()->IncreaseTextSize(); + break; + case TEXT_SIZE_DECREASE: + CurrentWebView()->DecreaseTextSize(); + break; + case TEXT_SIZE_RESET: + CurrentWebView()->ResetTextSize(); + break; - case TEXT_FIND_NEXT: - CurrentWebView()->FindString(m_findTextControl->Text(), true, - m_findCaseSensitiveCheckBox->Value()); - break; - case TEXT_FIND_PREVIOUS: - CurrentWebView()->FindString(m_findTextControl->Text(), false, - m_findCaseSensitiveCheckBox->Value()); - break; - case TEXT_SHOW_FIND_GROUP: - if (!m_findGroup->IsVisible()) - m_findGroup->SetVisible(true); - m_findTextControl->MakeFocus(true); - break; - case TEXT_HIDE_FIND_GROUP: - if (m_findGroup->IsVisible()) - m_findGroup->SetVisible(false); - break; + case TEXT_FIND_NEXT: + CurrentWebView()->FindString(fFindTextControl->Text(), true, + fFindCaseSensitiveCheckBox->Value()); + break; + case TEXT_FIND_PREVIOUS: + CurrentWebView()->FindString(fFindTextControl->Text(), false, + fFindCaseSensitiveCheckBox->Value()); + break; + case TEXT_SHOW_FIND_GROUP: + if (!fFindGroup->IsVisible()) + fFindGroup->SetVisible(true); + fFindTextControl->MakeFocus(true); + break; + case TEXT_HIDE_FIND_GROUP: + if (fFindGroup->IsVisible()) + fFindGroup->SetVisible(false); + break; - case SHOW_DOWNLOAD_WINDOW: - message->AddUInt32("workspaces", Workspaces()); - be_app->PostMessage(message); - break; + case SHOW_DOWNLOAD_WINDOW: + message->AddUInt32("workspaces", Workspaces()); + be_app->PostMessage(message); + break; - case CLOSE_TAB: - if (m_tabManager->CountTabs() > 1) { - int32 index; - if (message->FindInt32("tab index", &index) != B_OK) - index = m_tabManager->SelectedTabIndex(); - delete m_tabManager->RemoveTab(index); - updateTabGroupVisibility(); - } else - PostMessage(B_QUIT_REQUESTED); - break; + case CLOSE_TAB: + if (fTabManager->CountTabs() > 1) { + int32 index; + if (message->FindInt32("tab index", &index) != B_OK) + index = fTabManager->SelectedTabIndex(); + delete fTabManager->RemoveTab(index); + _UpdateTabGroupVisibility(); + } else + PostMessage(B_QUIT_REQUESTED); + break; - case TAB_CHANGED: { - // This message may be received also when the last tab closed, i.e. with index == -1. - int32 index; - if (message->FindInt32("tab index", &index) != B_OK) - index = -1; - BWebView* webView = dynamic_cast(m_tabManager->ViewForTab(index)); - if (webView == CurrentWebView()) - break; - SetCurrentWebView(webView); - if (webView) - updateTitle(webView->MainFrameTitle()); - else - updateTitle(""); - if (webView) { - m_url->SetText(webView->MainFrameURL()); - // Trigger update of the interface to the new page, by requesting - // to resend all notifications. - webView->WebPage()->ResendNotifications(); - } - break; - } + case TAB_CHANGED: { + // This message may be received also when the last tab closed, i.e. with index == -1. + int32 index; + if (message->FindInt32("tab index", &index) != B_OK) + index = -1; + BWebView* webView = dynamic_cast(fTabManager->ViewForTab(index)); + if (webView == CurrentWebView()) + break; + SetCurrentWebView(webView); + if (webView) + _UpdateTitle(webView->MainFrameTitle()); + else + _UpdateTitle(""); + if (webView) { + fURLTextControl->SetText(webView->MainFrameURL()); + // Trigger update of the interface to the new page, by requesting + // to resend all notifications. + webView->WebPage()->ResendNotifications(); + } + break; + } - default: - BWebWindow::MessageReceived(message); - break; - } + default: + BWebWindow::MessageReceived(message); + break; + } } -bool LauncherWindow::QuitRequested() + +bool +BrowserWindow::QuitRequested() { - // TODO: Check for modified form data and ask user for confirmation, etc. + // TODO: Check for modified form data and ask user for confirmation, etc. - // Iterate over all tabs to delete all BWebViews. - // Do this here, so WebKit tear down happens earlier. - while (m_tabManager->CountTabs() > 0) - delete m_tabManager->RemoveTab(0L); - SetCurrentWebView(0); + // Iterate over all tabs to delete all BWebViews. + // Do this here, so WebKit tear down happens earlier. + while (fTabManager->CountTabs() > 0) + delete fTabManager->RemoveTab(0L); + SetCurrentWebView(0); - BMessage message(WINDOW_CLOSED); - message.AddRect("window frame", Frame()); - be_app->PostMessage(&message); - return true; + BMessage message(WINDOW_CLOSED); + message.AddRect("window frame", Frame()); + be_app->PostMessage(&message); + return true; } -void LauncherWindow::MenusBeginning() + +void +BrowserWindow::MenusBeginning() { - BMenuItem* menuItem; - while ((menuItem = m_goMenu->RemoveItem(0L))) - delete menuItem; + BMenuItem* menuItem; + while ((menuItem = fGoMenu->RemoveItem(0L))) + delete menuItem; - BrowsingHistory* history = BrowsingHistory::defaultInstance(); - if (!history->Lock()) - return; + BrowsingHistory* history = BrowsingHistory::defaultInstance(); + if (!history->Lock()) + return; - int32 count = history->countItems(); - for (int32 i = 0; i < count; i++) { - BrowsingHistoryItem historyItem = history->historyItemAt(i); - BMessage* message = new BMessage(GOTO_URL); - message->AddString("url", historyItem.url().String()); - // TODO: More sophisticated menu structure... sorted by days/weeks... - BString truncatedUrl(historyItem.url()); - be_plain_font->TruncateString(&truncatedUrl, B_TRUNCATE_END, 480); - menuItem = new BMenuItem(truncatedUrl, message); - m_goMenu->AddItem(menuItem); - } + int32 count = history->countItems(); + for (int32 i = 0; i < count; i++) { + BrowsingHistoryItem historyItem = history->historyItemAt(i); + BMessage* message = new BMessage(GOTO_URL); + message->AddString("url", historyItem.url().String()); + // TODO: More sophisticated menu structure... sorted by days/weeks... + BString truncatedUrl(historyItem.url()); + be_plain_font->TruncateString(&truncatedUrl, B_TRUNCATE_END, 480); + menuItem = new BMenuItem(truncatedUrl, message); + fGoMenu->AddItem(menuItem); + } - if (m_goMenu->CountItems() > 3) { - m_goMenu->AddSeparatorItem(); - m_goMenu->AddItem(new BMenuItem("Clear history", new BMessage(CLEAR_HISTORY))); - } + if (fGoMenu->CountItems() > 3) { + fGoMenu->AddSeparatorItem(); + fGoMenu->AddItem(new BMenuItem("Clear history", + new BMessage(CLEAR_HISTORY))); + } - history->Unlock(); + history->Unlock(); } -void LauncherWindow::newTab(const BString& url, bool select, BWebView* webView) + +void +BrowserWindow::CreateNewTab(const BString& url, bool select, BWebView* webView) { - // Executed in app thread (new BWebPage needs to be created in app thread). - if (!webView) - webView = new BWebView("web view"); - webView->WebPage()->SetDownloadListener(m_downloadListener); + // Executed in app thread (new BWebPage needs to be created in app thread). + if (!webView) + webView = new BWebView("web view"); + webView->WebPage()->SetDownloadListener(fDownloadListener); - m_tabManager->AddTab(webView, "New tab"); + fTabManager->AddTab(webView, "New tab"); - if (url.Length()) - webView->LoadURL(url.String()); + if (url.Length()) + webView->LoadURL(url.String()); - if (select) { - m_tabManager->SelectTab(m_tabManager->CountTabs() - 1); - SetCurrentWebView(webView); - NavigationCapabilitiesChanged(false, false, false, webView); - if (m_url) { - m_url->SetText(url.String()); - m_url->MakeFocus(true); - } - } + if (select) { + fTabManager->SelectTab(fTabManager->CountTabs() - 1); + SetCurrentWebView(webView); + NavigationCapabilitiesChanged(false, false, false, webView); + if (fURLTextControl) { + fURLTextControl->SetText(url.String()); + fURLTextControl->MakeFocus(true); + } + } - updateTabGroupVisibility(); + _UpdateTabGroupVisibility(); } + // #pragma mark - Notification API -void LauncherWindow::NavigationRequested(const BString& url, BWebView* view) + +void +BrowserWindow::NavigationRequested(const BString& url, BWebView* view) { } -void LauncherWindow::NewWindowRequested(const BString& url, bool primaryAction) + +void +BrowserWindow::NewWindowRequested(const BString& url, bool primaryAction) { - // Always open new windows in the application thread, since - // creating a BWebView will try to grab the application lock. - // But our own WebPage may already try to lock us from within - // the application thread -> dead-lock. Thus we can't wait for - // a reply here. - BMessage message(NEW_TAB); - message.AddPointer("window", this); - message.AddString("url", url); - message.AddBool("select", primaryAction); - be_app->PostMessage(&message); + // Always open new windows in the application thread, since + // creating a BWebView will try to grab the application lock. + // But our own WebPage may already try to lock us from within + // the application thread -> dead-lock. Thus we can't wait for + // a reply here. + BMessage message(NEW_TAB); + message.AddPointer("window", this); + message.AddString("url", url); + message.AddBool("select", primaryAction); + be_app->PostMessage(&message); } -void LauncherWindow::NewPageCreated(BWebView* view) + +void +BrowserWindow::NewPageCreated(BWebView* view) { - newTab(BString(), true, view); + CreateNewTab(BString(), true, view); } -void LauncherWindow::LoadNegotiating(const BString& url, BWebView* view) + +void +BrowserWindow::LoadNegotiating(const BString& url, BWebView* view) { - BString status("Requesting: "); - status << url; - StatusChanged(status, view); + BString status("Requesting: "); + status << url; + StatusChanged(status, view); } -void LauncherWindow::LoadCommitted(const BString& url, BWebView* view) + +void +BrowserWindow::LoadCommitted(const BString& url, BWebView* view) { - if (view != CurrentWebView()) - return; + if (view != CurrentWebView()) + return; // This hook is invoked when the load is commited. - if (m_url) - m_url->SetText(url.String()); + if (fURLTextControl) + fURLTextControl->SetText(url.String()); - BString status("Loading: "); - status << url; - StatusChanged(status, view); + BString status("Loading: "); + status << url; + StatusChanged(status, view); } -void LauncherWindow::LoadProgress(float progress, BWebView* view) + +void +BrowserWindow::LoadProgress(float progress, BWebView* view) { - if (view != CurrentWebView()) - return; + if (view != CurrentWebView()) + return; - if (m_loadingProgressBar) { - if (progress < 100 && m_loadingProgressBar->IsHidden()) - m_loadingProgressBar->Show(); - m_loadingProgressBar->SetTo(progress); - } + if (fLoadingProgressBar) { + if (progress < 100 && fLoadingProgressBar->IsHidden()) + fLoadingProgressBar->Show(); + fLoadingProgressBar->SetTo(progress); + } } -void LauncherWindow::LoadFailed(const BString& url, BWebView* view) + +void +BrowserWindow::LoadFailed(const BString& url, BWebView* view) { - if (view != CurrentWebView()) - return; + if (view != CurrentWebView()) + return; - BString status(url); - status << " failed."; - StatusChanged(status, view); - if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) - m_loadingProgressBar->Hide(); + BString status(url); + status << " failed."; + StatusChanged(status, view); + if (fLoadingProgressBar && !fLoadingProgressBar->IsHidden()) + fLoadingProgressBar->Hide(); } -void LauncherWindow::LoadFinished(const BString& url, BWebView* view) + +void +BrowserWindow::LoadFinished(const BString& url, BWebView* view) { - if (view != CurrentWebView()) - return; + if (view != CurrentWebView()) + return; - BString status(url); - status << " finished."; - StatusChanged(status, view); - if (m_loadingProgressBar && !m_loadingProgressBar->IsHidden()) - m_loadingProgressBar->Hide(); + BString status(url); + status << " finished."; + StatusChanged(status, view); + if (fLoadingProgressBar && !fLoadingProgressBar->IsHidden()) + fLoadingProgressBar->Hide(); - NavigationCapabilitiesChanged(m_BackButton->IsEnabled(), - m_ForwardButton->IsEnabled(), false, view); + NavigationCapabilitiesChanged(fBackButton->IsEnabled(), + fForwardButton->IsEnabled(), false, view); } -void LauncherWindow::ResizeRequested(float width, float height, BWebView* view) + +void +BrowserWindow::ResizeRequested(float width, float height, BWebView* view) { - if (view != CurrentWebView()) - return; + if (view != CurrentWebView()) + return; - // TODO: Ignore request when there is more than one BWebView embedded! + // TODO: Ignore request when there is more than one BWebView embedded! - ResizeTo(width, height); + ResizeTo(width, height); } -void LauncherWindow::SetToolBarsVisible(bool flag, BWebView* view) + +void +BrowserWindow::SetToolBarsVisible(bool flag, BWebView* view) { - // TODO - // TODO: Ignore request when there is more than one BWebView embedded! + // TODO + // TODO: Ignore request when there is more than one BWebView embedded! } -void LauncherWindow::SetStatusBarVisible(bool flag, BWebView* view) + +void +BrowserWindow::SetStatusBarVisible(bool flag, BWebView* view) { - // TODO - // TODO: Ignore request when there is more than one BWebView embedded! + // TODO + // TODO: Ignore request when there is more than one BWebView embedded! } -void LauncherWindow::SetMenuBarVisible(bool flag, BWebView* view) + +void +BrowserWindow::SetMenuBarVisible(bool flag, BWebView* view) { - // TODO - // TODO: Ignore request when there is more than one BWebView embedded! + // TODO + // TODO: Ignore request when there is more than one BWebView embedded! } -void LauncherWindow::SetResizable(bool flag, BWebView* view) + +void +BrowserWindow::SetResizable(bool flag, BWebView* view) { - // TODO: Ignore request when there is more than one BWebView embedded! + // TODO: Ignore request when there is more than one BWebView embedded! - if (flag) - SetFlags(Flags() & ~B_NOT_RESIZABLE); - else - SetFlags(Flags() | B_NOT_RESIZABLE); + if (flag) + SetFlags(Flags() & ~B_NOT_RESIZABLE); + else + SetFlags(Flags() | B_NOT_RESIZABLE); } -void LauncherWindow::TitleChanged(const BString& title, BWebView* view) + +void +BrowserWindow::TitleChanged(const BString& title, BWebView* view) { - for (int32 i = 0; i < m_tabManager->CountTabs(); i++) { - if (m_tabManager->ViewForTab(i) == view) { - m_tabManager->SetTabLabel(i, title); - break; - } - } - if (view != CurrentWebView()) - return; + for (int32 i = 0; i < fTabManager->CountTabs(); i++) { + if (fTabManager->ViewForTab(i) == view) { + fTabManager->SetTabLabel(i, title); + break; + } + } + if (view != CurrentWebView()) + return; - updateTitle(title); + _UpdateTitle(title); } -void LauncherWindow::StatusChanged(const BString& statusText, BWebView* view) + +void +BrowserWindow::StatusChanged(const BString& statusText, BWebView* view) { - if (view != CurrentWebView()) - return; + if (view != CurrentWebView()) + return; - if (m_statusText) - m_statusText->SetText(statusText.String()); + if (fStatusText) + fStatusText->SetText(statusText.String()); } -void LauncherWindow::NavigationCapabilitiesChanged(bool canGoBackward, - bool canGoForward, bool canStop, BWebView* view) + +void +BrowserWindow::NavigationCapabilitiesChanged(bool canGoBackward, + bool canGoForward, bool canStop, BWebView* view) { - if (view != CurrentWebView()) - return; + if (view != CurrentWebView()) + return; - if (m_BackButton) - m_BackButton->SetEnabled(canGoBackward); - if (m_ForwardButton) - m_ForwardButton->SetEnabled(canGoForward); - if (m_StopButton) - m_StopButton->SetEnabled(canStop); + if (fBackButton) + fBackButton->SetEnabled(canGoBackward); + if (fForwardButton) + fForwardButton->SetEnabled(canGoForward); + if (fStopButton) + fStopButton->SetEnabled(canStop); } -void LauncherWindow::UpdateGlobalHistory(const BString& url) + +void +BrowserWindow::UpdateGlobalHistory(const BString& url) { - BrowsingHistory::defaultInstance()->addItem(BrowsingHistoryItem(url)); + BrowsingHistory::defaultInstance()->addItem(BrowsingHistoryItem(url)); } -bool LauncherWindow::AuthenticationChallenge(BString message, BString& inOutUser, + +bool +BrowserWindow::AuthenticationChallenge(BString message, BString& inOutUser, BString& inOutPassword, bool& inOutRememberCredentials, uint32 failureCount, BWebView* view) { // Switch to the page for which this authentication is required. if (view != CurrentWebView()) { - m_tabManager->SelectTab(view); + fTabManager->SelectTab(view); UpdateIfNeeded(); } - AuthenticationPanel* panel = new AuthenticationPanel(Frame()); - // Panel auto-destructs. - return panel->getAuthentication(message, inOutUser, inOutPassword, - inOutRememberCredentials, failureCount > 0, inOutUser, inOutPassword, - &inOutRememberCredentials); + AuthenticationPanel* panel = new AuthenticationPanel(Frame()); + // Panel auto-destructs. + return panel->getAuthentication(message, inOutUser, inOutPassword, + inOutRememberCredentials, failureCount > 0, inOutUser, inOutPassword, + &inOutRememberCredentials); } -void LauncherWindow::updateTitle(const BString& title) + +// #pragma mark - private + + +void +BrowserWindow::_UpdateTitle(const BString& title) { - BString windowTitle = title; - if (windowTitle.Length() > 0) - windowTitle << " - "; - windowTitle << "HaikuLauncher"; - SetTitle(windowTitle.String()); + BString windowTitle = title; + if (windowTitle.Length() > 0) + windowTitle << " - "; + windowTitle << kApplicationName; + SetTitle(windowTitle.String()); } -void LauncherWindow::updateTabGroupVisibility() + +void +BrowserWindow::_UpdateTabGroupVisibility() { if (Lock()) { - //m_tabGroup->SetVisible(m_tabManager->CountTabs() > 1); - m_tabManager->SetCloseButtonsAvailable(m_tabManager->CountTabs() > 1); - Unlock(); + //fTabGroup->SetVisible(fTabManager->CountTabs() > 1); + fTabManager->SetCloseButtonsAvailable(fTabManager->CountTabs() > 1); + Unlock(); } } diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 018ac29a16..c646a4ab59 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -26,9 +26,9 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#ifndef BROWSER_WINDOW_H +#define BROWSER_WINDOW_H -#ifndef LauncherWindow_h -#define LauncherWindow_h #include "WebWindow.h" #include @@ -46,75 +46,91 @@ class TabManager; class BWebView; enum ToolbarPolicy { - HaveToolbar, - DoNotHaveToolbar + HaveToolbar, + DoNotHaveToolbar }; enum { - NEW_WINDOW = 'nwnd', - NEW_TAB = 'ntab', - WINDOW_OPENED = 'wndo', - WINDOW_CLOSED = 'wndc', - SHOW_DOWNLOAD_WINDOW = 'sdwd' + NEW_WINDOW = 'nwnd', + NEW_TAB = 'ntab', + WINDOW_OPENED = 'wndo', + WINDOW_CLOSED = 'wndc', + SHOW_DOWNLOAD_WINDOW = 'sdwd' }; -class LauncherWindow : public BWebWindow { + +class BrowserWindow : public BWebWindow { public: - LauncherWindow(BRect frame, const BMessenger& downloadListener, - ToolbarPolicy = HaveToolbar); - virtual ~LauncherWindow(); + BrowserWindow(BRect frame, + const BMessenger& downloadListener, + ToolbarPolicy = HaveToolbar); + virtual ~BrowserWindow(); - virtual void DispatchMessage(BMessage* message, BHandler* target); - virtual void MessageReceived(BMessage* message); - virtual bool QuitRequested(); - virtual void MenusBeginning(); + virtual void DispatchMessage(BMessage* message, + BHandler* target); + virtual void MessageReceived(BMessage* message); + virtual bool QuitRequested(); + virtual void MenusBeginning(); - void newTab(const BString& url, bool select, BWebView* webView = 0); + void CreateNewTab(const BString& url, bool select, + BWebView* webView = 0); private: - // WebPage notification API implementations - virtual void NavigationRequested(const BString& url, BWebView* view); - virtual void NewWindowRequested(const BString& url, bool primaryAction); - virtual void NewPageCreated(BWebView* view); - virtual void LoadNegotiating(const BString& url, BWebView* view); - virtual void LoadCommitted(const BString& url, BWebView* view); - virtual void LoadProgress(float progress, BWebView* view); - virtual void LoadFailed(const BString& url, BWebView* view); - virtual void LoadFinished(const BString& url, BWebView* view); - virtual void TitleChanged(const BString& title, BWebView* view); - virtual void ResizeRequested(float width, float height, BWebView* view); - virtual void SetToolBarsVisible(bool flag, BWebView* view); - virtual void SetStatusBarVisible(bool flag, BWebView* view); - virtual void SetMenuBarVisible(bool flag, BWebView* view); - virtual void SetResizable(bool flag, BWebView* view); - virtual void StatusChanged(const BString& status, BWebView* view); - virtual void NavigationCapabilitiesChanged(bool canGoBackward, - bool canGoForward, bool canStop, BWebView* view); - virtual void UpdateGlobalHistory(const BString& url); - virtual bool AuthenticationChallenge(BString message, BString& inOutUser, - BString& inOutPassword, bool& inOutRememberCredentials, - uint32 failureCount, BWebView* view); - - void updateTitle(const BString &title); - void updateTabGroupVisibility(); + // WebPage notification API implementations + virtual void NavigationRequested(const BString& url, + BWebView* view); + virtual void NewWindowRequested(const BString& url, + bool primaryAction); + virtual void NewPageCreated(BWebView* view); + virtual void LoadNegotiating(const BString& url, + BWebView* view); + virtual void LoadCommitted(const BString& url, + BWebView* view); + virtual void LoadProgress(float progress, BWebView* view); + virtual void LoadFailed(const BString& url, BWebView* view); + virtual void LoadFinished(const BString& url, + BWebView* view); + virtual void TitleChanged(const BString& title, + BWebView* view); + virtual void ResizeRequested(float width, float height, + BWebView* view); + virtual void SetToolBarsVisible(bool flag, BWebView* view); + virtual void SetStatusBarVisible(bool flag, BWebView* view); + virtual void SetMenuBarVisible(bool flag, BWebView* view); + virtual void SetResizable(bool flag, BWebView* view); + virtual void StatusChanged(const BString& status, + BWebView* view); + virtual void NavigationCapabilitiesChanged( + bool canGoBackward, bool canGoForward, + bool canStop, BWebView* view); + virtual void UpdateGlobalHistory(const BString& url); + virtual bool AuthenticationChallenge(BString message, + BString& inOutUser, BString& inOutPassword, + bool& inOutRememberCredentials, + uint32 failureCount, BWebView* view); private: - BMessenger m_downloadListener; - BMenuBar* m_menuBar; - BMenu* m_goMenu; - IconButton* m_BackButton; - IconButton* m_ForwardButton; - IconButton* m_StopButton; - BButton* m_goButton; - BTextControl* m_url; - BStringView* m_statusText; - BStatusBar* m_loadingProgressBar; - BLayoutItem* m_findGroup; - BLayoutItem* m_tabGroup; - BTextControl* m_findTextControl; - BCheckBox* m_findCaseSensitiveCheckBox; - TabManager* m_tabManager; + void _UpdateTitle(const BString &title); + void _UpdateTabGroupVisibility(); + +private: + BMessenger fDownloadListener; + BMenuBar* fMenuBar; + BMenu* fGoMenu; + IconButton* fBackButton; + IconButton* fForwardButton; + IconButton* fStopButton; + BButton* fGoButton; + BTextControl* fURLTextControl; + BStringView* fStatusText; + BStatusBar* fLoadingProgressBar; + BLayoutItem* fFindGroup; + BLayoutItem* fTabGroup; + BTextControl* fFindTextControl; + BCheckBox* fFindCaseSensitiveCheckBox; + TabManager* fTabManager; }; -#endif // LauncherWindow_h + +#endif // BROWSER_WINDOW_H diff --git a/src/apps/webpositive/BrowsingHistory.cpp b/src/apps/webpositive/BrowsingHistory.cpp index 7c5246df11..e5a7e8afe4 100644 --- a/src/apps/webpositive/BrowsingHistory.cpp +++ b/src/apps/webpositive/BrowsingHistory.cpp @@ -28,6 +28,7 @@ #include "config.h" #include "BrowsingHistory.h" +#include "BrowserApp.h" #include #include #include @@ -262,7 +263,8 @@ bool BrowsingHistory::openSettingsFile(BFile& file, uint32 mode) { BPath path; if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK - || path.Append("HaikuLauncher_BrowsingHistory") != B_OK) { + || path.Append(kApplicationName) != B_OK + || path.Append("BrowsingHistory") != B_OK) { return false; } return file.SetTo(path.Path(), mode) == B_OK; diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 248e3bde44..fbbe932118 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -28,6 +28,7 @@ #include "config.h" #include "DownloadWindow.h" +#include "BrowserApp.h" #include "WebDownload.h" #include "WebPage.h" #include @@ -550,7 +551,8 @@ bool DownloadWindow::openSettingsFile(BFile& file, uint32 mode) { BPath path; if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK - || path.Append("HaikuLauncher_Downloads") != B_OK) { + || path.Append(kApplicationName) != B_OK + || path.Append("Downloads") != B_OK) { return false; } return file.SetTo(path.Path(), mode) == B_OK; diff --git a/src/apps/webpositive/WebPositive.rdef b/src/apps/webpositive/WebPositive.rdef index fee9516509..f741a6a3e9 100644 --- a/src/apps/webpositive/WebPositive.rdef +++ b/src/apps/webpositive/WebPositive.rdef @@ -1,4 +1,4 @@ -resource app_signature "application/x-vnd.RJL-HaikuLauncher"; +resource app_signature "application/x-vnd.Haiku-WebPositive"; resource app_version { major = 0, @@ -6,8 +6,8 @@ resource app_version { minor = 1, variety = B_APPV_ALPHA, internal = 0, - short_info = "HaikuLauncher", - long_info = "HaikuLauncher ©2007-2010 The WebKit Haiku Project" + short_info = "WebPositive", + long_info = "WebPositive ©2007-2010 The WebKit Haiku Project" }; resource app_flags B_SINGLE_LAUNCH; From df6c7e475d73d6194330480ae044fdd054590ae5 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 27 Feb 2010 18:26:46 +0000 Subject: [PATCH 131/349] The BWebDownload was using BWebPage for stuff, but the BWebPage can be long gone when a BWebDownload wanted to use it. Now the class is more self-sufficient. One example of the problem was clicking a link that opens a blank page, then closing that page while the download was still loading. 1) The download finished notification never arrived and 2) clicking to cancel the download would crash after the download finished, since really it had already selfdestructed... git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@240 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index fbbe932118..44e5fa936e 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -272,6 +272,12 @@ public: // TOAST! return; } + case B_DOWNLOAD_REMOVED: + // TODO: This is a bit asymetric. The removed notification + // arrives here, but it would be nicer if it arrived + // at the window... + Window()->PostMessage(message); + break; default: BGridView::MessageReceived(message); } From 0d3093e5d8e31fe0d7ea1e86de09633b0bcb6589 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 28 Feb 2010 13:32:39 +0000 Subject: [PATCH 132/349] Implemented a neat new window management feature: When the app is asked to open a new file or url, check if there is already a window open on the current workspace, and if so, open a new tab in that window and bring it to front. ArgReceived() now reuses RefsReceived(), which has been extended to handle "url" string fields in the message, since ArgReceived() may also be asked to open urls and not only local files. The LOAD_AT_STARTING mechanism, which turned out to be broken for multiple args anyway, could be replaced, since RefsReceived() already buffers the message when it has been called earlier then ReadyToRun(). git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@244 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 74 ++++++++++++++--------------- src/apps/webpositive/BrowserApp.h | 1 + 2 files changed, 36 insertions(+), 39 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 3dd0d7a25a..c23e7cbd6b 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -49,11 +49,6 @@ const char* kApplicationSignature = "application/x-vnd.Haiku-WebPositive"; const char* kApplicationName = "WebPositive"; -enum { - LOAD_AT_STARTING = 'lost' -}; - - BrowserApp::BrowserApp() : BApplication(kApplicationSignature) , fWindowCount(0) @@ -85,17 +80,18 @@ BrowserApp::AboutRequested() void BrowserApp::ArgvReceived(int32 argc, char** argv) { + BMessage message(B_REFS_RECEIVED); for (int i = 1; i < argc; i++) { const char* url = argv[i]; BEntry entry(argv[i], true); BPath path; if (entry.Exists() && entry.GetPath(&path) == B_OK) url = path.Path(); - BMessage message(LOAD_AT_STARTING); message.AddString("url", url); - message.AddBool("new window", fInitialized || i > 1); - PostMessage(&message); } + // Upon program launch, it will buffer a copy of the message, since + // ArgReceived() is called before ReadyToRun(). + RefsReceived(&message); } @@ -141,37 +137,8 @@ void BrowserApp::MessageReceived(BMessage* message) { switch (message->what) { - case LOAD_AT_STARTING: { - BString url; - if (message->FindString("url", &url) != B_OK) - break; - bool openNewWindow = false; - message->FindBool("new window", &openNewWindow); - BrowserWindow* webWindow = NULL; - for (int i = 0; BWindow* window = WindowAt(i); i++) { - webWindow = dynamic_cast(window); - if (!webWindow) - continue; - if (!openNewWindow) { - // stop at the first window - break; - } - } - if (webWindow) { - // There should always be at least one window open. If not, maybe we are about - // to quit anyway... - if (openNewWindow) { - // open a new window with an offset to the last window - _CreateNewWindow(url); - } else { - // load the URL in the first window - webWindow->CurrentWebView()->LoadURL(url.String()); - } - } - break; - } case B_SILENT_RELAUNCH: - _CreateNewWindow(""); + _CreateNewPage(""); break; case NEW_WINDOW: { BString url; @@ -238,8 +205,12 @@ BrowserApp::RefsReceived(BMessage* message) continue; BString url; url << path.Path(); - _CreateNewWindow(url); + _CreateNewPage(url); } + + BString url; + for (int32 i = 0; message->FindString("url", i, &url) == B_OK; i++) + _CreateNewPage(url); } @@ -293,6 +264,31 @@ BrowserApp::_OpenSettingsFile(BFile& file, uint32 mode) } +void +BrowserApp::_CreateNewPage(const BString& url) +{ + uint32 workspace = 1 << current_workspace(); + + bool loadedInWindowOnCurrentWorkspace = false; + for (int i = 0; BWindow* window = WindowAt(i); i++) { + BrowserWindow* webWindow = dynamic_cast(window); + if (!webWindow) + continue; + if (webWindow->Lock()) { + if (webWindow->Workspaces() & workspace) { + webWindow->CreateNewTab(url, true); + webWindow->Activate(); + loadedInWindowOnCurrentWorkspace = true; + } + webWindow->Unlock(); + } + if (loadedInWindowOnCurrentWorkspace) + return; + } + _CreateNewWindow(url); +} + + void BrowserApp::_CreateNewWindow(const BString& url) { diff --git a/src/apps/webpositive/BrowserApp.h b/src/apps/webpositive/BrowserApp.h index f834d41f62..17ae54735a 100644 --- a/src/apps/webpositive/BrowserApp.h +++ b/src/apps/webpositive/BrowserApp.h @@ -51,6 +51,7 @@ public: private: bool _OpenSettingsFile(BFile& file, uint32 mode); + void _CreateNewPage(const BString& url); void _CreateNewWindow(const BString& url); void _CreateNewTab(BrowserWindow* window, const BString& url, bool select); From e335cb654c2d4a70a8532c01f2a62bc8ad7e087a Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 28 Feb 2010 13:50:06 +0000 Subject: [PATCH 133/349] Missing break in switch, but harmless in this case. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@245 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index c23e7cbd6b..b12c380eff 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -177,6 +177,7 @@ BrowserApp::MessageReceived(BMessage* message) fDownloadWindow->Show(); else fDownloadWindow->Activate(); + break; } default: From e6809b325a8abd0f8a2b83e366b5483358fc15b6 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 28 Feb 2010 20:48:31 +0000 Subject: [PATCH 134/349] Experimental integration of the main menu into the tab bar. Please tell me what you think, I am not 100% it's nicer than before. Can be easily reverted in any case. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@248 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 16 ++++----- src/apps/webpositive/BrowserWindow.h | 1 - src/apps/webpositive/WebTabView.cpp | 49 +++++++++++++++++++++++--- src/apps/webpositive/WebTabView.h | 4 +++ 4 files changed, 56 insertions(+), 14 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index ee11bf91ac..4a4413784d 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -106,7 +106,8 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, if (toolbarPolicy == HaveToolbar) { // Menu - fMenuBar = new BMenuBar("Main menu"); +// BMenu* mainMenu = new BMenuBar("Main menu"); + BMenu* mainMenu = fTabManager->Menu(); BMenu* menu = new BMenu("Window"); BMessage* newWindowMessage = new BMessage(NEW_WINDOW); newWindowMessage->AddString("url", ""); @@ -126,7 +127,7 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); menu->AddItem(quitItem); quitItem->SetTarget(be_app); - fMenuBar->AddItem(menu); + mainMenu->AddItem(menu); menu = new BMenu("Text"); menu->AddItem(new BMenuItem("Find", new BMessage(TEXT_SHOW_FIND_GROUP), 'F')); @@ -134,10 +135,10 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, menu->AddItem(new BMenuItem("Increase size", new BMessage(TEXT_SIZE_INCREASE), '+')); menu->AddItem(new BMenuItem("Decrease size", new BMessage(TEXT_SIZE_DECREASE), '-')); menu->AddItem(new BMenuItem("Reset size", new BMessage(TEXT_SIZE_RESET), '0')); - fMenuBar->AddItem(menu); + mainMenu->AddItem(menu); fGoMenu = new BMenu("Go"); - fMenuBar->AddItem(fGoMenu); + mainMenu->AddItem(fGoMenu); // Back, Forward & Stop fBackButton = new IconButton("Back", 0, NULL, new BMessage(GO_BACK)); @@ -175,8 +176,8 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, fLoadingProgressBar->Hide(); fLoadingProgressBar->SetBarHeight(12); - const float kInsetSpacing = 5; - const float kElementSpacing = 7; + const float kInsetSpacing = 3; + const float kElementSpacing = 5; fFindTextControl = new BTextControl("find", "Find:", "", new BMessage(TEXT_FIND_NEXT)); @@ -196,7 +197,7 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, ; // Layout AddChild(BGroupLayoutBuilder(B_VERTICAL) - .Add(fMenuBar) +// .Add(mainMenu) .Add(fTabManager->TabGroup()) .Add(BGridLayoutBuilder(kElementSpacing, kElementSpacing) .Add(fBackButton, 0, 0) @@ -228,7 +229,6 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, fStopButton = 0; fGoButton = 0; fURLTextControl = 0; - fMenuBar = 0; fStatusText = 0; fLoadingProgressBar = 0; diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index c646a4ab59..e245f4d576 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -115,7 +115,6 @@ private: private: BMessenger fDownloadListener; - BMenuBar* fMenuBar; BMenu* fGoMenu; IconButton* fBackButton; IconButton* fForwardButton; diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index 1b491385c0..b96e4a4fe9 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -863,10 +864,10 @@ void WebTabView::_DrawCloseButton(BView* owner, BRect& frame, rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); float tint = B_DARKEN_1_TINT; - if (!IsFront()) + if (!IsFront()) { + base = tint_color(base, tint); tint *= 1.02; - - base = tint_color(base, tint); + } if (fOverCloseRect) tint *= 1.2; @@ -916,6 +917,30 @@ TabManagerController::CloseTab(int32 index) } +// #pragma mark - TabButtonContainer + + +class TabButtonContainer : public BGroupView { +public: + TabButtonContainer() + : BGroupView(B_HORIZONTAL) + { + SetFlags(Flags() | B_WILL_DRAW); + SetViewColor(B_TRANSPARENT_COLOR); + SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + GroupLayout()->SetInsets(0, 6, 0, 0); + } + + virtual void Draw(BRect updateRect) + { + BRect bounds(Bounds()); + rgb_color base = LowColor(); + be_control_look->DrawInactiveTab(this, bounds, updateRect, + base, 0, BControlLook::B_TOP_BORDER); + } +}; + + // #pragma mark - TabButton @@ -1058,7 +1083,6 @@ public: // #pragma mark - TabManager - TabManager::TabManager(const BMessenger& target, BMessage* newTabMessage) : fController(new TabManagerController(this)), @@ -1068,9 +1092,17 @@ TabManager::TabManager(const BMessenger& target, BMessage* newTabMessage) fCardLayout = new BCardLayout(); fContainerView->SetLayout(fCardLayout); + fMenu = new BMenu("Menu"); fTabContainerView = new TabContainerView(fController); fTabContainerGroup = new BGroupView(B_HORIZONTAL); - fTabContainerGroup->GroupLayout()->SetInsets(0, 5, 0, 0); + fTabContainerGroup->GroupLayout()->SetInsets(0, 3, 0, 0); + + BMenuBar* menuBar = new BMenuBar("Menu bar"); + menuBar->AddItem(fMenu); + TabButtonContainer* menuBarContainer = new TabButtonContainer(); + menuBarContainer->GroupLayout()->AddView(menuBar); + fTabContainerGroup->GroupLayout()->AddView(menuBarContainer, 0.0f); + fTabContainerGroup->GroupLayout()->AddView(fTabContainerView); // fTabContainerGroup->GroupLayout()->AddView(new ScrollLeftTabButton(NULL), 0.0f); // fTabContainerGroup->GroupLayout()->AddView(new ScrollRightTabButton(NULL), 0.0f); @@ -1101,6 +1133,13 @@ TabManager::Target() const } +BMenu* +TabManager::Menu() const +{ + return fMenu; +} + + BView* TabManager::TabGroup() const { diff --git a/src/apps/webpositive/WebTabView.h b/src/apps/webpositive/WebTabView.h index 3f9f086755..e6d6c3abcd 100644 --- a/src/apps/webpositive/WebTabView.h +++ b/src/apps/webpositive/WebTabView.h @@ -38,6 +38,7 @@ enum { class BCardLayout; class BGroupView; +class BMenu; class TabContainerView; class TabManagerController; @@ -50,6 +51,8 @@ public: void SetTarget(const BMessenger& target); const BMessenger& Target() const; + BMenu* Menu() const; + BView* TabGroup() const; BView* ContainerView() const; @@ -69,6 +72,7 @@ public: void SetCloseButtonsAvailable(bool available); private: + BMenu* fMenu; BGroupView* fTabContainerGroup; TabContainerView* fTabContainerView; BView* fContainerView; From e64e6d933a418060ceedf20dad4f19d4901dd5be Mon Sep 17 00:00:00 2001 From: leavengood Date: Mon, 1 Mar 2010 04:25:55 +0000 Subject: [PATCH 135/349] Add shortcuts for using Alt-[1-9] to select that tab. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@249 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 4a4413784d..7b1406161c 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -79,6 +79,8 @@ enum { TEXT_HIDE_FIND_GROUP = 'hfnd', TEXT_FIND_NEXT = 'fndn', TEXT_FIND_PREVIOUS = 'fndp', + + SELECT_TAB = 'sltb', }; @@ -249,6 +251,15 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, AddShortcut('F', B_COMMAND_KEY, new BMessage(TEXT_SHOW_FIND_GROUP)); AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_HIDE_FIND_GROUP)); AddShortcut('R', B_COMMAND_KEY, new BMessage(RELOAD)); + + // Add shortcuts to select a particular tab + for (int32 i = 1; i <= 9; i++) { + BMessage *selectTab = new BMessage(SELECT_TAB); + selectTab->AddInt32("tab index", i - 1); + char numStr[2]; + snprintf(numStr, sizeof(numStr), "%d", (int) i); + AddShortcut(numStr[0], B_COMMAND_KEY, selectTab); + } be_app->PostMessage(WINDOW_OPENED); } @@ -396,6 +407,17 @@ BrowserWindow::MessageReceived(BMessage* message) PostMessage(B_QUIT_REQUESTED); break; + case SELECT_TAB: { + int32 index; + if (message->FindInt32("tab index", &index) == B_OK + && fTabManager->SelectedTabIndex() != index + && fTabManager->CountTabs() > index) { + fTabManager->SelectTab(index); + } + + break; + } + case TAB_CHANGED: { // This message may be received also when the last tab closed, i.e. with index == -1. int32 index; From 08d60e5886af0eddc762bababa1489d82c0bbe8a Mon Sep 17 00:00:00 2001 From: leavengood Date: Mon, 1 Mar 2010 04:31:07 +0000 Subject: [PATCH 136/349] Shortcut Alt-0 selects the 10th tab (index 9.) git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@250 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 7b1406161c..6fc92f8b65 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -253,9 +253,12 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, AddShortcut('R', B_COMMAND_KEY, new BMessage(RELOAD)); // Add shortcuts to select a particular tab - for (int32 i = 1; i <= 9; i++) { + for (int32 i = 0; i <= 9; i++) { BMessage *selectTab = new BMessage(SELECT_TAB); - selectTab->AddInt32("tab index", i - 1); + if (i == 0) + selectTab->AddInt32("tab index", 9); + else + selectTab->AddInt32("tab index", i - 1); char numStr[2]; snprintf(numStr, sizeof(numStr), "%d", (int) i); AddShortcut(numStr[0], B_COMMAND_KEY, selectTab); From ddb431ba2136284cd2362719858fb51345d25f03 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 1 Mar 2010 10:05:35 +0000 Subject: [PATCH 137/349] Made the integrated menu bar a build time configuration feature. I don't like it so much, since it somehow looks alien for no /really/ good reason. Maybe I'll integrate this option into the settings, when I get to those. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@253 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 9 +++++++-- src/apps/webpositive/BrowserWindow.h | 2 ++ src/apps/webpositive/WebTabView.cpp | 6 +++++- src/apps/webpositive/WebTabView.h | 4 ++++ 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 6fc92f8b65..0fa866009e 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -108,8 +108,11 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, if (toolbarPolicy == HaveToolbar) { // Menu -// BMenu* mainMenu = new BMenuBar("Main menu"); +#if INTEGRATE_MENU_INTO_TAB_BAR BMenu* mainMenu = fTabManager->Menu(); +#else + BMenu* mainMenu = new BMenuBar("Main menu"); +#endif BMenu* menu = new BMenu("Window"); BMessage* newWindowMessage = new BMessage(NEW_WINDOW); newWindowMessage->AddString("url", ""); @@ -199,7 +202,9 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, ; // Layout AddChild(BGroupLayoutBuilder(B_VERTICAL) -// .Add(mainMenu) +#if !INTEGRATE_MENU_INTO_TAB_BAR + .Add(mainMenu) +#endif .Add(fTabManager->TabGroup()) .Add(BGridLayoutBuilder(kElementSpacing, kElementSpacing) .Add(fBackButton, 0, 0) diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index e245f4d576..568a49670a 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -58,6 +58,8 @@ enum { SHOW_DOWNLOAD_WINDOW = 'sdwd' }; +#define INTEGRATE_MENU_INTO_TAB_BAR 0 + class BrowserWindow : public BWebWindow { public: diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index b96e4a4fe9..a4e073dc40 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -1092,16 +1092,18 @@ TabManager::TabManager(const BMessenger& target, BMessage* newTabMessage) fCardLayout = new BCardLayout(); fContainerView->SetLayout(fCardLayout); - fMenu = new BMenu("Menu"); fTabContainerView = new TabContainerView(fController); fTabContainerGroup = new BGroupView(B_HORIZONTAL); fTabContainerGroup->GroupLayout()->SetInsets(0, 3, 0, 0); +#if INTEGRATE_MENU_INTO_TAB_BAR + fMenu = new BMenu("Menu"); BMenuBar* menuBar = new BMenuBar("Menu bar"); menuBar->AddItem(fMenu); TabButtonContainer* menuBarContainer = new TabButtonContainer(); menuBarContainer->GroupLayout()->AddView(menuBar); fTabContainerGroup->GroupLayout()->AddView(menuBarContainer, 0.0f); +#endif fTabContainerGroup->GroupLayout()->AddView(fTabContainerView); // fTabContainerGroup->GroupLayout()->AddView(new ScrollLeftTabButton(NULL), 0.0f); @@ -1133,11 +1135,13 @@ TabManager::Target() const } +#if INTEGRATE_MENU_INTO_TAB_BAR BMenu* TabManager::Menu() const { return fMenu; } +#endif BView* diff --git a/src/apps/webpositive/WebTabView.h b/src/apps/webpositive/WebTabView.h index e6d6c3abcd..69d7a032d9 100644 --- a/src/apps/webpositive/WebTabView.h +++ b/src/apps/webpositive/WebTabView.h @@ -51,7 +51,9 @@ public: void SetTarget(const BMessenger& target); const BMessenger& Target() const; +#if INTEGRATE_MENU_INTO_TAB_BAR BMenu* Menu() const; +#endif BView* TabGroup() const; BView* ContainerView() const; @@ -72,7 +74,9 @@ public: void SetCloseButtonsAvailable(bool available); private: +#if INTEGRATE_MENU_INTO_TAB_BAR BMenu* fMenu; +#endif BGroupView* fTabContainerGroup; TabContainerView* fTabContainerView; BView* fContainerView; From 10d5754b9273aa826a36beb7c614d0fe0ac0b1d6 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 1 Mar 2010 17:41:43 +0000 Subject: [PATCH 138/349] Added BWebSettings and BPrivate::WebSettingsPrivate. Added all the wiring necessary. The only usable effect as of yet is that favicons arrive at the BrowserWindow. Favicons are stored in a database and are not fetched when they alreary exist. The application is expected to try and fetch an icon for a given url. This is currently done in BWebWindow when the URL for loading has been initiated. Otherwise it fetches the URL upon the new ICON_RECEIVED notification from the FrameLoaderClientHaiku. In any case it ends up at BWebWindow::IconReceived(), so derived classes don't have to worry about the difference. In any case, via BWebSettings, icons can also be fetched manually, like for the forthcomming autocompletion text control. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@257 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 4 +++- src/apps/webpositive/BrowserWindow.cpp | 7 +++++++ src/apps/webpositive/BrowserWindow.h | 2 ++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index b12c380eff..67ce27db15 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -32,8 +32,8 @@ #include "BrowserWindow.h" #include "DownloadWindow.h" #include "WebPage.h" +#include "WebSettings.h" #include "WebView.h" -#include "WebViewConstants.h" #include #include #include @@ -104,6 +104,8 @@ BrowserApp::ReadyToRun() BWebPage::InitializeOnce(); BWebPage::SetCacheModel(B_WEBKIT_CACHE_MODEL_WEB_BROWSER); + BWebSettings::SetPersistentStoragePath("/boot/home/config/settings/WebPositive"); + BFile settingsFile; BRect windowFrameFromSettings = fLastWindowFrame; BRect downloadWindowFrame(100, 100, 300, 250); diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 0fa866009e..c72925f889 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -700,6 +700,13 @@ BrowserWindow::TitleChanged(const BString& title, BWebView* view) } +void +BrowserWindow::IconReceived(const BBitmap* icon, BWebView* view) +{ + printf("BrowserWindow::IconReceived(%p, %p)\n", icon, view); +} + + void BrowserWindow::StatusChanged(const BString& statusText, BWebView* view) { diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 568a49670a..9ef4426942 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -94,6 +94,8 @@ private: BWebView* view); virtual void TitleChanged(const BString& title, BWebView* view); + virtual void IconReceived(const BBitmap* icon, + BWebView* view); virtual void ResizeRequested(float width, float height, BWebView* view); virtual void SetToolBarsVisible(bool flag, BWebView* view); From 606397473431bf7d5effa5bbfce7c224f652346b Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 1 Mar 2010 18:46:15 +0000 Subject: [PATCH 139/349] Finished all the wiring necessary for favicon support. Send the NAVIGATION_REQUESTED notification again from the FrameLoaderClient, this way we can try to fetch the icon even earlier. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@259 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 3 +- src/apps/webpositive/WebTabView.cpp | 91 +++++++++++++++++++++++--- src/apps/webpositive/WebTabView.h | 9 ++- 3 files changed, 91 insertions(+), 12 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index c72925f889..0e811e4c8d 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -321,6 +321,7 @@ BrowserWindow::MessageReceived(BMessage* message) BString url; if (message->FindString("url", &url) != B_OK) url = fURLTextControl->Text(); + fTabManager->SetTabIcon(CurrentWebView(), NULL); CurrentWebView()->LoadURL(url.String()); break; } @@ -703,7 +704,7 @@ BrowserWindow::TitleChanged(const BString& title, BWebView* view) void BrowserWindow::IconReceived(const BBitmap* icon, BWebView* view) { - printf("BrowserWindow::IconReceived(%p, %p)\n", icon, view); + fTabManager->SetTabIcon(view, icon); } diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index a4e073dc40..bdbeb85c0b 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -31,6 +31,7 @@ #include "WebView.h" #include #include +#include #include #include #include @@ -146,6 +147,7 @@ public: void AddTab(const char* label, int32 index = -1); void AddTab(TabView* tab, int32 index = -1); TabView* RemoveTab(int32 index); + TabView* TabAt(int32 index) const; int32 IndexOf(TabView* tab) const; @@ -382,6 +384,17 @@ TabContainerView::RemoveTab(int32 index) } +TabView* +TabContainerView::TabAt(int32 index) const +{ + TabLayoutItem* item = dynamic_cast( + GroupLayout()->ItemAt(index)); + if (item) + return item->Parent(); + return NULL; +} + + int32 TabContainerView::IndexOf(TabView* tab) const { @@ -738,6 +751,7 @@ private: class WebTabView : public TabView { public: WebTabView(TabManagerController* controller); + ~WebTabView(); virtual BSize MaxSize(); @@ -749,12 +763,15 @@ public: virtual void MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage); + void SetIcon(const BBitmap* icon); + private: void _DrawCloseButton(BView* owner, BRect& frame, const BRect& updateRect, bool isFirst, bool isLast, bool isFront); BRect _CloseRectFrame(BRect frame) const; private: + BBitmap* fIcon; TabManagerController* fController; bool fOverCloseRect; bool fClicked; @@ -764,6 +781,7 @@ private: WebTabView::WebTabView(TabManagerController* controller) : TabView(), + fIcon(NULL), fController(controller), fOverCloseRect(false), fClicked(false) @@ -771,11 +789,21 @@ WebTabView::WebTabView(TabManagerController* controller) } +WebTabView::~WebTabView() +{ + delete fIcon; +} + + BSize WebTabView::MaxSize() { - // Account for close button. + // Account for icon. BSize size(TabView::MaxSize()); + size.height = max_c(size.height, 16 + 8); + if (fIcon) + size.width += 16 + 8; + // Account for close button. size.width += size.height; return size; } @@ -788,6 +816,19 @@ WebTabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect, if (fController->CloseButtonsAvailable()) _DrawCloseButton(owner, frame, updateRect, isFirst, isLast, isFront); + if (fIcon) { + BRect iconBounds(0, 0, 15, 15); + // clip to icon bounds, if they are smaller + if (iconBounds.Contains(fIcon->Bounds())) + iconBounds = fIcon->Bounds(); + BPoint iconPos(frame.left + 4, + frame.top + (frame.Height() - iconBounds.Height()) / 2); + iconBounds.OffsetTo(iconPos); + owner->SetDrawingMode(B_OP_OVER); + owner->DrawBitmap(fIcon, fIcon->Bounds(), iconBounds); + frame.left = frame.left + 16 + 8; + } + TabView::DrawContents(owner, frame, updateRect, isFirst, isLast, isFront); } @@ -843,6 +884,18 @@ WebTabView::MouseMoved(BPoint where, uint32 transit, } +void +WebTabView::SetIcon(const BBitmap* icon) +{ + delete fIcon; + if (icon) + fIcon = new BBitmap(icon); + else + fIcon = NULL; + LayoutItem()->InvalidateLayout(); +} + + BRect WebTabView::_CloseRectFrame(BRect frame) const { @@ -1181,16 +1234,11 @@ TabManager::SelectTab(int32 tabIndex) void -TabManager::SelectTab(BView* containedView) +TabManager::SelectTab(const BView* containedView) { - int32 count = fCardLayout->CountItems(); - for (int32 i = 0; i < count; i++) { - BLayoutItem* item = fCardLayout->ItemAt(i); - if (item->View() == containedView) { - SelectTab(i); - break; - } - } + int32 tabIndex = _TabIndexForContainedView(containedView); + if (tabIndex > 0) + SelectTab(tabIndex); } @@ -1252,6 +1300,16 @@ TabManager::SetTabLabel(int32 tabIndex, const char* label) } +void +TabManager::SetTabIcon(const BView* containedView, const BBitmap* icon) +{ + WebTabView* tab = dynamic_cast(fTabContainerView->TabAt( + _TabIndexForContainedView(containedView))); + if (tab) + tab->SetIcon(icon); +} + + void TabManager::SetCloseButtonsAvailable(bool available) { @@ -1261,3 +1319,16 @@ TabManager::SetCloseButtonsAvailable(bool available) fTabContainerView->Invalidate(); } + +int32 +TabManager::_TabIndexForContainedView(const BView* containedView) const +{ + int32 count = fCardLayout->CountItems(); + for (int32 i = 0; i < count; i++) { + BLayoutItem* item = fCardLayout->ItemAt(i); + if (item->View() == containedView) + return i; + } + return -1; +} + diff --git a/src/apps/webpositive/WebTabView.h b/src/apps/webpositive/WebTabView.h index 69d7a032d9..93129b1b0c 100644 --- a/src/apps/webpositive/WebTabView.h +++ b/src/apps/webpositive/WebTabView.h @@ -36,6 +36,7 @@ enum { CLOSE_TAB = 'cltb' }; +class BBitmap; class BCardLayout; class BGroupView; class BMenu; @@ -61,7 +62,7 @@ public: BView* ViewForTab(int32 tabIndex) const; void SelectTab(int32 tabIndex); - void SelectTab(BView* containedView); + void SelectTab(const BView* containedView); int32 SelectedTabIndex() const; void CloseTab(int32 tabIndex); @@ -71,8 +72,14 @@ public: int32 CountTabs() const; void SetTabLabel(int32 tabIndex, const char* label); + void SetTabIcon(const BView* containedView, + const BBitmap* icon); void SetCloseButtonsAvailable(bool available); +private: + int32 _TabIndexForContainedView( + const BView* containedView) const; + private: #if INTEGRATE_MENU_INTO_TAB_BAR BMenu* fMenu; From 85fc02b33dc369109fe836474d3f0017f5b0bf1a Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 1 Mar 2010 19:15:07 +0000 Subject: [PATCH 140/349] Use 18x18 as standard icon size, as it seems more common. Position the icon slightly more pleasing. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@261 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/WebTabView.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index bdbeb85c0b..cda62fd150 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -795,14 +795,18 @@ WebTabView::~WebTabView() } +static const int kIconSize = 18; +static const int kIconInset = 3; + + BSize WebTabView::MaxSize() { // Account for icon. BSize size(TabView::MaxSize()); - size.height = max_c(size.height, 16 + 8); + size.height = max_c(size.height, kIconSize + kIconInset * 2); if (fIcon) - size.width += 16 + 8; + size.width += kIconSize + kIconInset * 2; // Account for close button. size.width += size.height; return size; @@ -817,16 +821,16 @@ WebTabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect, _DrawCloseButton(owner, frame, updateRect, isFirst, isLast, isFront); if (fIcon) { - BRect iconBounds(0, 0, 15, 15); + BRect iconBounds(0, 0, kIconSize - 1, kIconSize - 1); // clip to icon bounds, if they are smaller if (iconBounds.Contains(fIcon->Bounds())) iconBounds = fIcon->Bounds(); - BPoint iconPos(frame.left + 4, - frame.top + (frame.Height() - iconBounds.Height()) / 2); + BPoint iconPos(frame.left + kIconInset - 1, + frame.top + floorf((frame.Height() - iconBounds.Height()) / 2)); iconBounds.OffsetTo(iconPos); owner->SetDrawingMode(B_OP_OVER); owner->DrawBitmap(fIcon, fIcon->Bounds(), iconBounds); - frame.left = frame.left + 16 + 8; + frame.left = frame.left + kIconSize + kIconInset * 2; } TabView::DrawContents(owner, frame, updateRect, isFirst, isLast, isFront); From ea77068a8e791816cd78201bbe69af1e3083324d Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 2 Mar 2010 00:49:48 +0000 Subject: [PATCH 141/349] Added shortcuts Cmd-Left/Right for going back/forward. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@263 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 37 +++++++++++++++----------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 0e811e4c8d..3dc03d54de 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -281,21 +281,28 @@ BrowserWindow::~BrowserWindow() void BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) { - if (fURLTextControl && message->what == B_KEY_DOWN - && target == fURLTextControl->TextView()) { - // Handle B_RETURN in the URL text control. This is the easiest - // way to react *only* when the user presses the return key in the - // address bar, as opposed to trying to load whatever is in there when - // the text control just goes out of focus. - const char* bytes; - if (message->FindString("bytes", &bytes) == B_OK - && bytes[0] == B_RETURN) { - // Do it in such a way that the user sees the Go-button go down. - fGoButton->SetValue(B_CONTROL_ON); - UpdateIfNeeded(); - fGoButton->Invoke(); - snooze(1000); - fGoButton->SetValue(B_CONTROL_OFF); + const char* bytes; + int32 modifiers; + if ((message->what == B_KEY_DOWN || message->what == B_UNMAPPED_KEY_DOWN) + && message->FindString("bytes", &bytes) == B_OK + && message->FindInt32("modifiers", &modifiers) == B_OK) { + if (fURLTextControl && target == fURLTextControl->TextView()) { + // Handle B_RETURN in the URL text control. This is the easiest + // way to react *only* when the user presses the return key in the + // address bar, as opposed to trying to load whatever is in there when + // the text control just goes out of focus. + if (bytes[0] == B_RETURN) { + // Do it in such a way that the user sees the Go-button go down. + fGoButton->SetValue(B_CONTROL_ON); + UpdateIfNeeded(); + fGoButton->Invoke(); + snooze(1000); + fGoButton->SetValue(B_CONTROL_OFF); + } + } else if (bytes[0] == B_LEFT_ARROW && (modifiers & B_COMMAND_KEY) != 0) { + PostMessage(GO_BACK); + } else if (bytes[0] == B_RIGHT_ARROW && (modifiers & B_COMMAND_KEY) != 0) { + PostMessage(GO_FORWARD); } } BWebWindow::DispatchMessage(message, target); From 39274de5a348d095a9960ca51fe0aafae2a16190 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 2 Mar 2010 01:27:14 +0000 Subject: [PATCH 142/349] Double clicking beside the tabs opens a new tab. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@264 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/WebTabView.cpp | 44 ++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index cda62fd150..4dbb0bfc70 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -127,6 +127,7 @@ public: virtual void TabSelected(int32 tabIndex) = 0; virtual bool HasFrames() = 0; virtual TabView* CreateTabView() = 0; + virtual void DoubleClickOutsideTabs() = 0; }; public: @@ -252,10 +253,15 @@ TabContainerView::MouseDown(BPoint where) uint32 buttons; if (Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons) != B_OK) buttons = B_PRIMARY_MOUSE_BUTTON; + uint32 clicks; + if (Window()->CurrentMessage()->FindInt32("clicks", (int32*)&clicks) != B_OK) + clicks = 1; fMouseDown = true; SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); if (fLastMouseEventTab) fLastMouseEventTab->MouseDown(where, buttons); + else if (clicks > 1) + fController->DoubleClickOutsideTabs(); } @@ -715,6 +721,8 @@ class TabManagerController : public TabContainerView::Controller { public: TabManagerController(TabManager* manager); + virtual ~TabManagerController(); + virtual void TabSelected(int32 index) { fManager->SelectTab(index); @@ -727,6 +735,8 @@ public: virtual TabView* CreateTabView(); + virtual void DoubleClickOutsideTabs(); + void CloseTab(int32 index); void SetCloseButtonsAvailable(bool available) @@ -739,9 +749,14 @@ public: return fCloseButtonsAvailable; } + void SetDoubleClickOutsideTabsMessage(const BMessage& message, + const BMessenger& target); + private: TabManager* fManager; bool fCloseButtonsAvailable; + BMessage* fDoubleClickOutsideTabsMessage; + BMessenger fTarget; }; @@ -955,11 +970,18 @@ void WebTabView::_DrawCloseButton(BView* owner, BRect& frame, TabManagerController::TabManagerController(TabManager* manager) : fManager(manager), - fCloseButtonsAvailable(false) + fCloseButtonsAvailable(false), + fDoubleClickOutsideTabsMessage(NULL) { } +TabManagerController::~TabManagerController() +{ + delete fDoubleClickOutsideTabsMessage; +} + + TabView* TabManagerController::CreateTabView() { @@ -967,6 +989,13 @@ TabManagerController::CreateTabView() } +void +TabManagerController::DoubleClickOutsideTabs() +{ + fTarget.SendMessage(fDoubleClickOutsideTabsMessage); +} + + void TabManagerController::CloseTab(int32 index) { @@ -974,6 +1003,16 @@ TabManagerController::CloseTab(int32 index) } +void +TabManagerController::SetDoubleClickOutsideTabsMessage(const BMessage& message, + const BMessenger& target) +{ + delete fDoubleClickOutsideTabsMessage; + fDoubleClickOutsideTabsMessage = new BMessage(message); + fTarget = target; +} + + // #pragma mark - TabButtonContainer @@ -1145,6 +1184,9 @@ TabManager::TabManager(const BMessenger& target, BMessage* newTabMessage) fController(new TabManagerController(this)), fTarget(target) { + fController->SetDoubleClickOutsideTabsMessage(*newTabMessage, + be_app_messenger); + fContainerView = new BView("web view container", 0); fCardLayout = new BCardLayout(); fContainerView->SetLayout(fCardLayout); From fd5768c40d1eb05b345577285ec72788d7b115a5 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 2 Mar 2010 12:38:07 +0000 Subject: [PATCH 143/349] Imported Beam auto completion framework, converted license to MIT (with permission from Oliver) and applied Haiku coding style. The base classes have been named such that they could become official Haiku API in the future. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@266 94f232f2-1747-11df-bad5-a5bfde151594 --- .../autocompletion/AutoCompleter.cpp | 212 ++++++++++ .../autocompletion/AutoCompleter.h | 154 +++++++ .../AutoCompleterDefaultImpl.cpp | 377 ++++++++++++++++++ .../autocompletion/AutoCompleterDefaultImpl.h | 92 +++++ .../autocompletion/TextControlCompleter.cpp | 118 ++++++ .../autocompletion/TextControlCompleter.h | 41 ++ 6 files changed, 994 insertions(+) create mode 100644 src/apps/webpositive/autocompletion/AutoCompleter.cpp create mode 100644 src/apps/webpositive/autocompletion/AutoCompleter.h create mode 100644 src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp create mode 100644 src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h create mode 100644 src/apps/webpositive/autocompletion/TextControlCompleter.cpp create mode 100644 src/apps/webpositive/autocompletion/TextControlCompleter.h diff --git a/src/apps/webpositive/autocompletion/AutoCompleter.cpp b/src/apps/webpositive/autocompletion/AutoCompleter.cpp new file mode 100644 index 0000000000..c6583398f5 --- /dev/null +++ b/src/apps/webpositive/autocompletion/AutoCompleter.cpp @@ -0,0 +1,212 @@ +/* + * Copyright 2002-2006, project beam (http://sourceforge.net/projects/beam). + * All rights reserved. Distributed under the terms of the MIT License. + * + * Authors: + * Oliver Tappe + */ + +#include "AutoCompleter.h" + +#include +#include + +#include "AutoCompleterDefaultImpl.h" + + +// #pragma mark - DefaultPatternSelector + + +class DefaultPatternSelector : public BAutoCompleter::PatternSelector { +public: + virtual void SelectPatternBounds(const BString& text, int32 caretPos, + int32* start, int32* length); +}; + + +void +DefaultPatternSelector::SelectPatternBounds(const BString& text, + int32 caretPos, int32* start, int32* length) +{ + if (!start || !length) + return; + *start = 0; + *length = text.Length(); +} + + +// #pragma mark - CompletionStyle + + +BAutoCompleter::CompletionStyle::CompletionStyle(EditView* editView, + ChoiceModel* choiceModel, ChoiceView* choiceView, + PatternSelector* patternSelector) + : + fEditView(editView), + fPatternSelector(patternSelector ? patternSelector + : new DefaultPatternSelector()), + fChoiceModel(choiceModel), + fChoiceView(choiceView) +{ +} + + +BAutoCompleter::CompletionStyle::~CompletionStyle() +{ + delete fEditView; + delete fChoiceModel; + delete fChoiceView; + delete fPatternSelector; +} + + +void +BAutoCompleter::CompletionStyle::SetEditView(EditView* view) +{ + delete fEditView; + fEditView = view; +} + + +void +BAutoCompleter::CompletionStyle::SetPatternSelector( + PatternSelector* selector) +{ + delete fPatternSelector; + fPatternSelector = selector; +} + + +void +BAutoCompleter::CompletionStyle::SetChoiceModel(ChoiceModel* model) +{ + delete fChoiceModel; + fChoiceModel = model; +} + + +void +BAutoCompleter::CompletionStyle::SetChoiceView(ChoiceView* view) +{ + delete fChoiceView; + fChoiceView = view; +} + + +// #pragma mark - BAutoCompleter + + +BAutoCompleter::BAutoCompleter(CompletionStyle* completionStyle) + : + fCompletionStyle(completionStyle) +{ +} + + +BAutoCompleter::BAutoCompleter(EditView* editView, ChoiceModel* choiceModel, + ChoiceView* choiceView, PatternSelector* patternSelector) + : + fCompletionStyle(new BDefaultCompletionStyle(editView, choiceModel, + choiceView, patternSelector)) +{ +} + + +BAutoCompleter::~BAutoCompleter() +{ + delete fCompletionStyle; +} + + +bool +BAutoCompleter::Select(int32 index) +{ + if (fCompletionStyle) + return fCompletionStyle->Select(index); + else + return false; +} + + +bool +BAutoCompleter::SelectNext(bool wrap) +{ + if (fCompletionStyle) + return fCompletionStyle->SelectNext(wrap); + else + return false; +} + + +bool +BAutoCompleter::SelectPrevious(bool wrap) +{ + if (fCompletionStyle) + return fCompletionStyle->SelectPrevious(wrap); + else + return false; +} + + +void +BAutoCompleter::ApplyChoice(bool hideChoices) +{ + if (fCompletionStyle) + fCompletionStyle->ApplyChoice(hideChoices); +} + + +void +BAutoCompleter::CancelChoice() +{ + if (fCompletionStyle) + fCompletionStyle->CancelChoice(); +} + + +void +BAutoCompleter::EditViewStateChanged() +{ + if (fCompletionStyle) + fCompletionStyle->EditViewStateChanged(); +} + + +void +BAutoCompleter::SetEditView(EditView* view) +{ + if (fCompletionStyle) + fCompletionStyle->SetEditView(view); +} + + +void +BAutoCompleter::SetPatternSelector(PatternSelector* selector) +{ + if (fCompletionStyle) + fCompletionStyle->SetPatternSelector(selector); +} + + +void +BAutoCompleter::SetChoiceModel(ChoiceModel* model) +{ + if (fCompletionStyle) + fCompletionStyle->SetChoiceModel(model); +} + + +void +BAutoCompleter::SetChoiceView(ChoiceView* view) +{ + if (fCompletionStyle) + fCompletionStyle->SetChoiceView(view); +} + + +void +BAutoCompleter::SetCompletionStyle(CompletionStyle* style) +{ + delete fCompletionStyle; + fCompletionStyle = style; +} diff --git a/src/apps/webpositive/autocompletion/AutoCompleter.h b/src/apps/webpositive/autocompletion/AutoCompleter.h new file mode 100644 index 0000000000..443981f809 --- /dev/null +++ b/src/apps/webpositive/autocompletion/AutoCompleter.h @@ -0,0 +1,154 @@ +/* + * Copyright 2002-2006, project beam (http://sourceforge.net/projects/beam). + * All rights reserved. Distributed under the terms of the MIT License. + * + * Authors: + * Oliver Tappe + */ + +#ifndef AUTO_COMPLETEER_H +#define AUTO_COMPLETEER_H + +#include + +#include +#include + +class BAutoCompleter { +public: + class Choice { + public: + Choice(const BString& choiceText, + const BString& displayText, int32 matchPos, + int32 matchLen) + : + fText(choiceText), + fDisplayText(displayText), + fMatchPos(matchPos), + fMatchLen(matchLen) + { + } + virtual ~Choice() {} + const BString& Text() const { return fText; } + const BString& DisplayText() const { return fDisplayText; } + int32 MatchPos() const { return fMatchPos; } + int32 MatchLen() const { return fMatchLen; } + + private: + BString fText; + BString fDisplayText; + int32 fMatchPos; + int32 fMatchLen; + }; + + class EditView { + public: + virtual ~EditView() {} + + virtual BRect GetAdjustmentFrame() = 0; + virtual void GetEditViewState(BString& text, + int32* caretPos) = 0; + virtual void SetEditViewState(const BString& text, + int32 caretPos, + int32 selectionLength = 0) = 0; + }; + + class PatternSelector { + public: + virtual ~PatternSelector() {} + + virtual void SelectPatternBounds(const BString& text, + int32 caretPos, int32* start, + int32* length) = 0; + }; + + class ChoiceModel { + public: + + virtual ~ChoiceModel() {} + + virtual void FetchChoicesFor(const BString& pattern) = 0; + + virtual int32 CountChoices() const = 0; + virtual const Choice* ChoiceAt(int32 index) const = 0; + }; + + class CompletionStyle; + class ChoiceView { + public: + virtual ~ChoiceView() {} + + virtual void SelectChoiceAt(int32 index) = 0; + virtual void ShowChoices( + BAutoCompleter::CompletionStyle* completer) + = 0; + virtual void HideChoices() = 0; + virtual bool ChoicesAreShown() = 0; + }; + + class CompletionStyle { + public: + CompletionStyle(EditView* editView, + ChoiceModel* choiceModel, + ChoiceView* choiceView, + PatternSelector* patternSelector); + virtual ~CompletionStyle(); + + virtual bool Select(int32 index) = 0; + virtual bool SelectNext(bool wrap = false) = 0; + virtual bool SelectPrevious(bool wrap = false) = 0; + + virtual void ApplyChoice(bool hideChoices = true) = 0; + virtual void CancelChoice() = 0; + + virtual void EditViewStateChanged() = 0; + + void SetEditView(EditView* view); + void SetPatternSelector(PatternSelector* selector); + void SetChoiceModel(ChoiceModel* model); + void SetChoiceView(ChoiceView* view); + + EditView* GetEditView() { return fEditView; } + PatternSelector* GetPatternSelector() + { return fPatternSelector; } + ChoiceModel* GetChoiceModel() { return fChoiceModel; } + ChoiceView* GetChoiceView() { return fChoiceView; } + + protected: + EditView* fEditView; + PatternSelector* fPatternSelector; + ChoiceModel* fChoiceModel; + ChoiceView* fChoiceView; + }; + +protected: + BAutoCompleter( + CompletionStyle* completionStyle = NULL); + BAutoCompleter(EditView* editView, + ChoiceModel* choiceModel, + ChoiceView* choiceView, + PatternSelector* patternSelector); + virtual ~BAutoCompleter(); + + void EditViewStateChanged(); + + bool Select(int32 index); + bool SelectNext(bool wrap = false); + bool SelectPrevious(bool wrap = false); + + void ApplyChoice(bool hideChoices = true); + void CancelChoice(); + + void SetEditView(EditView* view); + void SetPatternSelector(PatternSelector* selector); + void SetChoiceModel(ChoiceModel* model); + void SetChoiceView(ChoiceView* view); + + void SetCompletionStyle(CompletionStyle* style); + +private: + CompletionStyle* fCompletionStyle; +}; + + +#endif // AUTO_COMPLETEER_H diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp new file mode 100644 index 0000000000..456a56f127 --- /dev/null +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp @@ -0,0 +1,377 @@ +/* + * Copyright 2002-2006, project beam (http://sourceforge.net/projects/beam). + * All rights reserved. Distributed under the terms of the MIT License. + * + * Authors: + * Oliver Tappe + */ + +#include "AutoCompleterDefaultImpl.h" + +#include +#include +#include + + +// #pragma mark - BDefaultPatternSelector + +void +BDefaultPatternSelector::SelectPatternBounds(const BString& text, + int32 caretPos, int32* start, int32* length) +{ + if (!start || !length) + return; + *start = 0; + *length = text.Length(); +} + + +// #pragma mark - BDefaultCompletionStyle + + +BDefaultCompletionStyle::BDefaultCompletionStyle( + BAutoCompleter::EditView* editView, + BAutoCompleter::ChoiceModel* choiceModel, + BAutoCompleter::ChoiceView* choiceView, + BAutoCompleter::PatternSelector* patternSelector) + : + CompletionStyle(editView, choiceModel, choiceView, patternSelector), + fSelectedIndex(-1), + fPatternStartPos(0), + fPatternLength(0) +{ +} + + +BDefaultCompletionStyle::~BDefaultCompletionStyle() +{ +} + + +bool +BDefaultCompletionStyle::Select(int32 index) +{ + if (!fChoiceView || !fChoiceModel || index == fSelectedIndex + || index < -1 || index >= fChoiceModel->CountChoices()) { + return false; + } + + fSelectedIndex = index; + fChoiceView->SelectChoiceAt(index); + return true; +} + + +bool +BDefaultCompletionStyle::SelectNext(bool wrap) +{ + if (!fChoiceModel || fChoiceModel->CountChoices() == 0) + return false; + + int32 newIndex = fSelectedIndex + 1; + if (newIndex >= fChoiceModel->CountChoices()) { + if (wrap) + newIndex = 0; + else + newIndex = fSelectedIndex; + } + return Select(newIndex); +} + + +bool +BDefaultCompletionStyle::SelectPrevious(bool wrap) +{ + if (!fChoiceModel || fChoiceModel->CountChoices() == 0) + return false; + + int32 newIndex = fSelectedIndex - 1; + if (newIndex < 0) { + if (wrap) + newIndex = fChoiceModel->CountChoices() - 1; + else + newIndex = 0; + } + return Select(newIndex); +} + + +void +BDefaultCompletionStyle::ApplyChoice(bool hideChoices) +{ + if (!fChoiceModel || !fChoiceView || !fEditView || fSelectedIndex < 0) + return; + + BString completedText(fFullEnteredText); + completedText.Remove(fPatternStartPos, fPatternLength); + const BString& choiceStr = fChoiceModel->ChoiceAt(fSelectedIndex)->Text(); + completedText.Insert(choiceStr, fPatternStartPos); + + fFullEnteredText = completedText; + fPatternLength = choiceStr.Length(); + fEditView->SetEditViewState(completedText, + fPatternStartPos+choiceStr.Length()); + + if (hideChoices) + fChoiceView->HideChoices(); +} + + +void +BDefaultCompletionStyle::CancelChoice() +{ + if (!fChoiceView || !fEditView) + return; + if (fChoiceView->ChoicesAreShown()) { + fEditView->SetEditViewState(fFullEnteredText, + fPatternStartPos+fPatternLength); + fChoiceView->HideChoices(); + Select(-1); + } +} + +void +BDefaultCompletionStyle::EditViewStateChanged() +{ + if (!fChoiceModel || !fChoiceView || !fEditView) + return; + + BString text; + int32 caretPos; + fEditView->GetEditViewState(text, &caretPos); + if (fFullEnteredText == text) + return; + fFullEnteredText = text; + fPatternSelector->SelectPatternBounds(text, caretPos, &fPatternStartPos, + &fPatternLength); + BString pattern(text.String() + fPatternStartPos, fPatternLength); + fChoiceModel->FetchChoicesFor(pattern); + + Select(-1); + // show a single choice only if it doesn't match the pattern exactly: + if (fChoiceModel->CountChoices() > 1 || (fChoiceModel->CountChoices() == 1 + && pattern.ICompare(fChoiceModel->ChoiceAt(0)->Text())) != 0) { + fChoiceView->ShowChoices(this); + fChoiceView->SelectChoiceAt(fSelectedIndex); + } else + fChoiceView->HideChoices(); +} + + +// #pragma mark - BDefaultChoiceView::ListView + + +static const int32 BM_INVOKED = 'bmin'; + + +BDefaultChoiceView::ListView::ListView( + BAutoCompleter::CompletionStyle* completer) + : + BListView(BRect(0,0,100,100), "ChoiceViewList"), + fCompleter(completer) +{ + // we need to check if user clicks outside of window-bounds: + SetEventMask(B_POINTER_EVENTS); +} + + +void +BDefaultChoiceView::ListView::AttachedToWindow() +{ + SetTarget(this); + SetInvocationMessage(new BMessage(BM_INVOKED)); + BListView::AttachedToWindow(); +} + + +void +BDefaultChoiceView::ListView::SelectionChanged() +{ + fCompleter->Select(CurrentSelection(0)); +} + + +void +BDefaultChoiceView::ListView::MessageReceived(BMessage* message) +{ + switch(message->what) { + case BM_INVOKED: + fCompleter->ApplyChoice(); + break; + default: + BListView::MessageReceived(message); + } +} + + +void +BDefaultChoiceView::ListView::MouseDown(BPoint point) +{ + if (!Window()->Frame().Contains(ConvertToScreen(point))) + // click outside of window, so we close it: + Window()->Quit(); + else + BListView::MouseDown(point); +} + + +// #pragma mark - BDefaultChoiceView::ListItem + + +BDefaultChoiceView::ListItem::ListItem(const BAutoCompleter::Choice* choice) + : + BListItem() +{ + fPreText = choice->DisplayText(); + if (choice->MatchLen() > 0) { + fPreText.MoveInto(fMatchText, choice->MatchPos(), choice->MatchLen()); + fPreText.MoveInto(fPostText, choice->MatchPos(), fPreText.Length()); + } +} + + +void +BDefaultChoiceView::ListItem::DrawItem(BView* owner, BRect frame, + bool complete) +{ + rgb_color textCol, backCol, matchCol; + if (IsSelected()) { + textCol = ui_color(B_MENU_SELECTED_ITEM_TEXT_COLOR); + backCol = ui_color(B_MENU_SELECTED_BACKGROUND_COLOR); + } else { + textCol = ui_color(B_DOCUMENT_TEXT_COLOR); + backCol = ui_color(B_DOCUMENT_BACKGROUND_COLOR); + } + matchCol = tint_color(backCol, B_LIGHTEN_2_TINT); + + BFont font; + font_height fontHeight; + owner->GetFont(&font); + font.GetHeight(&fontHeight); + float xPos = frame.left + 1; + float yPos = frame.top + fontHeight.ascent; + float w; + if (fPreText.Length()) { + w = owner->StringWidth(fPreText.String()); + owner->SetLowColor(backCol); + owner->FillRect(BRect(xPos, frame.top, xPos + w - 1, frame.bottom), + B_SOLID_LOW); + owner->SetHighColor(textCol); + owner->DrawString(fPreText.String(), BPoint(xPos, yPos)); + xPos += w; + } + if (fMatchText.Length()) { + w = owner->StringWidth(fMatchText.String()); + owner->SetLowColor(matchCol); + owner->FillRect(BRect(xPos, frame.top, xPos + w - 1, frame.bottom), + B_SOLID_LOW); + owner->DrawString(fMatchText.String(), BPoint(xPos, yPos)); + xPos += w; + } + if (fPostText.Length()) { + w = owner->StringWidth(fPostText.String()); + owner->SetLowColor(backCol); + owner->FillRect(BRect(xPos, frame.top, xPos + w - 1, frame.bottom), + B_SOLID_LOW); + owner->DrawString(fPostText.String(), BPoint(xPos, yPos)); + } +} + + +// #pragma mark - BDefaultChoiceView + + +BDefaultChoiceView::BDefaultChoiceView() + : + fWindow(NULL), + fListView(NULL) +{ + +} + + +BDefaultChoiceView::~BDefaultChoiceView() +{ + HideChoices(); +} + + +void +BDefaultChoiceView::SelectChoiceAt(int32 index) +{ + if (fListView && fListView->LockLooper()) { + if (index < 0) + fListView->DeselectAll(); + else { + fListView->Select(index); + fListView->ScrollToSelection(); + } + fListView->UnlockLooper(); + } +} + + +void +BDefaultChoiceView::ShowChoices(BAutoCompleter::CompletionStyle* completer) +{ + if (!completer) + return; + + HideChoices(); + + BAutoCompleter::ChoiceModel* choiceModel = completer->GetChoiceModel(); + BAutoCompleter::EditView* editView = completer->GetEditView(); + + if (!editView || !choiceModel || choiceModel->CountChoices() == 0) + return; + + fListView = new ListView(completer); + int32 count = choiceModel->CountChoices(); + for(int32 i=0; iAddItem( + new ListItem(choiceModel->ChoiceAt(i)) + ); + } + + fWindow = new BWindow(BRect(0, 0, 100, 100), "", B_BORDERED_WINDOW_LOOK, + B_NORMAL_WINDOW_FEEL, B_NOT_MOVABLE | B_WILL_ACCEPT_FIRST_CLICK + | B_AVOID_FOCUS | B_ASYNCHRONOUS_CONTROLS); + fWindow->AddChild(fListView); + + int32 visibleCount = min_c(count, 5); + float listHeight = fListView->ItemFrame(visibleCount - 1).bottom + 1; + + BRect pvRect = editView->GetAdjustmentFrame(); + BRect listRect = pvRect; + listRect.bottom = listRect.top + listHeight - 1; + BRect screenRect = BScreen().Frame(); + if (listRect.bottom + 1 + listHeight <= screenRect.bottom) + listRect.OffsetTo(pvRect.left, pvRect.bottom + 1); + else + listRect.OffsetTo(pvRect.left, pvRect.top - listHeight); + + fListView->MoveTo(0, 0); + fListView->ResizeTo(listRect.Width(), listRect.Height()); + fWindow->MoveTo(listRect.left, listRect.top); + fWindow->ResizeTo(listRect.Width(), listRect.Height()); + fWindow->Show(); +} + + +void +BDefaultChoiceView::HideChoices() +{ + if (fWindow && fWindow->Lock()) { + fWindow->Quit(); + fWindow = NULL; + fListView = NULL; + } +} + + +bool +BDefaultChoiceView::ChoicesAreShown() +{ + return (fWindow != NULL); +} + diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h new file mode 100644 index 0000000000..f697330915 --- /dev/null +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h @@ -0,0 +1,92 @@ +/* + * Copyright 2002-2006, project beam (http://sourceforge.net/projects/beam). + * All rights reserved. Distributed under the terms of the MIT License. + * + * Authors: + * Oliver Tappe + */ + +#ifndef AUTO_COMPLETER_DEFAULT_IMPL_H +#define AUTO_COMPLETER_DEFAULT_IMPL_H + +#include +#include + +#include "AutoCompleter.h" + +class BDefaultPatternSelector : public BAutoCompleter::PatternSelector { +public: + virtual void SelectPatternBounds(const BString& text, + int32 caretPos, int32* start, + int32* length); +}; + + +class BDefaultCompletionStyle : public BAutoCompleter::CompletionStyle { +public: + BDefaultCompletionStyle( + BAutoCompleter::EditView* editView, + BAutoCompleter::ChoiceModel* choiceModel, + BAutoCompleter::ChoiceView* choiceView, + BAutoCompleter::PatternSelector* + patternSelector); + virtual ~BDefaultCompletionStyle(); + + virtual bool Select(int32 index); + virtual bool SelectNext(bool wrap = false); + virtual bool SelectPrevious(bool wrap = false); + + virtual void ApplyChoice(bool hideChoices = true); + virtual void CancelChoice(); + + virtual void EditViewStateChanged(); + +private: + BString fFullEnteredText; + int32 fSelectedIndex; + int32 fPatternStartPos; + int32 fPatternLength; +}; + + +class BDefaultChoiceView : public BAutoCompleter::ChoiceView { +protected: + class ListView : public BListView { + public: + ListView( + BAutoCompleter::CompletionStyle* completer); + virtual void SelectionChanged(); + virtual void MessageReceived(BMessage* msg); + virtual void MouseDown(BPoint point); + virtual void AttachedToWindow(); + private: + BAutoCompleter::CompletionStyle* fCompleter; + }; + + class ListItem : public BListItem { + public: + ListItem(const BAutoCompleter::Choice* choice); + virtual void DrawItem(BView* owner, BRect frame, + bool complete = false); + private: + BString fPreText; + BString fMatchText; + BString fPostText; + }; + +public: + BDefaultChoiceView(); + virtual ~BDefaultChoiceView(); + + virtual void SelectChoiceAt(int32 index); + virtual void ShowChoices( + BAutoCompleter::CompletionStyle* completer); + virtual void HideChoices(); + virtual bool ChoicesAreShown(); + +private: + BWindow* fWindow; + ListView* fListView; +}; + +#endif // AUTO_COMPLETER_DEFAULT_IMPL_H diff --git a/src/apps/webpositive/autocompletion/TextControlCompleter.cpp b/src/apps/webpositive/autocompletion/TextControlCompleter.cpp new file mode 100644 index 0000000000..e8e9cb0f52 --- /dev/null +++ b/src/apps/webpositive/autocompletion/TextControlCompleter.cpp @@ -0,0 +1,118 @@ +/* + * Copyright 2002-2006, project beam (http://sourceforge.net/projects/beam). + * All rights reserved. Distributed under the terms of the MIT License. + * + * Authors: + * Oliver Tappe + */ + +#include "TextControlCompleter.h" + +#include +#include + +#include "AutoCompleterDefaultImpl.h" + + +// #pragma mark - TextControlWrapper + + +TextControlCompleter::TextControlWrapper::TextControlWrapper( + BTextControl* textControl) + : + fTextControl(textControl) +{ +} + + +void +TextControlCompleter::TextControlWrapper::GetEditViewState(BString& text, + int32* caretPos) +{ + if (fTextControl && fTextControl->LockLooper()) { + text = fTextControl->Text(); + if (caretPos) { + int32 end; + fTextControl->TextView()->GetSelection(caretPos, &end); + } + fTextControl->UnlockLooper(); + } +} + + +void +TextControlCompleter::TextControlWrapper::SetEditViewState(const BString& text, + int32 caretPos, int32 selectionLength) +{ + if (fTextControl && fTextControl->LockLooper()) { + fTextControl->TextView()->SetText(text.String(), text.Length()); + fTextControl->TextView()->Select(caretPos, caretPos + selectionLength); + fTextControl->TextView()->ScrollToSelection(); + fTextControl->UnlockLooper(); + } +} + + +BRect +TextControlCompleter::TextControlWrapper::GetAdjustmentFrame() +{ + BRect frame = fTextControl->TextView()->Bounds(); + frame = fTextControl->TextView()->ConvertToScreen(frame); + frame.InsetBy(-1, -3); + return frame; +} + + +TextControlCompleter::TextControlCompleter(BTextControl* textControl, + ChoiceModel* model, PatternSelector* patternSelector) + : + BAutoCompleter(new TextControlWrapper(textControl), model, + new BDefaultChoiceView(), patternSelector), + BMessageFilter(B_KEY_DOWN) +{ + textControl->TextView()->AddFilter(this); +} + + +TextControlCompleter::~TextControlCompleter() +{ +} + + +filter_result +TextControlCompleter::Filter(BMessage* message, BHandler** target) +{ + int32 rawChar, modifiers; + if (!target || message->FindInt32("raw_char", &rawChar) != B_OK + || message->FindInt32("modifiers", &modifiers) != B_OK) { + return B_DISPATCH_MESSAGE; + } + + switch (rawChar) { + case B_UP_ARROW: + SelectPrevious(); + return B_SKIP_MESSAGE; + case B_DOWN_ARROW: + SelectNext(); + return B_SKIP_MESSAGE; + case B_ESCAPE: + CancelChoice(); + return B_SKIP_MESSAGE; + case B_RETURN: + ApplyChoice(); + EditViewStateChanged(); + return B_SKIP_MESSAGE; + case B_TAB: { + // make sure that the choices-view is closed when tabbing out: + CancelChoice(); + return B_DISPATCH_MESSAGE; + } + default: + // dispatch message to textview manually... + Looper()->DispatchMessage(message, *target); + // ...and propagate the new state to the auto-completer: + EditViewStateChanged(); + return B_SKIP_MESSAGE; + } + return B_DISPATCH_MESSAGE; +} diff --git a/src/apps/webpositive/autocompletion/TextControlCompleter.h b/src/apps/webpositive/autocompletion/TextControlCompleter.h new file mode 100644 index 0000000000..66ae3558c3 --- /dev/null +++ b/src/apps/webpositive/autocompletion/TextControlCompleter.h @@ -0,0 +1,41 @@ +/* + * Copyright 2002-2006, project beam (http://sourceforge.net/projects/beam). + * All rights reserved. Distributed under the terms of the MIT License. + * + * Authors: + * Oliver Tappe + */ +#ifndef TEXT_CONTROL_COMPLETER_H +#define TEXT_CONTROL_COMPLETER_H + +#include + +#include "AutoCompleter.h" + + +class BTextControl; + +class TextControlCompleter : protected BAutoCompleter, public BMessageFilter { +public: + TextControlCompleter(BTextControl* textControl, + ChoiceModel* choiceModel = NULL, + PatternSelector* patternSelector = NULL); + virtual ~TextControlCompleter(); + +private: + virtual filter_result Filter(BMessage* message, BHandler** target); + + class TextControlWrapper : public EditView { + public: + TextControlWrapper(BTextControl* textControl); + virtual BRect GetAdjustmentFrame(); + virtual void GetEditViewState(BString& text, + int32* caretPos); + virtual void SetEditViewState(const BString& text, + int32 caretPos, int32 selectionLength = 0); + private: + BTextControl* fTextControl; + }; +}; + +#endif // TEXT_CONTROL_COMPLETER_H From 1a52acbc07a9c1b1024d76af44b5b8119fe98c39 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 2 Mar 2010 18:40:50 +0000 Subject: [PATCH 144/349] Wired everything and improved the TextControlCompleter behavior a bit with regards to eating the B_RETURN key before we can dispatch in BrowserWindow. So autocompletion for URLs basically works. What's missing is: * Much better grouping of matches. * Fix the delay when the BrowsingHistory is first accessed (lazy loads itself from disk just then, ought to do it in the application thread after startup, which probably makes it unnoticable before the user starts typing a URL). git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@268 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 68 +++++++++++++++++++ src/apps/webpositive/BrowserWindow.h | 2 + .../autocompletion/AutoCompleter.cpp | 11 +++ .../autocompletion/AutoCompleter.h | 2 + .../AutoCompleterDefaultImpl.cpp | 11 ++- .../autocompletion/AutoCompleterDefaultImpl.h | 1 + .../autocompletion/TextControlCompleter.cpp | 18 +++-- .../autocompletion/TextControlCompleter.h | 2 + 8 files changed, 108 insertions(+), 7 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 3dc03d54de..8ffbfd8797 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -37,6 +37,7 @@ #include "BrowserApp.h" #include "BrowsingHistory.h" #include "IconButton.h" +#include "TextControlCompleter.h" #include "WebPage.h" #include "WebTabView.h" #include "WebView.h" @@ -93,6 +94,66 @@ layoutItemFor(BView* view) } +class BrowsingHistoryChoiceModel : public BAutoCompleter::ChoiceModel { + virtual void FetchChoicesFor(const BString& pattern) + { + int32 count = CountChoices(); + for (int32 i = 0; i < count; i++) { + delete reinterpret_cast( + fChoices.ItemAtFast(i)); + } + fChoices.MakeEmpty(); + + // Search through BrowsingHistory for any matches. + BrowsingHistory* history = BrowsingHistory::defaultInstance(); + if (!history->Lock()) + return; + + count = history->countItems(); + for (int32 i = 0; i < count; i++) { + BrowsingHistoryItem item = history->historyItemAt(i); + const BString& choiceText = item.url(); + int32 matchPos = choiceText.IFindFirst(pattern); + if (matchPos < 0) + continue; + fChoices.AddItem(new BAutoCompleter::Choice(choiceText, + choiceText, matchPos, pattern.Length())); + } + + history->Unlock(); + } + + virtual int32 CountChoices() const + { + return fChoices.CountItems(); + } + + virtual const BAutoCompleter::Choice* ChoiceAt(int32 index) const + { + return reinterpret_cast( + fChoices.ItemAt(index)); + } + +private: + BList fChoices; +}; + + +class BrowsingHistoryPatternSelector : public BAutoCompleter::PatternSelector { + virtual void SelectPatternBounds(const BString& text, int32 caretPos, + int32* start, int32* length) + { + if (!start || !length) + return; + *start = 0; + *length = text.Length(); + } +}; + + +// #pragma mark - BrowserWindow + + BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, ToolbarPolicy toolbarPolicy) : BWebWindow(frame, kApplicationName, @@ -228,6 +289,10 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, fURLTextControl->MakeFocus(true); + fURLAutoCompleter = new TextControlCompleter(fURLTextControl, + new BrowsingHistoryChoiceModel(), + new BrowsingHistoryPatternSelector()); + fFindGroup = layoutItemFor(findGroup); fTabGroup = layoutItemFor(fTabManager->TabGroup()); } else { @@ -236,6 +301,7 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, fStopButton = 0; fGoButton = 0; fURLTextControl = 0; + fURLAutoCompleter = 0; fStatusText = 0; fLoadingProgressBar = 0; @@ -275,6 +341,8 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, BrowserWindow::~BrowserWindow() { + delete fURLAutoCompleter; + delete fTabManager; } diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 9ef4426942..a296727c41 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -43,6 +43,7 @@ class BStringView; class BTextControl; class IconButton; class TabManager; +class TextControlCompleter; class BWebView; enum ToolbarPolicy { @@ -125,6 +126,7 @@ private: IconButton* fStopButton; BButton* fGoButton; BTextControl* fURLTextControl; + TextControlCompleter* fURLAutoCompleter; BStringView* fStatusText; BStatusBar* fLoadingProgressBar; BLayoutItem* fFindGroup; diff --git a/src/apps/webpositive/autocompletion/AutoCompleter.cpp b/src/apps/webpositive/autocompletion/AutoCompleter.cpp index c6583398f5..98b659da40 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleter.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleter.cpp @@ -148,6 +148,16 @@ BAutoCompleter::SelectPrevious(bool wrap) } +bool +BAutoCompleter::IsChoiceSelected() const +{ + if (fCompletionStyle) + return fCompletionStyle->IsChoiceSelected(); + else + return false; +} + + void BAutoCompleter::ApplyChoice(bool hideChoices) { @@ -210,3 +220,4 @@ BAutoCompleter::SetCompletionStyle(CompletionStyle* style) delete fCompletionStyle; fCompletionStyle = style; } + diff --git a/src/apps/webpositive/autocompletion/AutoCompleter.h b/src/apps/webpositive/autocompletion/AutoCompleter.h index 443981f809..33cb8ceb77 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleter.h +++ b/src/apps/webpositive/autocompletion/AutoCompleter.h @@ -97,6 +97,7 @@ public: virtual bool Select(int32 index) = 0; virtual bool SelectNext(bool wrap = false) = 0; virtual bool SelectPrevious(bool wrap = false) = 0; + virtual bool IsChoiceSelected() const = 0; virtual void ApplyChoice(bool hideChoices = true) = 0; virtual void CancelChoice() = 0; @@ -135,6 +136,7 @@ protected: bool Select(int32 index); bool SelectNext(bool wrap = false); bool SelectPrevious(bool wrap = false); + bool IsChoiceSelected() const; void ApplyChoice(bool hideChoices = true); void CancelChoice(); diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp index 456a56f127..6f41c235a0 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp @@ -96,6 +96,13 @@ BDefaultCompletionStyle::SelectPrevious(bool wrap) } +bool +BDefaultCompletionStyle::IsChoiceSelected() const +{ + return fSelectedIndex >= 0; +} + + void BDefaultCompletionStyle::ApplyChoice(bool hideChoices) { @@ -112,8 +119,10 @@ BDefaultCompletionStyle::ApplyChoice(bool hideChoices) fEditView->SetEditViewState(completedText, fPatternStartPos+choiceStr.Length()); - if (hideChoices) + if (hideChoices) { fChoiceView->HideChoices(); + Select(-1); + } } diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h index f697330915..81bca0fd1e 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h @@ -35,6 +35,7 @@ public: virtual bool Select(int32 index); virtual bool SelectNext(bool wrap = false); virtual bool SelectPrevious(bool wrap = false); + virtual bool IsChoiceSelected() const; virtual void ApplyChoice(bool hideChoices = true); virtual void CancelChoice(); diff --git a/src/apps/webpositive/autocompletion/TextControlCompleter.cpp b/src/apps/webpositive/autocompletion/TextControlCompleter.cpp index e8e9cb0f52..6b3c257602 100644 --- a/src/apps/webpositive/autocompletion/TextControlCompleter.cpp +++ b/src/apps/webpositive/autocompletion/TextControlCompleter.cpp @@ -10,6 +10,7 @@ #include #include +#include #include "AutoCompleterDefaultImpl.h" @@ -58,7 +59,7 @@ TextControlCompleter::TextControlWrapper::GetAdjustmentFrame() { BRect frame = fTextControl->TextView()->Bounds(); frame = fTextControl->TextView()->ConvertToScreen(frame); - frame.InsetBy(-1, -3); + frame.InsetBy(0, -3); return frame; } @@ -68,14 +69,16 @@ TextControlCompleter::TextControlCompleter(BTextControl* textControl, : BAutoCompleter(new TextControlWrapper(textControl), model, new BDefaultChoiceView(), patternSelector), - BMessageFilter(B_KEY_DOWN) + BMessageFilter(B_KEY_DOWN), + fTextControl(textControl) { - textControl->TextView()->AddFilter(this); + fTextControl->TextView()->AddFilter(this); } TextControlCompleter::~TextControlCompleter() { + fTextControl->TextView()->RemoveFilter(this); } @@ -99,9 +102,12 @@ TextControlCompleter::Filter(BMessage* message, BHandler** target) CancelChoice(); return B_SKIP_MESSAGE; case B_RETURN: - ApplyChoice(); - EditViewStateChanged(); - return B_SKIP_MESSAGE; + if (IsChoiceSelected()) { + ApplyChoice(); + EditViewStateChanged(); + } else + CancelChoice(); + return B_DISPATCH_MESSAGE; case B_TAB: { // make sure that the choices-view is closed when tabbing out: CancelChoice(); diff --git a/src/apps/webpositive/autocompletion/TextControlCompleter.h b/src/apps/webpositive/autocompletion/TextControlCompleter.h index 66ae3558c3..89c5125f2e 100644 --- a/src/apps/webpositive/autocompletion/TextControlCompleter.h +++ b/src/apps/webpositive/autocompletion/TextControlCompleter.h @@ -36,6 +36,8 @@ private: private: BTextControl* fTextControl; }; +private: + BTextControl* fTextControl; }; #endif // TEXT_CONTROL_COMPLETER_H From 0cf34b77b1bcdb6e2d4b0d527026f0f47e4588f3 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 2 Mar 2010 18:56:42 +0000 Subject: [PATCH 145/349] Ok, the most simplistic way to avoid having too many similars in the autocompletion choices is to find the "base url" (I am taking the string between :// and the next /) and avoid adding any more urls with the same base URL. Seems to work reasonably well. If anyone has any smarter ideas, please speak up! :-) git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@269 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 8ffbfd8797..12008f1362 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -109,6 +109,8 @@ class BrowsingHistoryChoiceModel : public BAutoCompleter::ChoiceModel { if (!history->Lock()) return; + BString lastBaseURL; + count = history->countItems(); for (int32 i = 0; i < count; i++) { BrowsingHistoryItem item = history->historyItemAt(i); @@ -116,6 +118,14 @@ class BrowsingHistoryChoiceModel : public BAutoCompleter::ChoiceModel { int32 matchPos = choiceText.IFindFirst(pattern); if (matchPos < 0) continue; + if (lastBaseURL.Length() > 0 + && choiceText.FindFirst(lastBaseURL) >= 0) { + continue; + } + int32 baseURLStart = choiceText.FindFirst("://") + 3; + int32 baseURLEnd = choiceText.FindFirst("/", baseURLStart + 1); + lastBaseURL.SetTo(choiceText.String() + baseURLStart, + baseURLEnd - baseURLStart); fChoices.AddItem(new BAutoCompleter::Choice(choiceText, choiceText, matchPos, pattern.Length())); } From b943093b1bfd7178362d88c3bba8b4ce11989a3e Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 2 Mar 2010 21:23:44 +0000 Subject: [PATCH 146/349] Preload the browsing history after application start. This avoids the delay when beginning to type something in the URL text field and the autocompletion invoked the BrowsingHistory for the first time. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@270 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 67ce27db15..d4e05ac283 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -30,6 +30,7 @@ #include "BrowserApp.h" #include "BrowserWindow.h" +#include "BrowsingHistory.h" #include "DownloadWindow.h" #include "WebPage.h" #include "WebSettings.h" @@ -47,7 +48,7 @@ const char* kApplicationSignature = "application/x-vnd.Haiku-WebPositive"; const char* kApplicationName = "WebPositive"; - +static const uint32 PRELOAD_BROWSING_HISTORY = 'plbh'; BrowserApp::BrowserApp() : BApplication(kApplicationSignature) @@ -132,6 +133,7 @@ BrowserApp::ReadyToRun() BMessenger(fDownloadWindow)); window->Show(); } + PostMessage(PRELOAD_BROWSING_HISTORY); } @@ -139,6 +141,9 @@ void BrowserApp::MessageReceived(BMessage* message) { switch (message->what) { + case PRELOAD_BROWSING_HISTORY: + BrowsingHistory::defaultInstance(); + break; case B_SILENT_RELAUNCH: _CreateNewPage(""); break; From 572a465779ef393f440ace942e7617dcd227dc6a Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 2 Mar 2010 21:24:06 +0000 Subject: [PATCH 147/349] Fixed header guards, thanks Ryan! git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@271 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/autocompletion/AutoCompleter.h | 7 +++---- .../webpositive/autocompletion/AutoCompleterDefaultImpl.h | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/apps/webpositive/autocompletion/AutoCompleter.h b/src/apps/webpositive/autocompletion/AutoCompleter.h index 33cb8ceb77..8b5cb7be37 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleter.h +++ b/src/apps/webpositive/autocompletion/AutoCompleter.h @@ -5,9 +5,8 @@ * Authors: * Oliver Tappe */ - -#ifndef AUTO_COMPLETEER_H -#define AUTO_COMPLETEER_H +#ifndef _AUTO_COMPLETER_H +#define _AUTO_COMPLETER_H #include @@ -153,4 +152,4 @@ private: }; -#endif // AUTO_COMPLETEER_H +#endif // _AUTO_COMPLETER_H diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h index 81bca0fd1e..cf01dbbad1 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h @@ -5,9 +5,8 @@ * Authors: * Oliver Tappe */ - -#ifndef AUTO_COMPLETER_DEFAULT_IMPL_H -#define AUTO_COMPLETER_DEFAULT_IMPL_H +#ifndef _AUTO_COMPLETER_DEFAULT_IMPL_H +#define _AUTO_COMPLETER_DEFAULT_IMPL_H #include #include @@ -90,4 +89,4 @@ private: ListView* fListView; }; -#endif // AUTO_COMPLETER_DEFAULT_IMPL_H +#endif // _AUTO_COMPLETER_DEFAULT_IMPL_H From e25584f3c591de0311578ca53f735e5950d46cf3 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 3 Mar 2010 10:07:06 +0000 Subject: [PATCH 148/349] Wrap main thread in try-catch-block, in order to get a stack trace next time we hit that recursive init exception. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@273 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index d4e05ac283..df6b01832e 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include @@ -329,9 +330,13 @@ BrowserApp::_CreateNewTab(BrowserWindow* window, const BString& url, int main(int, char**) { - new BrowserApp(); - be_app->Run(); - delete be_app; + try { + new BrowserApp(); + be_app->Run(); + delete be_app; + } catch (...) { + debugger("Exception caught."); + } return 0; } From dad87be6e5f69b9a3b7094c0bb9aada9dfe04caa Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 3 Mar 2010 10:07:37 +0000 Subject: [PATCH 149/349] Better to darken the match color, this makes it visible also in non-selected choice items. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@274 94f232f2-1747-11df-bad5-a5bfde151594 --- .../webpositive/autocompletion/AutoCompleterDefaultImpl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp index 6f41c235a0..7818f5b81b 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp @@ -251,7 +251,7 @@ BDefaultChoiceView::ListItem::DrawItem(BView* owner, BRect frame, textCol = ui_color(B_DOCUMENT_TEXT_COLOR); backCol = ui_color(B_DOCUMENT_BACKGROUND_COLOR); } - matchCol = tint_color(backCol, B_LIGHTEN_2_TINT); + matchCol = tint_color(backCol, (B_NO_TINT + B_DARKEN_1_TINT) / 2); BFont font; font_height fontHeight; From c1bbe7400c2108119a06c4c5b9cd1c4d616f9338 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 3 Mar 2010 10:20:17 +0000 Subject: [PATCH 150/349] Improved coding style and the looks of the matched pattern in choices. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@275 94f232f2-1747-11df-bad5-a5bfde151594 --- .../AutoCompleterDefaultImpl.cpp | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp index 7818f5b81b..95ce32c7a0 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp @@ -243,15 +243,19 @@ void BDefaultChoiceView::ListItem::DrawItem(BView* owner, BRect frame, bool complete) { - rgb_color textCol, backCol, matchCol; + rgb_color textColor; + rgb_color nonMatchTextColor; + rgb_color backColor; + rgb_color matchColor; if (IsSelected()) { - textCol = ui_color(B_MENU_SELECTED_ITEM_TEXT_COLOR); - backCol = ui_color(B_MENU_SELECTED_BACKGROUND_COLOR); + textColor = ui_color(B_MENU_SELECTED_ITEM_TEXT_COLOR); + backColor = ui_color(B_MENU_SELECTED_BACKGROUND_COLOR); } else { - textCol = ui_color(B_DOCUMENT_TEXT_COLOR); - backCol = ui_color(B_DOCUMENT_BACKGROUND_COLOR); + textColor = ui_color(B_DOCUMENT_TEXT_COLOR); + backColor = ui_color(B_DOCUMENT_BACKGROUND_COLOR); } - matchCol = tint_color(backCol, (B_NO_TINT + B_DARKEN_1_TINT) / 2); + matchColor = tint_color(backColor, (B_NO_TINT + B_DARKEN_1_TINT) / 2); + nonMatchTextColor = tint_color(backColor, 1.7); BFont font; font_height fontHeight; @@ -262,26 +266,28 @@ BDefaultChoiceView::ListItem::DrawItem(BView* owner, BRect frame, float w; if (fPreText.Length()) { w = owner->StringWidth(fPreText.String()); - owner->SetLowColor(backCol); + owner->SetLowColor(backColor); owner->FillRect(BRect(xPos, frame.top, xPos + w - 1, frame.bottom), B_SOLID_LOW); - owner->SetHighColor(textCol); + owner->SetHighColor(nonMatchTextColor); owner->DrawString(fPreText.String(), BPoint(xPos, yPos)); xPos += w; } if (fMatchText.Length()) { w = owner->StringWidth(fMatchText.String()); - owner->SetLowColor(matchCol); + owner->SetLowColor(matchColor); owner->FillRect(BRect(xPos, frame.top, xPos + w - 1, frame.bottom), B_SOLID_LOW); + owner->SetHighColor(textColor); owner->DrawString(fMatchText.String(), BPoint(xPos, yPos)); xPos += w; } if (fPostText.Length()) { w = owner->StringWidth(fPostText.String()); - owner->SetLowColor(backCol); + owner->SetLowColor(backColor); owner->FillRect(BRect(xPos, frame.top, xPos + w - 1, frame.bottom), B_SOLID_LOW); + owner->SetHighColor(nonMatchTextColor); owner->DrawString(fPostText.String(), BPoint(xPos, yPos)); } } From c6662bd928d11cac7ff7c27bc74819c9506c66fd Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 3 Mar 2010 10:22:50 +0000 Subject: [PATCH 151/349] PatternSelector has a default implementation... git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@276 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 12008f1362..c29896f34f 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -149,18 +149,6 @@ private: }; -class BrowsingHistoryPatternSelector : public BAutoCompleter::PatternSelector { - virtual void SelectPatternBounds(const BString& text, int32 caretPos, - int32* start, int32* length) - { - if (!start || !length) - return; - *start = 0; - *length = text.Length(); - } -}; - - // #pragma mark - BrowserWindow @@ -300,8 +288,7 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, fURLTextControl->MakeFocus(true); fURLAutoCompleter = new TextControlCompleter(fURLTextControl, - new BrowsingHistoryChoiceModel(), - new BrowsingHistoryPatternSelector()); + new BrowsingHistoryChoiceModel()); fFindGroup = layoutItemFor(findGroup); fTabGroup = layoutItemFor(fTabManager->TabGroup()); From d0417c565a1a418ece0406d288dcd2e971b5d447 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 3 Mar 2010 10:57:46 +0000 Subject: [PATCH 152/349] Implemented basic settings window skeleton. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@277 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 63 +++++++---- src/apps/webpositive/BrowserApp.h | 4 + src/apps/webpositive/BrowserWindow.cpp | 2 + src/apps/webpositive/BrowserWindow.h | 3 +- src/apps/webpositive/SettingsWindow.cpp | 138 ++++++++++++++++++++++++ src/apps/webpositive/SettingsWindow.h | 55 ++++++++++ 6 files changed, 245 insertions(+), 20 deletions(-) create mode 100644 src/apps/webpositive/SettingsWindow.cpp create mode 100644 src/apps/webpositive/SettingsWindow.h diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index df6b01832e..81fcce7b28 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -32,6 +32,7 @@ #include "BrowserWindow.h" #include "BrowsingHistory.h" #include "DownloadWindow.h" +#include "SettingsWindow.h" #include "WebPage.h" #include "WebSettings.h" #include "WebView.h" @@ -52,12 +53,14 @@ const char* kApplicationName = "WebPositive"; static const uint32 PRELOAD_BROWSING_HISTORY = 'plbh'; BrowserApp::BrowserApp() - : BApplication(kApplicationSignature) - , fWindowCount(0) - , fLastWindowFrame(100, 100, 700, 750) - , fLaunchRefsMessage(0) - , fInitialized(false) - , fDownloadWindow(0) + : + BApplication(kApplicationSignature), + fWindowCount(0), + fLastWindowFrame(100, 100, 700, 750), + fLaunchRefsMessage(0), + fInitialized(false), + fDownloadWindow(NULL), + fSettingsWindow(NULL) { } @@ -111,17 +114,26 @@ BrowserApp::ReadyToRun() BFile settingsFile; BRect windowFrameFromSettings = fLastWindowFrame; BRect downloadWindowFrame(100, 100, 300, 250); + BRect settingsWindowFrame; bool showDownloads = false; if (_OpenSettingsFile(settingsFile, B_READ_ONLY)) { BMessage settingsArchive; settingsArchive.Unflatten(&settingsFile); - settingsArchive.FindRect("window frame", &windowFrameFromSettings); - settingsArchive.FindRect("downloads window frame", &downloadWindowFrame); - settingsArchive.FindBool("show downloads", &showDownloads); + BRect rect; + if (settingsArchive.FindRect("window frame", &rect) == B_OK) + windowFrameFromSettings = rect; + if (settingsArchive.FindRect("downloads window frame", &rect) == B_OK) + downloadWindowFrame = rect; + if (settingsArchive.FindRect("settings window frame", &rect) == B_OK) + settingsWindowFrame = rect; + bool flag; + if (settingsArchive.FindBool("show downloads", &flag) == B_OK) + showDownloads = flag; } fLastWindowFrame = windowFrameFromSettings; fDownloadWindow = new DownloadWindow(downloadWindowFrame, showDownloads); + fSettingsWindow = new SettingsWindow(settingsWindowFrame); fInitialized = true; @@ -176,17 +188,12 @@ BrowserApp::MessageReceived(BMessage* message) PostMessage(B_QUIT_REQUESTED); break; - case SHOW_DOWNLOAD_WINDOW: { - BAutolock _(fDownloadWindow); - uint32 workspaces; - if (message->FindUInt32("workspaces", &workspaces) == B_OK) - fDownloadWindow->SetWorkspaces(workspaces); - if (fDownloadWindow->IsHidden()) - fDownloadWindow->Show(); - else - fDownloadWindow->Activate(); + case SHOW_DOWNLOAD_WINDOW: + _ShowWindow(message, fDownloadWindow); + break; + case SHOW_SETTINGS_WINDOW: + _ShowWindow(message, fSettingsWindow); break; - } default: BApplication::MessageReceived(message); @@ -251,6 +258,10 @@ BrowserApp::QuitRequested() settingsArchive.AddBool("show downloads", !fDownloadWindow->IsHidden()); fDownloadWindow->Unlock(); } + if (fSettingsWindow->Lock()) { + settingsArchive.AddRect("settings window frame", fSettingsWindow->Frame()); + fSettingsWindow->Unlock(); + } settingsArchive.Flatten(&settingsFile); } @@ -324,6 +335,20 @@ BrowserApp::_CreateNewTab(BrowserWindow* window, const BString& url, } +void +BrowserApp::_ShowWindow(const BMessage* message, BWindow* window) +{ + BAutolock _(window); + uint32 workspaces; + if (message->FindUInt32("workspaces", &workspaces) == B_OK) + window->SetWorkspaces(workspaces); + if (window->IsHidden()) + window->Show(); + else + window->Activate(); +} + + // #pragma mark - diff --git a/src/apps/webpositive/BrowserApp.h b/src/apps/webpositive/BrowserApp.h index 17ae54735a..6b5402ba9a 100644 --- a/src/apps/webpositive/BrowserApp.h +++ b/src/apps/webpositive/BrowserApp.h @@ -35,6 +35,7 @@ class BFile; class DownloadWindow; class BrowserWindow; +class SettingsWindow; class BrowserApp : public BApplication { @@ -55,6 +56,8 @@ private: void _CreateNewWindow(const BString& url); void _CreateNewTab(BrowserWindow* window, const BString& url, bool select); + void _ShowWindow(const BMessage* message, + BWindow* window); private: int fWindowCount; @@ -63,6 +66,7 @@ private: bool fInitialized; DownloadWindow* fDownloadWindow; + SettingsWindow* fSettingsWindow; }; diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index c29896f34f..fc01924a22 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -187,6 +187,7 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, menu->AddItem(new BMenuItem("Close tab", new BMessage(CLOSE_TAB), 'W')); menu->AddSeparatorItem(); menu->AddItem(new BMenuItem("Show downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'J')); + menu->AddItem(new BMenuItem("Show settings", new BMessage(SHOW_SETTINGS_WINDOW))); menu->AddSeparatorItem(); BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); menu->AddItem(quitItem); @@ -473,6 +474,7 @@ BrowserWindow::MessageReceived(BMessage* message) break; case SHOW_DOWNLOAD_WINDOW: + case SHOW_SETTINGS_WINDOW: message->AddUInt32("workspaces", Workspaces()); be_app->PostMessage(message); break; diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index a296727c41..0fafb1ec2e 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -56,7 +56,8 @@ enum { NEW_TAB = 'ntab', WINDOW_OPENED = 'wndo', WINDOW_CLOSED = 'wndc', - SHOW_DOWNLOAD_WINDOW = 'sdwd' + SHOW_DOWNLOAD_WINDOW = 'sdwd', + SHOW_SETTINGS_WINDOW = 'sswd' }; #define INTEGRATE_MENU_INTO_TAB_BAR 0 diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp new file mode 100644 index 0000000000..77364539fe --- /dev/null +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "SettingsWindow.h" + +#include "BrowserApp.h" +#include "WebSettings.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +enum { + MSG_OK = 'aply', + MSG_CANCEL = 'cncl', + MSG_REVERT = 'rvrt', +}; + + +SettingsWindow::SettingsWindow(BRect frame) + : + BWindow(frame, "Settings", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, + B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE) +{ + SetLayout(new BGroupLayout(B_VERTICAL)); + + fOkButton = new BButton("OK", new BMessage(MSG_OK)); + fCancelButton = new BButton("Cancel", new BMessage(MSG_CANCEL)); + fRevertButton = new BButton("Revert", new BMessage(MSG_REVERT)); + + float spacing = be_control_look->DefaultItemSpacing(); + + AddChild(BGroupLayoutBuilder(B_VERTICAL) + .Add(BGridLayoutBuilder(spacing, spacing) + ) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(BGroupLayoutBuilder(B_HORIZONTAL, spacing) + .Add(fRevertButton) + .AddGlue() + .Add(fCancelButton) + .Add(fOkButton) + .SetInsets(spacing, spacing, spacing, spacing) + ) + ); + + fOkButton->MakeDefault(true); + + if (!frame.IsValid()) + CenterOnScreen(); + + // Start hidden + Hide(); + Show(); +} + + +SettingsWindow::~SettingsWindow() +{ +} + + +void +SettingsWindow::MessageReceived(BMessage* message) +{ + switch (message->what) { + case MSG_OK: + _ApplySettings(); + PostMessage(B_QUIT_REQUESTED); + break; + case MSG_CANCEL: + _RevertSettings(); + PostMessage(B_QUIT_REQUESTED); + break; + case MSG_REVERT: + _RevertSettings(); + break; + default: + BWindow::MessageReceived(message); + break; + } +} + + +bool +SettingsWindow::QuitRequested() +{ + if (!IsHidden()) + Hide(); + return false; +} + + +// #pragma mark - private + + +void +SettingsWindow::_ApplySettings() +{ +} + + +void +SettingsWindow::_RevertSettings() +{ +} + + diff --git a/src/apps/webpositive/SettingsWindow.h b/src/apps/webpositive/SettingsWindow.h new file mode 100644 index 0000000000..22ff3f7c10 --- /dev/null +++ b/src/apps/webpositive/SettingsWindow.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef SETTINGS_WINDOW_H +#define SETTINGS_WINDOW_H + +#include + +class BButton; + + +class SettingsWindow : public BWindow { +public: + SettingsWindow(BRect frame); + virtual ~SettingsWindow(); + + virtual void MessageReceived(BMessage* message); + virtual bool QuitRequested(); + +private: + void _ApplySettings(); + void _RevertSettings(); + +private: + BButton* fOkButton; + BButton* fCancelButton; + BButton* fRevertButton; +}; + + +#endif // SETTINGS_WINDOW_H + From 75c44a83ca47dbc46c82c9d972c2b22eaf8f946a Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 3 Mar 2010 11:08:50 +0000 Subject: [PATCH 153/349] Moved some utility stuff into new subfolder "support". Some of these needs to be removed too, once WebPositive is moved into Haiku. SettingsMessage comes straight from MediaPlayer. Should be moved into src/kits/shared eventually. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@278 94f232f2-1747-11df-bad5-a5bfde151594 --- .../webpositive/{ => support}/DateTime.cpp | 0 src/apps/webpositive/{ => support}/DateTime.h | 0 .../webpositive/{ => support}/IconButton.cpp | 0 .../webpositive/{ => support}/IconButton.h | 0 .../webpositive/{ => support}/IconUtils.h | 0 .../webpositive/support/SettingsMessage.cpp | 336 ++++++++++++++++++ .../webpositive/support/SettingsMessage.h | 79 ++++ 7 files changed, 415 insertions(+) rename src/apps/webpositive/{ => support}/DateTime.cpp (100%) rename src/apps/webpositive/{ => support}/DateTime.h (100%) rename src/apps/webpositive/{ => support}/IconButton.cpp (100%) rename src/apps/webpositive/{ => support}/IconButton.h (100%) rename src/apps/webpositive/{ => support}/IconUtils.h (100%) create mode 100644 src/apps/webpositive/support/SettingsMessage.cpp create mode 100644 src/apps/webpositive/support/SettingsMessage.h diff --git a/src/apps/webpositive/DateTime.cpp b/src/apps/webpositive/support/DateTime.cpp similarity index 100% rename from src/apps/webpositive/DateTime.cpp rename to src/apps/webpositive/support/DateTime.cpp diff --git a/src/apps/webpositive/DateTime.h b/src/apps/webpositive/support/DateTime.h similarity index 100% rename from src/apps/webpositive/DateTime.h rename to src/apps/webpositive/support/DateTime.h diff --git a/src/apps/webpositive/IconButton.cpp b/src/apps/webpositive/support/IconButton.cpp similarity index 100% rename from src/apps/webpositive/IconButton.cpp rename to src/apps/webpositive/support/IconButton.cpp diff --git a/src/apps/webpositive/IconButton.h b/src/apps/webpositive/support/IconButton.h similarity index 100% rename from src/apps/webpositive/IconButton.h rename to src/apps/webpositive/support/IconButton.h diff --git a/src/apps/webpositive/IconUtils.h b/src/apps/webpositive/support/IconUtils.h similarity index 100% rename from src/apps/webpositive/IconUtils.h rename to src/apps/webpositive/support/IconUtils.h diff --git a/src/apps/webpositive/support/SettingsMessage.cpp b/src/apps/webpositive/support/SettingsMessage.cpp new file mode 100644 index 0000000000..dad98820b2 --- /dev/null +++ b/src/apps/webpositive/support/SettingsMessage.cpp @@ -0,0 +1,336 @@ +/* + * Copyright 2008, Stephan Aßmus . + * Copyright 1998, Eric Shepherd. + * All rights reserved. Distributed under the terms of the Be Sample Code + * license. + */ + +//! Be Newsletter Volume II, Issue 35; September 2, 1998 (Eric Shepherd) + +#include "SettingsMessage.h" + +#include +#include +#include + + +SettingsMessage::SettingsMessage(directory_which directory, + const char* filename) + : BMessage('pref') +{ + fStatus = find_directory(directory, &fPath); + + if (fStatus == B_OK) + fStatus = fPath.Append(filename); + + if (fStatus == B_OK) + fStatus = Load(); +} + + +SettingsMessage::~SettingsMessage() +{ + Save(); +} + + +status_t +SettingsMessage::InitCheck() const +{ + return fStatus; +} + + +status_t +SettingsMessage::Load() +{ + BFile file(fPath.Path(), B_READ_ONLY); + status_t status = file.InitCheck(); + + if (status == B_OK) + status = Unflatten(&file); + + return status; +} + + +status_t +SettingsMessage::Save() const +{ + BFile file(fPath.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); + status_t status = file.InitCheck(); + + if (status == B_OK) + status = Flatten(&file); + + return status; +} + + +// #pragma mark - + + +status_t +SettingsMessage::SetValue(const char* name, bool value) +{ + if (ReplaceBool(name, value) == B_OK) + return B_OK; + return AddBool(name, value); +} + + +status_t +SettingsMessage::SetValue(const char* name, int8 value) +{ + if (ReplaceInt8(name, value) == B_OK) + return B_OK; + return AddInt8(name, value); +} + + +status_t +SettingsMessage::SetValue(const char* name, int16 value) +{ + if (ReplaceInt16(name, value) == B_OK) + return B_OK; + return AddInt16(name, value); +} + + +status_t +SettingsMessage::SetValue(const char* name, int32 value) +{ + if (ReplaceInt32(name, value) == B_OK) + return B_OK; + return AddInt32(name, value); +} + + +status_t +SettingsMessage::SetValue(const char* name, uint32 value) +{ + if (ReplaceInt32(name, (int32)value) == B_OK) + return B_OK; + return AddInt32(name, (int32)value); +} + + +status_t +SettingsMessage::SetValue(const char* name, int64 value) +{ + if (ReplaceInt64(name, value) == B_OK) + return B_OK; + return AddInt64(name, value); +} + + +status_t +SettingsMessage::SetValue(const char* name, float value) +{ + if (ReplaceFloat(name, value) == B_OK) + return B_OK; + return AddFloat(name, value); +} + + +status_t +SettingsMessage::SetValue(const char* name, double value) +{ + if (ReplaceDouble(name, value) == B_OK) + return B_OK; + return AddDouble(name, value); +} + + +status_t +SettingsMessage::SetValue(const char* name, const char* value) +{ + if (ReplaceString(name, value) == B_OK) + return B_OK; + return AddString(name, value); +} + + +status_t +SettingsMessage::SetValue(const char* name, const BString& value) +{ + return SetValue(name, value.String()); +} + + +status_t +SettingsMessage::SetValue(const char* name, const BPoint& value) +{ + if (ReplacePoint(name, value) == B_OK) + return B_OK; + return AddPoint(name, value); +} + + +status_t +SettingsMessage::SetValue(const char* name, const BRect& value) +{ + if (ReplaceRect(name, value) == B_OK) + return B_OK; + return AddRect(name, value); +} + + +status_t +SettingsMessage::SetValue(const char* name, const entry_ref& value) +{ + if (ReplaceRef(name, &value) == B_OK) + return B_OK; + return AddRef(name, &value); +} + + +status_t +SettingsMessage::SetValue(const char* name, const BMessage* value) +{ + if (ReplaceMessage(name, value) == B_OK) + return B_OK; + return AddMessage(name, value); +} + + +status_t +SettingsMessage::SetValue(const char* name, const BFlattenable* value) +{ + if (ReplaceFlat(name, const_cast(value)) == B_OK) + return B_OK; + return AddFlat(name, const_cast(value)); +} + + +// #pragma mark - + +bool +SettingsMessage::GetValue(const char* name, bool defaultValue) const +{ + bool value; + if (FindBool(name, &value) != B_OK) + return defaultValue; + return value; +} + + +int8 +SettingsMessage::GetValue(const char* name, int8 defaultValue) const +{ + int8 value; + if (FindInt8(name, &value) != B_OK) + return defaultValue; + return value; +} + + +int16 +SettingsMessage::GetValue(const char* name, int16 defaultValue) const +{ + int16 value; + if (FindInt16(name, &value) != B_OK) + return defaultValue; + return value; +} + + +int32 +SettingsMessage::GetValue(const char* name, int32 defaultValue) const +{ + int32 value; + if (FindInt32(name, &value) != B_OK) + return defaultValue; + return value; +} + + +uint32 +SettingsMessage::GetValue(const char* name, uint32 defaultValue) const +{ + int32 value; + if (FindInt32(name, &value) != B_OK) + return defaultValue; + return (uint32)value; +} + + +int64 +SettingsMessage::GetValue(const char* name, int64 defaultValue) const +{ + int64 value; + if (FindInt64(name, &value) != B_OK) + return defaultValue; + return value; +} + + +float +SettingsMessage::GetValue(const char* name, float defaultValue) const +{ + float value; + if (FindFloat(name, &value) != B_OK) + return defaultValue; + return value; +} + + +double +SettingsMessage::GetValue(const char* name, double defaultValue) const +{ + double value; + if (FindDouble(name, &value) != B_OK) + return defaultValue; + return value; +} + + +BString +SettingsMessage::GetValue(const char* name, const BString& defaultValue) const +{ + BString value; + if (FindString(name, &value) != B_OK) + return defaultValue; + return value; +} + + +BPoint +SettingsMessage::GetValue(const char *name, BPoint defaultValue) const +{ + BPoint value; + if (FindPoint(name, &value) != B_OK) + return defaultValue; + return value; +} + + +BRect +SettingsMessage::GetValue(const char* name, BRect defaultValue) const +{ + BRect value; + if (FindRect(name, &value) != B_OK) + return defaultValue; + return value; +} + + +entry_ref +SettingsMessage::GetValue(const char* name, const entry_ref& defaultValue) const +{ + entry_ref value; + if (FindRef(name, &value) != B_OK) + return defaultValue; + return value; +} + + +BMessage +SettingsMessage::GetValue(const char* name, const BMessage& defaultValue) const +{ + BMessage value; + if (FindMessage(name, &value) != B_OK) + return defaultValue; + return value; +} + diff --git a/src/apps/webpositive/support/SettingsMessage.h b/src/apps/webpositive/support/SettingsMessage.h new file mode 100644 index 0000000000..f98121b5bb --- /dev/null +++ b/src/apps/webpositive/support/SettingsMessage.h @@ -0,0 +1,79 @@ +/* + * Copyright 2008 Stephan Aßmus . + * Copyright 1998 Eric Shepherd. + * All rights reserved. Distributed under the terms of the Be Sample Code + * license. + */ +#ifndef SETTINGS_MESSAGE_H +#define SETTINGS_MESSAGE_H + +#include +#include +#include + +class BString; + +class SettingsMessage : public BMessage { +public: + SettingsMessage(directory_which directory, + const char* filename); + virtual ~SettingsMessage(); + + + status_t InitCheck() const; + status_t Load(); + status_t Save() const; + + status_t SetValue(const char* name, bool value); + status_t SetValue(const char* name, int8 value); + status_t SetValue(const char* name, int16 value); + status_t SetValue(const char* name, int32 value); + status_t SetValue(const char* name, uint32 value); + status_t SetValue(const char* name, int64 value); + status_t SetValue(const char* name, float value); + status_t SetValue(const char* name, double value); + status_t SetValue(const char* name, + const char* value); + status_t SetValue(const char* name, + const BString& value); + status_t SetValue(const char *name, const BPoint& value); + status_t SetValue(const char* name, const BRect& value); + status_t SetValue(const char* name, const entry_ref& value); + status_t SetValue(const char* name, + const BMessage* value); + status_t SetValue(const char* name, + const BFlattenable* value); + + bool GetValue(const char* name, + bool defaultValue) const; + int8 GetValue(const char* name, + int8 defaultValue) const; + int16 GetValue(const char* name, + int16 defaultValue) const; + int32 GetValue(const char* name, + int32 defaultValue) const; + uint32 GetValue(const char* name, + uint32 defaultValue) const; + int64 GetValue(const char* name, + int64 defaultValue) const; + float GetValue(const char* name, + float defaultValue) const; + double GetValue(const char* name, + double defaultValue) const; + BString GetValue(const char* name, + const BString& defaultValue) const; + BPoint GetValue(const char *name, + BPoint defaultValue) const; + BRect GetValue(const char* name, + BRect defaultValue) const; + entry_ref GetValue(const char* name, + const entry_ref& defaultValue) const; + BMessage GetValue(const char* name, + const BMessage& defaultValue) const; + +private: + BPath fPath; + status_t fStatus; +}; + +#endif // SETTINGS_MESSAGE_H From b5cd3e842fd3e758ea8fdb95ff00b38835ed8aec Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 3 Mar 2010 11:23:06 +0000 Subject: [PATCH 154/349] Reworked BrowserApp to use SettingsMessage. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@279 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 81 +++++++++---------------- src/apps/webpositive/BrowserApp.h | 5 +- src/apps/webpositive/SettingsWindow.cpp | 7 ++- src/apps/webpositive/SettingsWindow.h | 6 +- 4 files changed, 43 insertions(+), 56 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 81fcce7b28..aaffc30a1e 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -32,6 +32,7 @@ #include "BrowserWindow.h" #include "BrowsingHistory.h" #include "DownloadWindow.h" +#include "SettingsMessage.h" #include "SettingsWindow.h" #include "WebPage.h" #include "WebSettings.h" @@ -40,7 +41,6 @@ #include #include #include -#include #include #include #include @@ -59,6 +59,7 @@ BrowserApp::BrowserApp() fLastWindowFrame(100, 100, 700, 750), fLaunchRefsMessage(0), fInitialized(false), + fSettings(NULL), fDownloadWindow(NULL), fSettingsWindow(NULL) { @@ -68,6 +69,7 @@ BrowserApp::BrowserApp() BrowserApp::~BrowserApp() { delete fLaunchRefsMessage; + delete fSettings; } @@ -109,31 +111,28 @@ BrowserApp::ReadyToRun() BWebPage::InitializeOnce(); BWebPage::SetCacheModel(B_WEBKIT_CACHE_MODEL_WEB_BROWSER); - BWebSettings::SetPersistentStoragePath("/boot/home/config/settings/WebPositive"); + BPath path; + if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK + && path.Append(kApplicationName) == B_OK + && create_directory(path.Path(), 0777) == B_OK) { - BFile settingsFile; - BRect windowFrameFromSettings = fLastWindowFrame; - BRect downloadWindowFrame(100, 100, 300, 250); - BRect settingsWindowFrame; - bool showDownloads = false; - if (_OpenSettingsFile(settingsFile, B_READ_ONLY)) { - BMessage settingsArchive; - settingsArchive.Unflatten(&settingsFile); - BRect rect; - if (settingsArchive.FindRect("window frame", &rect) == B_OK) - windowFrameFromSettings = rect; - if (settingsArchive.FindRect("downloads window frame", &rect) == B_OK) - downloadWindowFrame = rect; - if (settingsArchive.FindRect("settings window frame", &rect) == B_OK) - settingsWindowFrame = rect; - bool flag; - if (settingsArchive.FindBool("show downloads", &flag) == B_OK) - showDownloads = flag; + BWebSettings::SetPersistentStoragePath(path.Path()); } - fLastWindowFrame = windowFrameFromSettings; + + BString mainSettingsPath(kApplicationName); + mainSettingsPath << "/Application"; + fSettings = new SettingsMessage(B_USER_SETTINGS_DIRECTORY, + mainSettingsPath.String()); + + fLastWindowFrame = fSettings->GetValue("window frame", fLastWindowFrame); + BRect downloadWindowFrame = fSettings->GetValue("downloads window frame", + BRect(100, 100, 300, 250)); + BRect settingsWindowFrame = fSettings->GetValue("settings window frame", + BRect()); + bool showDownloads = fSettings->GetValue("show downloads", false); fDownloadWindow = new DownloadWindow(downloadWindowFrame, showDownloads); - fSettingsWindow = new SettingsWindow(settingsWindowFrame); + fSettingsWindow = new SettingsWindow(settingsWindowFrame, fSettings); fInitialized = true; @@ -249,41 +248,21 @@ BrowserApp::QuitRequested() } } - BFile settingsFile; - if (_OpenSettingsFile(settingsFile, B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) { - BMessage settingsArchive; - settingsArchive.AddRect("window frame", fLastWindowFrame); - if (fDownloadWindow->Lock()) { - settingsArchive.AddRect("downloads window frame", fDownloadWindow->Frame()); - settingsArchive.AddBool("show downloads", !fDownloadWindow->IsHidden()); - fDownloadWindow->Unlock(); - } - if (fSettingsWindow->Lock()) { - settingsArchive.AddRect("settings window frame", fSettingsWindow->Frame()); - fSettingsWindow->Unlock(); - } - settingsArchive.Flatten(&settingsFile); + fSettings->SetValue("window frame", fLastWindowFrame); + if (fDownloadWindow->Lock()) { + fSettings->SetValue("downloads window frame", fDownloadWindow->Frame()); + fSettings->SetValue("show downloads", !fDownloadWindow->IsHidden()); + fDownloadWindow->Unlock(); + } + if (fSettingsWindow->Lock()) { + fSettings->SetValue("settings window frame", fSettingsWindow->Frame()); + fSettingsWindow->Unlock(); } return true; } -bool -BrowserApp::_OpenSettingsFile(BFile& file, uint32 mode) -{ - BPath path; - if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK - || path.Append(kApplicationName) != B_OK - || create_directory(path.Path(), 0777) != B_OK - || path.Append("Application") != B_OK) { - return false; - } - - return file.SetTo(path.Path(), mode) == B_OK; -} - - void BrowserApp::_CreateNewPage(const BString& url) { diff --git a/src/apps/webpositive/BrowserApp.h b/src/apps/webpositive/BrowserApp.h index 6b5402ba9a..531a88ffe0 100644 --- a/src/apps/webpositive/BrowserApp.h +++ b/src/apps/webpositive/BrowserApp.h @@ -32,9 +32,9 @@ #include #include -class BFile; class DownloadWindow; class BrowserWindow; +class SettingsMessage; class SettingsWindow; @@ -51,7 +51,6 @@ public: virtual bool QuitRequested(); private: - bool _OpenSettingsFile(BFile& file, uint32 mode); void _CreateNewPage(const BString& url); void _CreateNewWindow(const BString& url); void _CreateNewTab(BrowserWindow* window, @@ -65,6 +64,8 @@ private: BMessage* fLaunchRefsMessage; bool fInitialized; + SettingsMessage* fSettings; + DownloadWindow* fDownloadWindow; SettingsWindow* fSettingsWindow; }; diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 77364539fe..42c4492883 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -40,6 +40,8 @@ #include #include +#include "SettingsMessage.h" + enum { MSG_OK = 'aply', @@ -48,10 +50,11 @@ enum { }; -SettingsWindow::SettingsWindow(BRect frame) +SettingsWindow::SettingsWindow(BRect frame, SettingsMessage* settings) : BWindow(frame, "Settings", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, - B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE) + B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE), + fSettings(settings) { SetLayout(new BGroupLayout(B_VERTICAL)); diff --git a/src/apps/webpositive/SettingsWindow.h b/src/apps/webpositive/SettingsWindow.h index 22ff3f7c10..76b215b03e 100644 --- a/src/apps/webpositive/SettingsWindow.h +++ b/src/apps/webpositive/SettingsWindow.h @@ -30,11 +30,13 @@ #include class BButton; +class SettingsMessage; class SettingsWindow : public BWindow { public: - SettingsWindow(BRect frame); + SettingsWindow(BRect frame, + SettingsMessage* settings); virtual ~SettingsWindow(); virtual void MessageReceived(BMessage* message); @@ -45,6 +47,8 @@ private: void _RevertSettings(); private: + SettingsMessage* fSettings; + BButton* fOkButton; BButton* fCancelButton; BButton* fRevertButton; From 5c2095b4b08c8ccbc8ad97a1a2cf30c241b979ea Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 4 Mar 2010 18:17:24 +0000 Subject: [PATCH 155/349] * Link against liblocale.so and load app catalog. * Took FontSelectionView from Haiku Fonts preflet, but almost rewrote it to adapt for WebPositive needs. It's now a BHandler, so that it can actually receive messages itself. The Fonts version is a BView which is never attached, and only receives messages, because the window forwards them. Implemented option to use separate style menu. * Provide font settings in the Settings window. * Wired everything to make it work, although I am not sure standard font is applied. It does work for the serif font, though. Maybe I ought to install more fonts and check with simpler HTML. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@284 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 2 + src/apps/webpositive/BrowserApp.h | 3 + src/apps/webpositive/SettingsWindow.cpp | 243 ++++++++- src/apps/webpositive/SettingsWindow.h | 22 +- .../webpositive/support/FontSelectionView.cpp | 489 ++++++++++++++++++ .../webpositive/support/FontSelectionView.h | 83 +++ .../webpositive/support/SettingsMessage.cpp | 51 +- .../webpositive/support/SettingsMessage.h | 5 + 8 files changed, 883 insertions(+), 15 deletions(-) create mode 100644 src/apps/webpositive/support/FontSelectionView.cpp create mode 100644 src/apps/webpositive/support/FontSelectionView.h diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index aaffc30a1e..89bd3aeaeb 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -63,6 +64,7 @@ BrowserApp::BrowserApp() fDownloadWindow(NULL), fSettingsWindow(NULL) { + be_locale->GetAppCatalog(&fAppCatalog); } diff --git a/src/apps/webpositive/BrowserApp.h b/src/apps/webpositive/BrowserApp.h index 531a88ffe0..d4fb9fbf59 100644 --- a/src/apps/webpositive/BrowserApp.h +++ b/src/apps/webpositive/BrowserApp.h @@ -30,6 +30,7 @@ #include +#include #include class DownloadWindow; @@ -68,6 +69,8 @@ private: DownloadWindow* fDownloadWindow; SettingsWindow* fSettingsWindow; + + BCatalog fAppCatalog; }; diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 42c4492883..906a029dfb 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -26,62 +26,133 @@ */ #include "SettingsWindow.h" -#include "BrowserApp.h" -#include "WebSettings.h" - #include #include #include #include #include #include +#include +#include +#include #include #include #include +#include #include +#include "BrowserApp.h" +#include "FontSelectionView.h" #include "SettingsMessage.h" +#include "WebSettings.h" +#undef TR_CONTEXT +#define TR_CONTEXT "Settings Window" + enum { - MSG_OK = 'aply', - MSG_CANCEL = 'cncl', - MSG_REVERT = 'rvrt', + MSG_APPLY = 'aply', + MSG_CANCEL = 'cncl', + MSG_REVERT = 'rvrt', + MSG_STANDARD_FONT_SIZE_SELECTED = 'sfss', + MSG_FIXED_FONT_SIZE_SELECTED = 'ffss', }; +static const int32 kDefaultFontSize = 14; + SettingsWindow::SettingsWindow(BRect frame, SettingsMessage* settings) : - BWindow(frame, "Settings", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, + BWindow(frame, TR("Settings"), B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE), fSettings(settings) { SetLayout(new BGroupLayout(B_VERTICAL)); - fOkButton = new BButton("OK", new BMessage(MSG_OK)); + fStandardFontView = new FontSelectionView("standard", "Standard font:", + true, be_plain_font); + BFont defaultSerifFont = _FindDefaultSerifFont(); + fSerifFontView = new FontSelectionView("serif", "Serif font:", true, + &defaultSerifFont); + fSansSerifFontView = new FontSelectionView("sans serif", "Sans serif font:", + true, be_plain_font); + fFixedFontView = new FontSelectionView("fixed", "Fixed font:", true, + be_fixed_font); + + fStandardSizesMenu = new BMenuField("standard font size", + TR("Default standard font size:"), new BPopUpMenu("sizes"), NULL); + _BuildSizesMenu(fStandardSizesMenu->Menu(), MSG_STANDARD_FONT_SIZE_SELECTED); + + fFixedSizesMenu = new BMenuField("fixed font size", + TR("Default fixed font size:"), new BPopUpMenu("sizes"), NULL); + _BuildSizesMenu(fFixedSizesMenu->Menu(), MSG_FIXED_FONT_SIZE_SELECTED); + + fApplyButton = new BButton("Apply", new BMessage(MSG_APPLY)); fCancelButton = new BButton("Cancel", new BMessage(MSG_CANCEL)); fRevertButton = new BButton("Revert", new BMessage(MSG_REVERT)); float spacing = be_control_look->DefaultItemSpacing(); AddChild(BGroupLayoutBuilder(B_VERTICAL) - .Add(BGridLayoutBuilder(spacing, spacing) + .Add(BGridLayoutBuilder(spacing / 2, spacing / 2) + .Add(fStandardFontView->CreateFontsLabelLayoutItem(), 0, 0) + .Add(fStandardFontView->CreateFontsMenuBarLayoutItem(), 1, 0) + .Add(fStandardFontView->PreviewBox(), 0, 1, 2) + .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 2, 2) + + .Add(fSerifFontView->CreateFontsLabelLayoutItem(), 0, 3) + .Add(fSerifFontView->CreateFontsMenuBarLayoutItem(), 1, 3) + .Add(fSerifFontView->PreviewBox(), 0, 4, 2) + .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 5, 2) + + .Add(fSansSerifFontView->CreateFontsLabelLayoutItem(), 0, 6) + .Add(fSansSerifFontView->CreateFontsMenuBarLayoutItem(), 1, 6) + .Add(fSansSerifFontView->PreviewBox(), 0, 7, 2) + .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 8, 2) + + .Add(fFixedFontView->CreateFontsLabelLayoutItem(), 0, 9) + .Add(fFixedFontView->CreateFontsMenuBarLayoutItem(), 1, 9) + .Add(fFixedFontView->PreviewBox(), 0, 10, 2) + .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 11, 2) + + .Add(fStandardSizesMenu->CreateLabelLayoutItem(), 0, 12) + .Add(fStandardSizesMenu->CreateMenuBarLayoutItem(), 1, 12) + .Add(fFixedSizesMenu->CreateLabelLayoutItem(), 0, 13) + .Add(fFixedSizesMenu->CreateMenuBarLayoutItem(), 1, 13) + .SetInsets(spacing, spacing, spacing, spacing) ) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL, spacing) .Add(fRevertButton) .AddGlue() .Add(fCancelButton) - .Add(fOkButton) + .Add(fApplyButton) .SetInsets(spacing, spacing, spacing, spacing) ) ); - fOkButton->MakeDefault(true); + AddHandler(fStandardFontView); + fStandardFontView->AttachedToLooper(); + + AddHandler(fSerifFontView); + fSerifFontView->AttachedToLooper(); + + AddHandler(fSansSerifFontView); + fSansSerifFontView->AttachedToLooper(); + + AddHandler(fFixedFontView); + fFixedFontView->AttachedToLooper(); + + fApplyButton->MakeDefault(true); if (!frame.IsValid()) CenterOnScreen(); + // load settings from disk + _RevertSettings(); + // apply to WebKit + _ApplySettings(); + // Start hidden Hide(); Show(); @@ -90,6 +161,14 @@ SettingsWindow::SettingsWindow(BRect frame, SettingsMessage* settings) SettingsWindow::~SettingsWindow() { + RemoveHandler(fStandardFontView); + delete fStandardFontView; + RemoveHandler(fSerifFontView); + delete fSerifFontView; + RemoveHandler(fSansSerifFontView); + delete fSansSerifFontView; + RemoveHandler(fFixedFontView); + delete fFixedFontView; } @@ -97,9 +176,8 @@ void SettingsWindow::MessageReceived(BMessage* message) { switch (message->what) { - case MSG_OK: + case MSG_APPLY: _ApplySettings(); - PostMessage(B_QUIT_REQUESTED); break; case MSG_CANCEL: _RevertSettings(); @@ -108,6 +186,20 @@ SettingsWindow::MessageReceived(BMessage* message) case MSG_REVERT: _RevertSettings(); break; + + case MSG_STANDARD_FONT_SIZE_SELECTED: { + int32 size = _SizesMenuValue(fStandardSizesMenu->Menu()); + fStandardFontView->SetSize(size); + fSerifFontView->SetSize(size); + fSansSerifFontView->SetSize(size); + break; + } + case MSG_FIXED_FONT_SIZE_SELECTED: { + int32 size = _SizesMenuValue(fFixedSizesMenu->Menu()); + fFixedFontView->SetSize(size); + break; + } + default: BWindow::MessageReceived(message); break; @@ -124,18 +216,143 @@ SettingsWindow::QuitRequested() } +void +SettingsWindow::Show() +{ + // When showing the window, the this is always the + // point to which we can revert the settings. + _RevertSettings(); + BWindow::Show(); +} + + // #pragma mark - private void SettingsWindow::_ApplySettings() { + // Store settings + fSettings->SetValue("standard font", fStandardFontView->Font()); + fSettings->SetValue("serif font", fSerifFontView->Font()); + fSettings->SetValue("sans serif font", fSansSerifFontView->Font()); + fSettings->SetValue("fixed font", fFixedFontView->Font()); + int32 standardFontSize = _SizesMenuValue(fStandardSizesMenu->Menu()); + int32 fixedFontSize = _SizesMenuValue(fFixedSizesMenu->Menu()); + fSettings->SetValue("standard font size", standardFontSize); + fSettings->SetValue("fixed font size", fixedFontSize); + + fSettings->Save(); + + // Apply settings to default web page settings. + BWebSettings::Default()->SetStandardFont(fStandardFontView->Font()); + BWebSettings::Default()->SetSerifFont(fSerifFontView->Font()); + BWebSettings::Default()->SetSansSerifFont(fSansSerifFontView->Font()); + BWebSettings::Default()->SetFixedFont(fFixedFontView->Font()); + BWebSettings::Default()->SetDefaultStandardFontSize(standardFontSize); + BWebSettings::Default()->SetDefaultFixedFontSize(fixedFontSize); + + // This will find all currently instantiated page settings and apply + // the default values, unless the page settings have local overrides. + BWebSettings::Default()->Apply(); } void SettingsWindow::_RevertSettings() { + int32 defaultFontSize = fSettings->GetValue("standard font size", + kDefaultFontSize); + int32 defaultFixedFontSize = fSettings->GetValue("fixed font size", + kDefaultFontSize); + + _SetSizesMenuValue(fStandardSizesMenu->Menu(), defaultFontSize); + _SetSizesMenuValue(fFixedSizesMenu->Menu(), defaultFixedFontSize); + + fStandardFontView->SetFont(fSettings->GetValue("standard font", + *be_plain_font), defaultFontSize); + fSerifFontView->SetFont(fSettings->GetValue("serif font", + _FindDefaultSerifFont()), defaultFontSize); + fSansSerifFontView->SetFont(fSettings->GetValue("sans serif font", + *be_plain_font), defaultFontSize); + fFixedFontView->SetFont(fSettings->GetValue("fixed font", + *be_fixed_font), defaultFixedFontSize); } +void +SettingsWindow::_BuildSizesMenu(BMenu* menu, uint32 messageWhat) +{ + const float kMinSize = 8.0; + const float kMaxSize = 18.0; + + const int32 kSizes[] = {7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 21, 24, 0}; + + for (int32 i = 0; kSizes[i]; i++) { + int32 size = kSizes[i]; + if (size < kMinSize || size > kMaxSize) + continue; + + char label[32]; + snprintf(label, sizeof(label), "%ld", size); + + BMessage* message = new BMessage(messageWhat); + message->AddInt32("size", size); + + BMenuItem* item = new BMenuItem(label, message); + + menu->AddItem(item); + item->SetTarget(this); + } +} + + +void +SettingsWindow::_SetSizesMenuValue(BMenu* menu, int32 value) +{ + for (int32 i = 0; BMenuItem* item = menu->ItemAt(i); i++) { + bool marked = false; + if (BMessage* message = item->Message()) { + int32 size; + if (message->FindInt32("size", &size) == B_OK && size == value) + marked = true; + } + item->SetMarked(marked); + } +} + + +int32 +SettingsWindow::_SizesMenuValue(BMenu* menu) +{ + if (BMenuItem* item = menu->FindMarked()) { + if (BMessage* message = item->Message()) { + int32 size; + if (message->FindInt32("size", &size) == B_OK) + return size; + } + } + return kDefaultFontSize; +} + + +BFont +SettingsWindow::_FindDefaultSerifFont() const +{ + // Default to the first "serif" font we find. + BFont serifFont(*be_plain_font); + font_family family; + int32 familyCount = count_font_families(); + for (int32 i = 0; i < familyCount; i++) { + if (get_font_family(i, &family) == B_OK) { + BString familyString(family); + if (familyString.IFindFirst("sans") >= 0) + continue; + if (familyString.IFindFirst("serif") >= 0) { + serifFont.SetFamilyAndFace(family, B_REGULAR_FACE); + break; + } + } + } + return serifFont; +} diff --git a/src/apps/webpositive/SettingsWindow.h b/src/apps/webpositive/SettingsWindow.h index 76b215b03e..9a6b7d9373 100644 --- a/src/apps/webpositive/SettingsWindow.h +++ b/src/apps/webpositive/SettingsWindow.h @@ -30,6 +30,9 @@ #include class BButton; +class BMenu; +class BMenuField; +class FontSelectionView; class SettingsMessage; @@ -42,16 +45,33 @@ public: virtual void MessageReceived(BMessage* message); virtual bool QuitRequested(); + virtual void Show(); + private: void _ApplySettings(); void _RevertSettings(); + void _BuildSizesMenu(BMenu* menu, + uint32 messageWhat); + void _SetSizesMenuValue(BMenu* menu, int32 value); + int32 _SizesMenuValue(BMenu* menu); + + BFont _FindDefaultSerifFont() const; + private: SettingsMessage* fSettings; - BButton* fOkButton; + FontSelectionView* fStandardFontView; + FontSelectionView* fSerifFontView; + FontSelectionView* fSansSerifFontView; + FontSelectionView* fFixedFontView; + + BButton* fApplyButton; BButton* fCancelButton; BButton* fRevertButton; + + BMenuField* fStandardSizesMenu; + BMenuField* fFixedSizesMenu; }; diff --git a/src/apps/webpositive/support/FontSelectionView.cpp b/src/apps/webpositive/support/FontSelectionView.cpp new file mode 100644 index 0000000000..038f0cdacb --- /dev/null +++ b/src/apps/webpositive/support/FontSelectionView.cpp @@ -0,0 +1,489 @@ +/* + * Copyright 2001-2010, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Mark Hogben + * DarkWyrm + * Axel Dörfler, axeld@pinc-software.de + * Philippe Saint-Pierre, stpere@gmail.com + * Stephan Aßmus + */ + +#include "FontSelectionView.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#undef TR_CONTEXT +#define TR_CONTEXT "Font Selection view" + + +static const float kMinSize = 8.0; +static const float kMaxSize = 18.0; + +static const int32 kMsgSetFamily = 'fmly'; +static const int32 kMsgSetStyle = 'styl'; +static const int32 kMsgSetSize = 'size'; + + +// #pragma mark - + + +FontSelectionView::FontSelectionView(const char* name, const char* label, + bool separateStyles, const BFont* currentFont) + : + BHandler(name) +{ + if (currentFont == NULL) + fCurrentFont = _DefaultFont(); + else + fCurrentFont = *currentFont; + + fSavedFont = fCurrentFont; + + fSizesMenu = new BPopUpMenu("size menu"); + fFontsMenu = new BPopUpMenu("font menu"); + + // font menu + fFontsMenuField = new BMenuField("fonts", label, fFontsMenu, NULL); + fFontsMenuField->SetFont(be_bold_font); + + // styles menu, if desired + if (separateStyles) { + fStylesMenu = new BPopUpMenu("styles menu"); + fStylesMenuField = new BMenuField("styles", TR("Style:"), fStylesMenu, + NULL); + } else { + fStylesMenu = NULL; + fStylesMenuField = NULL; + } + + // size menu + fSizesMenuField = new BMenuField("size", TR("Size:"), fSizesMenu, NULL); + fSizesMenuField->SetAlignment(B_ALIGN_RIGHT); + + // preview + fPreviewText = new BStringView("preview text", + TR_CMT("The quick brown fox jumps over the lazy dog.","Don't translate this literally ! Use a phrase showing all chars from A to Z.")); + + fPreviewText->SetFont(&fCurrentFont); + fPreviewText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED)); + fPreviewText->SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), + 1.65)); + fPreviewText->SetAlignment(B_ALIGN_RIGHT); +} + + +FontSelectionView::~FontSelectionView() +{ + // Some controls may not have been attached... + if (!fPreviewText->Window()) + delete fPreviewText; + if (!fSizesMenuField->Window()) + delete fSizesMenuField; + if (fStylesMenuField && !fStylesMenuField->Window()) + delete fStylesMenuField; + if (!fFontsMenuField->Window()) + delete fFontsMenuField; +} + + +void +FontSelectionView::AttachedToLooper() +{ + _BuildSizesMenu(); + UpdateFontsMenu(); +} + + +void +FontSelectionView::MessageReceived(BMessage* message) +{ + switch (message->what) { + case kMsgSetSize: + { + int32 size; + if (message->FindInt32("size", &size) != B_OK + || size == fCurrentFont.Size()) + break; + + fCurrentFont.SetSize(size); + _UpdateFontPreview(); + break; + } + + case kMsgSetFamily: + { + const char* family; + if (message->FindString("family", &family) != B_OK) + break; + + font_style style; + fCurrentFont.GetFamilyAndStyle(NULL, &style); + + BMenuItem* familyItem = fFontsMenu->FindItem(family); + if (familyItem != NULL) { + _SelectCurrentFont(false); + + BMenuItem* styleItem; + if (fStylesMenuField != NULL) + styleItem = fStylesMenuField->Menu()->FindMarked(); + else { + styleItem = familyItem->Submenu()->FindItem(style); + if (styleItem == NULL) + styleItem = familyItem->Submenu()->ItemAt(0); + } + + if (styleItem != NULL) { + styleItem->SetMarked(true); + fCurrentFont.SetFamilyAndStyle(family, styleItem->Label()); + _UpdateFontPreview(); + } + if (fStylesMenuField != NULL) + _AddStylesToMenu(fCurrentFont, fStylesMenuField->Menu()); + } + break; + } + + case kMsgSetStyle: + { + const char* family; + const char* style; + if (message->FindString("family", &family) != B_OK + || message->FindString("style", &style) != B_OK) + break; + + BMenuItem *familyItem = fFontsMenu->FindItem(family); + if (!familyItem) + break; + + _SelectCurrentFont(false); + familyItem->SetMarked(true); + + fCurrentFont.SetFamilyAndStyle(family, style); + _UpdateFontPreview(); + break; + } + + default: + BHandler::MessageReceived(message); + } +} + + +// #pragma mark - + + +void +FontSelectionView::SetFont(const BFont& font, float size) +{ + BFont resizedFont(font); + resizedFont.SetSize(size); + SetFont(resizedFont); +} + + +void +FontSelectionView::SetFont(const BFont& font) +{ + if (font == fCurrentFont && font == fSavedFont) + return; + + _SelectCurrentFont(false); + fSavedFont = fCurrentFont = font; + _UpdateFontPreview(); + + _SelectCurrentFont(true); + _SelectCurrentSize(true); +} + + +void +FontSelectionView::SetSize(float size) +{ + SetFont(fCurrentFont, size); +} + + +const BFont& +FontSelectionView::Font() const +{ + return fCurrentFont; +} + + +void +FontSelectionView::SetDefaults() +{ + BFont defaultFont = _DefaultFont(); + if (defaultFont == fCurrentFont) + return; + + _SelectCurrentFont(false); + + fCurrentFont = defaultFont; + _UpdateFontPreview(); + + _SelectCurrentFont(true); + _SelectCurrentSize(true); +} + + +void +FontSelectionView::Revert() +{ + if (!IsRevertable()) + return; + + _SelectCurrentFont(false); + + fCurrentFont = fSavedFont; + _UpdateFontPreview(); + + _SelectCurrentFont(true); + _SelectCurrentSize(true); +} + + +bool +FontSelectionView::IsDefaultable() +{ + return fCurrentFont != _DefaultFont(); +} + + +bool +FontSelectionView::IsRevertable() +{ + return fCurrentFont != fSavedFont; +} + + +void +FontSelectionView::UpdateFontsMenu() +{ + int32 numFamilies = count_font_families(); + + fFontsMenu->RemoveItems(0, fFontsMenu->CountItems(), true); + + BFont font = fCurrentFont; + + font_family currentFamily; + font_style currentStyle; + font.GetFamilyAndStyle(¤tFamily, ¤tStyle); + + for (int32 i = 0; i < numFamilies; i++) { + font_family family; + uint32 flags; + if (get_font_family(i, &family, &flags) != B_OK) + continue; + + // if we're setting the fixed font, we only want to show fixed fonts + if (!strcmp(Name(), "fixed") && (flags & B_IS_FIXED) == 0) + continue; + + font.SetFamilyAndFace(family, B_REGULAR_FACE); + + BMessage* message = new BMessage(kMsgSetFamily); + message->AddString("family", family); + message->AddString("name", Name()); + + BMenuItem* familyItem; + if (fStylesMenuField != NULL) { + familyItem = new BMenuItem(family, message); + } else { + // Each family item has a submenu with all styles for that font. + BMenu* stylesMenu = new BMenu(family); + _AddStylesToMenu(font, stylesMenu); + familyItem = new BMenuItem(stylesMenu, message); + } + + familyItem->SetMarked(strcmp(family, currentFamily) == 0); + fFontsMenu->AddItem(familyItem); + familyItem->SetTarget(this); + } + + // Separate styles menu for only the current font. + if (fStylesMenuField != NULL) + _AddStylesToMenu(fCurrentFont, fStylesMenuField->Menu()); +} + + +// #pragma mark - private + + +BLayoutItem* +FontSelectionView::CreateSizesLabelLayoutItem() +{ + return fSizesMenuField->CreateLabelLayoutItem(); +} + + +BLayoutItem* +FontSelectionView::CreateSizesMenuBarLayoutItem() +{ + return fSizesMenuField->CreateMenuBarLayoutItem(); +} + + +BLayoutItem* +FontSelectionView::CreateFontsLabelLayoutItem() +{ + return fFontsMenuField->CreateLabelLayoutItem(); +} + + +BLayoutItem* +FontSelectionView::CreateFontsMenuBarLayoutItem() +{ + return fFontsMenuField->CreateMenuBarLayoutItem(); +} + + +BLayoutItem* +FontSelectionView::CreateStylesLabelLayoutItem() +{ + if (fStylesMenuField) + return fStylesMenuField->CreateLabelLayoutItem(); + return NULL; +} + + +BLayoutItem* +FontSelectionView::CreateStylesMenuBarLayoutItem() +{ + if (fStylesMenuField) + return fStylesMenuField->CreateMenuBarLayoutItem(); + return NULL; +} + + +BView* +FontSelectionView::PreviewBox() const +{ + return fPreviewText; +} + + +// #pragma mark - private + + +BFont +FontSelectionView::_DefaultFont() const +{ + if (strcmp(Name(), "bold") == 0) + return *be_bold_font; + if (strcmp(Name(), "fixed") == 0) + return *be_fixed_font; + else + return *be_plain_font; +} + + +void +FontSelectionView::_SelectCurrentFont(bool select) +{ + font_family family; + font_style style; + fCurrentFont.GetFamilyAndStyle(&family, &style); + + BMenuItem *item = fFontsMenu->FindItem(family); + if (item != NULL) { + item->SetMarked(select); + + if (item->Submenu() != NULL) { + item = item->Submenu()->FindItem(style); + if (item != NULL) + item->SetMarked(select); + } + } +} + + +void +FontSelectionView::_SelectCurrentSize(bool select) +{ + char label[16]; + snprintf(label, sizeof(label), "%ld", (int32)fCurrentFont.Size()); + + BMenuItem* item = fSizesMenu->FindItem(label); + if (item != NULL) + item->SetMarked(select); +} + + +void +FontSelectionView::_UpdateFontPreview() +{ + fPreviewText->SetFont(&fCurrentFont); +} + + +void +FontSelectionView::_BuildSizesMenu() +{ + const int32 sizes[] = {7, 8, 9, 10, 11, 12, 13, 14, 18, 21, 24, 0}; + + // build size menu + for (int32 i = 0; sizes[i]; i++) { + int32 size = sizes[i]; + if (size < kMinSize || size > kMaxSize) + continue; + + char label[32]; + snprintf(label, sizeof(label), "%ld", size); + + BMessage* message = new BMessage(kMsgSetSize); + message->AddInt32("size", size); + message->AddString("name", Name()); + + BMenuItem* item = new BMenuItem(label, message); + if (size == fCurrentFont.Size()) + item->SetMarked(true); + + fSizesMenu->AddItem(item); + item->SetTarget(this); + } +} + + +void +FontSelectionView::_AddStylesToMenu(const BFont& font, BMenu* stylesMenu) const +{ + stylesMenu->RemoveItems(0, stylesMenu->CountItems(), true); + stylesMenu->SetRadioMode(true); + + font_family family; + font_style style; + font.GetFamilyAndStyle(&family, &style); + BString currentStyle(style); + + int32 numStyles = count_font_styles(family); + + for (int32 j = 0; j < numStyles; j++) { + if (get_font_style(family, j, &style) != B_OK) + continue; + + BMessage* message = new BMessage(kMsgSetStyle); + message->AddString("family", (char*)family); + message->AddString("style", (char*)style); + + BMenuItem* item = new BMenuItem(style, message); + item->SetMarked(currentStyle == style); + + stylesMenu->AddItem(item); + item->SetTarget(this); + } +} + diff --git a/src/apps/webpositive/support/FontSelectionView.h b/src/apps/webpositive/support/FontSelectionView.h new file mode 100644 index 0000000000..f25801a840 --- /dev/null +++ b/src/apps/webpositive/support/FontSelectionView.h @@ -0,0 +1,83 @@ +/* + * Copyright 2001-2010, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Mark Hogben + * DarkWyrm + * Axel Dörfler, axeld@pinc-software.de + * Philippe Saint-Pierre, stpere@gmail.com + * Stephan Aßmus + */ +#ifndef FONT_SELECTION_VIEW_H +#define FONT_SELECTION_VIEW_H + + +#include +#include + +class BLayoutItem; +class BBox; +class BMenu; +class BMenuField; +class BPopUpMenu; +class BStringView; +class BView; + + +class FontSelectionView : public BHandler { +public: + FontSelectionView(const char* name, + const char* label, bool separateStyles, + const BFont* font = NULL); + virtual ~FontSelectionView(); + + void AttachedToLooper(); + virtual void MessageReceived(BMessage* message); + + void SetFont(const BFont& font, float size); + void SetFont(const BFont& font); + void SetSize(float size); + const BFont& Font() const; + + void SetDefaults(); + void Revert(); + bool IsDefaultable(); + bool IsRevertable(); + + void UpdateFontsMenu(); + + BLayoutItem* CreateSizesLabelLayoutItem(); + BLayoutItem* CreateSizesMenuBarLayoutItem(); + + BLayoutItem* CreateFontsLabelLayoutItem(); + BLayoutItem* CreateFontsMenuBarLayoutItem(); + + BLayoutItem* CreateStylesLabelLayoutItem(); + BLayoutItem* CreateStylesMenuBarLayoutItem(); + + BView* PreviewBox() const; + +private: + BFont _DefaultFont() const; + void _SelectCurrentFont(bool select); + void _SelectCurrentSize(bool select); + void _UpdateFontPreview(); + void _BuildSizesMenu(); + void _AddStylesToMenu(const BFont& font, + BMenu* menu) const; + +protected: + BMenuField* fFontsMenuField; + BMenuField* fStylesMenuField; + BMenuField* fSizesMenuField; + BPopUpMenu* fFontsMenu; + BPopUpMenu* fStylesMenu; + BPopUpMenu* fSizesMenu; + BStringView* fPreviewText; + + BFont fSavedFont; + BFont fCurrentFont; +}; + +#endif // FONT_SELECTION_VIEW_H diff --git a/src/apps/webpositive/support/SettingsMessage.cpp b/src/apps/webpositive/support/SettingsMessage.cpp index dad98820b2..7c2edddfc5 100644 --- a/src/apps/webpositive/support/SettingsMessage.cpp +++ b/src/apps/webpositive/support/SettingsMessage.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2008, Stephan Aßmus . + * Copyright 2008-2010, Stephan Aßmus . * Copyright 1998, Eric Shepherd. * All rights reserved. Distributed under the terms of the Be Sample Code * license. @@ -203,8 +203,31 @@ SettingsMessage::SetValue(const char* name, const BFlattenable* value) } +status_t +SettingsMessage::SetValue(const char* name, const BFont& value) +{ + font_family family; + font_style style; + value.GetFamilyAndStyle(&family, &style); + + BMessage fontMessage; + status_t ret = fontMessage.AddString("family", family); + if (ret == B_OK) + ret = fontMessage.AddString("style", style); + if (ret == B_OK) + ret = fontMessage.AddFloat("size", value.Size()); + + if (ret == B_OK) { + if (ReplaceMessage(name, &fontMessage) != B_OK) + ret = AddMessage(name, &fontMessage); + } + return ret; +} + + // #pragma mark - + bool SettingsMessage::GetValue(const char* name, bool defaultValue) const { @@ -334,3 +357,29 @@ SettingsMessage::GetValue(const char* name, const BMessage& defaultValue) const return value; } + +BFont +SettingsMessage::GetValue(const char* name, const BFont& defaultValue) const +{ + BMessage fontMessage; + if (FindMessage(name, &fontMessage) != B_OK) + return defaultValue; + + const char* family; + const char* style; + float size; + if (fontMessage.FindString("family", &family) != B_OK + || fontMessage.FindString("style", &style) != B_OK + || fontMessage.FindFloat("size", &size) != B_OK) { + return defaultValue; + } + + BFont value; + if (value.SetFamilyAndStyle(family, style) != B_OK) + return defaultValue; + + value.SetSize(size); + + return value; +} + diff --git a/src/apps/webpositive/support/SettingsMessage.h b/src/apps/webpositive/support/SettingsMessage.h index f98121b5bb..85a29320b8 100644 --- a/src/apps/webpositive/support/SettingsMessage.h +++ b/src/apps/webpositive/support/SettingsMessage.h @@ -8,6 +8,7 @@ #define SETTINGS_MESSAGE_H #include +#include #include #include @@ -43,6 +44,8 @@ public: const BMessage* value); status_t SetValue(const char* name, const BFlattenable* value); + status_t SetValue(const char* name, + const BFont& value); bool GetValue(const char* name, bool defaultValue) const; @@ -70,6 +73,8 @@ public: const entry_ref& defaultValue) const; BMessage GetValue(const char* name, const BMessage& defaultValue) const; + BFont GetValue(const char* name, + const BFont& defaultValue) const; private: BPath fPath; From 0fe64862b7c900e74058496e7fe439ded4a18f3d Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 4 Mar 2010 19:35:26 +0000 Subject: [PATCH 156/349] Changed how auto-completion fills the choices. It doesn't remove choices with the same base URL anymore, but simply uses a lower priority for every less recent choice with the same base URL, and then sorts the result list after fetching. Previously, you would only get one choice for a given base URL, and that one was more likely a longer URL, since it was visited more recently than the start page of the respective site. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@286 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 51 ++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index fc01924a22..46b04fed51 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -94,6 +94,34 @@ layoutItemFor(BView* view) } +class URLChoice : public BAutoCompleter::Choice { +public: + URLChoice(const BString& choiceText, const BString& displayText, + int32 matchPos, int32 matchLen, int32 priority) + : + BAutoCompleter::Choice(choiceText, displayText, matchPos, matchLen), + fPriority(priority) + { + } + + bool operator<(const URLChoice& other) const + { + if (fPriority > other.fPriority) + return true; + return DisplayText() < other.DisplayText(); + } + + bool operator==(const URLChoice& other) const + { + return fPriority == other.fPriority + && DisplayText() < other.DisplayText(); + } + +private: + int32 fPriority; +}; + + class BrowsingHistoryChoiceModel : public BAutoCompleter::ChoiceModel { virtual void FetchChoicesFor(const BString& pattern) { @@ -110,6 +138,7 @@ class BrowsingHistoryChoiceModel : public BAutoCompleter::ChoiceModel { return; BString lastBaseURL; + int32 priority = INT_MAX; count = history->countItems(); for (int32 i = 0; i < count; i++) { @@ -120,17 +149,20 @@ class BrowsingHistoryChoiceModel : public BAutoCompleter::ChoiceModel { continue; if (lastBaseURL.Length() > 0 && choiceText.FindFirst(lastBaseURL) >= 0) { - continue; - } + priority--; + } else + priority = INT_MAX; int32 baseURLStart = choiceText.FindFirst("://") + 3; int32 baseURLEnd = choiceText.FindFirst("/", baseURLStart + 1); lastBaseURL.SetTo(choiceText.String() + baseURLStart, baseURLEnd - baseURLStart); - fChoices.AddItem(new BAutoCompleter::Choice(choiceText, - choiceText, matchPos, pattern.Length())); + fChoices.AddItem(new URLChoice(choiceText, + choiceText, matchPos, pattern.Length(), priority)); } history->Unlock(); + + fChoices.SortItems(_CompareChoices); } virtual int32 CountChoices() const @@ -144,6 +176,17 @@ class BrowsingHistoryChoiceModel : public BAutoCompleter::ChoiceModel { fChoices.ItemAt(index)); } + static int _CompareChoices(const void* a, const void* b) + { + const URLChoice* aChoice = *reinterpret_cast(a); + const URLChoice* bChoice = *reinterpret_cast(b); + if (*aChoice < *bChoice) + return -1; + else if (*aChoice == *bChoice) + return 0; + return 1; + } + private: BList fChoices; }; From c108caf8653bd06bbf2dc98b22807178f0c3b652 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 6 Mar 2010 12:41:48 +0000 Subject: [PATCH 157/349] * Use a different deletion strategy for the BWebView. Since the BWebPage will delete itself in the application thread, we cannot delete the BWebView before this happens in the window thread. Now BWebPage is repsonsible for deleting the view. * Also make sure that there are not still loaders running on the frame. Since the timer messages arrive in a different handler than the BWebPage handler, the timer functions being called could operate on stale pointers. I am not sure why WebCore doesn't make sure of this itself. Perhaps we are not supposed to delete something directly, but via reference counting. Though I am not sure what it would be, since WebCore::Page is not reference countable. Maybe the frame... need to investigate. After all, there could be other timers in the queue besides loading related ones. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@295 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 16 ++++++++++++++-- src/apps/webpositive/BrowserWindow.h | 1 + 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 46b04fed51..a2ff746a89 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -527,7 +527,7 @@ BrowserWindow::MessageReceived(BMessage* message) int32 index; if (message->FindInt32("tab index", &index) != B_OK) index = fTabManager->SelectedTabIndex(); - delete fTabManager->RemoveTab(index); + _ShutdownTab(index); _UpdateTabGroupVisibility(); } else PostMessage(B_QUIT_REQUESTED); @@ -581,7 +581,7 @@ BrowserWindow::QuitRequested() // Iterate over all tabs to delete all BWebViews. // Do this here, so WebKit tear down happens earlier. while (fTabManager->CountTabs() > 0) - delete fTabManager->RemoveTab(0L); + _ShutdownTab(0); SetCurrentWebView(0); BMessage message(WINDOW_CLOSED); @@ -900,3 +900,15 @@ BrowserWindow::_UpdateTabGroupVisibility() Unlock(); } } + + +void +BrowserWindow::_ShutdownTab(int32 index) +{ + BView* view = fTabManager->RemoveTab(index); + BWebView* webView = dynamic_cast(view); + if (webView) + webView->Shutdown(); + else + delete view; +} diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 0fafb1ec2e..e52048f128 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -118,6 +118,7 @@ private: private: void _UpdateTitle(const BString &title); void _UpdateTabGroupVisibility(); + void _ShutdownTab(int32 index); private: BMessenger fDownloadListener; From 6faa5c3d74ae9ab65827194b88ba910dc83c301c Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 9 Mar 2010 09:26:44 +0000 Subject: [PATCH 158/349] Use the "bytes" member from the keydown message in order to get mapped keys. The 8 and 2 on the number pad would not work in the URL bar otherwise, since those map to "B_UP_ARROW" and "B_DOWN_ARROW" as raw char. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@302 94f232f2-1747-11df-bad5-a5bfde151594 --- .../webpositive/autocompletion/TextControlCompleter.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/autocompletion/TextControlCompleter.cpp b/src/apps/webpositive/autocompletion/TextControlCompleter.cpp index 6b3c257602..552c8b5f5d 100644 --- a/src/apps/webpositive/autocompletion/TextControlCompleter.cpp +++ b/src/apps/webpositive/autocompletion/TextControlCompleter.cpp @@ -85,13 +85,14 @@ TextControlCompleter::~TextControlCompleter() filter_result TextControlCompleter::Filter(BMessage* message, BHandler** target) { - int32 rawChar, modifiers; - if (!target || message->FindInt32("raw_char", &rawChar) != B_OK + const char* bytes; + int32 modifiers; + if (!target || message->FindString("bytes", &bytes) != B_OK || message->FindInt32("modifiers", &modifiers) != B_OK) { return B_DISPATCH_MESSAGE; } - switch (rawChar) { + switch (bytes[0]) { case B_UP_ARROW: SelectPrevious(); return B_SKIP_MESSAGE; From 7239ea752d0486bed93d1c3e97c26a8556822362 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 9 Mar 2010 11:49:34 +0000 Subject: [PATCH 159/349] * Added a class CookieJarClient to WebCore's CookieJar.h which provides the same functionality as the global methods for managing cookies. This is only enabled for the Haiku platform. Since the global cookie methods get a Document pointer, I envision, the CookieJarClient could eventually be a member of Document instances. It would then be passed upon WebCore::Page creation. Still waiting on feedback from other WebKit developers on this one. This change is more elegant than what the Qt port does, which is to use WebKit classes in WebCore (layering violation). Right now, a single global instance of a CookieJarClient can be assigned. * Implemented CookieJarClientHaiku which uses a BNetworkCookieJar to forward the requests. Eventually, the behaviour could be browser specific. * Added all the necessary wiring to BrowserApplication to make the cookie jar persistent. * TODO: Actually parse cookies and handle at least the expiration date, but other stuff like matching the domain of the cookie and the URL and "HTTP-only" cookies seems important as well. Even though I have confirmed that cookies are stored and restored correctly, and also retrieved via the global cookie methods, I can see no change in browser behaviour. For example enabling "Stay signed in" on googlemail.com does not work in WebPositive, although BeZillaBrowser automatically logs in in a new session when surfing to googlemail.com. No idea if this is even implemented with cookies, although it seems like it should be. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@303 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 16 ++++++++++++++++ src/apps/webpositive/BrowserApp.h | 3 +++ src/apps/webpositive/BrowserWindow.cpp | 14 ++++++-------- src/apps/webpositive/support/SettingsMessage.cpp | 6 +++--- src/apps/webpositive/support/SettingsMessage.h | 2 +- 5 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 89bd3aeaeb..29fe7b6ccd 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -34,6 +34,7 @@ #include "DownloadWindow.h" #include "SettingsMessage.h" #include "SettingsWindow.h" +#include "NetworkCookieJar.h" #include "WebPage.h" #include "WebSettings.h" #include "WebView.h" @@ -61,6 +62,7 @@ BrowserApp::BrowserApp() fLaunchRefsMessage(0), fInitialized(false), fSettings(NULL), + fCookieJar(NULL), fDownloadWindow(NULL), fSettingsWindow(NULL) { @@ -72,6 +74,8 @@ BrowserApp::~BrowserApp() { delete fLaunchRefsMessage; delete fSettings; + delete fCookies; + delete fCookieJar; } @@ -125,6 +129,14 @@ BrowserApp::ReadyToRun() mainSettingsPath << "/Application"; fSettings = new SettingsMessage(B_USER_SETTINGS_DIRECTORY, mainSettingsPath.String()); + mainSettingsPath = kApplicationName; + mainSettingsPath << "/Cookies"; + fCookies = new SettingsMessage(B_USER_SETTINGS_DIRECTORY, + mainSettingsPath.String()); + BMessage cookieArchive; + cookieArchive = fCookies->GetValue("cookies", cookieArchive); + fCookieJar = new BNetworkCookieJar(cookieArchive); + BWebPage::SetCookieJar(fCookieJar); fLastWindowFrame = fSettings->GetValue("window frame", fLastWindowFrame); BRect downloadWindowFrame = fSettings->GetValue("downloads window frame", @@ -261,6 +273,10 @@ BrowserApp::QuitRequested() fSettingsWindow->Unlock(); } + BMessage cookieArchive; + if (fCookieJar->Archive(&cookieArchive) == B_OK) + fCookies->SetValue("cookies", cookieArchive); + return true; } diff --git a/src/apps/webpositive/BrowserApp.h b/src/apps/webpositive/BrowserApp.h index d4fb9fbf59..dfc9433e5e 100644 --- a/src/apps/webpositive/BrowserApp.h +++ b/src/apps/webpositive/BrowserApp.h @@ -33,6 +33,7 @@ #include #include +class BNetworkCookieJar; class DownloadWindow; class BrowserWindow; class SettingsMessage; @@ -66,6 +67,8 @@ private: bool fInitialized; SettingsMessage* fSettings; + SettingsMessage* fCookies; + BNetworkCookieJar* fCookieJar; DownloadWindow* fDownloadWindow; SettingsWindow* fSettingsWindow; diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index a2ff746a89..4b0ef6b758 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -197,10 +197,11 @@ private: BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, ToolbarPolicy toolbarPolicy) - : BWebWindow(frame, kApplicationName, + : + BWebWindow(frame, kApplicationName, B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, - B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) - , fDownloadListener(downloadListener) + B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS), + fDownloadListener(downloadListener) { BMessage* newTabMessage = new BMessage(NEW_TAB); newTabMessage->AddString("url", ""); @@ -346,11 +347,8 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, fStatusText = 0; fLoadingProgressBar = 0; - BWebView* webView = new BWebView("web_view"); - SetCurrentWebView(webView); - - AddChild(BGroupLayoutBuilder(B_VERTICAL, 7) - .Add(CurrentWebView()) + AddChild(BGroupLayoutBuilder(B_VERTICAL) + .Add(fTabManager->ContainerView()) ); } diff --git a/src/apps/webpositive/support/SettingsMessage.cpp b/src/apps/webpositive/support/SettingsMessage.cpp index 7c2edddfc5..98e9ef1c94 100644 --- a/src/apps/webpositive/support/SettingsMessage.cpp +++ b/src/apps/webpositive/support/SettingsMessage.cpp @@ -186,11 +186,11 @@ SettingsMessage::SetValue(const char* name, const entry_ref& value) status_t -SettingsMessage::SetValue(const char* name, const BMessage* value) +SettingsMessage::SetValue(const char* name, const BMessage& value) { - if (ReplaceMessage(name, value) == B_OK) + if (ReplaceMessage(name, &value) == B_OK) return B_OK; - return AddMessage(name, value); + return AddMessage(name, &value); } diff --git a/src/apps/webpositive/support/SettingsMessage.h b/src/apps/webpositive/support/SettingsMessage.h index 85a29320b8..8420238be8 100644 --- a/src/apps/webpositive/support/SettingsMessage.h +++ b/src/apps/webpositive/support/SettingsMessage.h @@ -41,7 +41,7 @@ public: status_t SetValue(const char* name, const BRect& value); status_t SetValue(const char* name, const entry_ref& value); status_t SetValue(const char* name, - const BMessage* value); + const BMessage& value); status_t SetValue(const char* name, const BFlattenable* value); status_t SetValue(const char* name, From dcad381777abe240b6c4ce4a2da9f1dd445e4b0c Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 13 Mar 2010 14:10:14 +0000 Subject: [PATCH 160/349] Bugfixes for tab view click events: * When adding/removing tabs, process a fake mouse moved event to synchronize with the new tab layout. * Count the mouse clicks for the "double click into empty area opens new tab" feature in such a way that clicks into tabs never count (closing a tab was the first click before, the second would immediately open a new tab and similar issues). git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@309 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/WebTabView.cpp | 78 +++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 22 deletions(-) diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index 4dbb0bfc70..9f40c9aeef 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -111,7 +111,7 @@ private: private: TabContainerView* fContainerView; TabLayoutItem* fLayoutItem; - + BString fLabel; bool fIsFirst; @@ -145,6 +145,8 @@ public: virtual void MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage); + virtual void DoLayout(); + void AddTab(const char* label, int32 index = -1); void AddTab(TabView* tab, int32 index = -1); TabView* RemoveTab(int32 index); @@ -159,10 +161,13 @@ public: private: TabView* _TabAt(const BPoint& where) const; + void _MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMessage); private: TabView* fLastMouseEventTab; bool fMouseDown; + uint32 fClickCount; TabView* fSelectedTab; Controller* fController; }; @@ -179,6 +184,7 @@ TabContainerView::TabContainerView(Controller* controller) BGroupView(B_HORIZONTAL), fLastMouseEventTab(NULL), fMouseDown(false), + fClickCount(0), fSelectedTab(NULL), fController(controller) { @@ -260,8 +266,12 @@ TabContainerView::MouseDown(BPoint where) SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); if (fLastMouseEventTab) fLastMouseEventTab->MouseDown(where, buttons); - else if (clicks > 1) - fController->DoubleClickOutsideTabs(); + else { + if (clicks > 1) + fClickCount++; + else + fClickCount = 1; + } } @@ -271,6 +281,10 @@ TabContainerView::MouseUp(BPoint where) fMouseDown = false; if (fLastMouseEventTab) fLastMouseEventTab->MouseUp(where); + else if (fClickCount > 1) { + fClickCount = 0; + fController->DoubleClickOutsideTabs(); + } } @@ -278,27 +292,22 @@ void TabContainerView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage) { - TabView* tab = _TabAt(where); - if (fMouseDown) { - uint32 transit = tab == fLastMouseEventTab - ? B_INSIDE_VIEW : B_OUTSIDE_VIEW; - if (fLastMouseEventTab) - fLastMouseEventTab->MouseMoved(where, transit, dragMessage); - return; - } - - if (fLastMouseEventTab && fLastMouseEventTab == tab) - fLastMouseEventTab->MouseMoved(where, B_INSIDE_VIEW, dragMessage); - else { - if (fLastMouseEventTab) - fLastMouseEventTab->MouseMoved(where, B_EXITED_VIEW, dragMessage); - fLastMouseEventTab = tab; - if (fLastMouseEventTab) - fLastMouseEventTab->MouseMoved(where, B_ENTERED_VIEW, dragMessage); - } + _MouseMoved(where, transit, dragMessage); } +void +TabContainerView::DoLayout() +{ + BGroupView::DoLayout(); + + BPoint where; + uint32 buttons; + GetMouse(&where, &buttons, false); + if (Bounds().Contains(where)) + _MouseMoved(where, B_INSIDE_VIEW, NULL); +} + void TabContainerView::AddTab(const char* label, int32 index) { @@ -416,7 +425,7 @@ TabContainerView::SelectTab(int32 index) GroupLayout()->ItemAt(index)); if (item) tab = item->Parent(); - + SelectTab(tab); } @@ -472,6 +481,31 @@ TabContainerView::_TabAt(const BPoint& where) const } +void +TabContainerView::_MouseMoved(BPoint where, uint32 _transit, + const BMessage* dragMessage) +{ + TabView* tab = _TabAt(where); + if (fMouseDown) { + uint32 transit = tab == fLastMouseEventTab + ? B_INSIDE_VIEW : B_OUTSIDE_VIEW; + if (fLastMouseEventTab) + fLastMouseEventTab->MouseMoved(where, transit, dragMessage); + return; + } + + if (fLastMouseEventTab && fLastMouseEventTab == tab) + fLastMouseEventTab->MouseMoved(where, B_INSIDE_VIEW, dragMessage); + else { + if (fLastMouseEventTab) + fLastMouseEventTab->MouseMoved(where, B_EXITED_VIEW, dragMessage); + fLastMouseEventTab = tab; + if (fLastMouseEventTab) + fLastMouseEventTab->MouseMoved(where, B_ENTERED_VIEW, dragMessage); + } +} + + // #pragma mark - TabView From 88e373028cbb4d49b0098b89e1c26e1a92966e9b Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 14 Mar 2010 10:27:39 +0000 Subject: [PATCH 161/349] * Made BWebPage download related methods and listener member static. * Introduced BWebPage::RequestDownload() public API (expected to run synchronous). * Added necessary wiring for "Download this link" in context menus. * Restarting downloads works in principle, although with some quirks. (Sometimes it appears the "Desktop" is being downloaded...) git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@310 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 10 +++++----- src/apps/webpositive/BrowserWindow.cpp | 13 +++++-------- src/apps/webpositive/BrowserWindow.h | 2 -- src/apps/webpositive/DownloadWindow.cpp | 2 +- 4 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 29fe7b6ccd..e4b4c10d15 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -124,7 +124,7 @@ BrowserApp::ReadyToRun() BWebSettings::SetPersistentStoragePath(path.Path()); } - + BString mainSettingsPath(kApplicationName); mainSettingsPath << "/Application"; fSettings = new SettingsMessage(B_USER_SETTINGS_DIRECTORY, @@ -148,6 +148,8 @@ BrowserApp::ReadyToRun() fDownloadWindow = new DownloadWindow(downloadWindowFrame, showDownloads); fSettingsWindow = new SettingsWindow(settingsWindowFrame, fSettings); + BWebPage::SetDownloadListener(BMessenger(fDownloadWindow)); + fInitialized = true; if (fLaunchRefsMessage) { @@ -155,8 +157,7 @@ BrowserApp::ReadyToRun() delete fLaunchRefsMessage; fLaunchRefsMessage = 0; } else { - BrowserWindow* window = new BrowserWindow(fLastWindowFrame, - BMessenger(fDownloadWindow)); + BrowserWindow* window = new BrowserWindow(fLastWindowFrame); window->Show(); } PostMessage(PRELOAD_BROWSING_HISTORY); @@ -313,8 +314,7 @@ BrowserApp::_CreateNewWindow(const BString& url) if (!BScreen().Frame().Contains(fLastWindowFrame)) fLastWindowFrame.OffsetTo(50, 50); - BrowserWindow* window = new BrowserWindow(fLastWindowFrame, - BMessenger(fDownloadWindow)); + BrowserWindow* window = new BrowserWindow(fLastWindowFrame); window->Show(); if (url.Length()) window->CurrentWebView()->LoadURL(url.String()); diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 4b0ef6b758..6f09e9bc74 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -195,13 +195,11 @@ private: // #pragma mark - BrowserWindow -BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, - ToolbarPolicy toolbarPolicy) +BrowserWindow::BrowserWindow(BRect frame, ToolbarPolicy toolbarPolicy) : BWebWindow(frame, kApplicationName, B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, - B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS), - fDownloadListener(downloadListener) + B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) { BMessage* newTabMessage = new BMessage(NEW_TAB); newTabMessage->AddString("url", ""); @@ -373,7 +371,7 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, snprintf(numStr, sizeof(numStr), "%d", (int) i); AddShortcut(numStr[0], B_COMMAND_KEY, selectTab); } - + be_app->PostMessage(WINDOW_OPENED); } @@ -538,7 +536,7 @@ BrowserWindow::MessageReceived(BMessage* message) && fTabManager->CountTabs() > index) { fTabManager->SelectTab(index); } - + break; } @@ -629,7 +627,6 @@ BrowserWindow::CreateNewTab(const BString& url, bool select, BWebView* webView) // Executed in app thread (new BWebPage needs to be created in app thread). if (!webView) webView = new BWebView("web view"); - webView->WebPage()->SetDownloadListener(fDownloadListener); fTabManager->AddTab(webView, "New tab"); @@ -675,7 +672,7 @@ BrowserWindow::NewWindowRequested(const BString& url, bool primaryAction) } -void +void BrowserWindow::NewPageCreated(BWebView* view) { CreateNewTab(BString(), true, view); diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index e52048f128..0b2c4788ea 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -66,7 +66,6 @@ enum { class BrowserWindow : public BWebWindow { public: BrowserWindow(BRect frame, - const BMessenger& downloadListener, ToolbarPolicy = HaveToolbar); virtual ~BrowserWindow(); @@ -121,7 +120,6 @@ private: void _ShutdownTab(int32 index); private: - BMessenger fDownloadListener; BMenu* fGoMenu; IconButton* fBackButton; IconButton* fForwardButton; diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 44e5fa936e..60d9701e9b 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -257,7 +257,7 @@ public: break; } case RESTART_DOWNLOAD: - // TODO: + BWebPage::RequestDownload(m_url); break; case CANCEL_DOWNLOAD: From e509fd60c14849be0d9bc390f0761149fab42985 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 16 Mar 2010 13:04:01 +0000 Subject: [PATCH 162/349] Added code for bookmarking the current page and opening the Bookmarks folder in Tracker (or the preferred file manager). Populating the Bookmarks menu is still missing. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@314 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 149 +++++++++++++++++++++++++ src/apps/webpositive/BrowserWindow.h | 6 + 2 files changed, 155 insertions(+) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 6f09e9bc74..1bc8e407cc 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -47,13 +47,18 @@ #include #include #include +#include #include +#include +#include #include #include #include #include #include +#include #include +#include #include #include #include @@ -72,6 +77,9 @@ enum { RELOAD = 'reld', CLEAR_HISTORY = 'clhs', + CREATE_BOOKMARK = 'crbm', + SHOW_BOOKMARKS = 'shbm', + TEXT_SIZE_INCREASE = 'tsin', TEXT_SIZE_DECREASE = 'tsdc', TEXT_SIZE_RESET = 'tsrs', @@ -247,6 +255,14 @@ BrowserWindow::BrowserWindow(BRect frame, ToolbarPolicy toolbarPolicy) fGoMenu = new BMenu("Go"); mainMenu->AddItem(fGoMenu); + fBookmarkMenu = new BMenu("Bookmarks"); + fBookmarkMenu->AddItem(new BMenuItem("Bookmark this page", + new BMessage(CREATE_BOOKMARK), 'B')); + fBookmarkMenu->AddItem(new BMenuItem("Manage bookmarks", + new BMessage(SHOW_BOOKMARKS))); +// fBookmarkMenu->AddSeparatorItem(); + mainMenu->AddItem(fBookmarkMenu); + // Back, Forward & Stop fBackButton = new IconButton("Back", 0, NULL, new BMessage(GO_BACK)); fBackButton->SetIcon(201); @@ -458,6 +474,13 @@ BrowserWindow::MessageReceived(BMessage* message) break; } + case CREATE_BOOKMARK: + _CreateBookmark(); + break; + case SHOW_BOOKMARKS: + _ShowBookmarks(); + break; + case B_SIMPLE_DATA: { // User possibly dropped files on this window. // If there is more than one entry_ref, let the app handle it (open one @@ -907,3 +930,129 @@ BrowserWindow::_ShutdownTab(int32 index) else delete view; } + + +status_t +BrowserWindow::_BookmarkPath(BPath& path) const +{ + status_t ret = find_directory(B_USER_SETTINGS_DIRECTORY, &path); + if (ret != B_OK) + return ret; + + ret = path.Append(kApplicationName); + if (ret != B_OK) + return ret; + + ret = path.Append("Bookmarks"); + if (ret != B_OK) + return ret; + + return create_directory(path.Path(), 0777); +} + + +void +BrowserWindow::_CreateBookmark() +{ + BPath path; + status_t status = _BookmarkPath(path); + if (status != B_OK) { + BString message("There was an error retrieving the bookmark " + "folder.\n\n"); + message << "Error: " << strerror(status); + BAlert* alert = new BAlert("Bookmark error", message.String(), "OK", + NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); + alert->Go(); + return; + } + BWebView* webView = CurrentWebView(); + BString url(webView->MainFrameURL()); + // Create a bookmark file + BFile bookmarkFile; + BString bookmarkName(webView->MainFrameTitle()); + BPath entryPath(path); + status = entryPath.Append(bookmarkName); + BEntry entry; + if (status == B_OK) + status = entry.SetTo(entryPath.Path(), true); + if (status == B_OK) { + if (entry.Exists()) { + BString storedURL; + if (bookmarkFile.SetTo(&entry, B_READ_ONLY) == B_OK + && bookmarkFile.ReadAttrString("META:url", + &storedURL) == B_OK) { + // Just bail if the bookmark already exists + if (storedURL == url) { + BString message("A bookmark for this page ("); + message << webView->MainFrameTitle(); + message << ") already exists."; + BAlert* alert = new BAlert("Bookmark info", + message.String(), "OK"); + alert->Go(); + return; + } + } + } + int32 tries = 1; + while (entry.Exists()) { + // Find a unique name for the bookmark + bookmarkName = webView->MainFrameTitle(); + bookmarkName << " " << tries++; + entryPath = path; + status = entryPath.Append(bookmarkName); + if (status == B_OK) + status = entry.SetTo(entryPath.Path(), true); + if (status != B_OK) + break; + } + } + if (status == B_OK) { + status = bookmarkFile.SetTo(&entry, + B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY); + } + + if (status == B_OK) + status = bookmarkFile.WriteAttrString("META:url", &url); + if (status == B_OK) { + BString title = webView->MainFrameTitle(); + bookmarkFile.WriteAttrString("META:title", &title); + } + + BNodeInfo nodeInfo(&bookmarkFile); + if (status == B_OK) + status = nodeInfo.SetType("application/x-vnd.Be-bookmark"); + + if (status != B_OK) { + BString message("There was an error creating the bookmark " + "file.\n\n"); + message << "Error: " << strerror(status); + BAlert* alert = new BAlert("Bookmark error", message.String(), "OK", + NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); + alert->Go(); + return; + } +} + + +void +BrowserWindow::_ShowBookmarks() +{ + BPath path; + entry_ref ref; + status_t status = _BookmarkPath(path); + if (status == B_OK) + status = get_ref_for_path(path.Path(), &ref); + if (status == B_OK) + status = be_roster->Launch(&ref); + + if (status != B_OK && status != B_ALREADY_RUNNING) { + BString message("There was an error trying to show the Bookmarks " + "folder.\n\n"); + message << "Error: " << strerror(status); + BAlert* alert = new BAlert("Bookmark error", message.String(), "OK", + NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); + alert->Go(); + return; + } +} + diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 0b2c4788ea..caa53b4571 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -38,6 +38,7 @@ class BButton; class BCheckBox; class BLayoutItem; class BMenu; +class BPath; class BStatusBar; class BStringView; class BTextControl; @@ -119,8 +120,13 @@ private: void _UpdateTabGroupVisibility(); void _ShutdownTab(int32 index); + status_t _BookmarkPath(BPath& path) const; + void _CreateBookmark(); + void _ShowBookmarks(); + private: BMenu* fGoMenu; + BMenu* fBookmarkMenu; IconButton* fBackButton; IconButton* fForwardButton; IconButton* fStopButton; From 3760e5d86812dedd42fc9bcb0b2abfad9f65255c Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 16 Mar 2010 13:49:35 +0000 Subject: [PATCH 163/349] * Added Tracker Kit NavMenu.h and SlowMenu.h which ought to be removed when WebPositive is moved into the Haiku repo. * Convert the Bookmarks menu into a BNavMenu, make sure it updates to the current folder contens each time it opens. * Wire everything to complete the bookmark support. Managing bookmarks is fairly nice by re-using Tracker. One can even put anything into the book mark folder and WebPositive will launch the respective app if it doesn't have a META:url attribute. The most immediate benefit is that clicking sub-folders in the Bookmarks folder will also open that folder in Tracker. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@315 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 66 +++++++++- src/apps/webpositive/BrowserWindow.h | 1 - src/apps/webpositive/support/NavMenu.h | 168 ++++++++++++++++++++++++ src/apps/webpositive/support/SlowMenu.h | 76 +++++++++++ 4 files changed, 303 insertions(+), 8 deletions(-) create mode 100644 src/apps/webpositive/support/NavMenu.h create mode 100644 src/apps/webpositive/support/SlowMenu.h diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 1bc8e407cc..4d13b7eac8 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -37,6 +37,7 @@ #include "BrowserApp.h" #include "BrowsingHistory.h" #include "IconButton.h" +#include "NavMenu.h" #include "TextControlCompleter.h" #include "WebPage.h" #include "WebTabView.h" @@ -200,6 +201,31 @@ private: }; +class BookmarkMenu : public BNavMenu { +public: + BookmarkMenu(const char* title, BHandler* target, const entry_ref* navDir) + : + BNavMenu(title, B_REFS_RECEIVED, target) + { + SetNavDir(navDir); + } + + virtual void AttachedToWindow() + { + RemoveItems(0, CountItems(), true); + ForceRebuild(); + BNavMenu::AttachedToWindow(); + if (CountItems() > 0) + AddItem(new BSeparatorItem(), 0); + AddItem(new BMenuItem("Manage bookmarks", + new BMessage(SHOW_BOOKMARKS)), 0); + AddItem(new BMenuItem("Bookmark this page", + new BMessage(CREATE_BOOKMARK), 'B'), 0); + DoLayout(); + } +}; + + // #pragma mark - BrowserWindow @@ -255,13 +281,14 @@ BrowserWindow::BrowserWindow(BRect frame, ToolbarPolicy toolbarPolicy) fGoMenu = new BMenu("Go"); mainMenu->AddItem(fGoMenu); - fBookmarkMenu = new BMenu("Bookmarks"); - fBookmarkMenu->AddItem(new BMenuItem("Bookmark this page", - new BMessage(CREATE_BOOKMARK), 'B')); - fBookmarkMenu->AddItem(new BMenuItem("Manage bookmarks", - new BMessage(SHOW_BOOKMARKS))); -// fBookmarkMenu->AddSeparatorItem(); - mainMenu->AddItem(fBookmarkMenu); + BPath bookmarkPath; + entry_ref bookmarkRef; + if (_BookmarkPath(bookmarkPath) == B_OK + && get_ref_for_path(bookmarkPath.Path(), &bookmarkRef) == B_OK) { + BMenu* bookmarkMenu + = new BookmarkMenu("Bookmarks", this, &bookmarkRef); + mainMenu->AddItem(bookmarkMenu); + } // Back, Forward & Stop fBackButton = new IconButton("Back", 0, NULL, new BMessage(GO_BACK)); @@ -481,6 +508,31 @@ BrowserWindow::MessageReceived(BMessage* message) _ShowBookmarks(); break; + case B_REFS_RECEIVED: { + // Currently only source of these messages is the bookmarks menu. + // Filter refs into urls, this also gets rid of refs for folders. + // For clicks on sub-folders in the bookmarks menu, we have Tracker + // open the corresponding folder. + entry_ref ref; + for (int32 i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) { + BFile file(&ref, B_READ_ONLY); + bool isURL = false; + if (file.InitCheck() == B_OK) { + BString url; + if (file.ReadAttrString("META:url", &url) == B_OK) { + message->AddString("url", url.String()); + isURL = true; + } + } + if (!isURL) { + // Must be a folder or something else, have the system open it. + be_roster->Launch(&ref); + } + } + message->RemoveName("refs"); + be_app->PostMessage(message); + break; + } case B_SIMPLE_DATA: { // User possibly dropped files on this window. // If there is more than one entry_ref, let the app handle it (open one diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index caa53b4571..5def1c05ee 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -126,7 +126,6 @@ private: private: BMenu* fGoMenu; - BMenu* fBookmarkMenu; IconButton* fBackButton; IconButton* fForwardButton; IconButton* fStopButton; diff --git a/src/apps/webpositive/support/NavMenu.h b/src/apps/webpositive/support/NavMenu.h new file mode 100644 index 0000000000..127d94f255 --- /dev/null +++ b/src/apps/webpositive/support/NavMenu.h @@ -0,0 +1,168 @@ +/* +Open Tracker License + +Terms and Conditions + +Copyright (c) 1991-2000, Be Incorporated. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice applies to all licensees +and shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Be Incorporated shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from Be Incorporated. + +Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks +of Be Incorporated in the United States and other countries. Other brand product +names are registered trademarks or trademarks of their respective holders. +All rights reserved. +*/ + +// NavMenu is a hierarchical menu of volumes, folders, files and queries +// displays icons, uses the SlowMenu API for full interruptability + +#ifndef NAV_MENU_H +#define NAV_MENU_H + + +#include +#include +#include + +#include "SlowMenu.h" + + +template class BObjectList; +class BMenuItem; + +namespace BPrivate { + +class Model; +class BContainerWindow; +class ModelMenuItem; +class EntryListBase; + + +class TrackingHookData { + public: + TrackingHookData() + : + fTrackingHook(NULL), + fDragMessage(NULL) + { + } + + bool (*fTrackingHook)(BMenu *, void *); + BMessenger fTarget; + const BMessage *fDragMessage; +}; + + +class BNavMenu : public BSlowMenu { + public: + BNavMenu(const char* title, uint32 message, const BHandler *, + BWindow *parentWindow = NULL, const BObjectList *list = NULL); + BNavMenu(const char* title, uint32 message, const BMessenger &, + BWindow *parentWindow = NULL, const BObjectList *list = NULL); + // parentWindow, if specified, will be closed if nav menu item invoked + // with option held down + + virtual ~BNavMenu(); + + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + + void SetNavDir(const entry_ref *); + void ForceRebuild(); + bool NeedsToRebuild() const; + // will cause menu to get rebuilt next time it is shown + + virtual void ResetTargets(); + void SetTarget(const BMessenger &); + BMessenger Target(); + + void SetTypesList(const BObjectList *list); + const BObjectList *TypesList() const; + + void AddNavDir(const Model *model, uint32 what, BHandler *target, + bool populateSubmenu); + + void AddNavParentDir(const char *name, const Model *model, uint32 what, BHandler *target); + void AddNavParentDir(const Model *model, uint32 what, BHandler *target); + void SetShowParent(bool show); + + static int32 GetMaxMenuWidth(); + + static int CompareFolderNamesFirstOne(const BMenuItem *, const BMenuItem *); + static int CompareOne(const BMenuItem *, const BMenuItem *); + + static ModelMenuItem *NewModelItem(Model *, const BMessage *, const BMessenger &, + bool suppressFolderHierarchy=false, BContainerWindow * = NULL, + const BObjectList *typeslist = NULL, + TrackingHookData *hook = NULL); + + TrackingHookData *InitTrackingHook(bool (*hookfunction)(BMenu *, void *), + const BMessenger *target, const BMessage *dragMessage); + + protected: + virtual bool StartBuildingItemList(); + virtual bool AddNextItem(); + virtual void DoneBuildingItemList(); + virtual void ClearMenuBuildingState(); + + void BuildVolumeMenu(); + + void AddOneItem(Model *); + void AddRootItemsIfNeeded(); + void AddTrashItem(); + static void SetTrackingHookDeep(BMenu *, bool (*)(BMenu *, void *), void *); + + entry_ref fNavDir; + BMessage fMessage; + BMessenger fMessenger; + BWindow *fParentWindow; + + // menu building state + uint8 fFlags; + BObjectList *fItemList; + EntryListBase *fContainer; + bool fIteratingDesktop; + + const BObjectList *fTypesList; + + TrackingHookData fTrackingHook; +}; + +// Spring Loaded Folder convenience routines +// used in both Tracker and Deskbar +#ifndef _IMPEXP_TRACKER +# define _IMPEXP_TRACKER +#endif +_IMPEXP_TRACKER bool SpringLoadedFolderCompareMessages(const BMessage *incoming, + const BMessage *dragmessage); +_IMPEXP_TRACKER void SpringLoadedFolderSetMenuStates(const BMenu *menu, + const BObjectList *typeslist); +_IMPEXP_TRACKER void SpringLoadedFolderAddUniqueTypeToList(entry_ref *ref, + BObjectList *typeslist); +_IMPEXP_TRACKER void SpringLoadedFolderCacheDragData(const BMessage *incoming, + BMessage **, BObjectList **typeslist); + +} // namespace BPrivate + +using namespace BPrivate; + +#endif // NAV_MENU_H diff --git a/src/apps/webpositive/support/SlowMenu.h b/src/apps/webpositive/support/SlowMenu.h new file mode 100644 index 0000000000..62e9156b07 --- /dev/null +++ b/src/apps/webpositive/support/SlowMenu.h @@ -0,0 +1,76 @@ +/* +Open Tracker License + +Terms and Conditions + +Copyright (c) 1991-2000, Be Incorporated. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice applies to all licensees +and shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Be Incorporated shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from Be Incorporated. + +Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks +of Be Incorporated in the United States and other countries. Other brand product +names are registered trademarks or trademarks of their respective holders. +All rights reserved. +*/ + +#ifndef __SLOW_MENU__ +#define __SLOW_MENU__ + +#include +#include +#include + +// SlowMenu is a convenience class that makes it easier to +// use the AddDynamicItem callback to implement a menu that can +// checks periodically between creating new items and quits +// early if needed + +namespace BPrivate { + +class BSlowMenu : public BMenu { + public: + BSlowMenu(const char *title, menu_layout layout = B_ITEMS_IN_COLUMN); + + protected: + virtual bool StartBuildingItemList(); + // set up state to start building the item list + // returns false if setup failed + virtual bool AddNextItem() = 0; + // returns false if done + virtual void DoneBuildingItemList() = 0; + // default version adds items from itemList to menu and deletes + // the list; override to sort items first, etc. + + virtual void ClearMenuBuildingState() = 0; + + protected: + virtual bool AddDynamicItem(add_state state); + // this is the callback from BMenu, you shouldn't need to override this + + bool fMenuBuilt; +}; + +} // namespace BPrivate + +using namespace BPrivate; + +#endif /* __SLOW_MENU__ */ From c1f8fe4de1aeebf5829a597bed88f3f2ca4900cd Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 16 Mar 2010 18:08:30 +0000 Subject: [PATCH 164/349] Improvements in bookmark handling: * Search for existing bookmarks recursively. * Open all bookmarks at once, when the user clicks a bookmark folder in the menu (thanks Axel). But do ask for confirmation if there are more than ten bookmarks. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@318 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 144 ++++++++++++++++++++----- src/apps/webpositive/BrowserWindow.h | 11 ++ 2 files changed, 128 insertions(+), 27 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 4d13b7eac8..0a5d2f6940 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -509,27 +509,48 @@ BrowserWindow::MessageReceived(BMessage* message) break; case B_REFS_RECEIVED: { - // Currently only source of these messages is the bookmarks menu. - // Filter refs into urls, this also gets rid of refs for folders. + // Currently the only source of these messages is the bookmarks menu. + // Filter refs into URLs, this also gets rid of refs for folders. // For clicks on sub-folders in the bookmarks menu, we have Tracker // open the corresponding folder. entry_ref ref; + uint32 addedCount = 0; for (int32 i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) { - BFile file(&ref, B_READ_ONLY); - bool isURL = false; - if (file.InitCheck() == B_OK) { +printf("B_REFS_RECEIVED: %s\n", ref.name); + BEntry entry(&ref); + uint32 addedSubCount = 0; + if (entry.IsDirectory()) { + BDirectory directory(&entry); +printf(" directory ok\n"); + _AddBookmarkURLsRecursively(directory, message, addedSubCount); + } else { + BFile file(&ref, B_READ_ONLY); +printf(" file ok\n"); BString url; - if (file.ReadAttrString("META:url", &url) == B_OK) { + if (_ReadURLAttr(file, url)) { message->AddString("url", url.String()); - isURL = true; + addedSubCount++; } } - if (!isURL) { - // Must be a folder or something else, have the system open it. + if (addedSubCount == 0) { + // Don't know what to do with this entry, just pass it + // on to the system to handle. Note that this may result + // in us opening other supported files via the application + // mechanism. be_roster->Launch(&ref); } + addedCount += addedSubCount; } message->RemoveName("refs"); + if (addedCount > 10) { + BString string; + string << "Do you want to open " << addedCount; + string << " bookmarks all at once?"; + BAlert* alert = new BAlert("Open bookmarks confirmation", + string.String(), "Cancel", "Open all"); + if (alert->Go() == 0) + break; + } be_app->PostMessage(message); break; } @@ -1022,32 +1043,36 @@ BrowserWindow::_CreateBookmark() // Create a bookmark file BFile bookmarkFile; BString bookmarkName(webView->MainFrameTitle()); + if (bookmarkName.Length() == 0) { + bookmarkName = url; + int32 leafPos = bookmarkName.FindLast('/'); + if (leafPos >= 0) + bookmarkName.Remove(0, leafPos + 1); + } + + // Check that the bookmark exists nowhere in the bookmark hierarchy, + // though the intended file name must match, we don't search the stored + // URLs, only for matching file names. + BDirectory directory(path.Path()); + if (status == B_OK && _CheckBookmarkExists(directory, bookmarkName, url)) { + BString message("A bookmark for this page ("); + message << bookmarkName; + message << ") already exists."; + BAlert* alert = new BAlert("Bookmark info", message.String(), "OK"); + alert->Go(); + return; + } + BPath entryPath(path); status = entryPath.Append(bookmarkName); BEntry entry; if (status == B_OK) status = entry.SetTo(entryPath.Path(), true); if (status == B_OK) { - if (entry.Exists()) { - BString storedURL; - if (bookmarkFile.SetTo(&entry, B_READ_ONLY) == B_OK - && bookmarkFile.ReadAttrString("META:url", - &storedURL) == B_OK) { - // Just bail if the bookmark already exists - if (storedURL == url) { - BString message("A bookmark for this page ("); - message << webView->MainFrameTitle(); - message << ") already exists."; - BAlert* alert = new BAlert("Bookmark info", - message.String(), "OK"); - alert->Go(); - return; - } - } - } int32 tries = 1; while (entry.Exists()) { - // Find a unique name for the bookmark + // Find a unique name for the bookmark, there may still be a + // file in the way that stores a different URL. bookmarkName = webView->MainFrameTitle(); bookmarkName << " " << tries++; entryPath = path; @@ -1063,6 +1088,7 @@ BrowserWindow::_CreateBookmark() B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY); } + // Write bookmark meta data if (status == B_OK) status = bookmarkFile.WriteAttrString("META:url", &url); if (status == B_OK) { @@ -1108,3 +1134,67 @@ BrowserWindow::_ShowBookmarks() } } + +bool BrowserWindow::_CheckBookmarkExists(BDirectory& directory, + const BString& bookmarkName, const BString& url) const +{ + BEntry entry; + while (directory.GetNextEntry(&entry) == B_OK) { + if (entry.IsDirectory()) { + BDirectory subBirectory(&entry); + // At least preserve the entry file handle when recursing into + // sub-folders... eventually we will run out, though, with very + // deep hierarchy. + entry.Unset(); + if (_CheckBookmarkExists(subBirectory, bookmarkName, url)) + return true; + } else { + char entryName[B_FILE_NAME_LENGTH]; + if (entry.GetName(entryName) != B_OK || bookmarkName != entryName) + continue; + BString storedURL; + BFile file(&entry, B_READ_ONLY); + if (_ReadURLAttr(file, storedURL)) { + // Just bail if the bookmark already exists + if (storedURL == url) + return true; + } + } + } + return false; +} + + +bool +BrowserWindow::_ReadURLAttr(BFile& bookmarkFile, BString& url) const +{ + return bookmarkFile.InitCheck() == B_OK + && bookmarkFile.ReadAttrString("META:url", &url) == B_OK; +} + + +void +BrowserWindow::_AddBookmarkURLsRecursively(BDirectory& directory, + BMessage* message, uint32& addedCount) const +{ + BEntry entry; + while (directory.GetNextEntry(&entry) == B_OK) { + if (entry.IsDirectory()) { + BDirectory subBirectory(&entry); + // At least preserve the entry file handle when recursing into + // sub-folders... eventually we will run out, though, with very + // deep hierarchy. + entry.Unset(); + _AddBookmarkURLsRecursively(subBirectory, message, addedCount); + } else { + BString storedURL; + BFile file(&entry, B_READ_ONLY); + if (_ReadURLAttr(file, storedURL)) { + message->AddString("url", storedURL.String()); + addedCount++; + } + } + } +} + + diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 5def1c05ee..4e6cac811c 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -36,6 +36,8 @@ class BButton; class BCheckBox; +class BDirectory; +class BFile; class BLayoutItem; class BMenu; class BPath; @@ -123,6 +125,15 @@ private: status_t _BookmarkPath(BPath& path) const; void _CreateBookmark(); void _ShowBookmarks(); + bool _CheckBookmarkExists(BDirectory& directory, + const BString& fileName, + const BString& url) const; + bool _ReadURLAttr(BFile& bookmarkFile, + BString& url) const; + void _AddBookmarkURLsRecursively( + BDirectory& directory, + BMessage* message, + uint32& addedCount) const; private: BMenu* fGoMenu; From 193f6b806fc39c45f5760fa3918b01b79e8796fa Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 17 Mar 2010 19:37:15 +0000 Subject: [PATCH 165/349] Small cleanup. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@321 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/support/FontSelectionView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/support/FontSelectionView.cpp b/src/apps/webpositive/support/FontSelectionView.cpp index 038f0cdacb..24fcd248fb 100644 --- a/src/apps/webpositive/support/FontSelectionView.cpp +++ b/src/apps/webpositive/support/FontSelectionView.cpp @@ -77,11 +77,11 @@ FontSelectionView::FontSelectionView(const char* name, const char* label, fPreviewText = new BStringView("preview text", TR_CMT("The quick brown fox jumps over the lazy dog.","Don't translate this literally ! Use a phrase showing all chars from A to Z.")); - fPreviewText->SetFont(&fCurrentFont); fPreviewText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED)); fPreviewText->SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 1.65)); fPreviewText->SetAlignment(B_ALIGN_RIGHT); + _UpdateFontPreview(); } From e4b86f6ceb381edbf9f8358e7d248f97ab427785 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 17 Mar 2010 19:38:23 +0000 Subject: [PATCH 166/349] * Improved API for more convenience. * Fixed comparison operators. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@322 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/support/DateTime.cpp | 178 +++++++++++++++++----- src/apps/webpositive/support/DateTime.h | 34 +++-- 2 files changed, 164 insertions(+), 48 deletions(-) diff --git a/src/apps/webpositive/support/DateTime.cpp b/src/apps/webpositive/support/DateTime.cpp index 7818dc36c2..19030db00a 100644 --- a/src/apps/webpositive/support/DateTime.cpp +++ b/src/apps/webpositive/support/DateTime.cpp @@ -38,7 +38,18 @@ const bigtime_t kMicrosecondsPerDay = 86400000000LL; but be aware IsValid() will return false. */ BTime::BTime() - : fMicroseconds(-1) + : + fMicroseconds(-1) +{ +} + + +/*! + Constructs a new BTime object as a copy of \c other. +*/ +BTime::BTime(const BTime& other) + : + fMicroseconds(other.fMicroseconds) { } @@ -51,7 +62,8 @@ BTime::BTime() specified time is invalid, the time is not set and IsValid() returns false. */ BTime::BTime(int32 hour, int32 minute, int32 second, int32 microsecond) - : fMicroseconds(-1) + : + fMicroseconds(-1) { _SetTime(hour, minute, second, microsecond); } @@ -61,7 +73,8 @@ BTime::BTime(int32 hour, int32 minute, int32 second, int32 microsecond) Constructs a new BTime object from the provided BMessage archive. */ BTime::BTime(const BMessage* archive) - : fMicroseconds(-1) + : + fMicroseconds(-1) { if (archive == NULL) return; @@ -192,10 +205,11 @@ BTime::SetTime(int32 hour, int32 minute, int32 second, int32 microsecond) Adds \c hours to the current time. If the passed value is negativ it will become earlier. Note: The time will wrap if it passes midnight. */ -void +BTime& BTime::AddHours(int32 hours) { - _AddMicroseconds(bigtime_t(hours % kHoursPerDay) * kMicrosecondsPerHour); + return _AddMicroseconds(bigtime_t(hours % kHoursPerDay) + * kMicrosecondsPerHour); } @@ -203,11 +217,11 @@ BTime::AddHours(int32 hours) Adds \c minutes to the current time. If the passed value is negativ it will become earlier. Note: The time will wrap if it passes midnight. */ -void +BTime& BTime::AddMinutes(int32 minutes) { - _AddMicroseconds(bigtime_t(minutes % kMinutesPerDay) * - kMicrosecondsPerMinute); + return _AddMicroseconds(bigtime_t(minutes % kMinutesPerDay) + * kMicrosecondsPerMinute); } @@ -215,11 +229,11 @@ BTime::AddMinutes(int32 minutes) Adds \c seconds to the current time. If the passed value is negativ it will become earlier. Note: The time will wrap if it passes midnight. */ -void +BTime& BTime::AddSeconds(int32 seconds) { - _AddMicroseconds(bigtime_t(seconds % kSecondsPerDay) * - kMicrosecondsPerSecond); + return _AddMicroseconds(bigtime_t(seconds % kSecondsPerDay) + * kMicrosecondsPerSecond); } @@ -227,10 +241,11 @@ BTime::AddSeconds(int32 seconds) Adds \c milliseconds to the current time. If the passed value is negativ it will become earlier. Note: The time will wrap if it passes midnight. */ -void +BTime& BTime::AddMilliseconds(int32 milliseconds) { - _AddMicroseconds(bigtime_t(milliseconds % kMillisecondsPerDay) * 1000); + return _AddMicroseconds(bigtime_t(milliseconds % kMillisecondsPerDay) + * 1000); } @@ -238,10 +253,10 @@ BTime::AddMilliseconds(int32 milliseconds) Adds \c microseconds to the current time. If the passed value is negativ it will become earlier. Note: The time will wrap if it passes midnight. */ -void +BTime& BTime::AddMicroseconds(int32 microseconds) { - _AddMicroseconds(microseconds); + return _AddMicroseconds(microseconds); } @@ -396,7 +411,7 @@ BTime::operator>=(const BTime& time) const } -void +BTime& BTime::_AddMicroseconds(bigtime_t microseconds) { bigtime_t count = 0; @@ -405,6 +420,7 @@ BTime::_AddMicroseconds(bigtime_t microseconds) kMicrosecondsPerDay; } fMicroseconds = (_Microseconds() + microseconds + count) % kMicrosecondsPerDay; + return *this; } @@ -432,9 +448,22 @@ BTime::_SetTime(bigtime_t hour, bigtime_t minute, bigtime_t second, Constructs a new BDate object. IsValid() will return false. */ BDate::BDate() - : fDay(-1), - fYear(0), - fMonth(-1) + : + fDay(-1), + fYear(0), + fMonth(-1) +{ +} + + +/*! + Constructs a new BDate object as a copy of \c other. +*/ +BDate::BDate(const BDate& other) + : + fDay(other.fDay), + fYear(other.fYear), + fMonth(other.fMonth) { } @@ -458,9 +487,10 @@ BDate::BDate(int32 year, int32 month, int32 day) Constructs a new BDate object from the provided archive. */ BDate::BDate(const BMessage* archive) - : fDay(-1), - fYear(0), - fMonth(-1) + : + fDay(-1), + fYear(0), + fMonth(-1) { if (archive == NULL) return; @@ -863,13 +893,23 @@ BDate::DaysInMonth() const } +/*! + Returns the short day name of this object. +*/ +BString +BDate::ShortDayName() const +{ + return ShortDayName(DayOfWeek()); +} + + /*! Returns the short day name in case of an valid day, otherwise an empty string. The passed \c day must be in the range of 1 to 7 while 1 stands for monday. */ -BString -BDate::ShortDayName(int32 day) const +/*static*/ BString +BDate::ShortDayName(int32 day) { if (day < 1 || day > 7) return BString(); @@ -885,12 +925,22 @@ BDate::ShortDayName(int32 day) const } +/*! + Returns the short month name of this object. +*/ +BString +BDate::ShortMonthName() const +{ + return ShortMonthName(Month()); +} + + /*! Returns the short month name in case of an valid month, otherwise an empty string. The passed \c month must be in the range of 1 to 12. */ -BString -BDate::ShortMonthName(int32 month) const +/*static*/ BString +BDate::ShortMonthName(int32 month) { if (month < 1 || month > 12) return BString(); @@ -906,13 +956,23 @@ BDate::ShortMonthName(int32 month) const } +/*! + Returns the long day name of this object's week day. +*/ +BString +BDate::LongDayName() const +{ + return LongDayName(DayOfWeek()); +} + + /*! Returns the long day name in case of an valid day, otherwise an empty string. The passed \c day must be in the range of 1 to 7 while 1 stands for monday. */ -BString -BDate::LongDayName(int32 day) const +/*static*/ BString +BDate::LongDayName(int32 day) { if (day < 1 || day > 7) return BString(); @@ -928,12 +988,22 @@ BDate::LongDayName(int32 day) const } +/*! + Returns the long month name of this object's month. +*/ +BString +BDate::LongMonthName() const +{ + return LongMonthName(Month()); +} + + /*! Returns the long month name in case of an valid month, otherwise an empty string. The passed \c month must be in the range of 1 to 12. */ -BString -BDate::LongMonthName(int32 month) const +/*static*/ BString +BDate::LongMonthName(int32 month) { if (month < 1 || month > 12) return BString(); @@ -1218,7 +1288,17 @@ BDateTime::SetDateTime(const BDate& date, const BTime& time) /*! Returns the current date of this object. */ -BDate +BDate& +BDateTime::Date() +{ + return fDate; +} + + +/*! + Returns the current date of this object. +*/ +const BDate& BDateTime::Date() const { return fDate; @@ -1238,7 +1318,17 @@ BDateTime::SetDate(const BDate& date) /*! Returns the current time of this object. */ -BTime +BTime& +BDateTime::Time() +{ + return fTime; +} + + +/*! + Returns the current time of this object. +*/ +const BTime& BDateTime::Time() const { return fTime; @@ -1328,7 +1418,11 @@ BDateTime::operator==(const BDateTime& dateTime) const bool BDateTime::operator<(const BDateTime& dateTime) const { - return fTime < dateTime.fTime && fDate < dateTime.fDate; + if (fDate < dateTime.fDate) + return true; + if (fDate == dateTime.fDate) + return fTime < dateTime.fTime; + return false; } @@ -1339,7 +1433,11 @@ BDateTime::operator<(const BDateTime& dateTime) const bool BDateTime::operator<=(const BDateTime& dateTime) const { - return fTime <= dateTime.fTime && fDate <= dateTime.fDate; + if (fDate < dateTime.fDate) + return true; + if (fDate == dateTime.fDate) + return fTime <= dateTime.fTime; + return false; } @@ -1349,7 +1447,11 @@ BDateTime::operator<=(const BDateTime& dateTime) const bool BDateTime::operator>(const BDateTime& dateTime) const { - return fTime > dateTime.fTime && fDate > dateTime.fDate; + if (fDate > dateTime.fDate) + return true; + if (fDate == dateTime.fDate) + return fTime > dateTime.fTime; + return false; } @@ -1360,7 +1462,11 @@ BDateTime::operator>(const BDateTime& dateTime) const bool BDateTime::operator>=(const BDateTime& dateTime) const { - return fTime >= dateTime.fTime && fDate >= dateTime.fDate; + if (fDate > dateTime.fDate) + return true; + if (fDate == dateTime.fDate) + return fTime >= dateTime.fTime; + return false; } diff --git a/src/apps/webpositive/support/DateTime.h b/src/apps/webpositive/support/DateTime.h index fe92d86745..93f76399d6 100644 --- a/src/apps/webpositive/support/DateTime.h +++ b/src/apps/webpositive/support/DateTime.h @@ -33,6 +33,7 @@ enum diff_type { class BTime { public: BTime(); + BTime(const BTime& other); BTime(int32 hour, int32 minute, int32 second, int32 microsecond = 0); BTime(const BMessage* archive); @@ -52,11 +53,11 @@ public: bool SetTime(int32 hour, int32 minute, int32 second, int32 microsecond = 0); - void AddHours(int32 hours); - void AddMinutes(int32 minutes); - void AddSeconds(int32 seconds); - void AddMilliseconds(int32 milliseconds); - void AddMicroseconds(int32 microseconds); + BTime& AddHours(int32 hours); + BTime& AddMinutes(int32 minutes); + BTime& AddSeconds(int32 seconds); + BTime& AddMilliseconds(int32 milliseconds); + BTime& AddMicroseconds(int32 microseconds); int32 Hour() const; int32 Minute() const; @@ -77,7 +78,7 @@ public: private: bigtime_t _Microseconds() const; - void _AddMicroseconds(bigtime_t microseconds); + BTime& _AddMicroseconds(bigtime_t microseconds); bool _SetTime(bigtime_t hour, bigtime_t minute, bigtime_t second, bigtime_t microsecond); @@ -89,6 +90,7 @@ private: class BDate { public: BDate(); + BDate(const BDate& other); BDate(int32 year, int32 month, int32 day); BDate(const BMessage* archive); ~BDate(); @@ -126,11 +128,17 @@ public: int32 DaysInYear() const; int32 DaysInMonth() const; - BString ShortDayName(int32 day) const; - BString ShortMonthName(int32 month) const; + BString ShortDayName() const; + static BString ShortDayName(int32 day); - BString LongDayName(int32 day) const; - BString LongMonthName(int32 month) const; + BString ShortMonthName() const; + static BString ShortMonthName(int32 month); + + BString LongDayName() const; + static BString LongDayName(int32 day); + + BString LongMonthName() const; + static BString LongMonthName(int32 month); int32 DateToJulianDay() const; static BDate JulianDayToDate(int32 julianDay); @@ -171,10 +179,12 @@ public: static BDateTime CurrentDateTime(time_type type); void SetDateTime(const BDate &date, const BTime &time); - BDate Date() const; + BDate& Date(); + const BDate& Date() const; void SetDate(const BDate &date); - BTime Time() const; + BTime& Time(); + const BTime& Time() const; void SetTime(const BTime &time); int32 Time_t() const; From 2e8e305ebc16cfbf553f4b72f14255615ffb43be Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 17 Mar 2010 19:39:46 +0000 Subject: [PATCH 167/349] * Fixed bug that would save the history for each item in the history when loading the history from disk... * Don't touch items when loading them from disk, messing up their visited time. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@323 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowsingHistory.cpp | 56 ++++++++++++++---------- src/apps/webpositive/BrowsingHistory.h | 1 + 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/src/apps/webpositive/BrowsingHistory.cpp b/src/apps/webpositive/BrowsingHistory.cpp index e5a7e8afe4..c93482e088 100644 --- a/src/apps/webpositive/BrowsingHistory.cpp +++ b/src/apps/webpositive/BrowsingHistory.cpp @@ -154,7 +154,7 @@ BrowsingHistory::BrowsingHistory() BMessage historyItemArchive; for (int32 i = 0; settingsArchive.FindMessage("history item", i, &historyItemArchive) == B_OK; i++) { - addItem(BrowsingHistoryItem(&historyItemArchive)); + privateAddItem(BrowsingHistoryItem(&historyItemArchive), false); historyItemArchive.MakeEmpty(); } } @@ -177,28 +177,7 @@ bool BrowsingHistory::addItem(const BrowsingHistoryItem& item) { BAutolock _(this); - int32 count = countItems(); - int32 insertionIndex = count; - for (int32 i = 0; i < count; i++) { - BrowsingHistoryItem* existingItem = reinterpret_cast( - m_historyItems.ItemAtFast(i)); - if (item.url() == existingItem->url()) { - existingItem->invoked(); - return true; - } - if (item < *existingItem) - insertionIndex = i; - } - BrowsingHistoryItem* newItem = new(std::nothrow) BrowsingHistoryItem(item); - if (!newItem || !m_historyItems.AddItem(newItem, insertionIndex)) { - delete newItem; - return false; - } - - newItem->invoked(); - saveSettings(); - - return true; + return privateAddItem(item, false); } int32 BrowsingHistory::BrowsingHistory::countItems() const @@ -238,6 +217,37 @@ void BrowsingHistory::privateClear() m_historyItems.MakeEmpty(); } +bool BrowsingHistory::privateAddItem(const BrowsingHistoryItem& item, bool internal) +{ + int32 count = countItems(); + int32 insertionIndex = count; + for (int32 i = 0; i < count; i++) { + BrowsingHistoryItem* existingItem = reinterpret_cast( + m_historyItems.ItemAtFast(i)); + if (item.url() == existingItem->url()) { + if (!internal) { + existingItem->invoked(); + saveSettings(); + } + return true; + } + if (item < *existingItem) + insertionIndex = i; + } + BrowsingHistoryItem* newItem = new(std::nothrow) BrowsingHistoryItem(item); + if (!newItem || !m_historyItems.AddItem(newItem, insertionIndex)) { + delete newItem; + return false; + } + + if (!internal) { + newItem->invoked(); + saveSettings(); + } + + return true; +} + // #pragma mark - private void BrowsingHistory::saveSettings() diff --git a/src/apps/webpositive/BrowsingHistory.h b/src/apps/webpositive/BrowsingHistory.h index 00e4f3a5e7..e25dee27ed 100644 --- a/src/apps/webpositive/BrowsingHistory.h +++ b/src/apps/webpositive/BrowsingHistory.h @@ -79,6 +79,7 @@ private: BrowsingHistory(); virtual ~BrowsingHistory(); void privateClear(); + bool privateAddItem(const BrowsingHistoryItem& item, bool invoke); void saveSettings(); bool openSettingsFile(BFile& file, uint32 mode); From e405ff6af725ad922878842ea679edbabaa42bd7 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 17 Mar 2010 19:40:58 +0000 Subject: [PATCH 168/349] * Improved the Go menu by sorting items into sub-menus for each day, five days into the past, and the rest of them into "Earlier". * Moved the "Clear history" item to the top. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@324 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 83 ++++++++++++++++++++++---- 1 file changed, 73 insertions(+), 10 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 0a5d2f6940..a0e104ca7c 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -683,6 +683,16 @@ BrowserWindow::QuitRequested() } +static void +addOrDeleteMenu(BMenu* menu, BMenu* toMenu) +{ + if (menu->CountItems() > 0) + toMenu->AddItem(menu); + else + delete menu; +} + + void BrowserWindow::MenusBeginning() { @@ -695,25 +705,78 @@ BrowserWindow::MenusBeginning() return; int32 count = history->countItems(); + BMenuItem* clearHistoryItem = new BMenuItem("Clear history", + new BMessage(CLEAR_HISTORY)); + clearHistoryItem->SetEnabled(count > 0); + fGoMenu->AddItem(clearHistoryItem); + if (count == 0) { + history->Unlock(); + return; + } + fGoMenu->AddSeparatorItem(); + + BDateTime todayStart = BDateTime::CurrentDateTime(B_LOCAL_TIME); + todayStart.SetTime(BTime(0, 0, 0)); + + BDateTime oneDayAgoStart = todayStart; + oneDayAgoStart.Date().AddDays(-1); + + BDateTime twoDaysAgoStart = oneDayAgoStart; + twoDaysAgoStart.Date().AddDays(-1); + + BDateTime threeDaysAgoStart = twoDaysAgoStart; + threeDaysAgoStart.Date().AddDays(-1); + + BDateTime fourDaysAgoStart = threeDaysAgoStart; + fourDaysAgoStart.Date().AddDays(-1); + + BDateTime fiveDaysAgoStart = fourDaysAgoStart; + fiveDaysAgoStart.Date().AddDays(-1); + + BMenu* todayMenu = new BMenu("Today"); + BMenu* yesterdayMenu = new BMenu("Yesterday"); + BMenu* twoDaysAgoMenu = new BMenu( + twoDaysAgoStart.Date().LongDayName().String()); + BMenu* threeDaysAgoMenu = new BMenu( + threeDaysAgoStart.Date().LongDayName().String()); + BMenu* fourDaysAgoMenu = new BMenu( + fourDaysAgoStart.Date().LongDayName().String()); + BMenu* fiveDaysAgoMenu = new BMenu( + fiveDaysAgoStart.Date().LongDayName().String()); + BMenu* earlierMenu = new BMenu("Earlier"); + for (int32 i = 0; i < count; i++) { BrowsingHistoryItem historyItem = history->historyItemAt(i); BMessage* message = new BMessage(GOTO_URL); message->AddString("url", historyItem.url().String()); - // TODO: More sophisticated menu structure... sorted by days/weeks... + BString truncatedUrl(historyItem.url()); be_plain_font->TruncateString(&truncatedUrl, B_TRUNCATE_END, 480); menuItem = new BMenuItem(truncatedUrl, message); - fGoMenu->AddItem(menuItem); + + if (historyItem.dateTime() < fiveDaysAgoStart) + earlierMenu->AddItem(menuItem); + else if (historyItem.dateTime() < fourDaysAgoStart) + fiveDaysAgoMenu->AddItem(menuItem); + else if (historyItem.dateTime() < threeDaysAgoStart) + fourDaysAgoMenu->AddItem(menuItem); + else if (historyItem.dateTime() < twoDaysAgoStart) + threeDaysAgoMenu->AddItem(menuItem); + else if (historyItem.dateTime() < oneDayAgoStart) + twoDaysAgoMenu->AddItem(menuItem); + else if (historyItem.dateTime() < todayStart) + yesterdayMenu->AddItem(menuItem); + else + todayMenu->AddItem(menuItem); } - - - if (fGoMenu->CountItems() > 3) { - fGoMenu->AddSeparatorItem(); - fGoMenu->AddItem(new BMenuItem("Clear history", - new BMessage(CLEAR_HISTORY))); - } - history->Unlock(); + + addOrDeleteMenu(todayMenu, fGoMenu); + addOrDeleteMenu(yesterdayMenu, fGoMenu); + addOrDeleteMenu(twoDaysAgoMenu, fGoMenu); + addOrDeleteMenu(fourDaysAgoMenu, fGoMenu); + addOrDeleteMenu(fiveDaysAgoMenu, fGoMenu); + addOrDeleteMenu(earlierMenu, fGoMenu); } From 7cbf0e1d7e1a9a9f0cc28151bb9ed7e0c09eff21 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 17 Mar 2010 19:44:34 +0000 Subject: [PATCH 169/349] Fix the history restoration for real... duh! git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@325 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowsingHistory.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/BrowsingHistory.cpp b/src/apps/webpositive/BrowsingHistory.cpp index c93482e088..cadb86e5bb 100644 --- a/src/apps/webpositive/BrowsingHistory.cpp +++ b/src/apps/webpositive/BrowsingHistory.cpp @@ -154,7 +154,7 @@ BrowsingHistory::BrowsingHistory() BMessage historyItemArchive; for (int32 i = 0; settingsArchive.FindMessage("history item", i, &historyItemArchive) == B_OK; i++) { - privateAddItem(BrowsingHistoryItem(&historyItemArchive), false); + privateAddItem(BrowsingHistoryItem(&historyItemArchive), true); historyItemArchive.MakeEmpty(); } } @@ -206,6 +206,8 @@ void BrowsingHistory::clear() saveSettings(); } +// #pragma mark - private + void BrowsingHistory::privateClear() { int32 count = countItems(); @@ -248,8 +250,6 @@ bool BrowsingHistory::privateAddItem(const BrowsingHistoryItem& item, bool inter return true; } -// #pragma mark - private - void BrowsingHistory::saveSettings() { BFile settingsFile; From f1dcf19d1d35e7e8695ca9beaa52e2dcc9fcb510 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 19 Mar 2010 11:35:23 +0000 Subject: [PATCH 170/349] Sort items in the Go menu into submenus per base URL. This further reduces the clutter there. I'm quite happy now, but one issue could be that the Go menu is not stable: Any URL will always appear only once, somewhere in the hierarchy, depending on when you last visited it. The BrowsingHistory could be changed, though, feedback welcome. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@330 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 59 +++++++++++++++++++++----- 1 file changed, 48 insertions(+), 11 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index a0e104ca7c..33469bd5b0 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -131,6 +131,17 @@ private: }; +static BString +baseURL(const BString string) +{ + int32 baseURLStart = string.FindFirst("://") + 3; + int32 baseURLEnd = string.FindFirst("/", baseURLStart + 1); + BString result; + result.SetTo(string.String() + baseURLStart, baseURLEnd - baseURLStart); + return result; +} + + class BrowsingHistoryChoiceModel : public BAutoCompleter::ChoiceModel { virtual void FetchChoicesFor(const BString& pattern) { @@ -161,10 +172,7 @@ class BrowsingHistoryChoiceModel : public BAutoCompleter::ChoiceModel { priority--; } else priority = INT_MAX; - int32 baseURLStart = choiceText.FindFirst("://") + 3; - int32 baseURLEnd = choiceText.FindFirst("/", baseURLStart + 1); - lastBaseURL.SetTo(choiceText.String() + baseURLStart, - baseURLEnd - baseURLStart); + lastBaseURL = baseURL(choiceText); fChoices.AddItem(new URLChoice(choiceText, choiceText, matchPos, pattern.Length(), priority)); } @@ -683,6 +691,35 @@ BrowserWindow::QuitRequested() } +static void +addItemToMenuOrSubmenu(BMenu* menu, BMenuItem* newItem) +{ + BString baseURLLabel = baseURL(BString(newItem->Label())); + for (int32 i = menu->CountItems() - 1; i >= 0; i--) { + BMenuItem* item = menu->ItemAt(i); + BString label = item->Label(); + if (label.FindFirst(baseURLLabel) >= 0) { + if (item->Submenu()) { + // Submenu was already added in previous iteration. + item->Submenu()->AddItem(newItem); + return; + } else { + menu->RemoveItem(item); + BMenu* subMenu = new BMenu(baseURLLabel.String()); + subMenu->AddItem(item); + subMenu->AddItem(newItem); + // Add common submenu for this base URL, clickable. + BMessage* message = new BMessage(GOTO_URL); + message->AddString("url", baseURLLabel.String()); + menu->AddItem(new BMenuItem(subMenu, message)); + return; + } + } + } + menu->AddItem(newItem); +} + + static void addOrDeleteMenu(BMenu* menu, BMenu* toMenu) { @@ -755,19 +792,19 @@ BrowserWindow::MenusBeginning() menuItem = new BMenuItem(truncatedUrl, message); if (historyItem.dateTime() < fiveDaysAgoStart) - earlierMenu->AddItem(menuItem); + addItemToMenuOrSubmenu(earlierMenu, menuItem); else if (historyItem.dateTime() < fourDaysAgoStart) - fiveDaysAgoMenu->AddItem(menuItem); + addItemToMenuOrSubmenu(fiveDaysAgoMenu, menuItem); else if (historyItem.dateTime() < threeDaysAgoStart) - fourDaysAgoMenu->AddItem(menuItem); + addItemToMenuOrSubmenu(fourDaysAgoMenu, menuItem); else if (historyItem.dateTime() < twoDaysAgoStart) - threeDaysAgoMenu->AddItem(menuItem); + addItemToMenuOrSubmenu(threeDaysAgoMenu, menuItem); else if (historyItem.dateTime() < oneDayAgoStart) - twoDaysAgoMenu->AddItem(menuItem); + addItemToMenuOrSubmenu(twoDaysAgoMenu, menuItem); else if (historyItem.dateTime() < todayStart) - yesterdayMenu->AddItem(menuItem); + addItemToMenuOrSubmenu(yesterdayMenu, menuItem); else - todayMenu->AddItem(menuItem); + addItemToMenuOrSubmenu(todayMenu, menuItem); } history->Unlock(); From 0fc94bdcbc50b4122603ac653a61f8349bb5e0d3 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 19 Mar 2010 11:36:36 +0000 Subject: [PATCH 171/349] At the common submenu at the location where the item was removed. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@331 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 33469bd5b0..55cac2f605 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -711,7 +711,7 @@ addItemToMenuOrSubmenu(BMenu* menu, BMenuItem* newItem) // Add common submenu for this base URL, clickable. BMessage* message = new BMessage(GOTO_URL); message->AddString("url", baseURLLabel.String()); - menu->AddItem(new BMenuItem(subMenu, message)); + menu->AddItem(new BMenuItem(subMenu, message), i); return; } } From cb8b9e4ffd504ced209fb21ee0c4c577f3ae3554 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 19 Mar 2010 13:03:26 +0000 Subject: [PATCH 172/349] Some notifications are now channeled through BWebPage, the loading progress and status. This allows the browser to set those properties to the current page when switching pages. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@333 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 55cac2f605..ad6a19b6e1 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -832,7 +832,7 @@ BrowserWindow::CreateNewTab(const BString& url, bool select, BWebView* webView) if (select) { fTabManager->SelectTab(fTabManager->CountTabs() - 1); SetCurrentWebView(webView); - NavigationCapabilitiesChanged(false, false, false, webView); + webView->WebPage()->ResendNotifications(); if (fURLTextControl) { fURLTextControl->SetText(url.String()); fURLTextControl->MakeFocus(true); @@ -880,7 +880,7 @@ BrowserWindow::LoadNegotiating(const BString& url, BWebView* view) { BString status("Requesting: "); status << url; - StatusChanged(status, view); + view->WebPage()->SetStatusMessage(status); } @@ -896,7 +896,7 @@ BrowserWindow::LoadCommitted(const BString& url, BWebView* view) BString status("Loading: "); status << url; - StatusChanged(status, view); + view->WebPage()->SetStatusMessage(status); } @@ -909,6 +909,8 @@ BrowserWindow::LoadProgress(float progress, BWebView* view) if (fLoadingProgressBar) { if (progress < 100 && fLoadingProgressBar->IsHidden()) fLoadingProgressBar->Show(); + else if (progress == 100 && !fLoadingProgressBar->IsHidden()) + fLoadingProgressBar->Hide(); fLoadingProgressBar->SetTo(progress); } } @@ -922,7 +924,7 @@ BrowserWindow::LoadFailed(const BString& url, BWebView* view) BString status(url); status << " failed."; - StatusChanged(status, view); + view->WebPage()->SetStatusMessage(status); if (fLoadingProgressBar && !fLoadingProgressBar->IsHidden()) fLoadingProgressBar->Hide(); } @@ -936,7 +938,7 @@ BrowserWindow::LoadFinished(const BString& url, BWebView* view) BString status(url); status << " finished."; - StatusChanged(status, view); + view->WebPage()->SetStatusMessage(status); if (fLoadingProgressBar && !fLoadingProgressBar->IsHidden()) fLoadingProgressBar->Hide(); From e91fdd924a9e7b92f9254ec3082d2f6e5485875e Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 20 Mar 2010 17:15:42 +0000 Subject: [PATCH 173/349] * Converted BrowsingHistory.h/cpp to Haiku coding style. * Probably fixed a race condition on program launch. If you started typing into the URL field really fast, the static instance in BrowsingHistory::DefaultInstance() could be created by two threads, which may be responsible for the "recursive init" exception that GCC throws in this situation. It's not easy to trigger, maybe this was it. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@335 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 3 +- src/apps/webpositive/BrowserWindow.cpp | 38 +-- src/apps/webpositive/BrowsingHistory.cpp | 368 ++++++++++++++--------- src/apps/webpositive/BrowsingHistory.h | 88 +++--- 4 files changed, 292 insertions(+), 205 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index e4b4c10d15..7bbb63c633 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -169,7 +169,8 @@ BrowserApp::MessageReceived(BMessage* message) { switch (message->what) { case PRELOAD_BROWSING_HISTORY: - BrowsingHistory::defaultInstance(); + // Accessing the default instance will load the history from disk. + BrowsingHistory::DefaultInstance(); break; case B_SILENT_RELAUNCH: _CreateNewPage(""); diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index ad6a19b6e1..0c60ca1f91 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -153,17 +153,17 @@ class BrowsingHistoryChoiceModel : public BAutoCompleter::ChoiceModel { fChoices.MakeEmpty(); // Search through BrowsingHistory for any matches. - BrowsingHistory* history = BrowsingHistory::defaultInstance(); + BrowsingHistory* history = BrowsingHistory::DefaultInstance(); if (!history->Lock()) return; BString lastBaseURL; int32 priority = INT_MAX; - count = history->countItems(); + count = history->CountItems(); for (int32 i = 0; i < count; i++) { - BrowsingHistoryItem item = history->historyItemAt(i); - const BString& choiceText = item.url(); + BrowsingHistoryItem item = history->HistoryItemAt(i); + const BString& choiceText = item.URL(); int32 matchPos = choiceText.IFindFirst(pattern); if (matchPos < 0) continue; @@ -499,13 +499,13 @@ BrowserWindow::MessageReceived(BMessage* message) break; case CLEAR_HISTORY: { - BrowsingHistory* history = BrowsingHistory::defaultInstance(); - if (history->countItems() == 0) + BrowsingHistory* history = BrowsingHistory::DefaultInstance(); + if (history->CountItems() == 0) break; BAlert* alert = new BAlert("Confirmation", "Do you really want to " "clear the browsing history?", "Clear", "Cancel"); if (alert->Go() == 0) - history->clear(); + history->Clear(); break; } @@ -737,11 +737,11 @@ BrowserWindow::MenusBeginning() while ((menuItem = fGoMenu->RemoveItem(0L))) delete menuItem; - BrowsingHistory* history = BrowsingHistory::defaultInstance(); + BrowsingHistory* history = BrowsingHistory::DefaultInstance(); if (!history->Lock()) return; - int32 count = history->countItems(); + int32 count = history->CountItems(); BMenuItem* clearHistoryItem = new BMenuItem("Clear history", new BMessage(CLEAR_HISTORY)); clearHistoryItem->SetEnabled(count > 0); @@ -783,25 +783,25 @@ BrowserWindow::MenusBeginning() BMenu* earlierMenu = new BMenu("Earlier"); for (int32 i = 0; i < count; i++) { - BrowsingHistoryItem historyItem = history->historyItemAt(i); + BrowsingHistoryItem historyItem = history->HistoryItemAt(i); BMessage* message = new BMessage(GOTO_URL); - message->AddString("url", historyItem.url().String()); + message->AddString("url", historyItem.URL().String()); - BString truncatedUrl(historyItem.url()); + BString truncatedUrl(historyItem.URL()); be_plain_font->TruncateString(&truncatedUrl, B_TRUNCATE_END, 480); menuItem = new BMenuItem(truncatedUrl, message); - if (historyItem.dateTime() < fiveDaysAgoStart) + if (historyItem.DateTime() < fiveDaysAgoStart) addItemToMenuOrSubmenu(earlierMenu, menuItem); - else if (historyItem.dateTime() < fourDaysAgoStart) + else if (historyItem.DateTime() < fourDaysAgoStart) addItemToMenuOrSubmenu(fiveDaysAgoMenu, menuItem); - else if (historyItem.dateTime() < threeDaysAgoStart) + else if (historyItem.DateTime() < threeDaysAgoStart) addItemToMenuOrSubmenu(fourDaysAgoMenu, menuItem); - else if (historyItem.dateTime() < twoDaysAgoStart) + else if (historyItem.DateTime() < twoDaysAgoStart) addItemToMenuOrSubmenu(threeDaysAgoMenu, menuItem); - else if (historyItem.dateTime() < oneDayAgoStart) + else if (historyItem.DateTime() < oneDayAgoStart) addItemToMenuOrSubmenu(twoDaysAgoMenu, menuItem); - else if (historyItem.dateTime() < todayStart) + else if (historyItem.DateTime() < todayStart) addItemToMenuOrSubmenu(yesterdayMenu, menuItem); else addItemToMenuOrSubmenu(todayMenu, menuItem); @@ -1048,7 +1048,7 @@ BrowserWindow::NavigationCapabilitiesChanged(bool canGoBackward, void BrowserWindow::UpdateGlobalHistory(const BString& url) { - BrowsingHistory::defaultInstance()->addItem(BrowsingHistoryItem(url)); + BrowsingHistory::DefaultInstance()->AddItem(BrowsingHistoryItem(url)); } diff --git a/src/apps/webpositive/BrowsingHistory.cpp b/src/apps/webpositive/BrowsingHistory.cpp index cadb86e5bb..f89d4bf77f 100644 --- a/src/apps/webpositive/BrowsingHistory.cpp +++ b/src/apps/webpositive/BrowsingHistory.cpp @@ -25,251 +25,321 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" #include "BrowsingHistory.h" -#include "BrowserApp.h" +#include +#include + #include #include #include #include #include #include -#include -#include + +#include "BrowserApp.h" BrowsingHistoryItem::BrowsingHistoryItem(const BString& url) - : m_url(url) - , m_dateTime(BDateTime::CurrentDateTime(B_LOCAL_TIME)) - , m_invokationCount(0) + : + fURL(url), + fDateTime(BDateTime::CurrentDateTime(B_LOCAL_TIME)), + fInvokationCount(0) { } + BrowsingHistoryItem::BrowsingHistoryItem(const BrowsingHistoryItem& other) { *this = other; } + BrowsingHistoryItem::BrowsingHistoryItem(const BMessage* archive) { if (!archive) - return; + return; BMessage dateTimeArchive; if (archive->FindMessage("date time", &dateTimeArchive) == B_OK) - m_dateTime = BDateTime(&dateTimeArchive); - archive->FindString("url", &m_url); - archive->FindUInt32("invokations", &m_invokationCount); + fDateTime = BDateTime(&dateTimeArchive); + archive->FindString("url", &fURL); + archive->FindUInt32("invokations", &fInvokationCount); } + BrowsingHistoryItem::~BrowsingHistoryItem() { } -status_t BrowsingHistoryItem::archive(BMessage* archive) const + +status_t +BrowsingHistoryItem::Archive(BMessage* archive) const { if (!archive) - return B_BAD_VALUE; + return B_BAD_VALUE; BMessage dateTimeArchive; - status_t status = m_dateTime.Archive(&dateTimeArchive); + status_t status = fDateTime.Archive(&dateTimeArchive); if (status == B_OK) - status = archive->AddMessage("date time", &dateTimeArchive); + status = archive->AddMessage("date time", &dateTimeArchive); if (status == B_OK) - status = archive->AddString("url", m_url.String()); + status = archive->AddString("url", fURL.String()); if (status == B_OK) - status = archive->AddUInt32("invokations", m_invokationCount); - return status; + status = archive->AddUInt32("invokations", fInvokationCount); + return status; } -BrowsingHistoryItem& BrowsingHistoryItem::operator=(const BrowsingHistoryItem& other) -{ - if (this == &other) - return *this; - m_url = other.m_url; - m_dateTime = other.m_dateTime; - m_invokationCount = other.m_invokationCount; - - return *this; -} - -bool BrowsingHistoryItem::operator==(const BrowsingHistoryItem& other) const +BrowsingHistoryItem& +BrowsingHistoryItem::operator=(const BrowsingHistoryItem& other) { if (this == &other) - return true; + return *this; - return m_url == other.m_url && m_dateTime == other.m_dateTime - && m_invokationCount == other.m_invokationCount; + fURL = other.fURL; + fDateTime = other.fDateTime; + fInvokationCount = other.fInvokationCount; + + return *this; } -bool BrowsingHistoryItem::operator!=(const BrowsingHistoryItem& other) const + +bool +BrowsingHistoryItem::operator==(const BrowsingHistoryItem& other) const +{ + if (this == &other) + return true; + + return fURL == other.fURL && fDateTime == other.fDateTime + && fInvokationCount == other.fInvokationCount; +} + + +bool +BrowsingHistoryItem::operator!=(const BrowsingHistoryItem& other) const { return !(*this == other); } -bool BrowsingHistoryItem::operator<(const BrowsingHistoryItem& other) const + +bool +BrowsingHistoryItem::operator<(const BrowsingHistoryItem& other) const { if (this == &other) - return false; + return false; - return m_dateTime < other.m_dateTime || m_url < other.m_url; + return fDateTime < other.fDateTime || fURL < other.fURL; } -bool BrowsingHistoryItem::operator<=(const BrowsingHistoryItem& other) const + +bool +BrowsingHistoryItem::operator<=(const BrowsingHistoryItem& other) const { return (*this == other) || (*this < other); } -bool BrowsingHistoryItem::operator>(const BrowsingHistoryItem& other) const + +bool +BrowsingHistoryItem::operator>(const BrowsingHistoryItem& other) const { if (this == &other) - return false; + return false; - return m_dateTime > other.m_dateTime || m_url > other.m_url; + return fDateTime > other.fDateTime || fURL > other.fURL; } -bool BrowsingHistoryItem::operator>=(const BrowsingHistoryItem& other) const + +bool +BrowsingHistoryItem::operator>=(const BrowsingHistoryItem& other) const { return (*this == other) || (*this > other); } -void BrowsingHistoryItem::invoked() + +void +BrowsingHistoryItem::Invoked() { // Eventually, we may overflow... - uint32 count = m_invokationCount + 1; - if (count > m_invokationCount) - m_invokationCount = count; - m_dateTime = BDateTime::CurrentDateTime(B_LOCAL_TIME); + uint32 count = fInvokationCount + 1; + if (count > fInvokationCount) + fInvokationCount = count; + fDateTime = BDateTime::CurrentDateTime(B_LOCAL_TIME); } + // #pragma mark - BrowsingHistory + +BrowsingHistory +BrowsingHistory::sDefaultInstance; + + BrowsingHistory::BrowsingHistory() - : BLocker("browsing history") + : + BLocker("browsing history"), + fHistoryItems(64), + fSettingsLoaded(false) { +} + + +BrowsingHistory::~BrowsingHistory() +{ + _SaveSettings(); + _Clear(); +} + + +/*static*/ BrowsingHistory* +BrowsingHistory::DefaultInstance() +{ + if (sDefaultInstance.Lock()) { + sDefaultInstance._LoadSettings(); + sDefaultInstance.Unlock(); + } + return &sDefaultInstance; +} + + +bool +BrowsingHistory::AddItem(const BrowsingHistoryItem& item) +{ + BAutolock _(this); + + return _AddItem(item, false); +} + + +int32 +BrowsingHistory::BrowsingHistory::CountItems() const +{ + BAutolock _(const_cast(this)); + + return fHistoryItems.CountItems(); +} + + +BrowsingHistoryItem +BrowsingHistory::HistoryItemAt(int32 index) const +{ + BAutolock _(const_cast(this)); + + BrowsingHistoryItem* existingItem = reinterpret_cast( + fHistoryItems.ItemAt(index)); + if (!existingItem) + return BrowsingHistoryItem(BString()); + + return BrowsingHistoryItem(*existingItem); +} + + +void +BrowsingHistory::Clear() +{ + BAutolock _(this); + _Clear(); + _SaveSettings(); +} + + +// #pragma mark - private + + +void +BrowsingHistory::_Clear() +{ + int32 count = CountItems(); + for (int32 i = 0; i < count; i++) { + BrowsingHistoryItem* item = reinterpret_cast( + fHistoryItems.ItemAtFast(i)); + delete item; + } + fHistoryItems.MakeEmpty(); +} + + +bool +BrowsingHistory::_AddItem(const BrowsingHistoryItem& item, bool internal) +{ + int32 count = CountItems(); + int32 insertionIndex = count; + for (int32 i = 0; i < count; i++) { + BrowsingHistoryItem* existingItem + = reinterpret_cast( + fHistoryItems.ItemAtFast(i)); + if (item.URL() == existingItem->URL()) { + if (!internal) { + existingItem->Invoked(); + _SaveSettings(); + } + return true; + } + if (item < *existingItem) + insertionIndex = i; + } + BrowsingHistoryItem* newItem = new(std::nothrow) BrowsingHistoryItem(item); + if (!newItem || !fHistoryItems.AddItem(newItem, insertionIndex)) { + delete newItem; + return false; + } + + if (!internal) { + newItem->Invoked(); + _SaveSettings(); + } + + return true; +} + + +void +BrowsingHistory::_LoadSettings() +{ + if (fSettingsLoaded) + return; + + fSettingsLoaded = true; + BFile settingsFile; - if (openSettingsFile(settingsFile, B_READ_ONLY)) { + if (_OpenSettingsFile(settingsFile, B_READ_ONLY)) { BMessage settingsArchive; settingsArchive.Unflatten(&settingsFile); BMessage historyItemArchive; - for (int32 i = 0; settingsArchive.FindMessage("history item", i, &historyItemArchive) == B_OK; i++) { - privateAddItem(BrowsingHistoryItem(&historyItemArchive), true); + for (int32 i = 0; settingsArchive.FindMessage("history item", i, + &historyItemArchive) == B_OK; i++) { + _AddItem(BrowsingHistoryItem(&historyItemArchive), true); historyItemArchive.MakeEmpty(); } } } -BrowsingHistory::~BrowsingHistory() -{ - saveSettings(); - privateClear(); -} -/*static*/ BrowsingHistory* BrowsingHistory::defaultInstance() -{ - static BrowsingHistory defaultInstance; - - return &defaultInstance; -} - -bool BrowsingHistory::addItem(const BrowsingHistoryItem& item) -{ - BAutolock _(this); - - return privateAddItem(item, false); -} - -int32 BrowsingHistory::BrowsingHistory::countItems() const -{ - BAutolock _(const_cast(this)); - - return m_historyItems.CountItems(); -} - -BrowsingHistoryItem BrowsingHistory::historyItemAt(int32 index) const -{ - BAutolock _(const_cast(this)); - - BrowsingHistoryItem* existingItem = reinterpret_cast( - m_historyItems.ItemAt(index)); - if (!existingItem) - return BrowsingHistoryItem(BString()); - - return BrowsingHistoryItem(*existingItem); -} - -void BrowsingHistory::clear() -{ - BAutolock _(this); - privateClear(); - saveSettings(); -} - -// #pragma mark - private - -void BrowsingHistory::privateClear() -{ - int32 count = countItems(); - for (int32 i = 0; i < count; i++) { - BrowsingHistoryItem* item = reinterpret_cast( - m_historyItems.ItemAtFast(i)); - delete item; - } - m_historyItems.MakeEmpty(); -} - -bool BrowsingHistory::privateAddItem(const BrowsingHistoryItem& item, bool internal) -{ - int32 count = countItems(); - int32 insertionIndex = count; - for (int32 i = 0; i < count; i++) { - BrowsingHistoryItem* existingItem = reinterpret_cast( - m_historyItems.ItemAtFast(i)); - if (item.url() == existingItem->url()) { - if (!internal) { - existingItem->invoked(); - saveSettings(); - } - return true; - } - if (item < *existingItem) - insertionIndex = i; - } - BrowsingHistoryItem* newItem = new(std::nothrow) BrowsingHistoryItem(item); - if (!newItem || !m_historyItems.AddItem(newItem, insertionIndex)) { - delete newItem; - return false; - } - - if (!internal) { - newItem->invoked(); - saveSettings(); - } - - return true; -} - -void BrowsingHistory::saveSettings() +void +BrowsingHistory::_SaveSettings() { BFile settingsFile; - if (openSettingsFile(settingsFile, B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) { + if (_OpenSettingsFile(settingsFile, + B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) { BMessage settingsArchive; BMessage historyItemArchive; - int32 count = countItems(); + int32 count = CountItems(); for (int32 i = 0; i < count; i++) { - BrowsingHistoryItem item = historyItemAt(i); - if (item.archive(&historyItemArchive) != B_OK) - break; - if (settingsArchive.AddMessage("history item", &historyItemArchive) != B_OK) - break; + BrowsingHistoryItem item = HistoryItemAt(i); + if (item.Archive(&historyItemArchive) != B_OK) + break; + if (settingsArchive.AddMessage("history item", + &historyItemArchive) != B_OK) { + break; + } historyItemArchive.MakeEmpty(); } settingsArchive.Flatten(&settingsFile); } } -bool BrowsingHistory::openSettingsFile(BFile& file, uint32 mode) + +bool +BrowsingHistory::_OpenSettingsFile(BFile& file, uint32 mode) { BPath path; if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK diff --git a/src/apps/webpositive/BrowsingHistory.h b/src/apps/webpositive/BrowsingHistory.h index e25dee27ed..43ca33ac5c 100644 --- a/src/apps/webpositive/BrowsingHistory.h +++ b/src/apps/webpositive/BrowsingHistory.h @@ -24,9 +24,8 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -#ifndef BrowsingHistory_h -#define BrowsingHistory_h +#ifndef BROWSING_HISTORY_H +#define BROWSING_HISTORY_H #include "DateTime.h" #include @@ -35,58 +34,75 @@ class BFile; class BString; + class BrowsingHistoryItem { public: - BrowsingHistoryItem(const BString& url); - BrowsingHistoryItem(const BrowsingHistoryItem& other); - BrowsingHistoryItem(const BMessage* archive); - ~BrowsingHistoryItem(); + BrowsingHistoryItem(const BString& url); + BrowsingHistoryItem( + const BrowsingHistoryItem& other); + BrowsingHistoryItem(const BMessage* archive); + ~BrowsingHistoryItem(); - status_t archive(BMessage* archive) const; + status_t Archive(BMessage* archive) const; - BrowsingHistoryItem& operator=(const BrowsingHistoryItem& other); + BrowsingHistoryItem& operator=(const BrowsingHistoryItem& other); - bool operator==(const BrowsingHistoryItem& other) const; - bool operator!=(const BrowsingHistoryItem& other) const; - bool operator<(const BrowsingHistoryItem& other) const; - bool operator<=(const BrowsingHistoryItem& other) const; - bool operator>(const BrowsingHistoryItem& other) const; - bool operator>=(const BrowsingHistoryItem& other) const; + bool operator==( + const BrowsingHistoryItem& other) const; + bool operator!=( + const BrowsingHistoryItem& other) const; + bool operator<( + const BrowsingHistoryItem& other) const; + bool operator<=( + const BrowsingHistoryItem& other) const; + bool operator>( + const BrowsingHistoryItem& other) const; + bool operator>=( + const BrowsingHistoryItem& other) const; - const BString& url() const { return m_url; } - const BDateTime& dateTime() const { return m_dateTime; } - uint32 invokationCount() const { return m_invokationCount; } - void invoked(); + const BString& URL() const { return fURL; } + const BDateTime& DateTime() const { return fDateTime; } + uint32 InvokationCount() const { + return fInvokationCount; } + void Invoked(); private: - BString m_url; - BDateTime m_dateTime; - uint32 m_invokationCount; + BString fURL; + BDateTime fDateTime; + uint32 fInvokationCount; }; + class BrowsingHistory : public BLocker { public: - static BrowsingHistory* defaultInstance(); + static BrowsingHistory* DefaultInstance(); - bool addItem(const BrowsingHistoryItem& item); + bool AddItem(const BrowsingHistoryItem& item); - // Should Lock() the object when using these in some loop or so: - int32 countItems() const; - BrowsingHistoryItem historyItemAt(int32 index) const; - void clear(); + // Should Lock() the object when using these in some loop or so: + int32 CountItems() const; + BrowsingHistoryItem HistoryItemAt(int32 index) const; + void Clear(); private: - BrowsingHistory(); - virtual ~BrowsingHistory(); - void privateClear(); - bool privateAddItem(const BrowsingHistoryItem& item, bool invoke); + BrowsingHistory(); + virtual ~BrowsingHistory(); - void saveSettings(); - bool openSettingsFile(BFile& file, uint32 mode); + void _Clear(); + bool _AddItem(const BrowsingHistoryItem& item, + bool invoke); + + void _LoadSettings(); + void _SaveSettings(); + bool _OpenSettingsFile(BFile& file, uint32 mode); private: - BList m_historyItems; + BList fHistoryItems; + + static BrowsingHistory sDefaultInstance; + bool fSettingsLoaded; }; -#endif // BrowsingHistory_h + +#endif // BROWSING_HISTORY_H From aa5ba348ea3f8d64cb7e0ac47904127f6e09b3f4 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 20 Mar 2010 19:05:47 +0000 Subject: [PATCH 174/349] * Added General page in Settings window with option to specify the maximum age (in days) of items in the browsing history. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@336 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowsingHistory.cpp | 31 +++- src/apps/webpositive/BrowsingHistory.h | 6 +- src/apps/webpositive/SettingsWindow.cpp | 190 +++++++++++++++++------ src/apps/webpositive/SettingsWindow.h | 13 ++ 4 files changed, 188 insertions(+), 52 deletions(-) diff --git a/src/apps/webpositive/BrowsingHistory.cpp b/src/apps/webpositive/BrowsingHistory.cpp index f89d4bf77f..42a0442d0f 100644 --- a/src/apps/webpositive/BrowsingHistory.cpp +++ b/src/apps/webpositive/BrowsingHistory.cpp @@ -177,6 +177,7 @@ BrowsingHistory::BrowsingHistory() : BLocker("browsing history"), fHistoryItems(64), + fMaxHistoryItemAge(7), fSettingsLoaded(false) { } @@ -241,6 +242,24 @@ BrowsingHistory::Clear() } +void +BrowsingHistory::SetMaxHistoryItemAge(int32 days) +{ + BAutolock _(this); + if (fMaxHistoryItemAge != days) { + fMaxHistoryItemAge = days; + _SaveSettings(); + } +} + + +int32 +BrowsingHistory::MaxHistoryItemAge() const +{ + return fMaxHistoryItemAge; +} + + // #pragma mark - private @@ -303,11 +322,20 @@ BrowsingHistory::_LoadSettings() if (_OpenSettingsFile(settingsFile, B_READ_ONLY)) { BMessage settingsArchive; settingsArchive.Unflatten(&settingsFile); + if (settingsArchive.FindInt32("max history item age", + &fMaxHistoryItemAge) != B_OK) { + fMaxHistoryItemAge = 7; + } + BDateTime oldestAllowedDateTime + = BDateTime::CurrentDateTime(B_LOCAL_TIME); + oldestAllowedDateTime.Date().AddDays(-fMaxHistoryItemAge); BMessage historyItemArchive; for (int32 i = 0; settingsArchive.FindMessage("history item", i, &historyItemArchive) == B_OK; i++) { - _AddItem(BrowsingHistoryItem(&historyItemArchive), true); + BrowsingHistoryItem item(&historyItemArchive); + if (oldestAllowedDateTime < item.DateTime()) + _AddItem(item, true); historyItemArchive.MakeEmpty(); } } @@ -321,6 +349,7 @@ BrowsingHistory::_SaveSettings() if (_OpenSettingsFile(settingsFile, B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) { BMessage settingsArchive; + settingsArchive.AddInt32("max history item age", fMaxHistoryItemAge); BMessage historyItemArchive; int32 count = CountItems(); for (int32 i = 0; i < count; i++) { diff --git a/src/apps/webpositive/BrowsingHistory.h b/src/apps/webpositive/BrowsingHistory.h index 43ca33ac5c..bf8f7f15b8 100644 --- a/src/apps/webpositive/BrowsingHistory.h +++ b/src/apps/webpositive/BrowsingHistory.h @@ -84,6 +84,9 @@ public: BrowsingHistoryItem HistoryItemAt(int32 index) const; void Clear(); + void SetMaxHistoryItemAge(int32 days); + int32 MaxHistoryItemAge() const; + private: BrowsingHistory(); virtual ~BrowsingHistory(); @@ -98,8 +101,9 @@ private: private: BList fHistoryItems; + int32 fMaxHistoryItemAge; - static BrowsingHistory sDefaultInstance; + static BrowsingHistory sDefaultInstance; bool fSettingsLoaded; }; diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 906a029dfb..e240147f2d 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -38,10 +38,15 @@ #include #include #include +#include +#include #include + #include +#include #include "BrowserApp.h" +#include "BrowsingHistory.h" #include "FontSelectionView.h" #include "SettingsMessage.h" #include "WebSettings.h" @@ -56,6 +61,9 @@ enum { MSG_REVERT = 'rvrt', MSG_STANDARD_FONT_SIZE_SELECTED = 'sfss', MSG_FIXED_FONT_SIZE_SELECTED = 'ffss', + MSG_DOWNLOAD_FOLDER_CHANGED = 'dnfc', + MSG_NEW_PAGE_BEHAVIOR_CHANGED = 'npbc', + MSG_GO_MENU_DAYS_CHANGED = 'digm', }; static const int32 kDefaultFontSize = 14; @@ -69,68 +77,28 @@ SettingsWindow::SettingsWindow(BRect frame, SettingsMessage* settings) { SetLayout(new BGroupLayout(B_VERTICAL)); - fStandardFontView = new FontSelectionView("standard", "Standard font:", - true, be_plain_font); - BFont defaultSerifFont = _FindDefaultSerifFont(); - fSerifFontView = new FontSelectionView("serif", "Serif font:", true, - &defaultSerifFont); - fSansSerifFontView = new FontSelectionView("sans serif", "Sans serif font:", - true, be_plain_font); - fFixedFontView = new FontSelectionView("fixed", "Fixed font:", true, - be_fixed_font); - - fStandardSizesMenu = new BMenuField("standard font size", - TR("Default standard font size:"), new BPopUpMenu("sizes"), NULL); - _BuildSizesMenu(fStandardSizesMenu->Menu(), MSG_STANDARD_FONT_SIZE_SELECTED); - - fFixedSizesMenu = new BMenuField("fixed font size", - TR("Default fixed font size:"), new BPopUpMenu("sizes"), NULL); - _BuildSizesMenu(fFixedSizesMenu->Menu(), MSG_FIXED_FONT_SIZE_SELECTED); - - fApplyButton = new BButton("Apply", new BMessage(MSG_APPLY)); - fCancelButton = new BButton("Cancel", new BMessage(MSG_CANCEL)); - fRevertButton = new BButton("Revert", new BMessage(MSG_REVERT)); + fApplyButton = new BButton(TR("Apply"), new BMessage(MSG_APPLY)); + fCancelButton = new BButton(TR("Cancel"), new BMessage(MSG_CANCEL)); + fRevertButton = new BButton(TR("Revert"), new BMessage(MSG_REVERT)); float spacing = be_control_look->DefaultItemSpacing(); - AddChild(BGroupLayoutBuilder(B_VERTICAL) - .Add(BGridLayoutBuilder(spacing / 2, spacing / 2) - .Add(fStandardFontView->CreateFontsLabelLayoutItem(), 0, 0) - .Add(fStandardFontView->CreateFontsMenuBarLayoutItem(), 1, 0) - .Add(fStandardFontView->PreviewBox(), 0, 1, 2) - .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 2, 2) + BTabView* tabView = new BTabView("settings pages", B_WIDTH_FROM_LABEL); - .Add(fSerifFontView->CreateFontsLabelLayoutItem(), 0, 3) - .Add(fSerifFontView->CreateFontsMenuBarLayoutItem(), 1, 3) - .Add(fSerifFontView->PreviewBox(), 0, 4, 2) - .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 5, 2) - - .Add(fSansSerifFontView->CreateFontsLabelLayoutItem(), 0, 6) - .Add(fSansSerifFontView->CreateFontsMenuBarLayoutItem(), 1, 6) - .Add(fSansSerifFontView->PreviewBox(), 0, 7, 2) - .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 8, 2) - - .Add(fFixedFontView->CreateFontsLabelLayoutItem(), 0, 9) - .Add(fFixedFontView->CreateFontsMenuBarLayoutItem(), 1, 9) - .Add(fFixedFontView->PreviewBox(), 0, 10, 2) - .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 11, 2) - - .Add(fStandardSizesMenu->CreateLabelLayoutItem(), 0, 12) - .Add(fStandardSizesMenu->CreateMenuBarLayoutItem(), 1, 12) - .Add(fFixedSizesMenu->CreateLabelLayoutItem(), 0, 13) - .Add(fFixedSizesMenu->CreateMenuBarLayoutItem(), 1, 13) - .SetInsets(spacing, spacing, spacing, spacing) - ) - .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + AddChild(BGroupLayoutBuilder(B_VERTICAL, spacing) + .Add(tabView) .Add(BGroupLayoutBuilder(B_HORIZONTAL, spacing) .Add(fRevertButton) .AddGlue() .Add(fCancelButton) .Add(fApplyButton) - .SetInsets(spacing, spacing, spacing, spacing) ) + .SetInsets(spacing, spacing, spacing, spacing) ); + tabView->AddTab(_CreateGeneralPage(spacing)); + tabView->AddTab(_CreateFontsPage(spacing)); + AddHandler(fStandardFontView); fStandardFontView->AttachedToLooper(); @@ -229,6 +197,118 @@ SettingsWindow::Show() // #pragma mark - private +BView* +SettingsWindow::_CreateGeneralPage(float spacing) +{ + fDownloadFolderControl = new BTextControl("download folder", + TR("Download folder:"), "", new BMessage(MSG_DOWNLOAD_FOLDER_CHANGED)); +fDownloadFolderControl->SetEnabled(false); + + fNewPageBehaviorCloneCurrentItem = new BMenuItem(TR("Clone current page"), + NULL); + fNewPageBehaviorCloneCurrentItem->SetEnabled(false); + fNewPageBehaviorOpenHomeItem = new BMenuItem(TR("Open home page"), NULL); + fNewPageBehaviorOpenHomeItem->SetEnabled(false); + fNewPageBehaviorOpenSearchItem = new BMenuItem(TR("Open search page"), + NULL); + fNewPageBehaviorOpenSearchItem->SetEnabled(false); + fNewPageBehaviorOpenBlankItem = new BMenuItem(TR("Open blank page"), NULL); + fNewPageBehaviorOpenBlankItem->SetMarked(true); + + BPopUpMenu* newPageBehaviorMenu = new BPopUpMenu("New pages"); + newPageBehaviorMenu->AddItem(fNewPageBehaviorCloneCurrentItem); + newPageBehaviorMenu->AddItem(fNewPageBehaviorOpenHomeItem); + newPageBehaviorMenu->AddItem(fNewPageBehaviorOpenSearchItem); + newPageBehaviorMenu->AddItem(fNewPageBehaviorOpenBlankItem); + fNewPageBehaviorMenu = new BMenuField("new page behavior", + TR("New pages:"), newPageBehaviorMenu, + new BMessage(MSG_NEW_PAGE_BEHAVIOR_CHANGED)); +fNewPageBehaviorMenu->SetEnabled(false); + + fDaysInGoMenuControl = new BTextControl("days in go menu", + TR("Number of days to keep links in Go menu:"), "", + new BMessage(MSG_GO_MENU_DAYS_CHANGED)); + BString maxHistoryAge; + maxHistoryAge << BrowsingHistory::DefaultInstance()->MaxHistoryItemAge(); + fDaysInGoMenuControl->SetText(maxHistoryAge.String()); + for (uchar i = 0; i < '0'; i++) + fDaysInGoMenuControl->TextView()->DisallowChar(i); + for (uchar i = '9' + 1; i <= 128; i++) + fDaysInGoMenuControl->TextView()->DisallowChar(i); + + BView* view = BGridLayoutBuilder(spacing / 2, spacing / 2) + .Add(fDownloadFolderControl->CreateLabelLayoutItem(), 0, 1) + .Add(fDownloadFolderControl->CreateTextViewLayoutItem(), 1, 1) + + .Add(fNewPageBehaviorMenu->CreateLabelLayoutItem(), 0, 2) + .Add(fNewPageBehaviorMenu->CreateMenuBarLayoutItem(), 1, 2) + + .Add(fDaysInGoMenuControl->CreateLabelLayoutItem(), 0, 3) + .Add(fDaysInGoMenuControl->CreateTextViewLayoutItem(), 1, 3) + + .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 4, 2) + + .SetInsets(spacing, spacing, spacing, spacing) + ; + view->SetName("General"); + return view; +} + + +BView* +SettingsWindow::_CreateFontsPage(float spacing) +{ + fStandardFontView = new FontSelectionView("standard", TR("Standard font:"), + true, be_plain_font); + BFont defaultSerifFont = _FindDefaultSerifFont(); + fSerifFontView = new FontSelectionView("serif", TR("Serif font:"), true, + &defaultSerifFont); + fSansSerifFontView = new FontSelectionView("sans serif", + TR("Sans serif font:"), true, be_plain_font); + fFixedFontView = new FontSelectionView("fixed", TR("Fixed font:"), true, + be_fixed_font); + + fStandardSizesMenu = new BMenuField("standard font size", + TR("Default standard font size:"), new BPopUpMenu("sizes"), NULL); + _BuildSizesMenu(fStandardSizesMenu->Menu(), MSG_STANDARD_FONT_SIZE_SELECTED); + + fFixedSizesMenu = new BMenuField("fixed font size", + TR("Default fixed font size:"), new BPopUpMenu("sizes"), NULL); + _BuildSizesMenu(fFixedSizesMenu->Menu(), MSG_FIXED_FONT_SIZE_SELECTED); + + BView* view = BGridLayoutBuilder(spacing / 2, spacing / 2) + .Add(fStandardFontView->CreateFontsLabelLayoutItem(), 0, 0) + .Add(fStandardFontView->CreateFontsMenuBarLayoutItem(), 1, 0) + .Add(fStandardFontView->PreviewBox(), 0, 1, 2) + .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 2, 2) + + .Add(fSerifFontView->CreateFontsLabelLayoutItem(), 0, 3) + .Add(fSerifFontView->CreateFontsMenuBarLayoutItem(), 1, 3) + .Add(fSerifFontView->PreviewBox(), 0, 4, 2) + .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 5, 2) + + .Add(fSansSerifFontView->CreateFontsLabelLayoutItem(), 0, 6) + .Add(fSansSerifFontView->CreateFontsMenuBarLayoutItem(), 1, 6) + .Add(fSansSerifFontView->PreviewBox(), 0, 7, 2) + .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 8, 2) + + .Add(fFixedFontView->CreateFontsLabelLayoutItem(), 0, 9) + .Add(fFixedFontView->CreateFontsMenuBarLayoutItem(), 1, 9) + .Add(fFixedFontView->PreviewBox(), 0, 10, 2) + .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 11, 2) + + .Add(fStandardSizesMenu->CreateLabelLayoutItem(), 0, 12) + .Add(fStandardSizesMenu->CreateMenuBarLayoutItem(), 1, 12) + .Add(fFixedSizesMenu->CreateLabelLayoutItem(), 0, 13) + .Add(fFixedSizesMenu->CreateMenuBarLayoutItem(), 1, 13) + + .SetInsets(spacing, spacing, spacing, spacing) + ; + view->SetName("Fonts"); + return view; +} + + void SettingsWindow::_ApplySettings() { @@ -255,6 +335,16 @@ SettingsWindow::_ApplySettings() // This will find all currently instantiated page settings and apply // the default values, unless the page settings have local overrides. BWebSettings::Default()->Apply(); + + int32 maxHistoryAge = atoi(fDaysInGoMenuControl->Text()); + if (maxHistoryAge <= 0) + maxHistoryAge = 1; + if (maxHistoryAge >= 35) + maxHistoryAge = 35; + BString text; + text << maxHistoryAge; + fDaysInGoMenuControl->SetText(text.String()); + BrowsingHistory::DefaultInstance()->SetMaxHistoryItemAge(maxHistoryAge); } diff --git a/src/apps/webpositive/SettingsWindow.h b/src/apps/webpositive/SettingsWindow.h index 9a6b7d9373..124b85f7e6 100644 --- a/src/apps/webpositive/SettingsWindow.h +++ b/src/apps/webpositive/SettingsWindow.h @@ -32,6 +32,8 @@ class BButton; class BMenu; class BMenuField; +class BMenuItem; +class BTextControl; class FontSelectionView; class SettingsMessage; @@ -48,6 +50,9 @@ public: virtual void Show(); private: + BView* _CreateGeneralPage(float spacing); + BView* _CreateFontsPage(float spacing); + void _ApplySettings(); void _RevertSettings(); @@ -61,6 +66,14 @@ private: private: SettingsMessage* fSettings; + BTextControl* fDownloadFolderControl; + BMenuField* fNewPageBehaviorMenu; + BMenuItem* fNewPageBehaviorCloneCurrentItem; + BMenuItem* fNewPageBehaviorOpenHomeItem; + BMenuItem* fNewPageBehaviorOpenSearchItem; + BMenuItem* fNewPageBehaviorOpenBlankItem; + BTextControl* fDaysInGoMenuControl; + FontSelectionView* fStandardFontView; FontSelectionView* fSerifFontView; FontSelectionView* fSansSerifFontView; From 9ccfda9c50ab958a4545588d888850694ec86ee5 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 22 Mar 2010 16:59:50 +0000 Subject: [PATCH 175/349] Converted to Haiku coding style. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@337 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 792 +++++++++++++----------- src/apps/webpositive/DownloadWindow.h | 31 +- 2 files changed, 435 insertions(+), 388 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 60d9701e9b..f852cb6f2e 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -25,12 +25,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" #include "DownloadWindow.h" -#include "BrowserApp.h" -#include "WebDownload.h" -#include "WebPage.h" +#include + #include #include #include @@ -48,296 +46,310 @@ #include #include #include -#include + +#include "BrowserApp.h" +#include "WebDownload.h" +#include "WebPage.h" + enum { - REMOVE_FINISHED_DOWNLOADS = 'rmfd', - OPEN_DOWNLOAD = 'opdn', - RESTART_DOWNLOAD = 'rsdn', - CANCEL_DOWNLOAD = 'cndn', - REMOVE_DOWNLOAD = 'rmdn', - SAVE_SETTINGS = 'svst' + REMOVE_FINISHED_DOWNLOADS = 'rmfd', + OPEN_DOWNLOAD = 'opdn', + RESTART_DOWNLOAD = 'rsdn', + CANCEL_DOWNLOAD = 'cndn', + REMOVE_DOWNLOAD = 'rmdn', + SAVE_SETTINGS = 'svst' }; + class IconView : public BView { public: - IconView(const BEntry& entry) - : BView("Download icon", B_WILL_DRAW) - , m_iconBitmap(BRect(0, 0, 31, 31), 0, B_RGBA32) - { - BNode node(&entry); - BNodeInfo info(&node); - info.GetTrackerIcon(&m_iconBitmap, B_LARGE_ICON); - SetDrawingMode(B_OP_OVER); - } + IconView(const BEntry& entry) + : + BView("Download icon", B_WILL_DRAW), + fIconBitmap(BRect(0, 0, 31, 31), 0, B_RGBA32) + { + BNode node(&entry); + BNodeInfo info(&node); + info.GetTrackerIcon(&fIconBitmap, B_LARGE_ICON); + SetDrawingMode(B_OP_OVER); + } - IconView(BMessage* archive) - : BView("Download icon", B_WILL_DRAW) - , m_iconBitmap(archive) - { - SetDrawingMode(B_OP_OVER); - } + IconView(BMessage* archive) + : + BView("Download icon", B_WILL_DRAW), + fIconBitmap(archive) + { + SetDrawingMode(B_OP_OVER); + } - status_t saveSettings(BMessage* archive) - { - return m_iconBitmap.Archive(archive); - } + status_t SaveSettings(BMessage* archive) + { + return fIconBitmap.Archive(archive); + } - virtual void AttachedToWindow() - { - SetViewColor(Parent()->ViewColor()); - } + virtual void AttachedToWindow() + { + SetViewColor(Parent()->ViewColor()); + } - virtual void Draw(BRect updateRect) - { - DrawBitmapAsync(&m_iconBitmap); - } + virtual void Draw(BRect updateRect) + { + DrawBitmapAsync(&fIconBitmap); + } - virtual BSize MinSize() - { - return BSize(m_iconBitmap.Bounds().Width(), m_iconBitmap.Bounds().Height()); - } + virtual BSize MinSize() + { + return BSize(fIconBitmap.Bounds().Width(), fIconBitmap.Bounds().Height()); + } - virtual BSize PreferredSize() - { - return MinSize(); - } + virtual BSize PreferredSize() + { + return MinSize(); + } - virtual BSize MaxSize() - { - return MinSize(); - } + virtual BSize MaxSize() + { + return MinSize(); + } private: - BBitmap m_iconBitmap; + BBitmap fIconBitmap; }; + class SmallButton : public BButton { public: - SmallButton(const char* label, BMessage* message = NULL) - : BButton(label, message) - { - BFont font; - GetFont(&font); - float size = ceilf(font.Size() * 0.8); - font.SetSize(max_c(8, size)); - SetFont(&font, B_FONT_SIZE); - } + SmallButton(const char* label, BMessage* message = NULL) + : + BButton(label, message) + { + BFont font; + GetFont(&font); + float size = ceilf(font.Size() * 0.8); + font.SetSize(max_c(8, size)); + SetFont(&font, B_FONT_SIZE); + } }; + class DownloadProgressView : public BGridView { public: - DownloadProgressView(BWebDownload* download) - : BGridView(8, 3) - , m_download(download) - , m_url(download->URL()) - , m_path(download->Path()) - , m_expectedSize(download->ExpectedSize()) - { - } + DownloadProgressView(BWebDownload* download) + : + BGridView(8, 3), + fDownload(download), + fURL(download->URL()), + fPath(download->Path()), + fExpectedSize(download->ExpectedSize()) + { + } - DownloadProgressView(const BMessage* archive) - : BGridView(8, 3) - , m_download(NULL) - , m_url() - , m_path() - , m_expectedSize(0) - { - const char* string; - if (archive->FindString("path", &string) == B_OK) - m_path.SetTo(string); - if (archive->FindString("url", &string) == B_OK) - m_url = string; - } + DownloadProgressView(const BMessage* archive) + : + BGridView(8, 3), + fDownload(NULL), + fURL(), + fPath(), + fExpectedSize(0) + { + const char* string; + if (archive->FindString("path", &string) == B_OK) + fPath.SetTo(string); + if (archive->FindString("url", &string) == B_OK) + fURL = string; + } - bool init(BMessage* archive = NULL) - { - BEntry entry(m_path.Path()); - if (!entry.Exists() && !archive) - return false; + bool Init(BMessage* archive = NULL) + { + BEntry entry(fPath.Path()); + if (!entry.Exists() && !archive) + return false; - SetViewColor(245, 245, 245); - SetFlags(Flags() | B_FULL_UPDATE_ON_RESIZE | B_WILL_DRAW); + SetViewColor(245, 245, 245); + SetFlags(Flags() | B_FULL_UPDATE_ON_RESIZE | B_WILL_DRAW); - BGridLayout* layout = GridLayout(); - m_statusBar = new BStatusBar("download progress", m_path.Leaf()); - m_statusBar->SetMaxValue(100); - if (archive) { - float value; - if (archive->FindFloat("value", &value) == B_OK) - m_statusBar->SetTo(value); - } - m_statusBar->SetBarHeight(12); + BGridLayout* layout = GridLayout(); + fStatusBar = new BStatusBar("download progress", fPath.Leaf()); + fStatusBar->SetMaxValue(100); + if (archive) { + float value; + if (archive->FindFloat("value", &value) == B_OK) + fStatusBar->SetTo(value); + } + fStatusBar->SetBarHeight(12); - if (entry.Exists()) - m_iconView = new IconView(entry); - else - m_iconView = new IconView(archive); + if (entry.Exists()) + fIconView = new IconView(entry); + else + fIconView = new IconView(archive); - if (!m_download && m_statusBar->CurrentValue() < 100) - m_button1 = new SmallButton("Restart", new BMessage(RESTART_DOWNLOAD)); - else { - m_button1 = new SmallButton("Open", new BMessage(OPEN_DOWNLOAD)); - m_button1->SetEnabled(m_download == NULL); - } - if (m_download) - m_button2 = new SmallButton("Cancel", new BMessage(CANCEL_DOWNLOAD)); - else { - m_button2 = new SmallButton("Remove", new BMessage(REMOVE_DOWNLOAD)); - m_button2->SetEnabled(m_download == NULL); - } + if (!fDownload && fStatusBar->CurrentValue() < 100) + fTopButton = new SmallButton("Restart", new BMessage(RESTART_DOWNLOAD)); + else { + fTopButton = new SmallButton("Open", new BMessage(OPEN_DOWNLOAD)); + fTopButton->SetEnabled(fDownload == NULL); + } + if (fDownload) + fBottomButton = new SmallButton("Cancel", new BMessage(CANCEL_DOWNLOAD)); + else { + fBottomButton = new SmallButton("Remove", new BMessage(REMOVE_DOWNLOAD)); + fBottomButton->SetEnabled(fDownload == NULL); + } layout->SetInsets(8, 5, 5, 6); - layout->AddView(m_iconView, 0, 0, 1, 2); - layout->AddView(m_statusBar, 1, 0, 1, 2); - layout->AddView(m_button1, 2, 0); - layout->AddView(m_button2, 2, 1); + layout->AddView(fIconView, 0, 0, 1, 2); + layout->AddView(fStatusBar, 1, 0, 1, 2); + layout->AddView(fTopButton, 2, 0); + layout->AddView(fBottomButton, 2, 1); - return true; - } + return true; + } - status_t saveSettings(BMessage* archive) - { - if (!archive) - return B_BAD_VALUE; - status_t ret = archive->AddString("path", m_path.Path()); - if (ret == B_OK) - ret = archive->AddString("url", m_url.String()); - if (ret == B_OK) - ret = archive->AddFloat("value", m_statusBar->CurrentValue()); - if (ret == B_OK) - ret = m_iconView->saveSettings(archive); - return ret; - } + status_t SaveSettings(BMessage* archive) + { + if (!archive) + return B_BAD_VALUE; + status_t ret = archive->AddString("path", fPath.Path()); + if (ret == B_OK) + ret = archive->AddString("url", fURL.String()); + if (ret == B_OK) + ret = archive->AddFloat("value", fStatusBar->CurrentValue()); + if (ret == B_OK) + ret = fIconView->SaveSettings(archive); + return ret; + } - virtual void AttachedToWindow() - { - if (m_download) - m_download->SetProgressListener(BMessenger(this)); - m_button1->SetTarget(this); - m_button2->SetTarget(this); - } + virtual void AttachedToWindow() + { + if (fDownload) + fDownload->SetProgressListener(BMessenger(this)); + fTopButton->SetTarget(this); + fBottomButton->SetTarget(this); + } - virtual void AllAttached() - { - SetViewColor(B_TRANSPARENT_COLOR); - SetLowColor(245, 245, 245); - SetHighColor(tint_color(LowColor(), B_DARKEN_1_TINT)); - } + virtual void AllAttached() + { + SetViewColor(B_TRANSPARENT_COLOR); + SetLowColor(245, 245, 245); + SetHighColor(tint_color(LowColor(), B_DARKEN_1_TINT)); + } - virtual void Draw(BRect updateRect) - { - BRect bounds(Bounds()); - bounds.bottom--; - FillRect(bounds, B_SOLID_LOW); - bounds.bottom++; - StrokeLine(bounds.LeftBottom(), bounds.RightBottom()); - } + virtual void Draw(BRect updateRect) + { + BRect bounds(Bounds()); + bounds.bottom--; + FillRect(bounds, B_SOLID_LOW); + bounds.bottom++; + StrokeLine(bounds.LeftBottom(), bounds.RightBottom()); + } - virtual void MessageReceived(BMessage* message) - { - switch (message->what) { - case B_DOWNLOAD_PROGRESS: { - float progress; - if (message->FindFloat("progress", &progress) == B_OK) - m_statusBar->SetTo(progress); - break; - } - case OPEN_DOWNLOAD: { - // TODO: In case of executable files, ask the user first! - entry_ref ref; - status_t status = get_ref_for_path(m_path.Path(), &ref); - if (status == B_OK) - status = be_roster->Launch(&ref); - if (status != B_OK && status != B_ALREADY_RUNNING) { - BAlert* alert = new BAlert("Open download error", - "The download could not be opened.", "OK"); - alert->Go(NULL); - } - break; - } - case RESTART_DOWNLOAD: - BWebPage::RequestDownload(m_url); - break; + virtual void MessageReceived(BMessage* message) + { + switch (message->what) { + case B_DOWNLOAD_PROGRESS: { + float progress; + if (message->FindFloat("progress", &progress) == B_OK) + fStatusBar->SetTo(progress); + break; + } + case OPEN_DOWNLOAD: { + // TODO: In case of executable files, ask the user first! + entry_ref ref; + status_t status = get_ref_for_path(fPath.Path(), &ref); + if (status == B_OK) + status = be_roster->Launch(&ref); + if (status != B_OK && status != B_ALREADY_RUNNING) { + BAlert* alert = new BAlert("Open download error", + "The download could not be opened.", "OK"); + alert->Go(NULL); + } + break; + } + case RESTART_DOWNLOAD: + BWebPage::RequestDownload(fURL); + break; + + case CANCEL_DOWNLOAD: + fDownload->Cancel(); + DownloadCanceled(); + break; + + case REMOVE_DOWNLOAD: { + Window()->PostMessage(SAVE_SETTINGS); + RemoveSelf(); + delete this; + // TOAST! + return; + } + case B_DOWNLOAD_REMOVED: + // TODO: This is a bit asymetric. The removed notification + // arrives here, but it would be nicer if it arrived + // at the window... + Window()->PostMessage(message); + break; + default: + BGridView::MessageReceived(message); + } + } - case CANCEL_DOWNLOAD: - m_download->Cancel(); - downloadCanceled(); - break; + BWebDownload* Download() const + { + return fDownload; + } - case REMOVE_DOWNLOAD: { - Window()->PostMessage(SAVE_SETTINGS); - RemoveSelf(); - delete this; - // TOAST! - return; - } - case B_DOWNLOAD_REMOVED: - // TODO: This is a bit asymetric. The removed notification - // arrives here, but it would be nicer if it arrived - // at the window... - Window()->PostMessage(message); - break; - default: - BGridView::MessageReceived(message); - } - } + const BString& URL() const + { + return fURL; + } - BWebDownload* download() const - { - return m_download; - } + void DownloadFinished() + { + fDownload = NULL; + fTopButton->SetEnabled(true); + fBottomButton->SetLabel("Remove"); + fBottomButton->SetMessage(new BMessage(REMOVE_DOWNLOAD)); + fBottomButton->SetEnabled(true); + } - const BString& url() const - { - return m_url; - } - - void downloadFinished() - { - m_download = NULL; - m_button1->SetEnabled(true); - m_button2->SetLabel("Remove"); - m_button2->SetMessage(new BMessage(REMOVE_DOWNLOAD)); - m_button2->SetEnabled(true); - } - - void downloadCanceled() - { - m_download = NULL; - m_button1->SetLabel("Restart"); - m_button1->SetMessage(new BMessage(RESTART_DOWNLOAD)); - m_button1->SetEnabled(true); - m_button2->SetLabel("Remove"); - m_button2->SetMessage(new BMessage(REMOVE_DOWNLOAD)); - m_button2->SetEnabled(true); - } + void DownloadCanceled() + { + fDownload = NULL; + fTopButton->SetLabel("Restart"); + fTopButton->SetMessage(new BMessage(RESTART_DOWNLOAD)); + fTopButton->SetEnabled(true); + fBottomButton->SetLabel("Remove"); + fBottomButton->SetMessage(new BMessage(REMOVE_DOWNLOAD)); + fBottomButton->SetEnabled(true); + } private: - IconView* m_iconView; - BStatusBar* m_statusBar; - SmallButton* m_button1; - SmallButton* m_button2; - BWebDownload* m_download; - BString m_url; - BPath m_path; - off_t m_expectedSize; + IconView* fIconView; + BStatusBar* fStatusBar; + SmallButton* fTopButton; + SmallButton* fBottomButton; + BWebDownload* fDownload; + BString fURL; + BPath fPath; + off_t fExpectedSize; }; + class DownloadsContainerView : public BGroupView { public: DownloadsContainerView() - : BGroupView(B_VERTICAL) + : + BGroupView(B_VERTICAL) { - SetViewColor(245, 245, 245); - AddChild(BSpaceLayoutItem::CreateGlue()); + SetViewColor(245, 245, 245); + AddChild(BSpaceLayoutItem::CreateGlue()); } - virtual BSize MinSize() - { - BSize minSize = BGroupView::MinSize(); - return BSize(minSize.width, 80); - } + virtual BSize MinSize() + { + BSize minSize = BGroupView::MinSize(); + return BSize(minSize.width, 80); + } protected: virtual void DoLayout() @@ -349,211 +361,245 @@ protected: float max = minSize.height - height; scrollBar->SetRange(0, max); if (minSize.height > 0) - scrollBar->SetProportion(height / minSize.height); + scrollBar->SetProportion(height / minSize.height); else - scrollBar->SetProportion(1); + scrollBar->SetProportion(1); } } }; + class DownloadContainerScrollView : public BScrollView { public: - DownloadContainerScrollView(BView* target) - : BScrollView("Downloads scroll view", target, 0, false, true, B_NO_BORDER) - { - } + DownloadContainerScrollView(BView* target) + : + BScrollView("Downloads scroll view", target, 0, false, true, + B_NO_BORDER) + { + } protected: - virtual void DoLayout() - { - BScrollView::DoLayout(); - // Tweak scroll bar layout to hide part of the frame for better looks. - BScrollBar* scrollBar = ScrollBar(B_VERTICAL); - scrollBar->MoveBy(1, -1); - scrollBar->ResizeBy(0, 2); - Target()->ResizeBy(1, 0); - } + virtual void DoLayout() + { + BScrollView::DoLayout(); + // Tweak scroll bar layout to hide part of the frame for better looks. + BScrollBar* scrollBar = ScrollBar(B_VERTICAL); + scrollBar->MoveBy(1, -1); + scrollBar->ResizeBy(0, 2); + Target()->ResizeBy(1, 0); + } }; + DownloadWindow::DownloadWindow(BRect frame, bool visible) - : BWindow(frame, "Downloads", - B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, - B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE) + : BWindow(frame, "Downloads", + B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, + B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE) { SetLayout(new BGroupLayout(B_VERTICAL)); DownloadsContainerView* downloadsGroupView = new DownloadsContainerView(); - m_downloadViewsLayout = downloadsGroupView->GroupLayout(); + fDownloadViewsLayout = downloadsGroupView->GroupLayout(); - BMenuBar* menuBar = new BMenuBar("Menu bar"); - BMenu* menu = new BMenu("Window"); - menu->AddItem(new BMenuItem("Hide", new BMessage(B_QUIT_REQUESTED), 'H')); - menuBar->AddItem(menu); + BMenuBar* menuBar = new BMenuBar("Menu bar"); + BMenu* menu = new BMenu("Window"); + menu->AddItem(new BMenuItem("Hide", new BMessage(B_QUIT_REQUESTED), 'H')); + menuBar->AddItem(menu); - BScrollView* scrollView = new DownloadContainerScrollView(downloadsGroupView); + BScrollView* scrollView = new DownloadContainerScrollView( + downloadsGroupView); - m_removeFinishedButton = new BButton("Remove finished", - new BMessage(REMOVE_FINISHED_DOWNLOADS)); - m_removeFinishedButton->SetEnabled(false); + fRemoveFinishedButton = new BButton("Remove finished", + new BMessage(REMOVE_FINISHED_DOWNLOADS)); + fRemoveFinishedButton->SetEnabled(false); - AddChild(BGroupLayoutBuilder(B_VERTICAL) - .Add(menuBar) - .Add(scrollView) - .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) - .Add(BGroupLayoutBuilder(B_HORIZONTAL) - .AddGlue() - .Add(m_removeFinishedButton) - .SetInsets(5, 5, 5, 5) - ) - ); + AddChild(BGroupLayoutBuilder(B_VERTICAL) + .Add(menuBar) + .Add(scrollView) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(BGroupLayoutBuilder(B_HORIZONTAL) + .AddGlue() + .Add(fRemoveFinishedButton) + .SetInsets(5, 5, 5, 5) + ) + ); - loadSettings(); - // Small trick to get the correct enabled status of the Remove finished button - downloadFinished(NULL); + _LoadSettings(); + // Small trick to get the correct enabled status of the Remove finished button + _DownloadFinished(NULL); if (!visible) - Hide(); + Hide(); Show(); } + DownloadWindow::~DownloadWindow() { // Only necessary to save the current progress of unfinished downloads: - saveSettings(); + _SaveSettings(); } -void DownloadWindow::MessageReceived(BMessage* message) + +void +DownloadWindow::MessageReceived(BMessage* message) { - switch (message->what) { - case B_DOWNLOAD_ADDED: { - BWebDownload* download; - if (message->FindPointer("download", reinterpret_cast(&download)) == B_OK) - downloadStarted(download); - break; - } - case B_DOWNLOAD_REMOVED: { - BWebDownload* download; - if (message->FindPointer("download", reinterpret_cast(&download)) == B_OK) - downloadFinished(download); - break; - } - case REMOVE_FINISHED_DOWNLOADS: - removeFinishedDownloads(); - break; - case SAVE_SETTINGS: - saveSettings(); - break; - default: - BWindow::MessageReceived(message); - break; - } + switch (message->what) { + case B_DOWNLOAD_ADDED: { + BWebDownload* download; + if (message->FindPointer("download", reinterpret_cast( + &download)) == B_OK) { + _DownloadStarted(download); + } + break; + } + case B_DOWNLOAD_REMOVED: { + BWebDownload* download; + if (message->FindPointer("download", reinterpret_cast( + &download)) == B_OK) { + _DownloadFinished(download); + } + break; + } + case REMOVE_FINISHED_DOWNLOADS: + _RemoveFinishedDownloads(); + break; + case SAVE_SETTINGS: + _SaveSettings(); + break; + default: + BWindow::MessageReceived(message); + break; + } } -bool DownloadWindow::QuitRequested() + +bool +DownloadWindow::QuitRequested() { if (!IsHidden()) - Hide(); - return false; + Hide(); + return false; } -void DownloadWindow::downloadStarted(BWebDownload* download) + +void +DownloadWindow::_DownloadStarted(BWebDownload* download) { int32 finishedCount = 0; int32 index = 0; - for (int32 i = m_downloadViewsLayout->CountItems() - 1; - BLayoutItem* item = m_downloadViewsLayout->ItemAt(i); i--) { - DownloadProgressView* view = dynamic_cast(item->View()); - if (!view) - continue; - if (view->url() == download->URL()) { - index = i; - view->RemoveSelf(); - delete view; - } else if (!view->download()) - finishedCount++; + for (int32 i = fDownloadViewsLayout->CountItems() - 1; + BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) { + DownloadProgressView* view = dynamic_cast( + item->View()); + if (!view) + continue; + if (view->URL() == download->URL()) { + index = i; + view->RemoveSelf(); + delete view; + } else if (!view->Download()) + finishedCount++; } - m_removeFinishedButton->SetEnabled(finishedCount > 0); + fRemoveFinishedButton->SetEnabled(finishedCount > 0); DownloadProgressView* view = new DownloadProgressView(download); - if (!view->init()) + if (!view->Init()) return; - m_downloadViewsLayout->AddView(index, view); - saveSettings(); + fDownloadViewsLayout->AddView(index, view); + _SaveSettings(); SetWorkspaces(B_CURRENT_WORKSPACE); if (IsHidden()) Show(); } -void DownloadWindow::downloadFinished(BWebDownload* download) + +void +DownloadWindow::_DownloadFinished(BWebDownload* download) { int32 finishedCount = 0; - for (int32 i = 0; BLayoutItem* item = m_downloadViewsLayout->ItemAt(i); i++) { - DownloadProgressView* view = dynamic_cast(item->View()); - if (!view) - continue; - if (view->download() == download) { - view->downloadFinished(); - finishedCount++; - } else if (!view->download()) - finishedCount++; + for (int32 i = 0; + BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i++) { + DownloadProgressView* view = dynamic_cast( + item->View()); + if (!view) + continue; + if (view->Download() == download) { + view->DownloadFinished(); + finishedCount++; + } else if (!view->Download()) + finishedCount++; } - m_removeFinishedButton->SetEnabled(finishedCount > 0); + fRemoveFinishedButton->SetEnabled(finishedCount > 0); if (download) - saveSettings(); + _SaveSettings(); } -void DownloadWindow::removeFinishedDownloads() + +void +DownloadWindow::_RemoveFinishedDownloads() { - for (int32 i = m_downloadViewsLayout->CountItems() - 1; - BLayoutItem* item = m_downloadViewsLayout->ItemAt(i); i--) { - DownloadProgressView* view = dynamic_cast(item->View()); - if (!view) - continue; - if (!view->download()) { - view->RemoveSelf(); - delete view; - } + for (int32 i = fDownloadViewsLayout->CountItems() - 1; + BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) { + DownloadProgressView* view = dynamic_cast( + item->View()); + if (!view) + continue; + if (!view->Download()) { + view->RemoveSelf(); + delete view; + } } - m_removeFinishedButton->SetEnabled(false); - saveSettings(); + fRemoveFinishedButton->SetEnabled(false); + _SaveSettings(); } -void DownloadWindow::saveSettings() + +void +DownloadWindow::_SaveSettings() { BFile file; - if (!openSettingsFile(file, B_ERASE_FILE | B_CREATE_FILE | B_WRITE_ONLY)) - return; + if (!_OpenSettingsFile(file, B_ERASE_FILE | B_CREATE_FILE | B_WRITE_ONLY)) + return; BMessage message; - for (int32 i = m_downloadViewsLayout->CountItems() - 1; - BLayoutItem* item = m_downloadViewsLayout->ItemAt(i); i--) { - DownloadProgressView* view = dynamic_cast(item->View()); - if (!view) - continue; - BMessage downloadArchive; - if (view->saveSettings(&downloadArchive) == B_OK) - message.AddMessage("download", &downloadArchive); + for (int32 i = fDownloadViewsLayout->CountItems() - 1; + BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) { + DownloadProgressView* view = dynamic_cast( + item->View()); + if (!view) + continue; + BMessage downloadArchive; + if (view->SaveSettings(&downloadArchive) == B_OK) + message.AddMessage("download", &downloadArchive); } message.Flatten(&file); } -void DownloadWindow::loadSettings() + +void +DownloadWindow::_LoadSettings() { BFile file; - if (!openSettingsFile(file, B_READ_ONLY)) - return; + if (!_OpenSettingsFile(file, B_READ_ONLY)) + return; BMessage message; if (message.Unflatten(&file) != B_OK) - return; - BMessage downloadArchive; - for (int32 i = 0; message.FindMessage("download", i, &downloadArchive) == B_OK; i++) { - DownloadProgressView* view = new DownloadProgressView(&downloadArchive); - if (!view->init(&downloadArchive)) + return; + BMessage downloadArchive; + for (int32 i = 0; + message.FindMessage("download", i, &downloadArchive) == B_OK; + i++) { + DownloadProgressView* view = new DownloadProgressView( + &downloadArchive); + if (!view->Init(&downloadArchive)) continue; - m_downloadViewsLayout->AddView(0, view); + fDownloadViewsLayout->AddView(0, view); } } -bool DownloadWindow::openSettingsFile(BFile& file, uint32 mode) + +bool +DownloadWindow::_OpenSettingsFile(BFile& file, uint32 mode) { BPath path; if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index c7819ffdec..c901b2dda7 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -24,9 +24,9 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#ifndef DOWNLOAD_WINDOW_H +#define DOWNLOAD_WINDOW_H -#ifndef DownloadWindow_h -#define DownloadWindow_h #include @@ -35,26 +35,27 @@ class BFile; class BGroupLayout; class BWebDownload; + class DownloadWindow : public BWindow { public: - DownloadWindow(BRect frame, bool visible); - virtual ~DownloadWindow(); + DownloadWindow(BRect frame, bool visible); + virtual ~DownloadWindow(); - virtual void MessageReceived(BMessage*); - virtual bool QuitRequested(); + virtual void MessageReceived(BMessage* message); + virtual bool QuitRequested(); private: - void downloadStarted(BWebDownload* download); - void downloadFinished(BWebDownload* download); - void removeFinishedDownloads(); - void saveSettings(); - void loadSettings(); - bool openSettingsFile(BFile& file, uint32 mode); + void _DownloadStarted(BWebDownload* download); + void _DownloadFinished(BWebDownload* download); + void _RemoveFinishedDownloads(); + void _SaveSettings(); + void _LoadSettings(); + bool _OpenSettingsFile(BFile& file, uint32 mode); private: - BGroupLayout* m_downloadViewsLayout; - BButton* m_removeFinishedButton; + BGroupLayout* fDownloadViewsLayout; + BButton* fRemoveFinishedButton; }; -#endif // DownloadWindow_h +#endif // DOWNLOAD_WINDOW_H From 0ba16dd4c1bde479b0e91162f63b163858d3dd82 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 22 Mar 2010 18:04:31 +0000 Subject: [PATCH 176/349] Added support for attaching listeners to the SettingsMessage, to be notified when a named value changes. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@338 94f232f2-1747-11df-bad5-a5bfde151594 --- .../webpositive/support/SettingsMessage.cpp | 188 ++++++++++++++---- .../webpositive/support/SettingsMessage.h | 18 +- 2 files changed, 161 insertions(+), 45 deletions(-) diff --git a/src/apps/webpositive/support/SettingsMessage.cpp b/src/apps/webpositive/support/SettingsMessage.cpp index 98e9ef1c94..d96ceb1e64 100644 --- a/src/apps/webpositive/support/SettingsMessage.cpp +++ b/src/apps/webpositive/support/SettingsMessage.cpp @@ -9,14 +9,19 @@ #include "SettingsMessage.h" +#include + #include #include +#include #include SettingsMessage::SettingsMessage(directory_which directory, const char* filename) - : BMessage('pref') + : + BMessage('pref'), + fListeners(4) { fStatus = find_directory(directory, &fPath); @@ -31,6 +36,9 @@ SettingsMessage::SettingsMessage(directory_which directory, SettingsMessage::~SettingsMessage() { Save(); + + for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) + delete reinterpret_cast(fListeners.ItemAtFast(i)); } @@ -67,139 +75,212 @@ SettingsMessage::Save() const } +bool +SettingsMessage::AddListener(const BMessenger& listener) +{ + BMessenger* listenerCopy = new(std::nothrow) BMessenger(listener); + if (listenerCopy && fListeners.AddItem(listenerCopy)) + return true; + delete listenerCopy; + return false; +} + + +void +SettingsMessage::RemoveListener(const BMessenger& listener) +{ + for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) { + BMessenger* listenerItem = reinterpret_cast( + fListeners.ItemAtFast(i)); + if (*listenerItem == listener) { + fListeners.RemoveItem(i); + delete listenerItem; + return; + } + } +} + + // #pragma mark - status_t SettingsMessage::SetValue(const char* name, bool value) { - if (ReplaceBool(name, value) == B_OK) - return B_OK; - return AddBool(name, value); + status_t ret = ReplaceBool(name, value); + if (ret != B_OK) + ret = AddBool(name, value); + if (ret == B_OK) + _NotifyValueChanged(name); + return ret; } status_t SettingsMessage::SetValue(const char* name, int8 value) { - if (ReplaceInt8(name, value) == B_OK) - return B_OK; - return AddInt8(name, value); + status_t ret = ReplaceInt8(name, value); + if (ret != B_OK) + ret = AddInt8(name, value); + if (ret == B_OK) + _NotifyValueChanged(name); + return ret; } status_t SettingsMessage::SetValue(const char* name, int16 value) { - if (ReplaceInt16(name, value) == B_OK) - return B_OK; - return AddInt16(name, value); + status_t ret = ReplaceInt16(name, value); + if (ret != B_OK) + ret = AddInt16(name, value); + if (ret == B_OK) + _NotifyValueChanged(name); + return ret; } status_t SettingsMessage::SetValue(const char* name, int32 value) { - if (ReplaceInt32(name, value) == B_OK) - return B_OK; - return AddInt32(name, value); + status_t ret = ReplaceInt32(name, value); + if (ret != B_OK) + ret = AddInt32(name, value); + if (ret == B_OK) + _NotifyValueChanged(name); + return ret; } status_t SettingsMessage::SetValue(const char* name, uint32 value) { - if (ReplaceInt32(name, (int32)value) == B_OK) - return B_OK; - return AddInt32(name, (int32)value); + status_t ret = ReplaceUInt32(name, value); + if (ret != B_OK) + ret = AddUInt32(name, value); + if (ret == B_OK) + _NotifyValueChanged(name); + return ret; } status_t SettingsMessage::SetValue(const char* name, int64 value) { - if (ReplaceInt64(name, value) == B_OK) - return B_OK; - return AddInt64(name, value); + status_t ret = ReplaceInt64(name, value); + if (ret != B_OK) + ret = AddInt64(name, value); + if (ret == B_OK) + _NotifyValueChanged(name); + return ret; } status_t SettingsMessage::SetValue(const char* name, float value) { - if (ReplaceFloat(name, value) == B_OK) - return B_OK; - return AddFloat(name, value); + status_t ret = ReplaceFloat(name, value); + if (ret != B_OK) + ret = AddFloat(name, value); + if (ret == B_OK) + _NotifyValueChanged(name); + return ret; } status_t SettingsMessage::SetValue(const char* name, double value) { - if (ReplaceDouble(name, value) == B_OK) - return B_OK; - return AddDouble(name, value); + status_t ret = ReplaceDouble(name, value); + if (ret != B_OK) + ret = AddDouble(name, value); + if (ret == B_OK) + _NotifyValueChanged(name); + return ret; } status_t SettingsMessage::SetValue(const char* name, const char* value) { - if (ReplaceString(name, value) == B_OK) - return B_OK; - return AddString(name, value); + status_t ret = ReplaceString(name, value); + if (ret != B_OK) + ret = AddString(name, value); + if (ret == B_OK) + _NotifyValueChanged(name); + return ret; } status_t SettingsMessage::SetValue(const char* name, const BString& value) { - return SetValue(name, value.String()); + status_t ret = ReplaceString(name, value); + if (ret != B_OK) + ret = AddString(name, value); + if (ret == B_OK) + _NotifyValueChanged(name); + return ret; } status_t SettingsMessage::SetValue(const char* name, const BPoint& value) { - if (ReplacePoint(name, value) == B_OK) - return B_OK; - return AddPoint(name, value); + status_t ret = ReplacePoint(name, value); + if (ret != B_OK) + ret = AddPoint(name, value); + if (ret == B_OK) + _NotifyValueChanged(name); + return ret; } status_t SettingsMessage::SetValue(const char* name, const BRect& value) { - if (ReplaceRect(name, value) == B_OK) - return B_OK; - return AddRect(name, value); + status_t ret = ReplaceRect(name, value); + if (ret != B_OK) + ret = AddRect(name, value); + if (ret == B_OK) + _NotifyValueChanged(name); + return ret; } status_t SettingsMessage::SetValue(const char* name, const entry_ref& value) { - if (ReplaceRef(name, &value) == B_OK) - return B_OK; - return AddRef(name, &value); + status_t ret = ReplaceRef(name, &value); + if (ret != B_OK) + ret = AddRef(name, &value); + if (ret == B_OK) + _NotifyValueChanged(name); + return ret; } status_t SettingsMessage::SetValue(const char* name, const BMessage& value) { - if (ReplaceMessage(name, &value) == B_OK) - return B_OK; - return AddMessage(name, &value); + status_t ret = ReplaceMessage(name, &value); + if (ret != B_OK) + ret = AddMessage(name, &value); + if (ret == B_OK) + _NotifyValueChanged(name); + return ret; } status_t SettingsMessage::SetValue(const char* name, const BFlattenable* value) { - if (ReplaceFlat(name, const_cast(value)) == B_OK) - return B_OK; - return AddFlat(name, const_cast(value)); + status_t ret = ReplaceFlat(name, const_cast(value)); + if (ret != B_OK) + ret = AddFlat(name, const_cast(value)); + if (ret == B_OK) + _NotifyValueChanged(name); + return ret; } @@ -221,6 +302,8 @@ SettingsMessage::SetValue(const char* name, const BFont& value) if (ReplaceMessage(name, &fontMessage) != B_OK) ret = AddMessage(name, &fontMessage); } + if (ret == B_OK) + _NotifyValueChanged(name); return ret; } @@ -383,3 +466,20 @@ SettingsMessage::GetValue(const char* name, const BFont& defaultValue) const return value; } + +// #pragma mark - private + + +void +SettingsMessage::_NotifyValueChanged(const char* name) const +{ + BMessage message(MSG_SETTINGS_VALUE_CHANGED); + message.AddString("name", name); + int32 count = fListeners.CountItems(); + for (int32 i = 0; i < count; i++) { + BMessenger* listener = reinterpret_cast( + fListeners.ItemAtFast(i)); + listener->SendMessage(&message); + } +} + diff --git a/src/apps/webpositive/support/SettingsMessage.h b/src/apps/webpositive/support/SettingsMessage.h index 8420238be8..b4d37e6009 100644 --- a/src/apps/webpositive/support/SettingsMessage.h +++ b/src/apps/webpositive/support/SettingsMessage.h @@ -1,5 +1,5 @@ /* - * Copyright 2008 Stephan Aßmus . + * Copyright 2008-2010 Stephan Aßmus . * Copyright 1998 Eric Shepherd. * All rights reserved. Distributed under the terms of the Be Sample Code * license. @@ -7,13 +7,22 @@ #ifndef SETTINGS_MESSAGE_H #define SETTINGS_MESSAGE_H + #include #include +#include #include #include +class BMessenger; class BString; + +enum { + MSG_SETTINGS_VALUE_CHANGED = 'stvc' +}; + + class SettingsMessage : public BMessage { public: SettingsMessage(directory_which directory, @@ -25,6 +34,9 @@ public: status_t Load(); status_t Save() const; + bool AddListener(const BMessenger& listener); + void RemoveListener(const BMessenger& listener); + status_t SetValue(const char* name, bool value); status_t SetValue(const char* name, int8 value); status_t SetValue(const char* name, int16 value); @@ -76,9 +88,13 @@ public: BFont GetValue(const char* name, const BFont& defaultValue) const; +private: + void _NotifyValueChanged(const char* name) const; + private: BPath fPath; status_t fStatus; + BList fListeners; }; #endif // SETTINGS_MESSAGE_H From 6463044ee7867e256bb409283a463a0055979769 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 22 Mar 2010 18:10:49 +0000 Subject: [PATCH 177/349] Add the value to the notification message as well. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@339 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.h | 5 ++++- src/apps/webpositive/support/SettingsMessage.cpp | 10 ++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index c901b2dda7..be0e84da6b 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -34,11 +34,13 @@ class BButton; class BFile; class BGroupLayout; class BWebDownload; +class SettingsMessage; class DownloadWindow : public BWindow { public: - DownloadWindow(BRect frame, bool visible); + DownloadWindow(BRect frame, bool visible, + SettingsMessage* settings); virtual ~DownloadWindow(); virtual void MessageReceived(BMessage* message); @@ -55,6 +57,7 @@ private: private: BGroupLayout* fDownloadViewsLayout; BButton* fRemoveFinishedButton; + SettingsMessage* fSettings; }; diff --git a/src/apps/webpositive/support/SettingsMessage.cpp b/src/apps/webpositive/support/SettingsMessage.cpp index d96ceb1e64..de17c8d3a4 100644 --- a/src/apps/webpositive/support/SettingsMessage.cpp +++ b/src/apps/webpositive/support/SettingsMessage.cpp @@ -475,6 +475,16 @@ SettingsMessage::_NotifyValueChanged(const char* name) const { BMessage message(MSG_SETTINGS_VALUE_CHANGED); message.AddString("name", name); + + // Add the value of that name to the notification. + type_code type; + if (GetInfo(name, &type) == B_OK) { + const void* data; + ssize_t numBytes; + if (FindData(name, type, &data, &numBytes) == B_OK) + message.AddData("value", type, data, numBytes); + } + int32 count = fListeners.CountItems(); for (int32 i = 0; i < count; i++) { BMessenger* listener = reinterpret_cast( From 1beb8c80351e03b8ab4920ce9cd822ec4624f4a0 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 22 Mar 2010 18:11:27 +0000 Subject: [PATCH 178/349] Whoops... should not have been part of the commit... git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@340 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index be0e84da6b..571c7f303b 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -34,13 +34,11 @@ class BButton; class BFile; class BGroupLayout; class BWebDownload; -class SettingsMessage; class DownloadWindow : public BWindow { public: - DownloadWindow(BRect frame, bool visible, - SettingsMessage* settings); + DownloadWindow(BRect frame, bool visible); virtual ~DownloadWindow(); virtual void MessageReceived(BMessage* message); @@ -57,8 +55,6 @@ private: private: BGroupLayout* fDownloadViewsLayout; BButton* fRemoveFinishedButton; - SettingsMessage* fSettings; }; - #endif // DOWNLOAD_WINDOW_H From 636f175b1500fc2bbaf462d29f46af8c6d0ee0b9 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 23 Mar 2010 00:02:05 +0000 Subject: [PATCH 179/349] Work in progress on better download management... * Allow to specify the downloads folder in the General settings page. * Added necessary wiring. * The listener notification was not synchronous anymore because of mixed up default function params in BWebPage. * Added temporary debug output to WebDownloadPrivate.cpp... the restarting downloads code path needs testing yet. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@341 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 3 +- src/apps/webpositive/DownloadWindow.cpp | 75 ++++++++++++++----- src/apps/webpositive/DownloadWindow.h | 6 +- src/apps/webpositive/SettingsWindow.cpp | 27 ++++--- .../webpositive/support/SettingsMessage.cpp | 21 +++++- .../webpositive/support/SettingsMessage.h | 13 +++- 6 files changed, 109 insertions(+), 36 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 7bbb63c633..db118555b5 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -145,7 +145,8 @@ BrowserApp::ReadyToRun() BRect()); bool showDownloads = fSettings->GetValue("show downloads", false); - fDownloadWindow = new DownloadWindow(downloadWindowFrame, showDownloads); + fDownloadWindow = new DownloadWindow(downloadWindowFrame, showDownloads, + fSettings); fSettingsWindow = new SettingsWindow(settingsWindowFrame, fSettings); BWebPage::SetDownloadListener(BMessenger(fDownloadWindow)); diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index f852cb6f2e..6eb6f0c45c 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -48,6 +48,7 @@ #include #include "BrowserApp.h" +#include "SettingsMessage.h" #include "WebDownload.h" #include "WebPage.h" @@ -64,15 +65,13 @@ enum { class IconView : public BView { public: - IconView(const BEntry& entry) + IconView() : BView("Download icon", B_WILL_DRAW), fIconBitmap(BRect(0, 0, 31, 31), 0, B_RGBA32) { - BNode node(&entry); - BNodeInfo info(&node); - info.GetTrackerIcon(&fIconBitmap, B_LARGE_ICON); SetDrawingMode(B_OP_OVER); + memset(fIconBitmap.Bits(), 0, fIconBitmap.BitsLength()); } IconView(BMessage* archive) @@ -83,6 +82,14 @@ public: SetDrawingMode(B_OP_OVER); } + void SetTo(const BEntry& entry) + { + BNode node(&entry); + BNodeInfo info(&node); + info.GetTrackerIcon(&fIconBitmap, B_LARGE_ICON); + Invalidate(); + } + status_t SaveSettings(BMessage* archive) { return fIconBitmap.Archive(archive); @@ -162,27 +169,24 @@ public: bool Init(BMessage* archive = NULL) { - BEntry entry(fPath.Path()); - if (!entry.Exists() && !archive) - return false; - SetViewColor(245, 245, 245); SetFlags(Flags() | B_FULL_UPDATE_ON_RESIZE | B_WILL_DRAW); BGridLayout* layout = GridLayout(); - fStatusBar = new BStatusBar("download progress", fPath.Leaf()); - fStatusBar->SetMaxValue(100); if (archive) { + fStatusBar = new BStatusBar("download progress", fPath.Leaf()); float value; if (archive->FindFloat("value", &value) == B_OK) fStatusBar->SetTo(value); - } + } else + fStatusBar = new BStatusBar("download progress", "Download"); + fStatusBar->SetMaxValue(100); fStatusBar->SetBarHeight(12); - if (entry.Exists()) - fIconView = new IconView(entry); - else + if (archive) fIconView = new IconView(archive); + else + fIconView = new IconView(); if (!fDownload && fStatusBar->CurrentValue() < 100) fTopButton = new SmallButton("Restart", new BMessage(RESTART_DOWNLOAD)); @@ -247,6 +251,17 @@ public: virtual void MessageReceived(BMessage* message) { switch (message->what) { + case B_DOWNLOAD_STARTED: { + BString path; + if (message->FindString("path", &path) != B_OK) + break; + fPath.SetTo(path); + BEntry entry(fPath.Path()); + fIconView->SetTo(entry); +printf("B_DOWNLOAD_STARTED: %s\n", fPath.Leaf()); + fStatusBar->Reset(fPath.Leaf()); + break; + }; case B_DOWNLOAD_PROGRESS: { float progress; if (message->FindFloat("progress", &progress) == B_OK) @@ -391,11 +406,22 @@ protected: }; -DownloadWindow::DownloadWindow(BRect frame, bool visible) +// #pragma mark - + + +DownloadWindow::DownloadWindow(BRect frame, bool visible, + SettingsMessage* settings) : BWindow(frame, "Downloads", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE) { + settings->AddListener(BMessenger(this)); + BPath downloadPath; + if (find_directory(B_DESKTOP_DIRECTORY, &downloadPath) != B_OK) + downloadPath.SetTo("/boot/home/Desktop"); + fDownloadPath = settings->GetValue("download path", downloadPath.Path()); + settings->SetValue("download path", fDownloadPath); + SetLayout(new BGroupLayout(B_VERTICAL)); DownloadsContainerView* downloadsGroupView = new DownloadsContainerView(); @@ -445,7 +471,8 @@ void DownloadWindow::MessageReceived(BMessage* message) { switch (message->what) { - case B_DOWNLOAD_ADDED: { + case B_DOWNLOAD_ADDED: + { BWebDownload* download; if (message->FindPointer("download", reinterpret_cast( &download)) == B_OK) { @@ -453,7 +480,8 @@ DownloadWindow::MessageReceived(BMessage* message) } break; } - case B_DOWNLOAD_REMOVED: { + case B_DOWNLOAD_REMOVED: + { BWebDownload* download; if (message->FindPointer("download", reinterpret_cast( &download)) == B_OK) { @@ -467,6 +495,17 @@ DownloadWindow::MessageReceived(BMessage* message) case SAVE_SETTINGS: _SaveSettings(); break; + + case SETTINGS_VALUE_CHANGED: + { + BString string; + if (message->FindString("name", &string) == B_OK + && string == "download path" + && message->FindString("value", &string) == B_OK) { + fDownloadPath = string; + } + break; + } default: BWindow::MessageReceived(message); break; @@ -486,6 +525,8 @@ DownloadWindow::QuitRequested() void DownloadWindow::_DownloadStarted(BWebDownload* download) { + download->Start(BPath(fDownloadPath.String())); + int32 finishedCount = 0; int32 index = 0; for (int32 i = fDownloadViewsLayout->CountItems() - 1; diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index 571c7f303b..bf7365e1ee 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -28,17 +28,20 @@ #define DOWNLOAD_WINDOW_H +#include #include class BButton; class BFile; class BGroupLayout; class BWebDownload; +class SettingsMessage; class DownloadWindow : public BWindow { public: - DownloadWindow(BRect frame, bool visible); + DownloadWindow(BRect frame, bool visible, + SettingsMessage* settings); virtual ~DownloadWindow(); virtual void MessageReceived(BMessage* message); @@ -55,6 +58,7 @@ private: private: BGroupLayout* fDownloadViewsLayout; BButton* fRemoveFinishedButton; + BString fDownloadPath; }; #endif // DOWNLOAD_WINDOW_H diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index e240147f2d..833924b7a2 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -202,7 +202,7 @@ SettingsWindow::_CreateGeneralPage(float spacing) { fDownloadFolderControl = new BTextControl("download folder", TR("Download folder:"), "", new BMessage(MSG_DOWNLOAD_FOLDER_CHANGED)); -fDownloadFolderControl->SetEnabled(false); + fDownloadFolderControl->SetText(fSettings->GetValue("download path", "")); fNewPageBehaviorCloneCurrentItem = new BMenuItem(TR("Clone current page"), NULL); @@ -312,7 +312,20 @@ SettingsWindow::_CreateFontsPage(float spacing) void SettingsWindow::_ApplySettings() { - // Store settings + // Store general settings + int32 maxHistoryAge = atoi(fDaysInGoMenuControl->Text()); + if (maxHistoryAge <= 0) + maxHistoryAge = 1; + if (maxHistoryAge >= 35) + maxHistoryAge = 35; + BString text; + text << maxHistoryAge; + fDaysInGoMenuControl->SetText(text.String()); + BrowsingHistory::DefaultInstance()->SetMaxHistoryItemAge(maxHistoryAge); + + fSettings->SetValue("download path", fDownloadFolderControl->Text()); + + // Store fond settings fSettings->SetValue("standard font", fStandardFontView->Font()); fSettings->SetValue("serif font", fSerifFontView->Font()); fSettings->SetValue("sans serif font", fSansSerifFontView->Font()); @@ -335,16 +348,6 @@ SettingsWindow::_ApplySettings() // This will find all currently instantiated page settings and apply // the default values, unless the page settings have local overrides. BWebSettings::Default()->Apply(); - - int32 maxHistoryAge = atoi(fDaysInGoMenuControl->Text()); - if (maxHistoryAge <= 0) - maxHistoryAge = 1; - if (maxHistoryAge >= 35) - maxHistoryAge = 35; - BString text; - text << maxHistoryAge; - fDaysInGoMenuControl->SetText(text.String()); - BrowsingHistory::DefaultInstance()->SetMaxHistoryItemAge(maxHistoryAge); } diff --git a/src/apps/webpositive/support/SettingsMessage.cpp b/src/apps/webpositive/support/SettingsMessage.cpp index de17c8d3a4..e11900b1b5 100644 --- a/src/apps/webpositive/support/SettingsMessage.cpp +++ b/src/apps/webpositive/support/SettingsMessage.cpp @@ -11,6 +11,7 @@ #include +#include #include #include #include @@ -52,6 +53,8 @@ SettingsMessage::InitCheck() const status_t SettingsMessage::Load() { + BAutolock _(this); + BFile file(fPath.Path(), B_READ_ONLY); status_t status = file.InitCheck(); @@ -65,6 +68,8 @@ SettingsMessage::Load() status_t SettingsMessage::Save() const { + BAutolock _(const_cast(this)); + BFile file(fPath.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); status_t status = file.InitCheck(); @@ -78,6 +83,8 @@ SettingsMessage::Save() const bool SettingsMessage::AddListener(const BMessenger& listener) { + BAutolock _(this); + BMessenger* listenerCopy = new(std::nothrow) BMessenger(listener); if (listenerCopy && fListeners.AddItem(listenerCopy)) return true; @@ -89,6 +96,8 @@ SettingsMessage::AddListener(const BMessenger& listener) void SettingsMessage::RemoveListener(const BMessenger& listener) { + BAutolock _(this); + for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) { BMessenger* listenerItem = reinterpret_cast( fListeners.ItemAtFast(i)); @@ -401,6 +410,16 @@ SettingsMessage::GetValue(const char* name, const BString& defaultValue) const } +const char* +SettingsMessage::GetValue(const char* name, const char* defaultValue) const +{ + const char* value; + if (FindString(name, &value) != B_OK) + return defaultValue; + return value; +} + + BPoint SettingsMessage::GetValue(const char *name, BPoint defaultValue) const { @@ -473,7 +492,7 @@ SettingsMessage::GetValue(const char* name, const BFont& defaultValue) const void SettingsMessage::_NotifyValueChanged(const char* name) const { - BMessage message(MSG_SETTINGS_VALUE_CHANGED); + BMessage message(SETTINGS_VALUE_CHANGED); message.AddString("name", name); // Add the value of that name to the notification. diff --git a/src/apps/webpositive/support/SettingsMessage.h b/src/apps/webpositive/support/SettingsMessage.h index b4d37e6009..bf2822dd8e 100644 --- a/src/apps/webpositive/support/SettingsMessage.h +++ b/src/apps/webpositive/support/SettingsMessage.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -19,11 +20,11 @@ class BString; enum { - MSG_SETTINGS_VALUE_CHANGED = 'stvc' + SETTINGS_VALUE_CHANGED = '_svc' }; -class SettingsMessage : public BMessage { +class SettingsMessage : public BMessage, public BLocker { public: SettingsMessage(directory_which directory, const char* filename); @@ -49,9 +50,11 @@ public: const char* value); status_t SetValue(const char* name, const BString& value); - status_t SetValue(const char *name, const BPoint& value); + status_t SetValue(const char *name, + const BPoint& value); status_t SetValue(const char* name, const BRect& value); - status_t SetValue(const char* name, const entry_ref& value); + status_t SetValue(const char* name, + const entry_ref& value); status_t SetValue(const char* name, const BMessage& value); status_t SetValue(const char* name, @@ -75,6 +78,8 @@ public: float defaultValue) const; double GetValue(const char* name, double defaultValue) const; + const char* GetValue(const char* name, + const char* defaultValue) const; BString GetValue(const char* name, const BString& defaultValue) const; BPoint GetValue(const char *name, From 0430f93fe3647138259f4207515c1a58ad00765c Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 23 Mar 2010 13:06:33 +0000 Subject: [PATCH 180/349] * Finished testing of downloads interaction with listener and removed debug output. * Optimized download restoration at program start and moved it into download window thread in order not to block app startup. * Downloads which have been removed meanwhile, are displayed with dimmed icon, and the option to Restart it is given. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@342 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 81 +++++++++++++++++++++---- 1 file changed, 69 insertions(+), 12 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 6eb6f0c45c..40f8312af3 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -54,6 +54,8 @@ enum { + INIT = 'init', + OPEN_DOWNLOADS_FOLDER = 'odnf', REMOVE_FINISHED_DOWNLOADS = 'rmfd', OPEN_DOWNLOAD = 'opdn', RESTART_DOWNLOAD = 'rsdn', @@ -65,10 +67,21 @@ enum { class IconView : public BView { public: + IconView(const BEntry& entry) + : + BView("Download icon", B_WILL_DRAW), + fIconBitmap(BRect(0, 0, 31, 31), 0, B_RGBA32), + fDimmedIcon(false) + { + SetDrawingMode(B_OP_OVER); + SetTo(entry); + } + IconView() : BView("Download icon", B_WILL_DRAW), - fIconBitmap(BRect(0, 0, 31, 31), 0, B_RGBA32) + fIconBitmap(BRect(0, 0, 31, 31), 0, B_RGBA32), + fDimmedIcon(false) { SetDrawingMode(B_OP_OVER); memset(fIconBitmap.Bits(), 0, fIconBitmap.BitsLength()); @@ -77,7 +90,8 @@ public: IconView(BMessage* archive) : BView("Download icon", B_WILL_DRAW), - fIconBitmap(archive) + fIconBitmap(archive), + fDimmedIcon(true) { SetDrawingMode(B_OP_OVER); } @@ -90,6 +104,14 @@ public: Invalidate(); } + void SetIconDimmed(bool iconDimmed) + { + if (fDimmedIcon != iconDimmed) { + fDimmedIcon = iconDimmed; + Invalidate(); + } + } + status_t SaveSettings(BMessage* archive) { return fIconBitmap.Archive(archive); @@ -102,6 +124,11 @@ public: virtual void Draw(BRect updateRect) { + if (fDimmedIcon) { + SetDrawingMode(B_OP_ALPHA); + SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY); + SetHighColor(0, 0, 0, 100); + } DrawBitmapAsync(&fIconBitmap); } @@ -121,7 +148,8 @@ public: } private: - BBitmap fIconBitmap; + BBitmap fIconBitmap; + bool fDimmedIcon; }; @@ -183,12 +211,18 @@ public: fStatusBar->SetMaxValue(100); fStatusBar->SetBarHeight(12); - if (archive) - fIconView = new IconView(archive); - else + // fPath is only valid when constructed from archive (fDownload == NULL) + BEntry entry(fPath.Path()); + + if (archive) { + if (!entry.Exists()) + fIconView = new IconView(archive); + else + fIconView = new IconView(entry); + } else fIconView = new IconView(); - if (!fDownload && fStatusBar->CurrentValue() < 100) + if (!fDownload && (fStatusBar->CurrentValue() < 100 || !entry.Exists())) fTopButton = new SmallButton("Restart", new BMessage(RESTART_DOWNLOAD)); else { fTopButton = new SmallButton("Open", new BMessage(OPEN_DOWNLOAD)); @@ -258,7 +292,6 @@ public: fPath.SetTo(path); BEntry entry(fPath.Path()); fIconView->SetTo(entry); -printf("B_DOWNLOAD_STARTED: %s\n", fPath.Leaf()); fStatusBar->Reset(fPath.Leaf()); break; }; @@ -428,7 +461,9 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, fDownloadViewsLayout = downloadsGroupView->GroupLayout(); BMenuBar* menuBar = new BMenuBar("Menu bar"); - BMenu* menu = new BMenu("Window"); + BMenu* menu = new BMenu("Downloads"); + menu->AddItem(new BMenuItem("Open downloads folder", + new BMessage(OPEN_DOWNLOADS_FOLDER))); menu->AddItem(new BMenuItem("Hide", new BMessage(B_QUIT_REQUESTED), 'H')); menuBar->AddItem(menu); @@ -450,9 +485,7 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, ) ); - _LoadSettings(); - // Small trick to get the correct enabled status of the Remove finished button - _DownloadFinished(NULL); + PostMessage(INIT); if (!visible) Hide(); @@ -471,6 +504,14 @@ void DownloadWindow::MessageReceived(BMessage* message) { switch (message->what) { + case INIT: + { + _LoadSettings(); + // Small trick to get the correct enabled status of the Remove + // finished button + _DownloadFinished(NULL); + break; + } case B_DOWNLOAD_ADDED: { BWebDownload* download; @@ -489,6 +530,22 @@ DownloadWindow::MessageReceived(BMessage* message) } break; } + case OPEN_DOWNLOADS_FOLDER: + { + entry_ref ref; + status_t status = get_ref_for_path(fDownloadPath.String(), &ref); + if (status == B_OK) + status = be_roster->Launch(&ref); + if (status != B_OK && status != B_ALREADY_RUNNING) { + BString errorString("The downloads folder could not be " + "opened.\n\n"); + errorString << "Error: " << strerror(status); + BAlert* alert = new BAlert("Error opening downloads folder", + errorString.String(), "OK"); + alert->Go(NULL); + } + break; + } case REMOVE_FINISHED_DOWNLOADS: _RemoveFinishedDownloads(); break; From 2e70c4bf9b51331438ac7fc48f116b7f0479ec18 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 23 Mar 2010 13:17:03 +0000 Subject: [PATCH 181/349] Adjust the steps of the downloads window scrollbar. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@343 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 40f8312af3..aa54a4ee7c 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -435,6 +435,11 @@ protected: scrollBar->MoveBy(1, -1); scrollBar->ResizeBy(0, 2); Target()->ResizeBy(1, 0); + // Set the scroll steps + if (BView* item = Target()->ChildAt(0)) { + scrollBar->SetSteps(item->MinSize().height + 1, + item->MinSize().height + 1); + } } }; From 61c96f4e5ef25a9b1a14aa9486a8a66bcf461bcc Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 23 Mar 2010 14:00:13 +0000 Subject: [PATCH 182/349] Added node monitoring to downloads window. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@344 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 84 +++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 4 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index aa54a4ee7c..0a4fa8fd58 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -264,6 +265,15 @@ public: fDownload->SetProgressListener(BMessenger(this)); fTopButton->SetTarget(this); fBottomButton->SetTarget(this); + + BEntry entry(fPath.Path()); + if (entry.Exists()) + _StartNodeMonitor(entry); + } + + virtual void DetachedFromWindow() + { + _StopNodeMonitor(); } virtual void AllAttached() @@ -285,7 +295,8 @@ public: virtual void MessageReceived(BMessage* message) { switch (message->what) { - case B_DOWNLOAD_STARTED: { + case B_DOWNLOAD_STARTED: + { BString path; if (message->FindString("path", &path) != B_OK) break; @@ -293,15 +304,18 @@ public: BEntry entry(fPath.Path()); fIconView->SetTo(entry); fStatusBar->Reset(fPath.Leaf()); + _StartNodeMonitor(entry); break; }; - case B_DOWNLOAD_PROGRESS: { + case B_DOWNLOAD_PROGRESS: + { float progress; if (message->FindFloat("progress", &progress) == B_OK) fStatusBar->SetTo(progress); break; } - case OPEN_DOWNLOAD: { + case OPEN_DOWNLOAD: + { // TODO: In case of executable files, ask the user first! entry_ref ref; status_t status = get_ref_for_path(fPath.Path(), &ref); @@ -323,7 +337,8 @@ public: DownloadCanceled(); break; - case REMOVE_DOWNLOAD: { + case REMOVE_DOWNLOAD: + { Window()->PostMessage(SAVE_SETTINGS); RemoveSelf(); delete this; @@ -336,6 +351,54 @@ public: // at the window... Window()->PostMessage(message); break; + case B_NODE_MONITOR: + { + int32 opCode; + if (message->FindInt32("opcode", &opCode) != B_OK) + break; + switch (opCode) { + case B_ENTRY_REMOVED: + fIconView->SetIconDimmed(true); + DownloadCanceled(); + break; + case B_ENTRY_MOVED: + { + int64 fromDirectory; + int64 toDirectory; + if (message->FindInt64("from directory", + &fromDirectory) != B_OK + || message->FindInt64("to directory", + &toDirectory) != B_OK) { + break; + } + if (fromDirectory == toDirectory) { + // Entry was renamed + const char* name; + if (message->FindString("name", &name) != B_OK + || strlen(name) == 0) { + break; + } + fPath.GetParent(&fPath); + fPath.Append(name); + fStatusBar->SetText(name); + Window()->PostMessage(SAVE_SETTINGS); + } else { + // Entry was moved elsewhere + fIconView->SetIconDimmed(true); + DownloadCanceled(); + } + break; + } + case B_ATTR_CHANGED: + { + BEntry entry(fPath.Path()); + fIconView->SetIconDimmed(false); + fIconView->SetTo(entry); + break; + } + } + break; + } default: BGridView::MessageReceived(message); } @@ -371,6 +434,19 @@ public: fBottomButton->SetEnabled(true); } +private: + void _StartNodeMonitor(const BEntry& entry) + { + node_ref nref; + if (entry.GetNodeRef(&nref) == B_OK) + watch_node(&nref, B_WATCH_ALL, this); + } + + void _StopNodeMonitor() + { + stop_watching(this); + } + private: IconView* fIconView; BStatusBar* fStatusBar; From b65e0ec04eda1f31059cdac01cf99c9d447bb217 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 23 Mar 2010 14:48:58 +0000 Subject: [PATCH 183/349] Just follow a moved download file, as Axel suggested. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@345 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 30 ++++++++++--------------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 0a4fa8fd58..b9039636cc 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -363,29 +363,23 @@ public: break; case B_ENTRY_MOVED: { - int64 fromDirectory; - int64 toDirectory; - if (message->FindInt64("from directory", - &fromDirectory) != B_OK + // Follow the entry to the new location + dev_t device; + ino_t directory; + const char* name; + if (message->FindInt32("device", + reinterpret_cast(&device)) != B_OK || message->FindInt64("to directory", - &toDirectory) != B_OK) { + reinterpret_cast(&directory)) != B_OK + || message->FindString("name", &name) != B_OK + || strlen(name) == 0) { break; } - if (fromDirectory == toDirectory) { - // Entry was renamed - const char* name; - if (message->FindString("name", &name) != B_OK - || strlen(name) == 0) { - break; - } - fPath.GetParent(&fPath); - fPath.Append(name); + entry_ref ref(device, directory, name); + BEntry entry(&ref); + if (entry.GetPath(&fPath) == B_OK) { fStatusBar->SetText(name); Window()->PostMessage(SAVE_SETTINGS); - } else { - // Entry was moved elsewhere - fIconView->SetIconDimmed(true); - DownloadCanceled(); } break; } From f28abe9d244e9b3b58c3bf988e44430f99092610 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 23 Mar 2010 15:11:29 +0000 Subject: [PATCH 184/349] * An unfinished download is no longer considered finished, just because it isn't currently in progress anymore. * Added feature to remove "missing" downloads, i.e. those for which no corresponding file exists. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@346 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 63 +++++++++++++++++++++++-- src/apps/webpositive/DownloadWindow.h | 2 + 2 files changed, 61 insertions(+), 4 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index b9039636cc..ae60ac4f5f 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -58,6 +58,7 @@ enum { INIT = 'init', OPEN_DOWNLOADS_FOLDER = 'odnf', REMOVE_FINISHED_DOWNLOADS = 'rmfd', + REMOVE_MISSING_DOWNLOADS = 'rmmd', OPEN_DOWNLOAD = 'opdn', RESTART_DOWNLOAD = 'rsdn', CANCEL_DOWNLOAD = 'cndn', @@ -112,6 +113,11 @@ public: Invalidate(); } } + + bool IsIconDimmed() const + { + return fDimmedIcon; + } status_t SaveSettings(BMessage* archive) { @@ -408,6 +414,16 @@ public: return fURL; } + bool IsMissing() const + { + return fIconView->IsIconDimmed(); + } + + bool IsFinished() const + { + return !fDownload && fStatusBar->CurrentValue() == 100; + } + void DownloadFinished() { fDownload = NULL; @@ -549,12 +565,17 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, new BMessage(REMOVE_FINISHED_DOWNLOADS)); fRemoveFinishedButton->SetEnabled(false); + fRemoveMissingButton = new BButton("Remove missing", + new BMessage(REMOVE_MISSING_DOWNLOADS)); + fRemoveMissingButton->SetEnabled(false); + AddChild(BGroupLayoutBuilder(B_VERTICAL) .Add(menuBar) .Add(scrollView) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL) .AddGlue() + .Add(fRemoveMissingButton) .Add(fRemoveFinishedButton) .SetInsets(5, 5, 5, 5) ) @@ -624,6 +645,9 @@ DownloadWindow::MessageReceived(BMessage* message) case REMOVE_FINISHED_DOWNLOADS: _RemoveFinishedDownloads(); break; + case REMOVE_MISSING_DOWNLOADS: + _RemoveMissingDownloads(); + break; case SAVE_SETTINGS: _SaveSettings(); break; @@ -660,6 +684,7 @@ DownloadWindow::_DownloadStarted(BWebDownload* download) download->Start(BPath(fDownloadPath.String())); int32 finishedCount = 0; + int32 missingCount = 0; int32 index = 0; for (int32 i = fDownloadViewsLayout->CountItems() - 1; BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) { @@ -671,10 +696,15 @@ DownloadWindow::_DownloadStarted(BWebDownload* download) index = i; view->RemoveSelf(); delete view; - } else if (!view->Download()) + continue; + } + if (view->IsFinished()) finishedCount++; + if (view->IsMissing()) + missingCount++; } fRemoveFinishedButton->SetEnabled(finishedCount > 0); + fRemoveMissingButton->SetEnabled(missingCount > 0); DownloadProgressView* view = new DownloadProgressView(download); if (!view->Init()) return; @@ -691,19 +721,25 @@ void DownloadWindow::_DownloadFinished(BWebDownload* download) { int32 finishedCount = 0; + int32 missingCount = 0; for (int32 i = 0; BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i++) { DownloadProgressView* view = dynamic_cast( item->View()); if (!view) continue; - if (view->Download() == download) { + if (download && view->Download() == download) { view->DownloadFinished(); finishedCount++; - } else if (!view->Download()) + continue; + } + if (view->IsFinished()) finishedCount++; + if (view->IsMissing()) + missingCount++; } fRemoveFinishedButton->SetEnabled(finishedCount > 0); + fRemoveMissingButton->SetEnabled(missingCount > 0); if (download) _SaveSettings(); } @@ -718,7 +754,7 @@ DownloadWindow::_RemoveFinishedDownloads() item->View()); if (!view) continue; - if (!view->Download()) { + if (view->IsFinished()) { view->RemoveSelf(); delete view; } @@ -728,6 +764,25 @@ DownloadWindow::_RemoveFinishedDownloads() } +void +DownloadWindow::_RemoveMissingDownloads() +{ + for (int32 i = fDownloadViewsLayout->CountItems() - 1; + BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) { + DownloadProgressView* view = dynamic_cast( + item->View()); + if (!view) + continue; + if (view->IsMissing()) { + view->RemoveSelf(); + delete view; + } + } + fRemoveMissingButton->SetEnabled(false); + _SaveSettings(); +} + + void DownloadWindow::_SaveSettings() { diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index bf7365e1ee..3275620293 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -51,6 +51,7 @@ private: void _DownloadStarted(BWebDownload* download); void _DownloadFinished(BWebDownload* download); void _RemoveFinishedDownloads(); + void _RemoveMissingDownloads(); void _SaveSettings(); void _LoadSettings(); bool _OpenSettingsFile(BFile& file, uint32 mode); @@ -58,6 +59,7 @@ private: private: BGroupLayout* fDownloadViewsLayout; BButton* fRemoveFinishedButton; + BButton* fRemoveMissingButton; BString fDownloadPath; }; From f65c57d54eca61c834926836f25da9ab9f7f8c46 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 23 Mar 2010 15:13:56 +0000 Subject: [PATCH 185/349] Removing finished or missing downloads may have to disable the respective other button. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@347 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index ae60ac4f5f..c22a8602cc 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -748,6 +748,7 @@ DownloadWindow::_DownloadFinished(BWebDownload* download) void DownloadWindow::_RemoveFinishedDownloads() { + int32 missingCount = 0; for (int32 i = fDownloadViewsLayout->CountItems() - 1; BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) { DownloadProgressView* view = dynamic_cast( @@ -757,9 +758,11 @@ DownloadWindow::_RemoveFinishedDownloads() if (view->IsFinished()) { view->RemoveSelf(); delete view; - } + } else if (view->IsMissing()) + missingCount++; } fRemoveFinishedButton->SetEnabled(false); + fRemoveMissingButton->SetEnabled(missingCount > 0); _SaveSettings(); } @@ -767,6 +770,7 @@ DownloadWindow::_RemoveFinishedDownloads() void DownloadWindow::_RemoveMissingDownloads() { + int32 finishedCount = 0; for (int32 i = fDownloadViewsLayout->CountItems() - 1; BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) { DownloadProgressView* view = dynamic_cast( @@ -776,9 +780,11 @@ DownloadWindow::_RemoveMissingDownloads() if (view->IsMissing()) { view->RemoveSelf(); delete view; - } + } else if (view->IsFinished()) + finishedCount++; } fRemoveMissingButton->SetEnabled(false); + fRemoveFinishedButton->SetEnabled(finishedCount > 0); _SaveSettings(); } From 34c5cb8c83b6ad9111c2d7649dc040a96aac2f44 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 23 Mar 2010 15:37:01 +0000 Subject: [PATCH 186/349] Following another suggestion by Axel: Check if a download file is being moved into the trash. If it's still in progress, cancel it. Dim the icon in any case. Undim the icon if a download is moved back out of the trash (restarting still has to happen manually). git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@348 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 31 ++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index c22a8602cc..ad0b6d90a5 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -381,12 +382,36 @@ public: || strlen(name) == 0) { break; } + // Construct the BEntry and update fPath entry_ref ref(device, directory, name); BEntry entry(&ref); - if (entry.GetPath(&fPath) == B_OK) { - fStatusBar->SetText(name); - Window()->PostMessage(SAVE_SETTINGS); + if (entry.GetPath(&fPath) != B_OK) + break; + // Find out if the directory is the Trash for this + // volume + char trashPath[B_PATH_NAME_LENGTH]; + if (find_directory(B_TRASH_DIRECTORY, device, false, + trashPath, B_PATH_NAME_LENGTH) == B_OK) { + BPath trashDirectory(trashPath); + BPath parentDirectory; + fPath.GetParent(&parentDirectory); + if (parentDirectory == trashDirectory) { + // The entry was moved into the Trash. + // If the download is still in progress, + // cancel it. + if (fDownload) + fDownload->Cancel(); + fIconView->SetIconDimmed(true); + DownloadCanceled(); + break; + } else if (fIconView->IsIconDimmed()) { + // Maybe it was moved out of the trash. + fIconView->SetIconDimmed(false); + } } + + fStatusBar->SetText(name); + Window()->PostMessage(SAVE_SETTINGS); break; } case B_ATTR_CHANGED: From 7ac6b59c333c879894c189812643e5e2a8768eb2 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Mar 2010 18:41:38 +0000 Subject: [PATCH 187/349] Moved DownloadProgressView and related private classes out into their own source file. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@350 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadProgressView.cpp | 504 ++++++++++++++++++ src/apps/webpositive/DownloadProgressView.h | 86 +++ src/apps/webpositive/DownloadWindow.cpp | 441 +-------------- 3 files changed, 593 insertions(+), 438 deletions(-) create mode 100644 src/apps/webpositive/DownloadProgressView.cpp create mode 100644 src/apps/webpositive/DownloadProgressView.h diff --git a/src/apps/webpositive/DownloadProgressView.cpp b/src/apps/webpositive/DownloadProgressView.cpp new file mode 100644 index 0000000000..bedbc67bad --- /dev/null +++ b/src/apps/webpositive/DownloadProgressView.cpp @@ -0,0 +1,504 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "DownloadProgressView.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "WebDownload.h" +#include "WebPage.h" + + +enum { + OPEN_DOWNLOAD = 'opdn', + RESTART_DOWNLOAD = 'rsdn', + CANCEL_DOWNLOAD = 'cndn', + REMOVE_DOWNLOAD = 'rmdn', +}; + + +class IconView : public BView { +public: + IconView(const BEntry& entry) + : + BView("Download icon", B_WILL_DRAW), + fIconBitmap(BRect(0, 0, 31, 31), 0, B_RGBA32), + fDimmedIcon(false) + { + SetDrawingMode(B_OP_OVER); + SetTo(entry); + } + + IconView() + : + BView("Download icon", B_WILL_DRAW), + fIconBitmap(BRect(0, 0, 31, 31), 0, B_RGBA32), + fDimmedIcon(false) + { + SetDrawingMode(B_OP_OVER); + memset(fIconBitmap.Bits(), 0, fIconBitmap.BitsLength()); + } + + IconView(BMessage* archive) + : + BView("Download icon", B_WILL_DRAW), + fIconBitmap(archive), + fDimmedIcon(true) + { + SetDrawingMode(B_OP_OVER); + } + + void SetTo(const BEntry& entry) + { + BNode node(&entry); + BNodeInfo info(&node); + info.GetTrackerIcon(&fIconBitmap, B_LARGE_ICON); + Invalidate(); + } + + void SetIconDimmed(bool iconDimmed) + { + if (fDimmedIcon != iconDimmed) { + fDimmedIcon = iconDimmed; + Invalidate(); + } + } + + bool IsIconDimmed() const + { + return fDimmedIcon; + } + + status_t SaveSettings(BMessage* archive) + { + return fIconBitmap.Archive(archive); + } + + virtual void AttachedToWindow() + { + SetViewColor(Parent()->ViewColor()); + } + + virtual void Draw(BRect updateRect) + { + if (fDimmedIcon) { + SetDrawingMode(B_OP_ALPHA); + SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY); + SetHighColor(0, 0, 0, 100); + } + DrawBitmapAsync(&fIconBitmap); + } + + virtual BSize MinSize() + { + return BSize(fIconBitmap.Bounds().Width(), fIconBitmap.Bounds().Height()); + } + + virtual BSize PreferredSize() + { + return MinSize(); + } + + virtual BSize MaxSize() + { + return MinSize(); + } + +private: + BBitmap fIconBitmap; + bool fDimmedIcon; +}; + + +class SmallButton : public BButton { +public: + SmallButton(const char* label, BMessage* message = NULL) + : + BButton(label, message) + { + BFont font; + GetFont(&font); + float size = ceilf(font.Size() * 0.8); + font.SetSize(max_c(8, size)); + SetFont(&font, B_FONT_SIZE); + } +}; + + +// #pragma mark - DownloadProgressView + + +DownloadProgressView::DownloadProgressView(BWebDownload* download) + : + BGridView(8, 3), + fDownload(download), + fURL(download->URL()), + fPath(download->Path()), + fExpectedSize(download->ExpectedSize()) +{ +} + + +DownloadProgressView::DownloadProgressView(const BMessage* archive) + : + BGridView(8, 3), + fDownload(NULL), + fURL(), + fPath(), + fExpectedSize(0) +{ + const char* string; + if (archive->FindString("path", &string) == B_OK) + fPath.SetTo(string); + if (archive->FindString("url", &string) == B_OK) + fURL = string; +} + + +bool +DownloadProgressView::Init(BMessage* archive) +{ + SetViewColor(245, 245, 245); + SetFlags(Flags() | B_FULL_UPDATE_ON_RESIZE | B_WILL_DRAW); + + BGridLayout* layout = GridLayout(); + if (archive) { + fStatusBar = new BStatusBar("download progress", fPath.Leaf()); + float value; + if (archive->FindFloat("value", &value) == B_OK) + fStatusBar->SetTo(value); + } else + fStatusBar = new BStatusBar("download progress", "Download"); + fStatusBar->SetMaxValue(100); + fStatusBar->SetBarHeight(12); + + // fPath is only valid when constructed from archive (fDownload == NULL) + BEntry entry(fPath.Path()); + + if (archive) { + if (!entry.Exists()) + fIconView = new IconView(archive); + else + fIconView = new IconView(entry); + } else + fIconView = new IconView(); + + if (!fDownload && (fStatusBar->CurrentValue() < 100 || !entry.Exists())) + fTopButton = new SmallButton("Restart", new BMessage(RESTART_DOWNLOAD)); + else { + fTopButton = new SmallButton("Open", new BMessage(OPEN_DOWNLOAD)); + fTopButton->SetEnabled(fDownload == NULL); + } + if (fDownload) + fBottomButton = new SmallButton("Cancel", new BMessage(CANCEL_DOWNLOAD)); + else { + fBottomButton = new SmallButton("Remove", new BMessage(REMOVE_DOWNLOAD)); + fBottomButton->SetEnabled(fDownload == NULL); + } + + layout->SetInsets(8, 5, 5, 6); + layout->AddView(fIconView, 0, 0, 1, 2); + layout->AddView(fStatusBar, 1, 0, 1, 2); + layout->AddView(fTopButton, 2, 0); + layout->AddView(fBottomButton, 2, 1); + + return true; +} + + +status_t +DownloadProgressView::SaveSettings(BMessage* archive) +{ + if (!archive) + return B_BAD_VALUE; + status_t ret = archive->AddString("path", fPath.Path()); + if (ret == B_OK) + ret = archive->AddString("url", fURL.String()); + if (ret == B_OK) + ret = archive->AddFloat("value", fStatusBar->CurrentValue()); + if (ret == B_OK) + ret = fIconView->SaveSettings(archive); + return ret; +} + + +void +DownloadProgressView::AttachedToWindow() +{ + if (fDownload) + fDownload->SetProgressListener(BMessenger(this)); + fTopButton->SetTarget(this); + fBottomButton->SetTarget(this); + + BEntry entry(fPath.Path()); + if (entry.Exists()) + _StartNodeMonitor(entry); +} + + +void +DownloadProgressView::DetachedFromWindow() +{ + _StopNodeMonitor(); +} + + +void +DownloadProgressView::AllAttached() +{ + SetViewColor(B_TRANSPARENT_COLOR); + SetLowColor(245, 245, 245); + SetHighColor(tint_color(LowColor(), B_DARKEN_1_TINT)); +} + + +void +DownloadProgressView::Draw(BRect updateRect) +{ + BRect bounds(Bounds()); + bounds.bottom--; + FillRect(bounds, B_SOLID_LOW); + bounds.bottom++; + StrokeLine(bounds.LeftBottom(), bounds.RightBottom()); +} + + +void +DownloadProgressView::MessageReceived(BMessage* message) +{ + switch (message->what) { + case B_DOWNLOAD_STARTED: + { + BString path; + if (message->FindString("path", &path) != B_OK) + break; + fPath.SetTo(path); + BEntry entry(fPath.Path()); + fIconView->SetTo(entry); + fStatusBar->Reset(fPath.Leaf()); + _StartNodeMonitor(entry); + break; + }; + case B_DOWNLOAD_PROGRESS: + { + float progress; + if (message->FindFloat("progress", &progress) == B_OK) + fStatusBar->SetTo(progress); + break; + } + case OPEN_DOWNLOAD: + { + // TODO: In case of executable files, ask the user first! + entry_ref ref; + status_t status = get_ref_for_path(fPath.Path(), &ref); + if (status == B_OK) + status = be_roster->Launch(&ref); + if (status != B_OK && status != B_ALREADY_RUNNING) { + BAlert* alert = new BAlert("Open download error", + "The download could not be opened.", "OK"); + alert->Go(NULL); + } + break; + } + case RESTART_DOWNLOAD: + BWebPage::RequestDownload(fURL); + break; + + case CANCEL_DOWNLOAD: + fDownload->Cancel(); + DownloadCanceled(); + break; + + case REMOVE_DOWNLOAD: + { + Window()->PostMessage(SAVE_SETTINGS); + RemoveSelf(); + delete this; + // TOAST! + return; + } + case B_DOWNLOAD_REMOVED: + // TODO: This is a bit asymetric. The removed notification + // arrives here, but it would be nicer if it arrived + // at the window... + Window()->PostMessage(message); + break; + case B_NODE_MONITOR: + { + int32 opCode; + if (message->FindInt32("opcode", &opCode) != B_OK) + break; + switch (opCode) { + case B_ENTRY_REMOVED: + fIconView->SetIconDimmed(true); + DownloadCanceled(); + break; + case B_ENTRY_MOVED: + { + // Follow the entry to the new location + dev_t device; + ino_t directory; + const char* name; + if (message->FindInt32("device", + reinterpret_cast(&device)) != B_OK + || message->FindInt64("to directory", + reinterpret_cast(&directory)) != B_OK + || message->FindString("name", &name) != B_OK + || strlen(name) == 0) { + break; + } + // Construct the BEntry and update fPath + entry_ref ref(device, directory, name); + BEntry entry(&ref); + if (entry.GetPath(&fPath) != B_OK) + break; + // Find out if the directory is the Trash for this + // volume + char trashPath[B_PATH_NAME_LENGTH]; + if (find_directory(B_TRASH_DIRECTORY, device, false, + trashPath, B_PATH_NAME_LENGTH) == B_OK) { + BPath trashDirectory(trashPath); + BPath parentDirectory; + fPath.GetParent(&parentDirectory); + if (parentDirectory == trashDirectory) { + // The entry was moved into the Trash. + // If the download is still in progress, + // cancel it. + if (fDownload) + fDownload->Cancel(); + fIconView->SetIconDimmed(true); + DownloadCanceled(); + break; + } else if (fIconView->IsIconDimmed()) { + // Maybe it was moved out of the trash. + fIconView->SetIconDimmed(false); + } + } + + fStatusBar->SetText(name); + Window()->PostMessage(SAVE_SETTINGS); + break; + } + case B_ATTR_CHANGED: + { + BEntry entry(fPath.Path()); + fIconView->SetIconDimmed(false); + fIconView->SetTo(entry); + break; + } + } + break; + } + default: + BGridView::MessageReceived(message); + } +} + + +BWebDownload* +DownloadProgressView::Download() const +{ + return fDownload; +} + + +const BString& +DownloadProgressView::URL() const +{ + return fURL; +} + + +bool +DownloadProgressView::IsMissing() const +{ + return fIconView->IsIconDimmed(); +} + + +bool +DownloadProgressView::IsFinished() const +{ + return !fDownload && fStatusBar->CurrentValue() == 100; +} + + +void +DownloadProgressView::DownloadFinished() +{ + fDownload = NULL; + fTopButton->SetEnabled(true); + fBottomButton->SetLabel("Remove"); + fBottomButton->SetMessage(new BMessage(REMOVE_DOWNLOAD)); + fBottomButton->SetEnabled(true); +} + + +void +DownloadProgressView::DownloadCanceled() +{ + fDownload = NULL; + fTopButton->SetLabel("Restart"); + fTopButton->SetMessage(new BMessage(RESTART_DOWNLOAD)); + fTopButton->SetEnabled(true); + fBottomButton->SetLabel("Remove"); + fBottomButton->SetMessage(new BMessage(REMOVE_DOWNLOAD)); + fBottomButton->SetEnabled(true); +} + + +// #pragma mark - private + + +void +DownloadProgressView::_StartNodeMonitor(const BEntry& entry) +{ + node_ref nref; + if (entry.GetNodeRef(&nref) == B_OK) + watch_node(&nref, B_WATCH_ALL, this); +} + + +void +DownloadProgressView::_StopNodeMonitor() +{ + stop_watching(this); +} + diff --git a/src/apps/webpositive/DownloadProgressView.h b/src/apps/webpositive/DownloadProgressView.h new file mode 100644 index 0000000000..d39ca93380 --- /dev/null +++ b/src/apps/webpositive/DownloadProgressView.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef DOWNLOAD_PROGRESS_VIEW_H +#define DOWNLOAD_PROGRESS_VIEW_H + + +#include +#include +#include + +class BEntry; +class BStatusBar; +class BWebDownload; +class IconView; +class SmallButton; + + +enum { + SAVE_SETTINGS = 'svst' +}; + + +class DownloadProgressView : public BGridView { +public: + DownloadProgressView(BWebDownload* download); + DownloadProgressView(const BMessage* archive); + + bool Init(BMessage* archive = NULL); + + status_t SaveSettings(BMessage* archive); + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + virtual void AllAttached(); + + virtual void Draw(BRect updateRect); + + virtual void MessageReceived(BMessage* message); + + BWebDownload* Download() const; + const BString& URL() const; + bool IsMissing() const; + bool IsFinished() const; + + void DownloadFinished(); + void DownloadCanceled(); + +private: + void _StartNodeMonitor(const BEntry& entry); + void _StopNodeMonitor(); + +private: + IconView* fIconView; + BStatusBar* fStatusBar; + SmallButton* fTopButton; + SmallButton* fBottomButton; + BWebDownload* fDownload; + BString fURL; + BPath fPath; + off_t fExpectedSize; +}; + +#endif // DOWNLOAD_PROGRESS_VIEW_H diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index ad0b6d90a5..a2f3f38aff 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -30,26 +30,22 @@ #include #include -#include #include -#include #include +#include #include -#include #include #include #include #include -#include -#include #include #include #include #include #include -#include #include "BrowserApp.h" +#include "DownloadProgressView.h" #include "SettingsMessage.h" #include "WebDownload.h" #include "WebPage.h" @@ -59,438 +55,7 @@ enum { INIT = 'init', OPEN_DOWNLOADS_FOLDER = 'odnf', REMOVE_FINISHED_DOWNLOADS = 'rmfd', - REMOVE_MISSING_DOWNLOADS = 'rmmd', - OPEN_DOWNLOAD = 'opdn', - RESTART_DOWNLOAD = 'rsdn', - CANCEL_DOWNLOAD = 'cndn', - REMOVE_DOWNLOAD = 'rmdn', - SAVE_SETTINGS = 'svst' -}; - - -class IconView : public BView { -public: - IconView(const BEntry& entry) - : - BView("Download icon", B_WILL_DRAW), - fIconBitmap(BRect(0, 0, 31, 31), 0, B_RGBA32), - fDimmedIcon(false) - { - SetDrawingMode(B_OP_OVER); - SetTo(entry); - } - - IconView() - : - BView("Download icon", B_WILL_DRAW), - fIconBitmap(BRect(0, 0, 31, 31), 0, B_RGBA32), - fDimmedIcon(false) - { - SetDrawingMode(B_OP_OVER); - memset(fIconBitmap.Bits(), 0, fIconBitmap.BitsLength()); - } - - IconView(BMessage* archive) - : - BView("Download icon", B_WILL_DRAW), - fIconBitmap(archive), - fDimmedIcon(true) - { - SetDrawingMode(B_OP_OVER); - } - - void SetTo(const BEntry& entry) - { - BNode node(&entry); - BNodeInfo info(&node); - info.GetTrackerIcon(&fIconBitmap, B_LARGE_ICON); - Invalidate(); - } - - void SetIconDimmed(bool iconDimmed) - { - if (fDimmedIcon != iconDimmed) { - fDimmedIcon = iconDimmed; - Invalidate(); - } - } - - bool IsIconDimmed() const - { - return fDimmedIcon; - } - - status_t SaveSettings(BMessage* archive) - { - return fIconBitmap.Archive(archive); - } - - virtual void AttachedToWindow() - { - SetViewColor(Parent()->ViewColor()); - } - - virtual void Draw(BRect updateRect) - { - if (fDimmedIcon) { - SetDrawingMode(B_OP_ALPHA); - SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY); - SetHighColor(0, 0, 0, 100); - } - DrawBitmapAsync(&fIconBitmap); - } - - virtual BSize MinSize() - { - return BSize(fIconBitmap.Bounds().Width(), fIconBitmap.Bounds().Height()); - } - - virtual BSize PreferredSize() - { - return MinSize(); - } - - virtual BSize MaxSize() - { - return MinSize(); - } - -private: - BBitmap fIconBitmap; - bool fDimmedIcon; -}; - - -class SmallButton : public BButton { -public: - SmallButton(const char* label, BMessage* message = NULL) - : - BButton(label, message) - { - BFont font; - GetFont(&font); - float size = ceilf(font.Size() * 0.8); - font.SetSize(max_c(8, size)); - SetFont(&font, B_FONT_SIZE); - } -}; - - -class DownloadProgressView : public BGridView { -public: - DownloadProgressView(BWebDownload* download) - : - BGridView(8, 3), - fDownload(download), - fURL(download->URL()), - fPath(download->Path()), - fExpectedSize(download->ExpectedSize()) - { - } - - DownloadProgressView(const BMessage* archive) - : - BGridView(8, 3), - fDownload(NULL), - fURL(), - fPath(), - fExpectedSize(0) - { - const char* string; - if (archive->FindString("path", &string) == B_OK) - fPath.SetTo(string); - if (archive->FindString("url", &string) == B_OK) - fURL = string; - } - - bool Init(BMessage* archive = NULL) - { - SetViewColor(245, 245, 245); - SetFlags(Flags() | B_FULL_UPDATE_ON_RESIZE | B_WILL_DRAW); - - BGridLayout* layout = GridLayout(); - if (archive) { - fStatusBar = new BStatusBar("download progress", fPath.Leaf()); - float value; - if (archive->FindFloat("value", &value) == B_OK) - fStatusBar->SetTo(value); - } else - fStatusBar = new BStatusBar("download progress", "Download"); - fStatusBar->SetMaxValue(100); - fStatusBar->SetBarHeight(12); - - // fPath is only valid when constructed from archive (fDownload == NULL) - BEntry entry(fPath.Path()); - - if (archive) { - if (!entry.Exists()) - fIconView = new IconView(archive); - else - fIconView = new IconView(entry); - } else - fIconView = new IconView(); - - if (!fDownload && (fStatusBar->CurrentValue() < 100 || !entry.Exists())) - fTopButton = new SmallButton("Restart", new BMessage(RESTART_DOWNLOAD)); - else { - fTopButton = new SmallButton("Open", new BMessage(OPEN_DOWNLOAD)); - fTopButton->SetEnabled(fDownload == NULL); - } - if (fDownload) - fBottomButton = new SmallButton("Cancel", new BMessage(CANCEL_DOWNLOAD)); - else { - fBottomButton = new SmallButton("Remove", new BMessage(REMOVE_DOWNLOAD)); - fBottomButton->SetEnabled(fDownload == NULL); - } - - layout->SetInsets(8, 5, 5, 6); - layout->AddView(fIconView, 0, 0, 1, 2); - layout->AddView(fStatusBar, 1, 0, 1, 2); - layout->AddView(fTopButton, 2, 0); - layout->AddView(fBottomButton, 2, 1); - - return true; - } - - status_t SaveSettings(BMessage* archive) - { - if (!archive) - return B_BAD_VALUE; - status_t ret = archive->AddString("path", fPath.Path()); - if (ret == B_OK) - ret = archive->AddString("url", fURL.String()); - if (ret == B_OK) - ret = archive->AddFloat("value", fStatusBar->CurrentValue()); - if (ret == B_OK) - ret = fIconView->SaveSettings(archive); - return ret; - } - - virtual void AttachedToWindow() - { - if (fDownload) - fDownload->SetProgressListener(BMessenger(this)); - fTopButton->SetTarget(this); - fBottomButton->SetTarget(this); - - BEntry entry(fPath.Path()); - if (entry.Exists()) - _StartNodeMonitor(entry); - } - - virtual void DetachedFromWindow() - { - _StopNodeMonitor(); - } - - virtual void AllAttached() - { - SetViewColor(B_TRANSPARENT_COLOR); - SetLowColor(245, 245, 245); - SetHighColor(tint_color(LowColor(), B_DARKEN_1_TINT)); - } - - virtual void Draw(BRect updateRect) - { - BRect bounds(Bounds()); - bounds.bottom--; - FillRect(bounds, B_SOLID_LOW); - bounds.bottom++; - StrokeLine(bounds.LeftBottom(), bounds.RightBottom()); - } - - virtual void MessageReceived(BMessage* message) - { - switch (message->what) { - case B_DOWNLOAD_STARTED: - { - BString path; - if (message->FindString("path", &path) != B_OK) - break; - fPath.SetTo(path); - BEntry entry(fPath.Path()); - fIconView->SetTo(entry); - fStatusBar->Reset(fPath.Leaf()); - _StartNodeMonitor(entry); - break; - }; - case B_DOWNLOAD_PROGRESS: - { - float progress; - if (message->FindFloat("progress", &progress) == B_OK) - fStatusBar->SetTo(progress); - break; - } - case OPEN_DOWNLOAD: - { - // TODO: In case of executable files, ask the user first! - entry_ref ref; - status_t status = get_ref_for_path(fPath.Path(), &ref); - if (status == B_OK) - status = be_roster->Launch(&ref); - if (status != B_OK && status != B_ALREADY_RUNNING) { - BAlert* alert = new BAlert("Open download error", - "The download could not be opened.", "OK"); - alert->Go(NULL); - } - break; - } - case RESTART_DOWNLOAD: - BWebPage::RequestDownload(fURL); - break; - - case CANCEL_DOWNLOAD: - fDownload->Cancel(); - DownloadCanceled(); - break; - - case REMOVE_DOWNLOAD: - { - Window()->PostMessage(SAVE_SETTINGS); - RemoveSelf(); - delete this; - // TOAST! - return; - } - case B_DOWNLOAD_REMOVED: - // TODO: This is a bit asymetric. The removed notification - // arrives here, but it would be nicer if it arrived - // at the window... - Window()->PostMessage(message); - break; - case B_NODE_MONITOR: - { - int32 opCode; - if (message->FindInt32("opcode", &opCode) != B_OK) - break; - switch (opCode) { - case B_ENTRY_REMOVED: - fIconView->SetIconDimmed(true); - DownloadCanceled(); - break; - case B_ENTRY_MOVED: - { - // Follow the entry to the new location - dev_t device; - ino_t directory; - const char* name; - if (message->FindInt32("device", - reinterpret_cast(&device)) != B_OK - || message->FindInt64("to directory", - reinterpret_cast(&directory)) != B_OK - || message->FindString("name", &name) != B_OK - || strlen(name) == 0) { - break; - } - // Construct the BEntry and update fPath - entry_ref ref(device, directory, name); - BEntry entry(&ref); - if (entry.GetPath(&fPath) != B_OK) - break; - // Find out if the directory is the Trash for this - // volume - char trashPath[B_PATH_NAME_LENGTH]; - if (find_directory(B_TRASH_DIRECTORY, device, false, - trashPath, B_PATH_NAME_LENGTH) == B_OK) { - BPath trashDirectory(trashPath); - BPath parentDirectory; - fPath.GetParent(&parentDirectory); - if (parentDirectory == trashDirectory) { - // The entry was moved into the Trash. - // If the download is still in progress, - // cancel it. - if (fDownload) - fDownload->Cancel(); - fIconView->SetIconDimmed(true); - DownloadCanceled(); - break; - } else if (fIconView->IsIconDimmed()) { - // Maybe it was moved out of the trash. - fIconView->SetIconDimmed(false); - } - } - - fStatusBar->SetText(name); - Window()->PostMessage(SAVE_SETTINGS); - break; - } - case B_ATTR_CHANGED: - { - BEntry entry(fPath.Path()); - fIconView->SetIconDimmed(false); - fIconView->SetTo(entry); - break; - } - } - break; - } - default: - BGridView::MessageReceived(message); - } - } - - BWebDownload* Download() const - { - return fDownload; - } - - const BString& URL() const - { - return fURL; - } - - bool IsMissing() const - { - return fIconView->IsIconDimmed(); - } - - bool IsFinished() const - { - return !fDownload && fStatusBar->CurrentValue() == 100; - } - - void DownloadFinished() - { - fDownload = NULL; - fTopButton->SetEnabled(true); - fBottomButton->SetLabel("Remove"); - fBottomButton->SetMessage(new BMessage(REMOVE_DOWNLOAD)); - fBottomButton->SetEnabled(true); - } - - void DownloadCanceled() - { - fDownload = NULL; - fTopButton->SetLabel("Restart"); - fTopButton->SetMessage(new BMessage(RESTART_DOWNLOAD)); - fTopButton->SetEnabled(true); - fBottomButton->SetLabel("Remove"); - fBottomButton->SetMessage(new BMessage(REMOVE_DOWNLOAD)); - fBottomButton->SetEnabled(true); - } - -private: - void _StartNodeMonitor(const BEntry& entry) - { - node_ref nref; - if (entry.GetNodeRef(&nref) == B_OK) - watch_node(&nref, B_WATCH_ALL, this); - } - - void _StopNodeMonitor() - { - stop_watching(this); - } - -private: - IconView* fIconView; - BStatusBar* fStatusBar; - SmallButton* fTopButton; - SmallButton* fBottomButton; - BWebDownload* fDownload; - BString fURL; - BPath fPath; - off_t fExpectedSize; + REMOVE_MISSING_DOWNLOADS = 'rmmd' }; From 799888211608ea8a3bed35e72d4f24e4da25f6ca Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Mar 2010 20:19:40 +0000 Subject: [PATCH 188/349] Imported StringForSize utility function from Haiku. To be removed when WebPositive is integrated into the Haiku source tree. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@351 94f232f2-1747-11df-bad5-a5bfde151594 --- .../webpositive/support/StringForSize.cpp | 43 +++++++++++++++++++ src/apps/webpositive/support/StringForSize.h | 23 ++++++++++ 2 files changed, 66 insertions(+) create mode 100644 src/apps/webpositive/support/StringForSize.cpp create mode 100644 src/apps/webpositive/support/StringForSize.h diff --git a/src/apps/webpositive/support/StringForSize.cpp b/src/apps/webpositive/support/StringForSize.cpp new file mode 100644 index 0000000000..ae7831e397 --- /dev/null +++ b/src/apps/webpositive/support/StringForSize.cpp @@ -0,0 +1,43 @@ +/* + * Copyright 2010 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#include "StringForSize.h" + +#include + + +namespace BPrivate { + + +const char* +string_for_size(double size, char* string, size_t stringSize) +{ + double kib = size / 1024.0; + if (kib < 1.0) { + snprintf(string, stringSize, "%d bytes", (int)size); + return string; + } + double mib = kib / 1024.0; + if (mib < 1.0) { + snprintf(string, stringSize, "%3.2f KiB", kib); + return string; + } + double gib = mib / 1024.0; + if (gib < 1.0) { + snprintf(string, stringSize, "%3.2f MiB", mib); + return string; + } + double tib = gib / 1024.0; + if (tib < 1.0) { + snprintf(string, stringSize, "%3.2f GiB", gib); + return string; + } + snprintf(string, stringSize, "%.2f TiB", tib); + return string; +} + + +} // namespace BPrivate + diff --git a/src/apps/webpositive/support/StringForSize.h b/src/apps/webpositive/support/StringForSize.h new file mode 100644 index 0000000000..fa3e13b115 --- /dev/null +++ b/src/apps/webpositive/support/StringForSize.h @@ -0,0 +1,23 @@ +/* + * Copyright 2010 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef STRING_FOR_SIZE_H +#define STRING_FOR_SIZE_H + +#include + + +namespace BPrivate { + + +const char* string_for_size(double size, char* string, size_t stringSize); + + +} // namespace BPrivate + + +using BPrivate::string_for_size; + + +#endif // COLOR_QUANTIZER_H From 90ac9c309c2294577ab6eb50f1591ccc0ad29780 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Mar 2010 20:20:53 +0000 Subject: [PATCH 189/349] Implemented displaying the download speed and estimated finish time. Looks and behaves the same as in Tracker's status window. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@352 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadProgressView.cpp | 251 ++++++++++++++++-- src/apps/webpositive/DownloadProgressView.h | 27 +- src/apps/webpositive/DownloadWindow.cpp | 15 +- 3 files changed, 273 insertions(+), 20 deletions(-) diff --git a/src/apps/webpositive/DownloadProgressView.cpp b/src/apps/webpositive/DownloadProgressView.cpp index bedbc67bad..5284fb2e31 100644 --- a/src/apps/webpositive/DownloadProgressView.cpp +++ b/src/apps/webpositive/DownloadProgressView.cpp @@ -35,15 +35,17 @@ #include #include #include -#include +#include #include #include #include #include #include +#include #include "WebDownload.h" #include "WebPage.h" +#include "StringForSize.h" enum { @@ -53,6 +55,14 @@ enum { REMOVE_DOWNLOAD = 'rmdn', }; +const bigtime_t kMaxUpdateInterval = 100000LL; +const bigtime_t kSpeedReferenceInterval = 500000LL; +const bigtime_t kShowSpeedInterval = 8000000LL; +const bigtime_t kShowEstimatedFinishInterval = 4000000LL; + +bigtime_t DownloadProgressView::sLastEstimatedFinishSpeedToggleTime = -1; +bool DownloadProgressView::sShowSpeed = true; + class IconView : public BView { public: @@ -167,22 +177,20 @@ public: DownloadProgressView::DownloadProgressView(BWebDownload* download) : - BGridView(8, 3), + BGroupView(B_HORIZONTAL, 8), fDownload(download), fURL(download->URL()), - fPath(download->Path()), - fExpectedSize(download->ExpectedSize()) + fPath(download->Path()) { } DownloadProgressView::DownloadProgressView(const BMessage* archive) : - BGridView(8, 3), + BGroupView(B_HORIZONTAL, 8), fDownload(NULL), fURL(), - fPath(), - fExpectedSize(0) + fPath() { const char* string; if (archive->FindString("path", &string) == B_OK) @@ -195,10 +203,22 @@ DownloadProgressView::DownloadProgressView(const BMessage* archive) bool DownloadProgressView::Init(BMessage* archive) { + fCurrentSize = 0; + fExpectedSize = 0; + fLastUpdateTime = 0; + fBytesPerSecond = 0.0; + for (size_t i = 0; i < kBytesPerSecondSlots; i++) + fBytesPerSecondSlot[i] = 0.0; + fCurrentBytesPerSecondSlot = 0; + fLastSpeedReferenceSize = 0; + fEstimatedFinishReferenceSize = 0; + + fProcessStartTime = fLastSpeedReferenceTime = fEstimatedFinishReferenceTime + = system_time(); + SetViewColor(245, 245, 245); SetFlags(Flags() | B_FULL_UPDATE_ON_RESIZE | B_WILL_DRAW); - BGridLayout* layout = GridLayout(); if (archive) { fStatusBar = new BStatusBar("download progress", fPath.Leaf()); float value; @@ -233,11 +253,37 @@ DownloadProgressView::Init(BMessage* archive) fBottomButton->SetEnabled(fDownload == NULL); } + fInfoView = new BStringView("info view", ""); + + BGroupLayout* layout = GroupLayout(); layout->SetInsets(8, 5, 5, 6); - layout->AddView(fIconView, 0, 0, 1, 2); - layout->AddView(fStatusBar, 1, 0, 1, 2); - layout->AddView(fTopButton, 2, 0); - layout->AddView(fBottomButton, 2, 1); + layout->AddView(fIconView); + BView* verticalGroup = BGroupLayoutBuilder(B_VERTICAL, 3) + .Add(fStatusBar) + .Add(fInfoView) + ; + verticalGroup->SetViewColor(ViewColor()); + layout->AddView(verticalGroup); + verticalGroup = BGroupLayoutBuilder(B_VERTICAL, 3) + .Add(fTopButton) + .Add(fBottomButton) + ; + verticalGroup->SetViewColor(ViewColor()); + layout->AddView(verticalGroup); + + BFont font; + fInfoView->GetFont(&font); + float fontSize = font.Size() * 0.8f; + font.SetSize(max_c(8.0f, fontSize)); + fInfoView->SetFont(&font, B_FONT_SIZE); + fInfoView->SetHighColor(tint_color(fInfoView->LowColor(), + B_DARKEN_4_TINT)); +// font_height fontHeight; +// font.GetHeight(&fontHeight); +// float textHeight = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent); +// fInfoView->SetExplicitMinSize(BSize(B_SIZE_UNSET, textHeight)); +// fInfoView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, textHeight)); + fInfoView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); return true; } @@ -314,13 +360,23 @@ DownloadProgressView::MessageReceived(BMessage* message) fIconView->SetTo(entry); fStatusBar->Reset(fPath.Leaf()); _StartNodeMonitor(entry); + + // Immediately switch to speed display whenever a new download + // starts. + sShowSpeed = true; + sLastEstimatedFinishSpeedToggleTime + = fProcessStartTime = fLastSpeedReferenceTime + = fEstimatedFinishReferenceTime = system_time(); break; }; case B_DOWNLOAD_PROGRESS: { - float progress; - if (message->FindFloat("progress", &progress) == B_OK) - fStatusBar->SetTo(progress); + int64 currentSize; + int64 expectedSize; + if (message->FindInt64("current size", ¤tSize) == B_OK + && message->FindInt64("expected size", &expectedSize) == B_OK) { + _UpdateStatus(currentSize, expectedSize); + } break; } case OPEN_DOWNLOAD: @@ -427,7 +483,7 @@ DownloadProgressView::MessageReceived(BMessage* message) break; } default: - BGridView::MessageReceived(message); + BGroupView::MessageReceived(message); } } @@ -468,6 +524,7 @@ DownloadProgressView::DownloadFinished() fBottomButton->SetLabel("Remove"); fBottomButton->SetMessage(new BMessage(REMOVE_DOWNLOAD)); fBottomButton->SetEnabled(true); + fInfoView->SetText(""); } @@ -484,9 +541,171 @@ DownloadProgressView::DownloadCanceled() } +/*static*/ void +DownloadProgressView::SpeedVersusEstimatedFinishTogglePulse() +{ + bigtime_t now = system_time(); + if (sShowSpeed + && sLastEstimatedFinishSpeedToggleTime + kShowSpeedInterval + <= now) { + sShowSpeed = false; + sLastEstimatedFinishSpeedToggleTime = now; + } else if (!sShowSpeed + && sLastEstimatedFinishSpeedToggleTime + + kShowEstimatedFinishInterval <= now) { + sShowSpeed = true; + sLastEstimatedFinishSpeedToggleTime = now; + } +} + + // #pragma mark - private +void +DownloadProgressView::_UpdateStatus(off_t currentSize, off_t expectedSize) +{ + fCurrentSize = currentSize; + fExpectedSize = expectedSize; + + fStatusBar->SetTo(100.0 * currentSize / expectedSize); + + bigtime_t currentTime = system_time(); + if ((currentTime - fLastUpdateTime) > kMaxUpdateInterval) { + fLastUpdateTime = currentTime; + + if (currentTime >= fLastSpeedReferenceTime + kSpeedReferenceInterval) { + // update current speed every kSpeedReferenceInterval + fCurrentBytesPerSecondSlot + = (fCurrentBytesPerSecondSlot + 1) % kBytesPerSecondSlots; + fBytesPerSecondSlot[fCurrentBytesPerSecondSlot] + = (double)(currentSize - fLastSpeedReferenceSize) + * 1000000LL / (currentTime - fLastSpeedReferenceTime); + fLastSpeedReferenceSize = currentSize; + fLastSpeedReferenceTime = currentTime; + fBytesPerSecond = 0.0; + size_t count = 0; + for (size_t i = 0; i < kBytesPerSecondSlots; i++) { + if (fBytesPerSecondSlot[i] != 0.0) { + fBytesPerSecond += fBytesPerSecondSlot[i]; + count++; + } + } + if (count > 0) + fBytesPerSecond /= count; + } + _UpdateStatusText(); + } +} + + +void +DownloadProgressView::_UpdateStatusText() +{ + fInfoView->SetText(""); + BString buffer; + if (sShowSpeed && fBytesPerSecond != 0.0) { + // Draw speed info + char sizeBuffer[128]; + buffer = "("; + buffer << string_for_size((double)fCurrentSize, sizeBuffer, + sizeof(sizeBuffer)); + buffer << " of "; + buffer << string_for_size((double)fExpectedSize, sizeBuffer, + sizeof(sizeBuffer)); + buffer << ", "; + buffer << string_for_size(fBytesPerSecond, sizeBuffer, + sizeof(sizeBuffer)); + buffer << "/s)"; + float stringWidth = fInfoView->StringWidth(buffer.String()); + if (stringWidth < fInfoView->Bounds().Width()) + fInfoView->SetText(buffer.String()); + else { + // complete string too wide, try with shorter version + buffer << string_for_size(fBytesPerSecond, sizeBuffer, + sizeof(sizeBuffer)); + buffer << "/s"; + stringWidth = fInfoView->StringWidth(buffer.String()); + if (stringWidth < fInfoView->Bounds().Width()) + fInfoView->SetText(buffer.String()); + } + } else if (!sShowSpeed && fCurrentSize < fExpectedSize) { + double totalBytesPerSecond = (double)(fCurrentSize + - fEstimatedFinishReferenceSize) + * 1000000LL / (system_time() - fEstimatedFinishReferenceTime); + double secondsRemaining = (fExpectedSize - fCurrentSize) + / totalBytesPerSecond; + time_t now = (time_t)real_time_clock(); + time_t finishTime = (time_t)(now + secondsRemaining); + + tm _time; + tm* time = localtime_r(&finishTime, &_time); + int32 year = time->tm_year + 1900; + + char timeText[32]; + time_t secondsPerDay = 24 * 60 * 60; + // TODO: Localization of time string... + if (now < finishTime - secondsPerDay) { + // process is going to take more than a day! + sprintf(timeText, "%0*d:%0*d %0*d/%0*d/%ld", + 2, time->tm_hour, 2, time->tm_min, + 2, time->tm_mon + 1, 2, time->tm_mday, year); + } else { + sprintf(timeText, "%0*d:%0*d", + 2, time->tm_hour, 2, time->tm_min); + } + + BString buffer1("Finish: "); + buffer1 << timeText; + finishTime -= now; + time = gmtime(&finishTime); + + BString buffer2; + if (finishTime > secondsPerDay) { + int64 days = finishTime / secondsPerDay; + if (days == 1) + buffer2 << "Over 1 day"; + else + buffer2 << "Over " << days << " days"; + } else if (finishTime > 60 * 60) { + int64 hours = finishTime / (60 * 60); + if (hours == 1) + buffer2 << "Over 1 hour"; + else + buffer2 << "Over " << hours << " hours"; + } else if (finishTime > 60) { + int64 minutes = finishTime / 60; + if (minutes == 1) + buffer2 << "Over 1 minute"; + else + buffer2 << minutes << " minutes"; + } else { + if (finishTime == 1) + buffer2 << "1 second"; + else + buffer2 << finishTime << " seconds"; + } + + buffer2 << " left"; + + buffer = "("; + buffer << buffer1 << " - " << buffer2 << ")"; + + float stringWidth = fInfoView->StringWidth(buffer.String()); + if (stringWidth < fInfoView->Bounds().Width()) + fInfoView->SetText(buffer.String()); + else { + // complete string too wide, try with shorter version + buffer = "("; + buffer << buffer1 << ")"; + stringWidth = fInfoView->StringWidth(buffer.String()); + if (stringWidth < fInfoView->Bounds().Width()) + fInfoView->SetText(buffer.String()); + } + } +} + + void DownloadProgressView::_StartNodeMonitor(const BEntry& entry) { diff --git a/src/apps/webpositive/DownloadProgressView.h b/src/apps/webpositive/DownloadProgressView.h index d39ca93380..4c4ae7e48f 100644 --- a/src/apps/webpositive/DownloadProgressView.h +++ b/src/apps/webpositive/DownloadProgressView.h @@ -28,12 +28,13 @@ #define DOWNLOAD_PROGRESS_VIEW_H -#include +#include #include #include class BEntry; class BStatusBar; +class BStringView; class BWebDownload; class IconView; class SmallButton; @@ -44,7 +45,7 @@ enum { }; -class DownloadProgressView : public BGridView { +class DownloadProgressView : public BGroupView { public: DownloadProgressView(BWebDownload* download); DownloadProgressView(const BMessage* archive); @@ -68,19 +69,41 @@ public: void DownloadFinished(); void DownloadCanceled(); + static void SpeedVersusEstimatedFinishTogglePulse(); + private: + void _UpdateStatus(off_t currentSize, + off_t expectedSize); + void _UpdateStatusText(); void _StartNodeMonitor(const BEntry& entry); void _StopNodeMonitor(); private: IconView* fIconView; BStatusBar* fStatusBar; + BStringView* fInfoView; SmallButton* fTopButton; SmallButton* fBottomButton; BWebDownload* fDownload; BString fURL; BPath fPath; + + off_t fCurrentSize; off_t fExpectedSize; + off_t fLastSpeedReferenceSize; + off_t fEstimatedFinishReferenceSize; + bigtime_t fLastUpdateTime; + bigtime_t fLastSpeedReferenceTime; + bigtime_t fProcessStartTime; + bigtime_t fLastSpeedUpdateTime; + bigtime_t fEstimatedFinishReferenceTime; + static const size_t kBytesPerSecondSlots = 10; + size_t fCurrentBytesPerSecondSlot; + double fBytesPerSecondSlot[kBytesPerSecondSlots]; + double fBytesPerSecond; + + static bigtime_t sLastEstimatedFinishSpeedToggleTime; + static bool sShowSpeed; }; #endif // DOWNLOAD_PROGRESS_VIEW_H diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index a2f3f38aff..5f6dbf1867 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -65,6 +66,7 @@ public: : BGroupView(B_VERTICAL) { + SetFlags(Flags() | B_PULSE_NEEDED); SetViewColor(245, 245, 245); AddChild(BSpaceLayoutItem::CreateGlue()); } @@ -75,6 +77,11 @@ public: return BSize(minSize.width, 80); } + virtual void Pulse() + { + DownloadProgressView::SpeedVersusEstimatedFinishTogglePulse(); + } + protected: virtual void DoLayout() { @@ -129,6 +136,8 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE) { + SetPulseRate(1000000); + settings->AddListener(BMessenger(this)); BPath downloadPath; if (find_directory(B_DESKTOP_DIRECTORY, &downloadPath) != B_OK) @@ -159,15 +168,17 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, new BMessage(REMOVE_MISSING_DOWNLOADS)); fRemoveMissingButton->SetEnabled(false); + const float spacing = be_control_look->DefaultItemSpacing(); + AddChild(BGroupLayoutBuilder(B_VERTICAL) .Add(menuBar) .Add(scrollView) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) - .Add(BGroupLayoutBuilder(B_HORIZONTAL) + .Add(BGroupLayoutBuilder(B_HORIZONTAL, spacing) .AddGlue() .Add(fRemoveMissingButton) .Add(fRemoveFinishedButton) - .SetInsets(5, 5, 5, 5) + .SetInsets(12, 5, 12, 5) ) ); From 3b7f919fb80f5f90a2be6f11a7602f49cad7242e Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Mar 2010 20:21:24 +0000 Subject: [PATCH 190/349] Removed commented out code which wasn't needed after all. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@353 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadProgressView.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/apps/webpositive/DownloadProgressView.cpp b/src/apps/webpositive/DownloadProgressView.cpp index 5284fb2e31..8d780ac695 100644 --- a/src/apps/webpositive/DownloadProgressView.cpp +++ b/src/apps/webpositive/DownloadProgressView.cpp @@ -278,11 +278,6 @@ DownloadProgressView::Init(BMessage* archive) fInfoView->SetFont(&font, B_FONT_SIZE); fInfoView->SetHighColor(tint_color(fInfoView->LowColor(), B_DARKEN_4_TINT)); -// font_height fontHeight; -// font.GetHeight(&fontHeight); -// float textHeight = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent); -// fInfoView->SetExplicitMinSize(BSize(B_SIZE_UNSET, textHeight)); -// fInfoView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, textHeight)); fInfoView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); return true; From c5d7a6c9490b6ed384171e082b032c52f7cb63b7 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Mar 2010 20:25:54 +0000 Subject: [PATCH 191/349] Manually removing downloads needs to trigger checking the button enabled status in the download window. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@354 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 22 ++++++++++++++++++++++ src/apps/webpositive/DownloadWindow.h | 1 + 2 files changed, 23 insertions(+) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 5f6dbf1867..71ba1a3894 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -250,6 +250,7 @@ DownloadWindow::MessageReceived(BMessage* message) _RemoveMissingDownloads(); break; case SAVE_SETTINGS: + _ValidateButtonStatus(); _SaveSettings(); break; @@ -390,6 +391,27 @@ DownloadWindow::_RemoveMissingDownloads() } +void +DownloadWindow::_ValidateButtonStatus() +{ + int32 finishedCount = 0; + int32 missingCount = 0; + for (int32 i = fDownloadViewsLayout->CountItems() - 1; + BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) { + DownloadProgressView* view = dynamic_cast( + item->View()); + if (!view) + continue; + if (view->IsFinished()) + finishedCount++; + if (view->IsMissing()) + missingCount++; + } + fRemoveFinishedButton->SetEnabled(finishedCount > 0); + fRemoveMissingButton->SetEnabled(missingCount > 0); +} + + void DownloadWindow::_SaveSettings() { diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index 3275620293..02f950b86b 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -52,6 +52,7 @@ private: void _DownloadFinished(BWebDownload* download); void _RemoveFinishedDownloads(); void _RemoveMissingDownloads(); + void _ValidateButtonStatus(); void _SaveSettings(); void _LoadSettings(); bool _OpenSettingsFile(BFile& file, uint32 mode); From 2232d801e0b2fc09f38a573e562295c64a842239 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Mar 2010 20:27:26 +0000 Subject: [PATCH 192/349] Canceling a download needs to unset the info text. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@355 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadProgressView.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/webpositive/DownloadProgressView.cpp b/src/apps/webpositive/DownloadProgressView.cpp index 8d780ac695..7ae7dc04e8 100644 --- a/src/apps/webpositive/DownloadProgressView.cpp +++ b/src/apps/webpositive/DownloadProgressView.cpp @@ -533,6 +533,7 @@ DownloadProgressView::DownloadCanceled() fBottomButton->SetLabel("Remove"); fBottomButton->SetMessage(new BMessage(REMOVE_DOWNLOAD)); fBottomButton->SetEnabled(true); + fInfoView->SetText(""); } From 98b056e146c200b0cff22904ea2f6b4dae94f8db Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Mar 2010 22:30:20 +0000 Subject: [PATCH 193/349] * Scroll the downloads which just started into view. * Delete the progress view when init fails. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@356 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 27 +++++++++++++++++++++---- src/apps/webpositive/DownloadWindow.h | 2 ++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 71ba1a3894..1a318338a1 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -157,8 +157,7 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, menu->AddItem(new BMenuItem("Hide", new BMessage(B_QUIT_REQUESTED), 'H')); menuBar->AddItem(menu); - BScrollView* scrollView = new DownloadContainerScrollView( - downloadsGroupView); + fDownloadsScrollView = new DownloadContainerScrollView(downloadsGroupView); fRemoveFinishedButton = new BButton("Remove finished", new BMessage(REMOVE_FINISHED_DOWNLOADS)); @@ -172,7 +171,7 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, AddChild(BGroupLayoutBuilder(B_VERTICAL) .Add(menuBar) - .Add(scrollView) + .Add(fDownloadsScrollView) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL, spacing) .AddGlue() @@ -280,6 +279,9 @@ DownloadWindow::QuitRequested() } +// #pragma mark - private + + void DownloadWindow::_DownloadStarted(BWebDownload* download) { @@ -308,9 +310,26 @@ DownloadWindow::_DownloadStarted(BWebDownload* download) fRemoveFinishedButton->SetEnabled(finishedCount > 0); fRemoveMissingButton->SetEnabled(missingCount > 0); DownloadProgressView* view = new DownloadProgressView(download); - if (!view->Init()) + if (!view->Init()) { + delete view; return; + } fDownloadViewsLayout->AddView(index, view); + float viewHeight = view->MinSize().height + 1; + if (BScrollBar* scrollBar = fDownloadsScrollView->ScrollBar(B_VERTICAL)) { + float min; + float max; + scrollBar->GetRange(&min, &max); + float scrollOffset = min + index * viewHeight; + float scrollBarHeight = scrollBar->Bounds().Height() - 1; + float value = scrollBar->Value(); + if (scrollOffset < value) + scrollBar->SetValue(scrollOffset); + else if (scrollOffset + viewHeight > value + scrollBarHeight) { + float diff = scrollOffset + viewHeight - (value + scrollBarHeight); + scrollBar->SetValue(value + diff); + } + } _SaveSettings(); SetWorkspaces(B_CURRENT_WORKSPACE); diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index 02f950b86b..92d299c89b 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -34,6 +34,7 @@ class BButton; class BFile; class BGroupLayout; +class BScrollView; class BWebDownload; class SettingsMessage; @@ -58,6 +59,7 @@ private: bool _OpenSettingsFile(BFile& file, uint32 mode); private: + BScrollView* fDownloadsScrollView; BGroupLayout* fDownloadViewsLayout; BButton* fRemoveFinishedButton; BButton* fRemoveMissingButton; From ec7e3b29c40b13246d3cbc916689da2c533ed0d9 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 24 Mar 2010 22:32:04 +0000 Subject: [PATCH 194/349] Move variable declaration into proper scope and where it's first needed. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@357 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 1a318338a1..225b3e931c 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -315,11 +315,13 @@ DownloadWindow::_DownloadStarted(BWebDownload* download) return; } fDownloadViewsLayout->AddView(index, view); - float viewHeight = view->MinSize().height + 1; + + // Scroll new download into view if (BScrollBar* scrollBar = fDownloadsScrollView->ScrollBar(B_VERTICAL)) { float min; float max; scrollBar->GetRange(&min, &max); + float viewHeight = view->MinSize().height + 1; float scrollOffset = min + index * viewHeight; float scrollBarHeight = scrollBar->Bounds().Height() - 1; float value = scrollBar->Value(); @@ -330,6 +332,7 @@ DownloadWindow::_DownloadStarted(BWebDownload* download) scrollBar->SetValue(value + diff); } } + _SaveSettings(); SetWorkspaces(B_CURRENT_WORKSPACE); From 5d164e55a582358fe0740e12dd6943d04d515164 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 28 Mar 2010 11:32:14 +0000 Subject: [PATCH 195/349] Use a better algorithm to figure out the final favicon display size. Icons which can be scaled down by an even factor will now be displayed better. Also enable smooth scaling and use a better drawing mode. The net result is that icons will be displayed between 14x14 and 18x18 with the best suitable scaling factor. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@358 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/WebTabView.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index 9f40c9aeef..997d359bad 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -874,11 +874,28 @@ WebTabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect, // clip to icon bounds, if they are smaller if (iconBounds.Contains(fIcon->Bounds())) iconBounds = fIcon->Bounds(); + else { + // Try to scale down the icon by an even factor so the + // final size is between 14 and 18 pixel size. If this fails, + // the icon will simply be displayed at 18x18. + float scale = 2; + while ((fIcon->Bounds().Width() + 1) / scale > kIconSize) + scale *= 2; + if ((fIcon->Bounds().Width() + 1) / scale >= kIconSize - 4 + && (fIcon->Bounds().Height() + 1) / scale >= kIconSize - 4 + && (fIcon->Bounds().Height() + 1) / scale <= kIconSize) { + iconBounds.right = (fIcon->Bounds().Width() + 1) / scale - 1; + iconBounds.bottom = (fIcon->Bounds().Height() + 1) / scale - 1; + } + } BPoint iconPos(frame.left + kIconInset - 1, frame.top + floorf((frame.Height() - iconBounds.Height()) / 2)); iconBounds.OffsetTo(iconPos); - owner->SetDrawingMode(B_OP_OVER); - owner->DrawBitmap(fIcon, fIcon->Bounds(), iconBounds); + owner->SetDrawingMode(B_OP_ALPHA); + owner->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); + owner->DrawBitmap(fIcon, fIcon->Bounds(), iconBounds, + B_FILTER_BITMAP_BILINEAR); + owner->SetDrawingMode(B_OP_COPY); frame.left = frame.left + kIconSize + kIconInset * 2; } From bef126e25eeb544adb3a3af89facb0bd481b9383 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 2 Apr 2010 13:40:04 +0000 Subject: [PATCH 196/349] white space cleanup. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@360 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 0c60ca1f91..c2f0173470 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1224,7 +1224,7 @@ BrowserWindow::_ShowBookmarks() status = get_ref_for_path(path.Path(), &ref); if (status == B_OK) status = be_roster->Launch(&ref); - + if (status != B_OK && status != B_ALREADY_RUNNING) { BString message("There was an error trying to show the Bookmarks " "folder.\n\n"); From 5a9074bc173ee55df43495bf0581542b38eec2e8 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 2 Apr 2010 13:48:17 +0000 Subject: [PATCH 197/349] * Added static method BWebPage::ShutdownOnce(), which the application can call for any at-exit-cleanup. Moved the closing of the favicon database from BWebSettings there, since I wasn't sure if closing the icon database happened at the right time, or perhaps too late if it was done via global destructors. * Temporarily disabled the native cookie support, as it only delays application startup time right now. We are really using the cURL cookies at the moment and they work just fine it seems. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@362 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index db118555b5..756970e686 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -54,6 +54,9 @@ const char* kApplicationSignature = "application/x-vnd.Haiku-WebPositive"; const char* kApplicationName = "WebPositive"; static const uint32 PRELOAD_BROWSING_HISTORY = 'plbh'; +#define ENABLE_NATIVE_COOKIES 0 + + BrowserApp::BrowserApp() : BApplication(kApplicationSignature), @@ -62,6 +65,7 @@ BrowserApp::BrowserApp() fLaunchRefsMessage(0), fInitialized(false), fSettings(NULL), + fCookies(NULL), fCookieJar(NULL), fDownloadWindow(NULL), fSettingsWindow(NULL) @@ -129,6 +133,7 @@ BrowserApp::ReadyToRun() mainSettingsPath << "/Application"; fSettings = new SettingsMessage(B_USER_SETTINGS_DIRECTORY, mainSettingsPath.String()); +#if ENABLE_NATIVE_COOKIES mainSettingsPath = kApplicationName; mainSettingsPath << "/Cookies"; fCookies = new SettingsMessage(B_USER_SETTINGS_DIRECTORY, @@ -137,6 +142,7 @@ BrowserApp::ReadyToRun() cookieArchive = fCookies->GetValue("cookies", cookieArchive); fCookieJar = new BNetworkCookieJar(cookieArchive); BWebPage::SetCookieJar(fCookieJar); +#endif fLastWindowFrame = fSettings->GetValue("window frame", fLastWindowFrame); BRect downloadWindowFrame = fSettings->GetValue("downloads window frame", @@ -265,6 +271,8 @@ BrowserApp::QuitRequested() } } + BWebPage::ShutdownOnce(); + fSettings->SetValue("window frame", fLastWindowFrame); if (fDownloadWindow->Lock()) { fSettings->SetValue("downloads window frame", fDownloadWindow->Frame()); @@ -277,7 +285,7 @@ BrowserApp::QuitRequested() } BMessage cookieArchive; - if (fCookieJar->Archive(&cookieArchive) == B_OK) + if (fCookieJar != NULL && fCookieJar->Archive(&cookieArchive) == B_OK) fCookies->SetValue("cookies", cookieArchive); return true; From 979c4b319ddb3362910b9cd3e197ee561da148f7 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 2 Apr 2010 21:16:25 +0000 Subject: [PATCH 198/349] Replace the previous resize request implementation by a more advanced one: * Ignore resize requests when the window has more than one tab at all. * Make sure the new size is not larger than the screen and shift the window so everything is visible. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@368 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 36 +++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index c2f0173470..b797a9c57e 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -60,6 +60,7 @@ #include #include #include +#include #include #include #include @@ -953,8 +954,41 @@ BrowserWindow::ResizeRequested(float width, float height, BWebView* view) if (view != CurrentWebView()) return; - // TODO: Ignore request when there is more than one BWebView embedded! + // Ignore request when there is more than one BWebView embedded. + if (fTabManager->CountTabs() > 1) + return; + // Make sure the new frame is not larger than the screen frame minus + // window decorator border. + BScreen screen(this); + BRect screenFrame = screen.Frame(); + BRect decoratorFrame = DecoratorFrame(); + BRect frame = Frame(); + + screenFrame.left += decoratorFrame.left - frame.left; + screenFrame.right += decoratorFrame.right - frame.right; + screenFrame.top += decoratorFrame.top - frame.top; + screenFrame.bottom += decoratorFrame.bottom - frame.bottom; + + width = min_c(width, screen.Frame().Width()); + height = min_c(height, screen.Frame().Height()); + + frame.right = frame.left + width; + frame.bottom = frame.top + height; + + // frame is now not larger than screenFrame, but may still be partly outside + if (!screenFrame.Contains(frame)) { + if (frame.left < screenFrame.left) + frame.OffsetBy(screenFrame.left - frame.left, 0); + else if (frame.right > screenFrame.right) + frame.OffsetBy(screenFrame.right - frame.right, 0); + if (frame.top < screenFrame.top) + frame.OffsetBy(screenFrame.top - frame.top, 0); + else if (frame.bottom > screenFrame.bottom) + frame.OffsetBy(screenFrame.bottom - frame.bottom, 0); + } + + MoveTo(frame.left, frame.top); ResizeTo(width, height); } From f41f9676685fd60ab63167aec3d128c44b596494 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 3 Apr 2010 12:45:22 +0000 Subject: [PATCH 199/349] Made method that returns the tab index for a contained view public. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@377 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/WebTabView.cpp | 29 +++++++++++++++-------------- src/apps/webpositive/WebTabView.h | 5 +---- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/WebTabView.cpp index 997d359bad..d953d2ee99 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/WebTabView.cpp @@ -1318,6 +1318,19 @@ TabManager::ViewForTab(int32 tabIndex) const } +int32 +TabManager::TabForView(const BView* containedView) const +{ + int32 count = fCardLayout->CountItems(); + for (int32 i = 0; i < count; i++) { + BLayoutItem* item = fCardLayout->ItemAt(i); + if (item->View() == containedView) + return i; + } + return -1; +} + + void TabManager::SelectTab(int32 tabIndex) { @@ -1333,7 +1346,7 @@ TabManager::SelectTab(int32 tabIndex) void TabManager::SelectTab(const BView* containedView) { - int32 tabIndex = _TabIndexForContainedView(containedView); + int32 tabIndex = TabForView(containedView); if (tabIndex > 0) SelectTab(tabIndex); } @@ -1401,7 +1414,7 @@ void TabManager::SetTabIcon(const BView* containedView, const BBitmap* icon) { WebTabView* tab = dynamic_cast(fTabContainerView->TabAt( - _TabIndexForContainedView(containedView))); + TabForView(containedView))); if (tab) tab->SetIcon(icon); } @@ -1417,15 +1430,3 @@ TabManager::SetCloseButtonsAvailable(bool available) } -int32 -TabManager::_TabIndexForContainedView(const BView* containedView) const -{ - int32 count = fCardLayout->CountItems(); - for (int32 i = 0; i < count; i++) { - BLayoutItem* item = fCardLayout->ItemAt(i); - if (item->View() == containedView) - return i; - } - return -1; -} - diff --git a/src/apps/webpositive/WebTabView.h b/src/apps/webpositive/WebTabView.h index 93129b1b0c..23ea4cc62f 100644 --- a/src/apps/webpositive/WebTabView.h +++ b/src/apps/webpositive/WebTabView.h @@ -60,6 +60,7 @@ public: BView* ContainerView() const; BView* ViewForTab(int32 tabIndex) const; + int32 TabForView(const BView* containedView) const; void SelectTab(int32 tabIndex); void SelectTab(const BView* containedView); @@ -76,10 +77,6 @@ public: const BBitmap* icon); void SetCloseButtonsAvailable(bool available); -private: - int32 _TabIndexForContainedView( - const BView* containedView) const; - private: #if INTEGRATE_MENU_INTO_TAB_BAR BMenu* fMenu; From ea8b6f3fd1eb3234a2c8b862276ee6104671fbd9 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 3 Apr 2010 12:47:12 +0000 Subject: [PATCH 200/349] * Reworked closing a page programatically. BWebPage no longer sends a plain B_QUIT_REQUESTED, instead BWebWindow has a new hook and derived classes can implement it. * Some refactoring in BrowserWindow to move code from MessageReceived into separate methods for easier debugging and cleaner code. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@378 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 51 ++++++++++++++++++-------- src/apps/webpositive/BrowserWindow.h | 2 + 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index b797a9c57e..8f7347ed18 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -650,20 +650,7 @@ printf(" file ok\n"); int32 index; if (message->FindInt32("tab index", &index) != B_OK) index = -1; - BWebView* webView = dynamic_cast(fTabManager->ViewForTab(index)); - if (webView == CurrentWebView()) - break; - SetCurrentWebView(webView); - if (webView) - _UpdateTitle(webView->MainFrameTitle()); - else - _UpdateTitle(""); - if (webView) { - fURLTextControl->SetText(webView->MainFrameURL()); - // Trigger update of the interface to the new page, by requesting - // to resend all notifications. - webView->WebPage()->ResendNotifications(); - } + _TabChanged(index); break; } @@ -876,6 +863,20 @@ BrowserWindow::NewPageCreated(BWebView* view) } +void +BrowserWindow::CloseWindowRequested(BWebView* view) +{ + int32 index = fTabManager->TabForView(view); + if (index < 0) { + // Tab is already gone. + return; + } + BMessage message(CLOSE_TAB); + message.AddInt32("tab index", index); + PostMessage(&message, this); +} + + void BrowserWindow::LoadNegotiating(const BString& url, BWebView* view) { @@ -1122,7 +1123,7 @@ void BrowserWindow::_UpdateTabGroupVisibility() { if (Lock()) { - //fTabGroup->SetVisible(fTabManager->CountTabs() > 1); +// fTabGroup->SetVisible(fTabManager->CountTabs() > 1); fTabManager->SetCloseButtonsAvailable(fTabManager->CountTabs() > 1); Unlock(); } @@ -1141,6 +1142,26 @@ BrowserWindow::_ShutdownTab(int32 index) } +void +BrowserWindow::_TabChanged(int32 index) +{ + BWebView* webView = dynamic_cast(fTabManager->ViewForTab(index)); + if (webView == CurrentWebView()) + return; + SetCurrentWebView(webView); + if (webView) + _UpdateTitle(webView->MainFrameTitle()); + else + _UpdateTitle(""); + if (webView) { + fURLTextControl->SetText(webView->MainFrameURL()); + // Trigger update of the interface to the new page, by requesting + // to resend all notifications. + webView->WebPage()->ResendNotifications(); + } +} + + status_t BrowserWindow::_BookmarkPath(BPath& path) const { diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 4e6cac811c..823db49adb 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -87,6 +87,7 @@ private: BWebView* view); virtual void NewWindowRequested(const BString& url, bool primaryAction); + virtual void CloseWindowRequested(BWebView* view); virtual void NewPageCreated(BWebView* view); virtual void LoadNegotiating(const BString& url, BWebView* view); @@ -121,6 +122,7 @@ private: void _UpdateTitle(const BString &title); void _UpdateTabGroupVisibility(); void _ShutdownTab(int32 index); + void _TabChanged(int32 index); status_t _BookmarkPath(BPath& path) const; void _CreateBookmark(); From 062b23723784dd9e91828e8a7bcf59b7518f81cb Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 3 Apr 2010 16:46:54 +0000 Subject: [PATCH 201/349] * Added optional BWebView parameter passed to BrowserWindow constructor, which will be passed to CreateNewTab(), so that BrowserWindows can be created to embed a view which already exists. * Extended NewPageCreated() hook with the additional information that BWebPage::createPage() already provides. It can be used to decide if new windows shall be created instead of creating another tab for the new page. * Reworked BrowserWindow constructor with regards to the "DoNotHaveToolbar" policy. All views are always created, BLayoutItems are remembered for the various groups and are being turned invisible depending on policy. This way each BrowserWindow is fully valid and can be reconfigured easily during runtime. (Settings could be exposed as well now.) * Changed ChromeClientHaiku::createWindow() implementation to not disregard the "window features" properties if only some of them are not set. All this combined makes the Haiku User Guide translation page open a separate window for editing the translations just like BeZillaBrowser. What does not work (but apparently also not in BeZillaBrowser) is clicking another block and having the editing window update to show that block instead. Don't know if this is actually supposed to work that way, it just seems like it should. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@380 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 306 +++++++++++++------------ src/apps/webpositive/BrowserWindow.h | 14 +- 2 files changed, 169 insertions(+), 151 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 8f7347ed18..07a5f62087 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -238,7 +238,8 @@ public: // #pragma mark - BrowserWindow -BrowserWindow::BrowserWindow(BRect frame, ToolbarPolicy toolbarPolicy) +BrowserWindow::BrowserWindow(BRect frame, ToolbarPolicy toolbarPolicy, + BWebView* webView) : BWebWindow(frame, kApplicationName, B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, @@ -250,162 +251,165 @@ BrowserWindow::BrowserWindow(BRect frame, ToolbarPolicy toolbarPolicy) newTabMessage->AddBool("select", true); fTabManager = new TabManager(BMessenger(this), newTabMessage); - if (toolbarPolicy == HaveToolbar) { - // Menu + // Menu #if INTEGRATE_MENU_INTO_TAB_BAR - BMenu* mainMenu = fTabManager->Menu(); + BMenu* mainMenu = fTabManager->Menu(); #else - BMenu* mainMenu = new BMenuBar("Main menu"); + BMenu* mainMenu = new BMenuBar("Main menu"); #endif - BMenu* menu = new BMenu("Window"); - BMessage* newWindowMessage = new BMessage(NEW_WINDOW); - newWindowMessage->AddString("url", ""); - BMenuItem* newItem = new BMenuItem("New window", newWindowMessage, 'N'); - menu->AddItem(newItem); - newItem->SetTarget(be_app); - newItem = new BMenuItem("New tab", new BMessage(*newTabMessage), 'T'); - menu->AddItem(newItem); - newItem->SetTarget(be_app); - menu->AddItem(new BMenuItem("Open location", new BMessage(OPEN_LOCATION), 'L')); - menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Close window", new BMessage(B_QUIT_REQUESTED), 'W', B_SHIFT_KEY)); - menu->AddItem(new BMenuItem("Close tab", new BMessage(CLOSE_TAB), 'W')); - menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Show downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'J')); - menu->AddItem(new BMenuItem("Show settings", new BMessage(SHOW_SETTINGS_WINDOW))); - menu->AddSeparatorItem(); - BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); - menu->AddItem(quitItem); - quitItem->SetTarget(be_app); - mainMenu->AddItem(menu); + BMenu* menu = new BMenu("Window"); + BMessage* newWindowMessage = new BMessage(NEW_WINDOW); + newWindowMessage->AddString("url", ""); + BMenuItem* newItem = new BMenuItem("New window", newWindowMessage, 'N'); + menu->AddItem(newItem); + newItem->SetTarget(be_app); + newItem = new BMenuItem("New tab", new BMessage(*newTabMessage), 'T'); + menu->AddItem(newItem); + newItem->SetTarget(be_app); + menu->AddItem(new BMenuItem("Open location", new BMessage(OPEN_LOCATION), 'L')); + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("Close window", new BMessage(B_QUIT_REQUESTED), 'W', B_SHIFT_KEY)); + menu->AddItem(new BMenuItem("Close tab", new BMessage(CLOSE_TAB), 'W')); + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("Show downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'J')); + menu->AddItem(new BMenuItem("Show settings", new BMessage(SHOW_SETTINGS_WINDOW))); + menu->AddSeparatorItem(); + BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); + menu->AddItem(quitItem); + quitItem->SetTarget(be_app); + mainMenu->AddItem(menu); - menu = new BMenu("Text"); - menu->AddItem(new BMenuItem("Find", new BMessage(TEXT_SHOW_FIND_GROUP), 'F')); - menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Increase size", new BMessage(TEXT_SIZE_INCREASE), '+')); - menu->AddItem(new BMenuItem("Decrease size", new BMessage(TEXT_SIZE_DECREASE), '-')); - menu->AddItem(new BMenuItem("Reset size", new BMessage(TEXT_SIZE_RESET), '0')); - mainMenu->AddItem(menu); + menu = new BMenu("Text"); + menu->AddItem(new BMenuItem("Find", new BMessage(TEXT_SHOW_FIND_GROUP), 'F')); + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("Increase size", new BMessage(TEXT_SIZE_INCREASE), '+')); + menu->AddItem(new BMenuItem("Decrease size", new BMessage(TEXT_SIZE_DECREASE), '-')); + menu->AddItem(new BMenuItem("Reset size", new BMessage(TEXT_SIZE_RESET), '0')); + mainMenu->AddItem(menu); - fGoMenu = new BMenu("Go"); - mainMenu->AddItem(fGoMenu); + fGoMenu = new BMenu("Go"); + mainMenu->AddItem(fGoMenu); - BPath bookmarkPath; - entry_ref bookmarkRef; - if (_BookmarkPath(bookmarkPath) == B_OK - && get_ref_for_path(bookmarkPath.Path(), &bookmarkRef) == B_OK) { - BMenu* bookmarkMenu - = new BookmarkMenu("Bookmarks", this, &bookmarkRef); - mainMenu->AddItem(bookmarkMenu); - } - - // Back, Forward & Stop - fBackButton = new IconButton("Back", 0, NULL, new BMessage(GO_BACK)); - fBackButton->SetIcon(201); - fBackButton->TrimIcon(); - - fForwardButton = new IconButton("Forward", 0, NULL, new BMessage(GO_FORWARD)); - fForwardButton->SetIcon(202); - fForwardButton->TrimIcon(); - - fStopButton = new IconButton("Stop", 0, NULL, new BMessage(STOP)); - fStopButton->SetIcon(204); - fStopButton->TrimIcon(); - - // URL - fURLTextControl = new BTextControl("url", "", "", NULL); - fURLTextControl->SetDivider(50.0); - - // Go - fGoButton = new BButton("", "Go", new BMessage(GOTO_URL)); - - // Status Bar - fStatusText = new BStringView("status", ""); - fStatusText->SetAlignment(B_ALIGN_LEFT); - fStatusText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); - fStatusText->SetExplicitMinSize(BSize(150, 12)); - // Prevent the window from growing to fit a long status message... - BFont font(be_plain_font); - font.SetSize(ceilf(font.Size() * 0.8)); - fStatusText->SetFont(&font, B_FONT_SIZE); - - // Loading progress bar - fLoadingProgressBar = new BStatusBar("progress"); - fLoadingProgressBar->SetMaxValue(100); - fLoadingProgressBar->Hide(); - fLoadingProgressBar->SetBarHeight(12); - - const float kInsetSpacing = 3; - const float kElementSpacing = 5; - - fFindTextControl = new BTextControl("find", "Find:", "", - new BMessage(TEXT_FIND_NEXT)); - fFindCaseSensitiveCheckBox = new BCheckBox("Match case"); - BView* findGroup = BGroupLayoutBuilder(B_VERTICAL) - .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) - .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) - .Add(fFindTextControl) - .Add(new BButton("Previous", new BMessage(TEXT_FIND_PREVIOUS))) - .Add(new BButton("Next", new BMessage(TEXT_FIND_NEXT))) - .Add(fFindCaseSensitiveCheckBox) - .Add(BSpaceLayoutItem::CreateGlue()) - .Add(new BButton("Close", new BMessage(TEXT_HIDE_FIND_GROUP))) - .SetInsets(kInsetSpacing, kInsetSpacing, - kInsetSpacing, kInsetSpacing) - ) - ; - // Layout - AddChild(BGroupLayoutBuilder(B_VERTICAL) -#if !INTEGRATE_MENU_INTO_TAB_BAR - .Add(mainMenu) -#endif - .Add(fTabManager->TabGroup()) - .Add(BGridLayoutBuilder(kElementSpacing, kElementSpacing) - .Add(fBackButton, 0, 0) - .Add(fForwardButton, 1, 0) - .Add(fStopButton, 2, 0) - .Add(fURLTextControl, 3, 0) - .Add(fGoButton, 4, 0) - .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) - ) - .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) - .Add(fTabManager->ContainerView()) - .Add(findGroup) - .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) - .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) - .Add(fStatusText) - .Add(fLoadingProgressBar, 0.2) - .AddStrut(12 - kElementSpacing) - .SetInsets(kInsetSpacing, 0, kInsetSpacing, 0) - ) - ); - - fURLTextControl->MakeFocus(true); - - fURLAutoCompleter = new TextControlCompleter(fURLTextControl, - new BrowsingHistoryChoiceModel()); - - fFindGroup = layoutItemFor(findGroup); - fTabGroup = layoutItemFor(fTabManager->TabGroup()); - } else { - fBackButton = 0; - fForwardButton = 0; - fStopButton = 0; - fGoButton = 0; - fURLTextControl = 0; - fURLAutoCompleter = 0; - fStatusText = 0; - fLoadingProgressBar = 0; - - AddChild(BGroupLayoutBuilder(B_VERTICAL) - .Add(fTabManager->ContainerView()) - ); + BPath bookmarkPath; + entry_ref bookmarkRef; + if (_BookmarkPath(bookmarkPath) == B_OK + && get_ref_for_path(bookmarkPath.Path(), &bookmarkRef) == B_OK) { + BMenu* bookmarkMenu + = new BookmarkMenu("Bookmarks", this, &bookmarkRef); + mainMenu->AddItem(bookmarkMenu); } - CreateNewTab("", true); + // Back, Forward & Stop + fBackButton = new IconButton("Back", 0, NULL, new BMessage(GO_BACK)); + fBackButton->SetIcon(201); + fBackButton->TrimIcon(); + + fForwardButton = new IconButton("Forward", 0, NULL, new BMessage(GO_FORWARD)); + fForwardButton->SetIcon(202); + fForwardButton->TrimIcon(); + + fStopButton = new IconButton("Stop", 0, NULL, new BMessage(STOP)); + fStopButton->SetIcon(204); + fStopButton->TrimIcon(); + + // URL + fURLTextControl = new BTextControl("url", "", "", NULL); + fURLTextControl->SetDivider(50.0); + + // Go + fGoButton = new BButton("", "Go", new BMessage(GOTO_URL)); + + // Status Bar + fStatusText = new BStringView("status", ""); + fStatusText->SetAlignment(B_ALIGN_LEFT); + fStatusText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); + fStatusText->SetExplicitMinSize(BSize(150, 12)); + // Prevent the window from growing to fit a long status message... + BFont font(be_plain_font); + font.SetSize(ceilf(font.Size() * 0.8)); + fStatusText->SetFont(&font, B_FONT_SIZE); + + // Loading progress bar + fLoadingProgressBar = new BStatusBar("progress"); + fLoadingProgressBar->SetMaxValue(100); + fLoadingProgressBar->Hide(); + fLoadingProgressBar->SetBarHeight(12); + + const float kInsetSpacing = 3; + const float kElementSpacing = 5; + + fFindTextControl = new BTextControl("find", "Find:", "", + new BMessage(TEXT_FIND_NEXT)); + fFindCaseSensitiveCheckBox = new BCheckBox("Match case"); + BView* findGroup = BGroupLayoutBuilder(B_VERTICAL) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) + .Add(fFindTextControl) + .Add(new BButton("Previous", new BMessage(TEXT_FIND_PREVIOUS))) + .Add(new BButton("Next", new BMessage(TEXT_FIND_NEXT))) + .Add(fFindCaseSensitiveCheckBox) + .Add(BSpaceLayoutItem::CreateGlue()) + .Add(new BButton("Close", new BMessage(TEXT_HIDE_FIND_GROUP))) + .SetInsets(kInsetSpacing, kInsetSpacing, + kInsetSpacing, kInsetSpacing) + ) + ; + + BView* navigationGroup = BGroupLayoutBuilder(B_VERTICAL) + .Add(BGridLayoutBuilder(kElementSpacing, kElementSpacing) + .Add(fBackButton, 0, 0) + .Add(fForwardButton, 1, 0) + .Add(fStopButton, 2, 0) + .Add(fURLTextControl, 3, 0) + .Add(fGoButton, 4, 0) + .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) + ) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + ; + + BView* statusGroup = BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) + .Add(fStatusText) + .Add(fLoadingProgressBar, 0.2) + .AddStrut(12 - kElementSpacing) + .SetInsets(kInsetSpacing, 0, kInsetSpacing, 0) + ; + + // Layout + AddChild(BGroupLayoutBuilder(B_VERTICAL) +#if !INTEGRATE_MENU_INTO_TAB_BAR + .Add(mainMenu) +#endif + .Add(fTabManager->TabGroup()) + .Add(navigationGroup) + .Add(fTabManager->ContainerView()) + .Add(findGroup) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(statusGroup) + ); + + fURLTextControl->MakeFocus(true); + + fURLAutoCompleter = new TextControlCompleter(fURLTextControl, + new BrowsingHistoryChoiceModel()); + + fMenuGroup = layoutItemFor(mainMenu); + fTabGroup = layoutItemFor(fTabManager->TabGroup()); + fNavigationGroup = layoutItemFor(navigationGroup); + fFindGroup = layoutItemFor(findGroup); + fStatusGroup = layoutItemFor(statusGroup); + + CreateNewTab("", true, webView); fFindGroup->SetVisible(false); + if (toolbarPolicy == DoNotHaveToolbar) { +#if !INTEGRATE_MENU_INTO_TAB_BAR + fMenuGroup->SetVisible(false); +#endif + fTabGroup->SetVisible(false); + fNavigationGroup->SetVisible(false); + } + AddShortcut('G', B_COMMAND_KEY, new BMessage(TEXT_FIND_NEXT)); AddShortcut('G', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_FIND_PREVIOUS)); AddShortcut('F', B_COMMAND_KEY, new BMessage(TEXT_SHOW_FIND_GROUP)); @@ -857,9 +861,15 @@ BrowserWindow::NewWindowRequested(const BString& url, bool primaryAction) void -BrowserWindow::NewPageCreated(BWebView* view) +BrowserWindow::NewPageCreated(BWebView* view, BRect windowFrame, + bool modalDialog, bool resizable) { - CreateNewTab(BString(), true, view); + if (windowFrame.IsValid()) { + BrowserWindow* window = new BrowserWindow(windowFrame, + DoNotHaveToolbar, view); + window->Show(); + } else + CreateNewTab(BString(), true, view); } diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 823db49adb..9d552f9b4d 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -69,7 +69,8 @@ enum { class BrowserWindow : public BWebWindow { public: BrowserWindow(BRect frame, - ToolbarPolicy = HaveToolbar); + ToolbarPolicy = HaveToolbar, + BWebView* webView = NULL); virtual ~BrowserWindow(); virtual void DispatchMessage(BMessage* message, @@ -88,7 +89,9 @@ private: virtual void NewWindowRequested(const BString& url, bool primaryAction); virtual void CloseWindowRequested(BWebView* view); - virtual void NewPageCreated(BWebView* view); + virtual void NewPageCreated(BWebView* view, + BRect windowFrame, bool modalDialog, + bool resizable); virtual void LoadNegotiating(const BString& url, BWebView* view); virtual void LoadCommitted(const BString& url, @@ -147,8 +150,13 @@ private: TextControlCompleter* fURLAutoCompleter; BStringView* fStatusText; BStatusBar* fLoadingProgressBar; - BLayoutItem* fFindGroup; + + BLayoutItem* fMenuGroup; BLayoutItem* fTabGroup; + BLayoutItem* fNavigationGroup; + BLayoutItem* fFindGroup; + BLayoutItem* fStatusGroup; + BTextControl* fFindTextControl; BCheckBox* fFindCaseSensitiveCheckBox; TabManager* fTabManager; From 92e8b344ace812f44309a3d8afd5e8572cc2a147 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 3 Apr 2010 19:32:47 +0000 Subject: [PATCH 202/349] Added option and infrastructure to zoom the whole page instead of the text only. (Currently not remembered, but the default (off) is often better than zooming images.) git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@381 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 38 +++++++++++++++++--------- src/apps/webpositive/BrowserWindow.h | 3 ++ 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 07a5f62087..399c258611 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -82,9 +82,10 @@ enum { CREATE_BOOKMARK = 'crbm', SHOW_BOOKMARKS = 'shbm', - TEXT_SIZE_INCREASE = 'tsin', - TEXT_SIZE_DECREASE = 'tsdc', - TEXT_SIZE_RESET = 'tsrs', + ZOOM_FACTOR_INCREASE = 'zfin', + ZOOM_FACTOR_DECREASE = 'zfdc', + ZOOM_FACTOR_RESET = 'zfrs', + ZOOM_TEXT_ONLY = 'zfto', TEXT_SHOW_FIND_GROUP = 'sfnd', TEXT_HIDE_FIND_GROUP = 'hfnd', @@ -243,7 +244,8 @@ BrowserWindow::BrowserWindow(BRect frame, ToolbarPolicy toolbarPolicy, : BWebWindow(frame, kApplicationName, B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, - B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS) + B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS), + fZoomTextOnly(true) { BMessage* newTabMessage = new BMessage(NEW_TAB); newTabMessage->AddString("url", ""); @@ -282,9 +284,13 @@ BrowserWindow::BrowserWindow(BRect frame, ToolbarPolicy toolbarPolicy, menu = new BMenu("Text"); menu->AddItem(new BMenuItem("Find", new BMessage(TEXT_SHOW_FIND_GROUP), 'F')); menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Increase size", new BMessage(TEXT_SIZE_INCREASE), '+')); - menu->AddItem(new BMenuItem("Decrease size", new BMessage(TEXT_SIZE_DECREASE), '-')); - menu->AddItem(new BMenuItem("Reset size", new BMessage(TEXT_SIZE_RESET), '0')); + menu->AddItem(new BMenuItem("Increase size", new BMessage(ZOOM_FACTOR_INCREASE), '+')); + menu->AddItem(new BMenuItem("Decrease size", new BMessage(ZOOM_FACTOR_DECREASE), '-')); + menu->AddItem(new BMenuItem("Reset size", new BMessage(ZOOM_FACTOR_RESET), '0')); + fZoomTextOnlyMenuItem = new BMenuItem("Zoom text only", + new BMessage(ZOOM_TEXT_ONLY)); + fZoomTextOnlyMenuItem->SetMarked(fZoomTextOnly); + menu->AddItem(fZoomTextOnlyMenuItem); mainMenu->AddItem(menu); fGoMenu = new BMenu("Go"); @@ -593,14 +599,20 @@ printf(" file ok\n"); break; } - case TEXT_SIZE_INCREASE: - CurrentWebView()->IncreaseTextSize(); + case ZOOM_FACTOR_INCREASE: + CurrentWebView()->IncreaseZoomFactor(fZoomTextOnly); break; - case TEXT_SIZE_DECREASE: - CurrentWebView()->DecreaseTextSize(); + case ZOOM_FACTOR_DECREASE: + CurrentWebView()->DecreaseZoomFactor(fZoomTextOnly); break; - case TEXT_SIZE_RESET: - CurrentWebView()->ResetTextSize(); + case ZOOM_FACTOR_RESET: + CurrentWebView()->ResetZoomFactor(); + break; + case ZOOM_TEXT_ONLY: + fZoomTextOnly = !fZoomTextOnly; + fZoomTextOnlyMenuItem->SetMarked(fZoomTextOnly); + // TODO: Would be nice to have an instant update if the page is already + // zoomed. break; case TEXT_FIND_NEXT: diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 9d552f9b4d..e1ec942b2e 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -40,6 +40,7 @@ class BDirectory; class BFile; class BLayoutItem; class BMenu; +class BMenuItem; class BPath; class BStatusBar; class BStringView; @@ -142,6 +143,8 @@ private: private: BMenu* fGoMenu; + BMenuItem* fZoomTextOnlyMenuItem; + bool fZoomTextOnly; IconButton* fBackButton; IconButton* fForwardButton; IconButton* fStopButton; From cb0b497952438ca8ddd066ae673d8692e66864e7 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 3 Apr 2010 19:49:12 +0000 Subject: [PATCH 203/349] Don't display the unit of the current size if it's the same as the unit of the expected size in the download progress view. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@382 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadProgressView.cpp | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/apps/webpositive/DownloadProgressView.cpp b/src/apps/webpositive/DownloadProgressView.cpp index 7ae7dc04e8..ddee6317c5 100644 --- a/src/apps/webpositive/DownloadProgressView.cpp +++ b/src/apps/webpositive/DownloadProgressView.cpp @@ -110,7 +110,7 @@ public: Invalidate(); } } - + bool IsIconDimmed() const { return fDimmedIcon; @@ -307,7 +307,7 @@ DownloadProgressView::AttachedToWindow() fDownload->SetProgressListener(BMessenger(this)); fTopButton->SetTarget(this); fBottomButton->SetTarget(this); - + BEntry entry(fPath.Path()); if (entry.Exists()) _StartNodeMonitor(entry); @@ -604,11 +604,23 @@ DownloadProgressView::_UpdateStatusText() // Draw speed info char sizeBuffer[128]; buffer = "("; - buffer << string_for_size((double)fCurrentSize, sizeBuffer, + // Get strings for current and expected size and remove the unit + // from the current size string if it's the same as the expected + // size unit. + BString currentSize = string_for_size((double)fCurrentSize, sizeBuffer, sizeof(sizeBuffer)); + BString expectedSize = string_for_size((double)fExpectedSize, sizeBuffer, + sizeof(sizeBuffer)); + int currentSizeUnitPos = currentSize.FindLast(' '); + int expectedSizeUnitPos = expectedSize.FindLast(' '); + if (currentSizeUnitPos >= 0 && expectedSizeUnitPos >= 0 + && strcmp(currentSize.String() + currentSizeUnitPos, + expectedSize.String() + expectedSizeUnitPos) == 0) { + currentSize.Truncate(currentSizeUnitPos); + } + buffer << currentSize; buffer << " of "; - buffer << string_for_size((double)fExpectedSize, sizeBuffer, - sizeof(sizeBuffer)); + buffer << expectedSize; buffer << ", "; buffer << string_for_size(fBytesPerSecond, sizeBuffer, sizeof(sizeBuffer)); From 65e61cdca4cce6bcc491608fb4971cb55ea37aa8 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 5 Apr 2010 17:05:17 +0000 Subject: [PATCH 204/349] * Make use of the new svn revision jam magic to embed the current svn version into the about window. * Give access to the about window from the browser windows. * Renamed the "Show *" entries in the Window menu to just "*". git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@387 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 9 ++++++--- src/apps/webpositive/BrowserWindow.cpp | 7 +++++-- src/apps/webpositive/svn_revision.cpp | 10 ++++++++++ src/apps/webpositive/svn_revision.h | 15 +++++++++++++++ 4 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 src/apps/webpositive/svn_revision.cpp create mode 100644 src/apps/webpositive/svn_revision.h diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 756970e686..29439d2fde 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -34,6 +34,7 @@ #include "DownloadWindow.h" #include "SettingsMessage.h" #include "SettingsWindow.h" +#include "svn_revision.h" #include "NetworkCookieJar.h" #include "WebPage.h" #include "WebSettings.h" @@ -86,9 +87,11 @@ BrowserApp::~BrowserApp() void BrowserApp::AboutRequested() { - BAlert* alert = new BAlert("About WebPositive", - "WebPositive\n\nby Ryan Leavengood, Andrea Anzani, " - "Maxime Simone, Michael Lotz, Rene Gollent and Stephan Aßmus", + BString aboutText("WebPositive\n\nby Ryan Leavengood, Andrea Anzani, " + "Maxime Simone, Michael Lotz, Rene Gollent and Stephan Aßmus"); + aboutText << "\n\nSVN revision: " << kSVNRevision; + + BAlert* alert = new BAlert("About WebPositive", aboutText.String(), "Sweet!"); alert->Go(); } diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 399c258611..4b7cdc8c4e 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -273,8 +273,11 @@ BrowserWindow::BrowserWindow(BRect frame, ToolbarPolicy toolbarPolicy, menu->AddItem(new BMenuItem("Close window", new BMessage(B_QUIT_REQUESTED), 'W', B_SHIFT_KEY)); menu->AddItem(new BMenuItem("Close tab", new BMessage(CLOSE_TAB), 'W')); menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Show downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'J')); - menu->AddItem(new BMenuItem("Show settings", new BMessage(SHOW_SETTINGS_WINDOW))); + menu->AddItem(new BMenuItem("Downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'J')); + menu->AddItem(new BMenuItem("Settings", new BMessage(SHOW_SETTINGS_WINDOW))); + BMenuItem* aboutItem = new BMenuItem("About", new BMessage(B_ABOUT_REQUESTED)); + menu->AddItem(aboutItem); + aboutItem->SetTarget(be_app); menu->AddSeparatorItem(); BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); menu->AddItem(quitItem); diff --git a/src/apps/webpositive/svn_revision.cpp b/src/apps/webpositive/svn_revision.cpp new file mode 100644 index 0000000000..489c64cdd4 --- /dev/null +++ b/src/apps/webpositive/svn_revision.cpp @@ -0,0 +1,10 @@ +/* + * Copyright 2006-2009, Ingo Weinhold + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#include "svn_revision.h" + +const int32 kSVNRevision = + #include "svn_revision" +; diff --git a/src/apps/webpositive/svn_revision.h b/src/apps/webpositive/svn_revision.h new file mode 100644 index 0000000000..fff9e9b122 --- /dev/null +++ b/src/apps/webpositive/svn_revision.h @@ -0,0 +1,15 @@ +/* + * Copyright 2006-2009, Ingo Weinhold + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#ifndef SVN_REVISION_H +#define SVN_REVISION_H + +#include + + +extern const int32 kSVNRevision; + + +#endif // SVN_REVISION_H From 0145cf4349fcd01b8daa93c46703d7a03c4c0a47 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 6 Apr 2010 01:24:07 +0000 Subject: [PATCH 205/349] Remember the currently focused view within a tab in the user data that can be associated with a BWebView and restore the focus when the tab changes. This fixes a number of annoying issues. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@391 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 28 ++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 4b7cdc8c4e..5f96f7fa5c 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -236,6 +236,24 @@ public: }; +class PageUserData : public BWebView::UserData { +public: + PageUserData(BView* focusedView) + : + fFocusedView(focusedView) + { + } + + BView* FocusedView() const + { + return fFocusedView; + } + +private: + BView* fFocusedView; +}; + + // #pragma mark - BrowserWindow @@ -1173,7 +1191,17 @@ BrowserWindow::_TabChanged(int32 index) BWebView* webView = dynamic_cast(fTabManager->ViewForTab(index)); if (webView == CurrentWebView()) return; + + CurrentWebView()->SetUserData(new PageUserData(CurrentFocus())); + SetCurrentWebView(webView); + + PageUserData* userData = static_cast(webView->GetUserData()); + if (userData) + userData->FocusedView()->MakeFocus(true); + else + webView->MakeFocus(true); + if (webView) _UpdateTitle(webView->MainFrameTitle()); else From bb68c7f66d8d4f445bec5fd4928f5d92cdb25e54 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 6 Apr 2010 23:50:17 +0000 Subject: [PATCH 206/349] White space cleanup git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@392 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/support/SettingsMessage.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/support/SettingsMessage.h b/src/apps/webpositive/support/SettingsMessage.h index bf2822dd8e..8f22785788 100644 --- a/src/apps/webpositive/support/SettingsMessage.h +++ b/src/apps/webpositive/support/SettingsMessage.h @@ -29,7 +29,7 @@ public: SettingsMessage(directory_which directory, const char* filename); virtual ~SettingsMessage(); - + status_t InitCheck() const; status_t Load(); From d5f0e82b842da208d3c297fa2c5eb22ad75539cf Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 6 Apr 2010 23:52:43 +0000 Subject: [PATCH 207/349] * Moved some settings keys into new files SettingsKeys.h/cpp to make it less likely to introduce erros with spelling settings keys wrong somewhere. * Introduced new setting for the behavior if tabs should show at all if only one page is showing in a window. Defaults to on, i.e. the previous behavior. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@393 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 4 +- src/apps/webpositive/BrowserWindow.cpp | 402 +++++++++++++----------- src/apps/webpositive/BrowserWindow.h | 9 +- src/apps/webpositive/SettingsKeys.cpp | 32 ++ src/apps/webpositive/SettingsKeys.h | 37 +++ src/apps/webpositive/SettingsWindow.cpp | 77 +++-- src/apps/webpositive/SettingsWindow.h | 2 + 7 files changed, 347 insertions(+), 216 deletions(-) create mode 100644 src/apps/webpositive/SettingsKeys.cpp create mode 100644 src/apps/webpositive/SettingsKeys.h diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 29439d2fde..1cade8cd09 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -167,7 +167,7 @@ BrowserApp::ReadyToRun() delete fLaunchRefsMessage; fLaunchRefsMessage = 0; } else { - BrowserWindow* window = new BrowserWindow(fLastWindowFrame); + BrowserWindow* window = new BrowserWindow(fLastWindowFrame, fSettings); window->Show(); } PostMessage(PRELOAD_BROWSING_HISTORY); @@ -327,7 +327,7 @@ BrowserApp::_CreateNewWindow(const BString& url) if (!BScreen().Frame().Contains(fLastWindowFrame)) fLastWindowFrame.OffsetTo(50, 50); - BrowserWindow* window = new BrowserWindow(fLastWindowFrame); + BrowserWindow* window = new BrowserWindow(fLastWindowFrame, fSettings); window->Show(); if (url.Length()) window->CurrentWebView()->LoadURL(url.String()); diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 5f96f7fa5c..a5d8fa2671 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -38,6 +38,8 @@ #include "BrowsingHistory.h" #include "IconButton.h" #include "NavMenu.h" +#include "SettingsKeys.h" +#include "SettingsMessage.h" #include "TextControlCompleter.h" #include "WebPage.h" #include "WebTabView.h" @@ -257,14 +259,21 @@ private: // #pragma mark - BrowserWindow -BrowserWindow::BrowserWindow(BRect frame, ToolbarPolicy toolbarPolicy, - BWebView* webView) +BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, + ToolbarPolicy toolbarPolicy, BWebView* webView) : BWebWindow(frame, kApplicationName, B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS), - fZoomTextOnly(true) + fAppSettings(appSettings), + fZoomTextOnly(true), + fShowTabsIfSinglePageOpen(true) { + fAppSettings->AddListener(BMessenger(this)); +// fZoomTextOnly = fAppSettings->GetValue("zoom text only", fZoomTextOnly); + fShowTabsIfSinglePageOpen = fAppSettings->GetValue( + kSettingsKeyShowTabsIfSinglePageOpen, fShowTabsIfSinglePageOpen); + BMessage* newTabMessage = new BMessage(NEW_TAB); newTabMessage->AddString("url", ""); newTabMessage->AddPointer("window", this); @@ -461,6 +470,7 @@ BrowserWindow::BrowserWindow(BRect frame, ToolbarPolicy toolbarPolicy, BrowserWindow::~BrowserWindow() { + fAppSettings->RemoveListener(BMessenger(this)); delete fURLAutoCompleter; delete fTabManager; } @@ -501,199 +511,220 @@ void BrowserWindow::MessageReceived(BMessage* message) { switch (message->what) { - case OPEN_LOCATION: - if (fURLTextControl) { - if (fURLTextControl->TextView()->IsFocus()) - fURLTextControl->TextView()->SelectAll(); - else - fURLTextControl->MakeFocus(true); - } - break; - case RELOAD: - CurrentWebView()->Reload(); - break; - case GOTO_URL: { - BString url; - if (message->FindString("url", &url) != B_OK) - url = fURLTextControl->Text(); - fTabManager->SetTabIcon(CurrentWebView(), NULL); - CurrentWebView()->LoadURL(url.String()); - break; - } - case GO_BACK: - CurrentWebView()->GoBack(); - break; - case GO_FORWARD: - CurrentWebView()->GoForward(); - break; - case STOP: - CurrentWebView()->StopLoading(); - break; - - case CLEAR_HISTORY: { - BrowsingHistory* history = BrowsingHistory::DefaultInstance(); - if (history->CountItems() == 0) + case OPEN_LOCATION: + if (fURLTextControl) { + if (fURLTextControl->TextView()->IsFocus()) + fURLTextControl->TextView()->SelectAll(); + else + fURLTextControl->MakeFocus(true); + } + break; + case RELOAD: + CurrentWebView()->Reload(); + break; + case GOTO_URL: + { + BString url; + if (message->FindString("url", &url) != B_OK) + url = fURLTextControl->Text(); + fTabManager->SetTabIcon(CurrentWebView(), NULL); + CurrentWebView()->LoadURL(url.String()); break; - BAlert* alert = new BAlert("Confirmation", "Do you really want to " - "clear the browsing history?", "Clear", "Cancel"); - if (alert->Go() == 0) - history->Clear(); - break; - } - - case CREATE_BOOKMARK: - _CreateBookmark(); - break; - case SHOW_BOOKMARKS: - _ShowBookmarks(); - break; - - case B_REFS_RECEIVED: { - // Currently the only source of these messages is the bookmarks menu. - // Filter refs into URLs, this also gets rid of refs for folders. - // For clicks on sub-folders in the bookmarks menu, we have Tracker - // open the corresponding folder. - entry_ref ref; - uint32 addedCount = 0; - for (int32 i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) { -printf("B_REFS_RECEIVED: %s\n", ref.name); - BEntry entry(&ref); - uint32 addedSubCount = 0; - if (entry.IsDirectory()) { - BDirectory directory(&entry); -printf(" directory ok\n"); - _AddBookmarkURLsRecursively(directory, message, addedSubCount); - } else { - BFile file(&ref, B_READ_ONLY); -printf(" file ok\n"); - BString url; - if (_ReadURLAttr(file, url)) { - message->AddString("url", url.String()); - addedSubCount++; - } - } - if (addedSubCount == 0) { - // Don't know what to do with this entry, just pass it - // on to the system to handle. Note that this may result - // in us opening other supported files via the application - // mechanism. - be_roster->Launch(&ref); - } - addedCount += addedSubCount; } - message->RemoveName("refs"); - if (addedCount > 10) { - BString string; - string << "Do you want to open " << addedCount; - string << " bookmarks all at once?"; - BAlert* alert = new BAlert("Open bookmarks confirmation", - string.String(), "Cancel", "Open all"); - if (alert->Go() == 0) + case GO_BACK: + CurrentWebView()->GoBack(); + break; + case GO_FORWARD: + CurrentWebView()->GoForward(); + break; + case STOP: + CurrentWebView()->StopLoading(); + break; + + case CLEAR_HISTORY: { + BrowsingHistory* history = BrowsingHistory::DefaultInstance(); + if (history->CountItems() == 0) break; - } - be_app->PostMessage(message); - break; - } - case B_SIMPLE_DATA: { - // User possibly dropped files on this window. - // If there is more than one entry_ref, let the app handle it (open one - // new page per ref). If there is one ref, open it in this window. - type_code type; - int32 countFound; - if (message->GetInfo("refs", &type, &countFound) != B_OK - || type != B_REF_TYPE) { + BAlert* alert = new BAlert("Confirmation", "Do you really want to " + "clear the browsing history?", "Clear", "Cancel"); + if (alert->Go() == 0) + history->Clear(); break; } - if (countFound > 1) { - message->what = B_REFS_RECEIVED; + + case CREATE_BOOKMARK: + _CreateBookmark(); + break; + case SHOW_BOOKMARKS: + _ShowBookmarks(); + break; + + case B_REFS_RECEIVED: + { + // Currently the only source of these messages is the bookmarks menu. + // Filter refs into URLs, this also gets rid of refs for folders. + // For clicks on sub-folders in the bookmarks menu, we have Tracker + // open the corresponding folder. + entry_ref ref; + uint32 addedCount = 0; + for (int32 i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) { + BEntry entry(&ref); + uint32 addedSubCount = 0; + if (entry.IsDirectory()) { + BDirectory directory(&entry); + _AddBookmarkURLsRecursively(directory, message, + addedSubCount); + } else { + BFile file(&ref, B_READ_ONLY); + BString url; + if (_ReadURLAttr(file, url)) { + message->AddString("url", url.String()); + addedSubCount++; + } + } + if (addedSubCount == 0) { + // Don't know what to do with this entry, just pass it + // on to the system to handle. Note that this may result + // in us opening other supported files via the application + // mechanism. + be_roster->Launch(&ref); + } + addedCount += addedSubCount; + } + message->RemoveName("refs"); + if (addedCount > 10) { + BString string; + string << "Do you want to open " << addedCount; + string << " bookmarks all at once?"; + BAlert* alert = new BAlert("Open bookmarks confirmation", + string.String(), "Cancel", "Open all"); + if (alert->Go() == 0) + break; + } be_app->PostMessage(message); break; } - entry_ref ref; - if (message->FindRef("refs", &ref) != B_OK) + case B_SIMPLE_DATA: + { + // User possibly dropped files on this window. + // If there is more than one entry_ref, let the app handle it + // (open one new page per ref). If there is one ref, open it in + // this window. + type_code type; + int32 countFound; + if (message->GetInfo("refs", &type, &countFound) != B_OK + || type != B_REF_TYPE) { + break; + } + if (countFound > 1) { + message->what = B_REFS_RECEIVED; + be_app->PostMessage(message); + break; + } + entry_ref ref; + if (message->FindRef("refs", &ref) != B_OK) + break; + BEntry entry(&ref, true); + BPath path; + if (!entry.Exists() || entry.GetPath(&path) != B_OK) + break; + CurrentWebView()->LoadURL(path.Path()); break; - BEntry entry(&ref, true); - BPath path; - if (!entry.Exists() || entry.GetPath(&path) != B_OK) - break; - CurrentWebView()->LoadURL(path.Path()); - break; - } - - case ZOOM_FACTOR_INCREASE: - CurrentWebView()->IncreaseZoomFactor(fZoomTextOnly); - break; - case ZOOM_FACTOR_DECREASE: - CurrentWebView()->DecreaseZoomFactor(fZoomTextOnly); - break; - case ZOOM_FACTOR_RESET: - CurrentWebView()->ResetZoomFactor(); - break; - case ZOOM_TEXT_ONLY: - fZoomTextOnly = !fZoomTextOnly; - fZoomTextOnlyMenuItem->SetMarked(fZoomTextOnly); - // TODO: Would be nice to have an instant update if the page is already - // zoomed. - break; - - case TEXT_FIND_NEXT: - CurrentWebView()->FindString(fFindTextControl->Text(), true, - fFindCaseSensitiveCheckBox->Value()); - break; - case TEXT_FIND_PREVIOUS: - CurrentWebView()->FindString(fFindTextControl->Text(), false, - fFindCaseSensitiveCheckBox->Value()); - break; - case TEXT_SHOW_FIND_GROUP: - if (!fFindGroup->IsVisible()) - fFindGroup->SetVisible(true); - fFindTextControl->MakeFocus(true); - break; - case TEXT_HIDE_FIND_GROUP: - if (fFindGroup->IsVisible()) - fFindGroup->SetVisible(false); - break; - - case SHOW_DOWNLOAD_WINDOW: - case SHOW_SETTINGS_WINDOW: - message->AddUInt32("workspaces", Workspaces()); - be_app->PostMessage(message); - break; - - case CLOSE_TAB: - if (fTabManager->CountTabs() > 1) { - int32 index; - if (message->FindInt32("tab index", &index) != B_OK) - index = fTabManager->SelectedTabIndex(); - _ShutdownTab(index); - _UpdateTabGroupVisibility(); - } else - PostMessage(B_QUIT_REQUESTED); - break; - - case SELECT_TAB: { - int32 index; - if (message->FindInt32("tab index", &index) == B_OK - && fTabManager->SelectedTabIndex() != index - && fTabManager->CountTabs() > index) { - fTabManager->SelectTab(index); } - break; - } + case ZOOM_FACTOR_INCREASE: + CurrentWebView()->IncreaseZoomFactor(fZoomTextOnly); + break; + case ZOOM_FACTOR_DECREASE: + CurrentWebView()->DecreaseZoomFactor(fZoomTextOnly); + break; + case ZOOM_FACTOR_RESET: + CurrentWebView()->ResetZoomFactor(); + break; + case ZOOM_TEXT_ONLY: + fZoomTextOnly = !fZoomTextOnly; + fZoomTextOnlyMenuItem->SetMarked(fZoomTextOnly); + // TODO: Would be nice to have an instant update if the page is + // already zoomed. + break; - case TAB_CHANGED: { - // This message may be received also when the last tab closed, i.e. with index == -1. - int32 index; - if (message->FindInt32("tab index", &index) != B_OK) - index = -1; - _TabChanged(index); - break; - } + case TEXT_FIND_NEXT: + CurrentWebView()->FindString(fFindTextControl->Text(), true, + fFindCaseSensitiveCheckBox->Value()); + break; + case TEXT_FIND_PREVIOUS: + CurrentWebView()->FindString(fFindTextControl->Text(), false, + fFindCaseSensitiveCheckBox->Value()); + break; + case TEXT_SHOW_FIND_GROUP: + if (!fFindGroup->IsVisible()) + fFindGroup->SetVisible(true); + fFindTextControl->MakeFocus(true); + break; + case TEXT_HIDE_FIND_GROUP: + if (fFindGroup->IsVisible()) + fFindGroup->SetVisible(false); + break; - default: - BWebWindow::MessageReceived(message); - break; + case SHOW_DOWNLOAD_WINDOW: + case SHOW_SETTINGS_WINDOW: + message->AddUInt32("workspaces", Workspaces()); + be_app->PostMessage(message); + break; + + case CLOSE_TAB: + if (fTabManager->CountTabs() > 1) { + int32 index; + if (message->FindInt32("tab index", &index) != B_OK) + index = fTabManager->SelectedTabIndex(); + _ShutdownTab(index); + _UpdateTabGroupVisibility(); + } else + PostMessage(B_QUIT_REQUESTED); + break; + + case SELECT_TAB: + { + int32 index; + if (message->FindInt32("tab index", &index) == B_OK + && fTabManager->SelectedTabIndex() != index + && fTabManager->CountTabs() > index) { + fTabManager->SelectTab(index); + } + + break; + } + + case TAB_CHANGED: + { + // This message may be received also when the last tab closed, + // i.e. with index == -1. + int32 index; + if (message->FindInt32("tab index", &index) != B_OK) + index = -1; + _TabChanged(index); + break; + } + + case SETTINGS_VALUE_CHANGED: + { + BString name; + if (message->FindString("name", &name) != B_OK) + break; + bool flag; + if (name == kSettingsKeyShowTabsIfSinglePageOpen + && message->FindBool("value", &flag) == B_OK) { + if (fShowTabsIfSinglePageOpen != flag) { + fShowTabsIfSinglePageOpen = flag; + _UpdateTabGroupVisibility(); + } + } + break; + } + + default: + BWebWindow::MessageReceived(message); + break; } } @@ -898,7 +929,7 @@ BrowserWindow::NewPageCreated(BWebView* view, BRect windowFrame, bool modalDialog, bool resizable) { if (windowFrame.IsValid()) { - BrowserWindow* window = new BrowserWindow(windowFrame, + BrowserWindow* window = new BrowserWindow(windowFrame, fAppSettings, DoNotHaveToolbar, view); window->Show(); } else @@ -1166,7 +1197,8 @@ void BrowserWindow::_UpdateTabGroupVisibility() { if (Lock()) { -// fTabGroup->SetVisible(fTabManager->CountTabs() > 1); + fTabGroup->SetVisible(fShowTabsIfSinglePageOpen + || fTabManager->CountTabs() > 1); fTabManager->SetCloseButtonsAvailable(fTabManager->CountTabs() > 1); Unlock(); } diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index e1ec942b2e..3f6e0a12b1 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -45,10 +45,11 @@ class BPath; class BStatusBar; class BStringView; class BTextControl; +class BWebView; class IconButton; +class SettingsMessage; class TabManager; class TextControlCompleter; -class BWebView; enum ToolbarPolicy { HaveToolbar, @@ -70,6 +71,7 @@ enum { class BrowserWindow : public BWebWindow { public: BrowserWindow(BRect frame, + SettingsMessage* appSettings, ToolbarPolicy = HaveToolbar, BWebView* webView = NULL); virtual ~BrowserWindow(); @@ -144,7 +146,6 @@ private: private: BMenu* fGoMenu; BMenuItem* fZoomTextOnlyMenuItem; - bool fZoomTextOnly; IconButton* fBackButton; IconButton* fForwardButton; IconButton* fStopButton; @@ -163,6 +164,10 @@ private: BTextControl* fFindTextControl; BCheckBox* fFindCaseSensitiveCheckBox; TabManager* fTabManager; + + SettingsMessage* fAppSettings; + bool fZoomTextOnly; + bool fShowTabsIfSinglePageOpen; }; diff --git a/src/apps/webpositive/SettingsKeys.cpp b/src/apps/webpositive/SettingsKeys.cpp new file mode 100644 index 0000000000..7fe0c4e1e2 --- /dev/null +++ b/src/apps/webpositive/SettingsKeys.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "SettingsKeys.h" + +const char* kSettingsKeyDownloadPath = "download path"; +const char* kSettingsKeyShowTabsIfSinglePageOpen + = "show tabs if single page open"; diff --git a/src/apps/webpositive/SettingsKeys.h b/src/apps/webpositive/SettingsKeys.h new file mode 100644 index 0000000000..584a320e86 --- /dev/null +++ b/src/apps/webpositive/SettingsKeys.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef SETTINGS_KEYS_H +#define SETTINGS_KEYS_H + +#include + + +extern const char* kSettingsKeyDownloadPath; +extern const char* kSettingsKeyShowTabsIfSinglePageOpen; + + +#endif // SETTINGS_KEYS_H diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 833924b7a2..8a7c4daa64 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -27,6 +27,7 @@ #include "SettingsWindow.h" #include +#include #include #include #include @@ -48,6 +49,7 @@ #include "BrowserApp.h" #include "BrowsingHistory.h" #include "FontSelectionView.h" +#include "SettingsKeys.h" #include "SettingsMessage.h" #include "WebSettings.h" @@ -64,6 +66,7 @@ enum { MSG_DOWNLOAD_FOLDER_CHANGED = 'dnfc', MSG_NEW_PAGE_BEHAVIOR_CHANGED = 'npbc', MSG_GO_MENU_DAYS_CHANGED = 'digm', + MSG_TAB_DISPLAY_BEHAVIOR_CHANGED = 'tdbc', }; static const int32 kDefaultFontSize = 14; @@ -144,33 +147,39 @@ void SettingsWindow::MessageReceived(BMessage* message) { switch (message->what) { - case MSG_APPLY: - _ApplySettings(); - break; - case MSG_CANCEL: - _RevertSettings(); - PostMessage(B_QUIT_REQUESTED); - break; - case MSG_REVERT: - _RevertSettings(); - break; + case MSG_APPLY: + _ApplySettings(); + break; + case MSG_CANCEL: + _RevertSettings(); + PostMessage(B_QUIT_REQUESTED); + break; + case MSG_REVERT: + _RevertSettings(); + break; - case MSG_STANDARD_FONT_SIZE_SELECTED: { - int32 size = _SizesMenuValue(fStandardSizesMenu->Menu()); - fStandardFontView->SetSize(size); - fSerifFontView->SetSize(size); - fSansSerifFontView->SetSize(size); - break; - } - case MSG_FIXED_FONT_SIZE_SELECTED: { - int32 size = _SizesMenuValue(fFixedSizesMenu->Menu()); - fFixedFontView->SetSize(size); - break; - } + case MSG_STANDARD_FONT_SIZE_SELECTED: + { + int32 size = _SizesMenuValue(fStandardSizesMenu->Menu()); + fStandardFontView->SetSize(size); + fSerifFontView->SetSize(size); + fSansSerifFontView->SetSize(size); + break; + } + case MSG_FIXED_FONT_SIZE_SELECTED: + { + int32 size = _SizesMenuValue(fFixedSizesMenu->Menu()); + fFixedFontView->SetSize(size); + break; + } - default: - BWindow::MessageReceived(message); - break; + case MSG_TAB_DISPLAY_BEHAVIOR_CHANGED: + // TODO: Some settings could change live, some others not? + break; + + default: + BWindow::MessageReceived(message); + break; } } @@ -236,6 +245,11 @@ fNewPageBehaviorMenu->SetEnabled(false); for (uchar i = '9' + 1; i <= 128; i++) fDaysInGoMenuControl->TextView()->DisallowChar(i); + fShowTabsIfOnlyOnePage = new BCheckBox("show tabs if only one page", + TR("Show tabs if only page is open."), + new BMessage(MSG_TAB_DISPLAY_BEHAVIOR_CHANGED)); + fShowTabsIfOnlyOnePage->SetValue(B_CONTROL_ON); + BView* view = BGridLayoutBuilder(spacing / 2, spacing / 2) .Add(fDownloadFolderControl->CreateLabelLayoutItem(), 0, 1) .Add(fDownloadFolderControl->CreateTextViewLayoutItem(), 1, 1) @@ -246,7 +260,9 @@ fNewPageBehaviorMenu->SetEnabled(false); .Add(fDaysInGoMenuControl->CreateLabelLayoutItem(), 0, 3) .Add(fDaysInGoMenuControl->CreateTextViewLayoutItem(), 1, 3) - .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 4, 2) + .Add(fShowTabsIfOnlyOnePage, 0, 4, 2) + + .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 5, 2) .SetInsets(spacing, spacing, spacing, spacing) ; @@ -323,7 +339,9 @@ SettingsWindow::_ApplySettings() fDaysInGoMenuControl->SetText(text.String()); BrowsingHistory::DefaultInstance()->SetMaxHistoryItemAge(maxHistoryAge); - fSettings->SetValue("download path", fDownloadFolderControl->Text()); + fSettings->SetValue(kSettingsKeyDownloadPath, fDownloadFolderControl->Text()); + fSettings->SetValue(kSettingsKeyShowTabsIfSinglePageOpen, + fShowTabsIfOnlyOnePage->Value() == B_CONTROL_ON); // Store fond settings fSettings->SetValue("standard font", fStandardFontView->Font()); @@ -354,6 +372,11 @@ SettingsWindow::_ApplySettings() void SettingsWindow::_RevertSettings() { + fDownloadFolderControl->SetText( + fSettings->GetValue(kSettingsKeyDownloadPath, "")); + fShowTabsIfOnlyOnePage->SetValue( + fSettings->GetValue(kSettingsKeyShowTabsIfSinglePageOpen, true)); + int32 defaultFontSize = fSettings->GetValue("standard font size", kDefaultFontSize); int32 defaultFixedFontSize = fSettings->GetValue("fixed font size", diff --git a/src/apps/webpositive/SettingsWindow.h b/src/apps/webpositive/SettingsWindow.h index 124b85f7e6..1e9d7e3421 100644 --- a/src/apps/webpositive/SettingsWindow.h +++ b/src/apps/webpositive/SettingsWindow.h @@ -30,6 +30,7 @@ #include class BButton; +class BCheckBox; class BMenu; class BMenuField; class BMenuItem; @@ -73,6 +74,7 @@ private: BMenuItem* fNewPageBehaviorOpenSearchItem; BMenuItem* fNewPageBehaviorOpenBlankItem; BTextControl* fDaysInGoMenuControl; + BCheckBox* fShowTabsIfOnlyOnePage; FontSelectionView* fStandardFontView; FontSelectionView* fSerifFontView; From 27ddac2e6e5965d9c4237adfc98028e696fe3536 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 6 Apr 2010 23:53:55 +0000 Subject: [PATCH 208/349] Use the new SettingsKeys.h also in the DownloadsWindow. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@394 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 225b3e931c..22a8b010ea 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -47,6 +47,7 @@ #include "BrowserApp.h" #include "DownloadProgressView.h" +#include "SettingsKeys.h" #include "SettingsMessage.h" #include "WebDownload.h" #include "WebPage.h" @@ -256,8 +257,8 @@ DownloadWindow::MessageReceived(BMessage* message) case SETTINGS_VALUE_CHANGED: { BString string; - if (message->FindString("name", &string) == B_OK - && string == "download path" + if (message->FindString("name", &string) == B_OK + && string == kSettingsKeyDownloadPath && message->FindString("value", &string) == B_OK) { fDownloadPath = string; } From 3ae87b10f1f7f6c44f6c488bc96b46a5eaa6c327 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 6 Apr 2010 23:55:21 +0000 Subject: [PATCH 209/349] Replace the remaining places where the string was redefined. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@395 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 5 +++-- src/apps/webpositive/SettingsWindow.cpp | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 22a8b010ea..7fa39a6b0a 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -143,8 +143,9 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, BPath downloadPath; if (find_directory(B_DESKTOP_DIRECTORY, &downloadPath) != B_OK) downloadPath.SetTo("/boot/home/Desktop"); - fDownloadPath = settings->GetValue("download path", downloadPath.Path()); - settings->SetValue("download path", fDownloadPath); + fDownloadPath = settings->GetValue(kSettingsKeyDownloadPath, + downloadPath.Path()); + settings->SetValue(kSettingsKeyDownloadPath, fDownloadPath); SetLayout(new BGroupLayout(B_VERTICAL)); diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 8a7c4daa64..2f4a463691 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -211,7 +211,8 @@ SettingsWindow::_CreateGeneralPage(float spacing) { fDownloadFolderControl = new BTextControl("download folder", TR("Download folder:"), "", new BMessage(MSG_DOWNLOAD_FOLDER_CHANGED)); - fDownloadFolderControl->SetText(fSettings->GetValue("download path", "")); + fDownloadFolderControl->SetText( + fSettings->GetValue(kSettingsKeyDownloadPath, "")); fNewPageBehaviorCloneCurrentItem = new BMenuItem(TR("Clone current page"), NULL); From c373752f789002d5cf8675ef0f6c7bcec892783f Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 7 Apr 2010 00:00:24 +0000 Subject: [PATCH 210/349] Fixed a spelling error. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@396 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/SettingsWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 2f4a463691..8591fd8c6a 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -247,7 +247,7 @@ fNewPageBehaviorMenu->SetEnabled(false); fDaysInGoMenuControl->TextView()->DisallowChar(i); fShowTabsIfOnlyOnePage = new BCheckBox("show tabs if only one page", - TR("Show tabs if only page is open."), + TR("Show tabs if only one page is open."), new BMessage(MSG_TAB_DISPLAY_BEHAVIOR_CHANGED)); fShowTabsIfOnlyOnePage->SetValue(B_CONTROL_ON); From 845ec8e102a5530f5a1e3037f7c6e0fe571438e3 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 7 Apr 2010 10:55:29 +0000 Subject: [PATCH 211/349] * Revised the application startup to check how many windows have been created at all. Open a blank page if no pages have been created from the arguments passed to the application. * If no pages have been created yet, don't offset the last known window frame. This fixes windows shifting over the screen from session to session. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@397 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 58 +++++++++++++++++++---------- src/apps/webpositive/BrowserApp.h | 2 + 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 1cade8cd09..a32bbd04c0 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -162,11 +162,13 @@ BrowserApp::ReadyToRun() fInitialized = true; + int32 pagesCreated = 0; if (fLaunchRefsMessage) { - RefsReceived(fLaunchRefsMessage); + _RefsReceived(fLaunchRefsMessage, &pagesCreated); delete fLaunchRefsMessage; fLaunchRefsMessage = 0; - } else { + } + if (pagesCreated == 0) { BrowserWindow* window = new BrowserWindow(fLastWindowFrame, fSettings); window->Show(); } @@ -236,22 +238,7 @@ BrowserApp::RefsReceived(BMessage* message) return; } - entry_ref ref; - for (int32 i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) { - BEntry entry(&ref, true); - if (!entry.Exists()) - continue; - BPath path; - if (entry.GetPath(&path) != B_OK) - continue; - BString url; - url << path.Path(); - _CreateNewPage(url); - } - - BString url; - for (int32 i = 0; message->FindString("url", i, &url) == B_OK; i++) - _CreateNewPage(url); + _RefsReceived(message); } @@ -295,6 +282,36 @@ BrowserApp::QuitRequested() } +void +BrowserApp::_RefsReceived(BMessage* message, int32* _pagesCreated) +{ + int32 pagesCreated = 0; + + entry_ref ref; + for (int32 i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) { + BEntry entry(&ref, true); + if (!entry.Exists()) + continue; + BPath path; + if (entry.GetPath(&path) != B_OK) + continue; + BString url; + url << path.Path(); + _CreateNewPage(url); + pagesCreated++; + } + + BString url; + for (int32 i = 0; message->FindString("url", i, &url) == B_OK; i++) { + _CreateNewPage(url); + pagesCreated++; + } + + if (_pagesCreated != NULL) + *_pagesCreated = pagesCreated; +} + + void BrowserApp::_CreateNewPage(const BString& url) { @@ -323,7 +340,10 @@ BrowserApp::_CreateNewPage(const BString& url) void BrowserApp::_CreateNewWindow(const BString& url) { - fLastWindowFrame.OffsetBy(20, 20); + // Offset the window frame unless this is the first window created in the + // session. + if (fWindowCount > 0) + fLastWindowFrame.OffsetBy(20, 20); if (!BScreen().Frame().Contains(fLastWindowFrame)) fLastWindowFrame.OffsetTo(50, 50); diff --git a/src/apps/webpositive/BrowserApp.h b/src/apps/webpositive/BrowserApp.h index dfc9433e5e..f83d379a63 100644 --- a/src/apps/webpositive/BrowserApp.h +++ b/src/apps/webpositive/BrowserApp.h @@ -53,6 +53,8 @@ public: virtual bool QuitRequested(); private: + void _RefsReceived(BMessage* message, + int32* pagesCreated = NULL); void _CreateNewPage(const BString& url); void _CreateNewWindow(const BString& url); void _CreateNewTab(BrowserWindow* window, From 8061d9ebfffff91d7a4fc1b8a2d8823aa36a83c2 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 7 Apr 2010 12:46:39 +0000 Subject: [PATCH 212/349] In BrowserWindow::_TabChanged(), the BWebView could be NULL. Also check if there is a focused view set at all. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@398 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index a5d8fa2671..c8369b2af1 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1228,17 +1228,19 @@ BrowserWindow::_TabChanged(int32 index) SetCurrentWebView(webView); - PageUserData* userData = static_cast(webView->GetUserData()); - if (userData) - userData->FocusedView()->MakeFocus(true); - else - webView->MakeFocus(true); - if (webView) _UpdateTitle(webView->MainFrameTitle()); else _UpdateTitle(""); + if (webView) { + PageUserData* userData = static_cast( + webView->GetUserData()); + if (userData && userData->FocusedView() != NULL) + userData->FocusedView()->MakeFocus(true); + else + webView->MakeFocus(true); + fURLTextControl->SetText(webView->MainFrameURL()); // Trigger update of the interface to the new page, by requesting // to resend all notifications. From 1137289fbc2ccb4f5a5417f5d4007c2fed311a99 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 7 Apr 2010 12:58:22 +0000 Subject: [PATCH 213/349] Simplify the code. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@399 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index c8369b2af1..4a4be2ba93 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1228,12 +1228,9 @@ BrowserWindow::_TabChanged(int32 index) SetCurrentWebView(webView); - if (webView) - _UpdateTitle(webView->MainFrameTitle()); - else - _UpdateTitle(""); - if (webView) { + _UpdateTitle(webView->MainFrameTitle()); + PageUserData* userData = static_cast( webView->GetUserData()); if (userData && userData->FocusedView() != NULL) @@ -1245,7 +1242,8 @@ BrowserWindow::_TabChanged(int32 index) // Trigger update of the interface to the new page, by requesting // to resend all notifications. webView->WebPage()->ResendNotifications(); - } + } else + _UpdateTitle(""); } From 1cad765a3b1d712ca669d75e33e24083d14bdf74 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 7 Apr 2010 13:00:55 +0000 Subject: [PATCH 214/349] Maybe CurrentWebView() is NULL too... git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@400 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 4a4be2ba93..b9ef820438 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1224,7 +1224,8 @@ BrowserWindow::_TabChanged(int32 index) if (webView == CurrentWebView()) return; - CurrentWebView()->SetUserData(new PageUserData(CurrentFocus())); + if (CurrentWebView() != NULL) + CurrentWebView()->SetUserData(new PageUserData(CurrentFocus())); SetCurrentWebView(webView); From 406b9363222b797a5f94dba7c33d2cf638414666 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 7 Apr 2010 13:07:44 +0000 Subject: [PATCH 215/349] Selecting the tab for which authentication was requested didn't work anymore. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@401 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index b9ef820438..f41760328d 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1168,7 +1168,13 @@ BrowserWindow::AuthenticationChallenge(BString message, BString& inOutUser, { // Switch to the page for which this authentication is required. if (view != CurrentWebView()) { - fTabManager->SelectTab(view); + int32 tabIndex = fTabManager->TabForView(view); + if (tabIndex < 0) { + // page seems to be gone already? + return false; + } + fTabManager->SelectTab(tabIndex); + _TabChanged(tabIndex); UpdateIfNeeded(); } AuthenticationPanel* panel = new AuthenticationPanel(Frame()); @@ -1210,7 +1216,7 @@ BrowserWindow::_ShutdownTab(int32 index) { BView* view = fTabManager->RemoveTab(index); BWebView* webView = dynamic_cast(view); - if (webView) + if (webView != NULL) webView->Shutdown(); else delete view; @@ -1229,12 +1235,12 @@ BrowserWindow::_TabChanged(int32 index) SetCurrentWebView(webView); - if (webView) { + if (webView != NULL) { _UpdateTitle(webView->MainFrameTitle()); PageUserData* userData = static_cast( webView->GetUserData()); - if (userData && userData->FocusedView() != NULL) + if (userData != NULL && userData->FocusedView() != NULL) userData->FocusedView()->MakeFocus(true); else webView->MakeFocus(true); From 312655fb6f521a6a769e3d7dd4cb908708848f29 Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 8 Apr 2010 12:42:58 +0000 Subject: [PATCH 216/349] * Renamed TextControlCompleter to TextViewCompleter, since it actually only works with the BTextView. * Factored out the URL text handling into a new class URLInputGroup, which is used instead of a plain BTextControl, but currently works much the same way. It's a BGroupView though and allows easy addition of other controls and items into the URL text field. * Moved baseURL() method into it's own file, since it's used from multiple places now. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@402 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 147 +------ src/apps/webpositive/BrowserWindow.h | 5 +- src/apps/webpositive/URLInputGroup.cpp | 384 ++++++++++++++++++ src/apps/webpositive/URLInputGroup.h | 35 ++ ...rolCompleter.cpp => TextViewCompleter.cpp} | 55 ++- ...ControlCompleter.h => TextViewCompleter.h} | 20 +- src/apps/webpositive/support/BaseURL.cpp | 18 + src/apps/webpositive/support/BaseURL.h | 14 + 8 files changed, 506 insertions(+), 172 deletions(-) create mode 100644 src/apps/webpositive/URLInputGroup.cpp create mode 100644 src/apps/webpositive/URLInputGroup.h rename src/apps/webpositive/autocompletion/{TextControlCompleter.cpp => TextViewCompleter.cpp} (53%) rename src/apps/webpositive/autocompletion/{TextControlCompleter.h => TextViewCompleter.h} (69%) create mode 100644 src/apps/webpositive/support/BaseURL.cpp create mode 100644 src/apps/webpositive/support/BaseURL.h diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index f41760328d..ae574c6f80 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -34,13 +34,14 @@ #include "BrowserWindow.h" #include "AuthenticationPanel.h" +#include "BaseURL.h" #include "BrowserApp.h" #include "BrowsingHistory.h" #include "IconButton.h" #include "NavMenu.h" #include "SettingsKeys.h" #include "SettingsMessage.h" -#include "TextControlCompleter.h" +#include "URLInputGroup.h" #include "WebPage.h" #include "WebTabView.h" #include "WebView.h" @@ -107,112 +108,6 @@ layoutItemFor(BView* view) } -class URLChoice : public BAutoCompleter::Choice { -public: - URLChoice(const BString& choiceText, const BString& displayText, - int32 matchPos, int32 matchLen, int32 priority) - : - BAutoCompleter::Choice(choiceText, displayText, matchPos, matchLen), - fPriority(priority) - { - } - - bool operator<(const URLChoice& other) const - { - if (fPriority > other.fPriority) - return true; - return DisplayText() < other.DisplayText(); - } - - bool operator==(const URLChoice& other) const - { - return fPriority == other.fPriority - && DisplayText() < other.DisplayText(); - } - -private: - int32 fPriority; -}; - - -static BString -baseURL(const BString string) -{ - int32 baseURLStart = string.FindFirst("://") + 3; - int32 baseURLEnd = string.FindFirst("/", baseURLStart + 1); - BString result; - result.SetTo(string.String() + baseURLStart, baseURLEnd - baseURLStart); - return result; -} - - -class BrowsingHistoryChoiceModel : public BAutoCompleter::ChoiceModel { - virtual void FetchChoicesFor(const BString& pattern) - { - int32 count = CountChoices(); - for (int32 i = 0; i < count; i++) { - delete reinterpret_cast( - fChoices.ItemAtFast(i)); - } - fChoices.MakeEmpty(); - - // Search through BrowsingHistory for any matches. - BrowsingHistory* history = BrowsingHistory::DefaultInstance(); - if (!history->Lock()) - return; - - BString lastBaseURL; - int32 priority = INT_MAX; - - count = history->CountItems(); - for (int32 i = 0; i < count; i++) { - BrowsingHistoryItem item = history->HistoryItemAt(i); - const BString& choiceText = item.URL(); - int32 matchPos = choiceText.IFindFirst(pattern); - if (matchPos < 0) - continue; - if (lastBaseURL.Length() > 0 - && choiceText.FindFirst(lastBaseURL) >= 0) { - priority--; - } else - priority = INT_MAX; - lastBaseURL = baseURL(choiceText); - fChoices.AddItem(new URLChoice(choiceText, - choiceText, matchPos, pattern.Length(), priority)); - } - - history->Unlock(); - - fChoices.SortItems(_CompareChoices); - } - - virtual int32 CountChoices() const - { - return fChoices.CountItems(); - } - - virtual const BAutoCompleter::Choice* ChoiceAt(int32 index) const - { - return reinterpret_cast( - fChoices.ItemAt(index)); - } - - static int _CompareChoices(const void* a, const void* b) - { - const URLChoice* aChoice = *reinterpret_cast(a); - const URLChoice* bChoice = *reinterpret_cast(b); - if (*aChoice < *bChoice) - return -1; - else if (*aChoice == *bChoice) - return 0; - return 1; - } - -private: - BList fChoices; -}; - - class BookmarkMenu : public BNavMenu { public: BookmarkMenu(const char* title, BHandler* target, const entry_ref* navDir) @@ -349,8 +244,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fStopButton->TrimIcon(); // URL - fURLTextControl = new BTextControl("url", "", "", NULL); - fURLTextControl->SetDivider(50.0); + fURLInputGroup = new URLInputGroup(); // Go fGoButton = new BButton("", "Go", new BMessage(GOTO_URL)); @@ -396,7 +290,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, .Add(fBackButton, 0, 0) .Add(fForwardButton, 1, 0) .Add(fStopButton, 2, 0) - .Add(fURLTextControl, 3, 0) + .Add(fURLInputGroup, 3, 0) .Add(fGoButton, 4, 0) .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) ) @@ -423,10 +317,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, .Add(statusGroup) ); - fURLTextControl->MakeFocus(true); - - fURLAutoCompleter = new TextControlCompleter(fURLTextControl, - new BrowsingHistoryChoiceModel()); + fURLInputGroup->MakeFocus(true); fMenuGroup = layoutItemFor(mainMenu); fTabGroup = layoutItemFor(fTabManager->TabGroup()); @@ -471,7 +362,6 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, BrowserWindow::~BrowserWindow() { fAppSettings->RemoveListener(BMessenger(this)); - delete fURLAutoCompleter; delete fTabManager; } @@ -484,7 +374,7 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) if ((message->what == B_KEY_DOWN || message->what == B_UNMAPPED_KEY_DOWN) && message->FindString("bytes", &bytes) == B_OK && message->FindInt32("modifiers", &modifiers) == B_OK) { - if (fURLTextControl && target == fURLTextControl->TextView()) { + if (target == fURLInputGroup->TextView()) { // Handle B_RETURN in the URL text control. This is the easiest // way to react *only* when the user presses the return key in the // address bar, as opposed to trying to load whatever is in there when @@ -512,12 +402,10 @@ BrowserWindow::MessageReceived(BMessage* message) { switch (message->what) { case OPEN_LOCATION: - if (fURLTextControl) { - if (fURLTextControl->TextView()->IsFocus()) - fURLTextControl->TextView()->SelectAll(); - else - fURLTextControl->MakeFocus(true); - } + if (fURLInputGroup->TextView()->IsFocus()) + fURLInputGroup->TextView()->SelectAll(); + else + fURLInputGroup->MakeFocus(true); break; case RELOAD: CurrentWebView()->Reload(); @@ -526,7 +414,7 @@ BrowserWindow::MessageReceived(BMessage* message) { BString url; if (message->FindString("url", &url) != B_OK) - url = fURLTextControl->Text(); + url = fURLInputGroup->Text(); fTabManager->SetTabIcon(CurrentWebView(), NULL); CurrentWebView()->LoadURL(url.String()); break; @@ -889,10 +777,8 @@ BrowserWindow::CreateNewTab(const BString& url, bool select, BWebView* webView) fTabManager->SelectTab(fTabManager->CountTabs() - 1); SetCurrentWebView(webView); webView->WebPage()->ResendNotifications(); - if (fURLTextControl) { - fURLTextControl->SetText(url.String()); - fURLTextControl->MakeFocus(true); - } + fURLInputGroup->SetText(url.String()); + fURLInputGroup->MakeFocus(true); } _UpdateTabGroupVisibility(); @@ -967,8 +853,7 @@ BrowserWindow::LoadCommitted(const BString& url, BWebView* view) return; // This hook is invoked when the load is commited. - if (fURLTextControl) - fURLTextControl->SetText(url.String()); + fURLInputGroup->SetText(url.String()); BString status("Loading: "); status << url; @@ -1170,7 +1055,7 @@ BrowserWindow::AuthenticationChallenge(BString message, BString& inOutUser, if (view != CurrentWebView()) { int32 tabIndex = fTabManager->TabForView(view); if (tabIndex < 0) { - // page seems to be gone already? + // Page seems to be gone already? return false; } fTabManager->SelectTab(tabIndex); @@ -1245,7 +1130,7 @@ BrowserWindow::_TabChanged(int32 index) else webView->MakeFocus(true); - fURLTextControl->SetText(webView->MainFrameURL()); + fURLInputGroup->SetText(webView->MainFrameURL()); // Trigger update of the interface to the new page, by requesting // to resend all notifications. webView->WebPage()->ResendNotifications(); diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 3f6e0a12b1..6146c8ecb2 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -49,7 +49,7 @@ class BWebView; class IconButton; class SettingsMessage; class TabManager; -class TextControlCompleter; +class URLInputGroup; enum ToolbarPolicy { HaveToolbar, @@ -150,8 +150,7 @@ private: IconButton* fForwardButton; IconButton* fStopButton; BButton* fGoButton; - BTextControl* fURLTextControl; - TextControlCompleter* fURLAutoCompleter; + URLInputGroup* fURLInputGroup; BStringView* fStatusText; BStatusBar* fLoadingProgressBar; diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp new file mode 100644 index 0000000000..07b4772c39 --- /dev/null +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -0,0 +1,384 @@ +/* + * Copyright 2010 Stephan Aßmus + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#include "URLInputGroup.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "BaseURL.h" +#include "BrowsingHistory.h" +#include "IconButton.h" +#include "TextViewCompleter.h" + + +class URLChoice : public BAutoCompleter::Choice { +public: + URLChoice(const BString& choiceText, const BString& displayText, + int32 matchPos, int32 matchLen, int32 priority) + : + BAutoCompleter::Choice(choiceText, displayText, matchPos, matchLen), + fPriority(priority) + { + } + + bool operator<(const URLChoice& other) const + { + if (fPriority > other.fPriority) + return true; + return DisplayText() < other.DisplayText(); + } + + bool operator==(const URLChoice& other) const + { + return fPriority == other.fPriority + && DisplayText() < other.DisplayText(); + } + +private: + int32 fPriority; +}; + + +class BrowsingHistoryChoiceModel : public BAutoCompleter::ChoiceModel { + virtual void FetchChoicesFor(const BString& pattern) + { + int32 count = CountChoices(); + for (int32 i = 0; i < count; i++) { + delete reinterpret_cast( + fChoices.ItemAtFast(i)); + } + fChoices.MakeEmpty(); + + // Search through BrowsingHistory for any matches. + BrowsingHistory* history = BrowsingHistory::DefaultInstance(); + if (!history->Lock()) + return; + + BString lastBaseURL; + int32 priority = INT_MAX; + + count = history->CountItems(); + for (int32 i = 0; i < count; i++) { + BrowsingHistoryItem item = history->HistoryItemAt(i); + const BString& choiceText = item.URL(); + int32 matchPos = choiceText.IFindFirst(pattern); + if (matchPos < 0) + continue; + if (lastBaseURL.Length() > 0 + && choiceText.FindFirst(lastBaseURL) >= 0) { + priority--; + } else + priority = INT_MAX; + lastBaseURL = baseURL(choiceText); + fChoices.AddItem(new URLChoice(choiceText, + choiceText, matchPos, pattern.Length(), priority)); + } + + history->Unlock(); + + fChoices.SortItems(_CompareChoices); + } + + virtual int32 CountChoices() const + { + return fChoices.CountItems(); + } + + virtual const BAutoCompleter::Choice* ChoiceAt(int32 index) const + { + return reinterpret_cast( + fChoices.ItemAt(index)); + } + + static int _CompareChoices(const void* a, const void* b) + { + const URLChoice* aChoice + = *reinterpret_cast(a); + const URLChoice* bChoice + = *reinterpret_cast(b); + if (*aChoice < *bChoice) + return -1; + else if (*aChoice == *bChoice) + return 0; + return 1; + } + +private: + BList fChoices; +}; + + +// #pragma mark - URLTextView + + +static const float kHorizontalTextRectInset = 3.0; + + +class URLInputGroup::URLTextView : public BTextView { +public: + URLTextView(URLInputGroup* parent); + virtual ~URLTextView(); + + virtual void FrameResized(float width, float height); + virtual void MouseDown(BPoint where); + virtual void KeyDown(const char* bytes, int32 numBytes); + virtual void MakeFocus(bool focused = true); + + virtual BSize MinSize(); + virtual BSize MaxSize(); + +protected: + virtual void InsertText(const char* inText, int32 inLength, + int32 inOffset, + const text_run_array* inRuns); +private: + void _AlignTextRect(); + +private: + URLInputGroup* fURLInputGroup; + TextViewCompleter* fURLAutoCompleter; + BString fPreviousText; +}; + + +URLInputGroup::URLTextView::URLTextView(URLInputGroup* parent) + : + BTextView("url"), + fURLInputGroup(parent), + fURLAutoCompleter(new TextViewCompleter(this, + new BrowsingHistoryChoiceModel())), + fPreviousText("") +{ + MakeResizable(true); +} + + +URLInputGroup::URLTextView::~URLTextView() +{ + delete fURLAutoCompleter; +} + + +void +URLInputGroup::URLTextView::FrameResized(float width, float height) +{ + BTextView::FrameResized(width, height); + _AlignTextRect(); +} + + +void +URLInputGroup::URLTextView::MouseDown(BPoint where) +{ + if (!IsFocus()) { + MakeFocus(true); + return; + } + + // Only pass through to base class if we already have focus. + BTextView::MouseDown(where); +} + + +void +URLInputGroup::URLTextView::KeyDown(const char* bytes, int32 numBytes) +{ + switch (bytes[0]) { + case B_TAB: + BView::KeyDown(bytes, numBytes); + break; + + case B_ESCAPE: + // Revert to text as it was when we received keyboard focus. + SetText(fPreviousText.String()); + SelectAll(); + break; + + default: + BTextView::KeyDown(bytes, numBytes); + break; + } +} + +void +URLInputGroup::URLTextView::MakeFocus(bool focus) +{ + if (focus == IsFocus()) + return; + + BTextView::MakeFocus(focus); + + if (focus) { + fPreviousText = Text(); + SelectAll(); + } + + fURLInputGroup->Invalidate(); +} + + +BSize +URLInputGroup::URLTextView::MinSize() +{ + BSize min; + min.height = ceilf(LineHeight(0) + kHorizontalTextRectInset); + // we always add at least one pixel vertical inset top/bottom for + // the text rect. + min.width = min.height * 3; + return BLayoutUtils::ComposeSize(ExplicitMinSize(), min); +} + + +BSize +URLInputGroup::URLTextView::MaxSize() +{ + BSize max(MinSize()); + max.width = B_SIZE_UNLIMITED; + return BLayoutUtils::ComposeSize(ExplicitMaxSize(), max); +} + + +void +URLInputGroup::URLTextView::InsertText(const char* inText, int32 inLength, + int32 inOffset, const text_run_array* inRuns) +{ + char* buffer = NULL; + + if (strpbrk(inText, "\r\n") && inLength <= 1024) { + buffer = (char*)malloc(inLength); + + if (buffer) { + strcpy(buffer, inText); + + for (int32 i = 0; i < inLength; i++) { + if (buffer[i] == '\r' || buffer[i] == '\n') + buffer[i] = ' '; + } + } + } + + BTextView::InsertText(buffer ? buffer : inText, inLength, inOffset, + inRuns); + + free(buffer); +} + + +void +URLInputGroup::URLTextView::_AlignTextRect() +{ + // Layout the text rect to be in the middle, normally this means there + // is one pixel spacing on each side. + BRect textRect(Bounds()); + textRect.left = 0.0; + float vInset = max_c(1, + floorf((textRect.Height() - LineHeight(0)) / 2.0 + 0.5)); + float hInset = kHorizontalTextRectInset; + + if (be_control_look) + hInset = be_control_look->DefaultLabelSpacing(); + + textRect.InsetBy(hInset, vInset); + SetTextRect(textRect); +} + + +// #pragma mark - URLInputGroup + + +URLInputGroup::URLInputGroup() + : + BGroupView(B_HORIZONTAL), + fWindowActive(false) +{ + GroupLayout()->SetInsets(2, 2, 2, 2); + + fTextView = new URLTextView(this); + AddChild(fTextView); + + SetFlags(Flags() | B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE); + SetLowColor(ViewColor()); + SetViewColor(B_TRANSPARENT_COLOR); + + SetExplicitAlignment(BAlignment(B_ALIGN_USE_FULL_WIDTH, + B_ALIGN_VERTICAL_CENTER)); +} + + +URLInputGroup::~URLInputGroup() +{ +} + + +void +URLInputGroup::AttachedToWindow() +{ + BGroupView::AttachedToWindow(); + fWindowActive = Window()->IsActive(); +} + + +void +URLInputGroup::WindowActivated(bool active) +{ + BGroupView::WindowActivated(active); + if (fWindowActive != active) { + fWindowActive = active; + Invalidate(); + } +} + + +void +URLInputGroup::Draw(BRect updateRect) +{ + BRect bounds(Bounds()); + rgb_color base(LowColor()); + uint32 flags = 0; + if (fWindowActive && fTextView->IsFocus()) + flags |= BControlLook::B_FOCUSED; + be_control_look->DrawTextControlBorder(this, bounds, updateRect, base, + flags); +} + + +void +URLInputGroup::MakeFocus(bool focus) +{ + // Forward this to the text view, we never accept focus ourselves. + fTextView->MakeFocus(focus); +} + + +BTextView* +URLInputGroup::TextView() const +{ + return fTextView; +} + + +void +URLInputGroup::SetText(const char* text) +{ + fTextView->SetText(text); +} + + +const char* +URLInputGroup::Text() const +{ + return fTextView->Text(); +} + diff --git a/src/apps/webpositive/URLInputGroup.h b/src/apps/webpositive/URLInputGroup.h new file mode 100644 index 0000000000..5f75590c6a --- /dev/null +++ b/src/apps/webpositive/URLInputGroup.h @@ -0,0 +1,35 @@ +/* + * Copyright 2010 Stephan Aßmus + * All rights reserved. Distributed under the terms of the MIT License. + */ +#ifndef URL_INPUT_GROUP_H +#define URL_INPUT_GROUP_H + +#include + +class BTextView; + + +class URLInputGroup : public BGroupView { +public: + URLInputGroup(); + virtual ~URLInputGroup(); + + virtual void AttachedToWindow(); + virtual void WindowActivated(bool active); + virtual void Draw(BRect updateRect); + virtual void MakeFocus(bool focus = true); + + BTextView* TextView() const; + void SetText(const char* text); + const char* Text() const; + +private: + class URLTextView; + + URLTextView* fTextView; + bool fWindowActive; +}; + +#endif // URL_INPUT_GROUP_H + diff --git a/src/apps/webpositive/autocompletion/TextControlCompleter.cpp b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp similarity index 53% rename from src/apps/webpositive/autocompletion/TextControlCompleter.cpp rename to src/apps/webpositive/autocompletion/TextViewCompleter.cpp index 552c8b5f5d..5ae515b529 100644 --- a/src/apps/webpositive/autocompletion/TextControlCompleter.cpp +++ b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp @@ -6,7 +6,7 @@ * Oliver Tappe */ -#include "TextControlCompleter.h" +#include "TextViewCompleter.h" #include #include @@ -15,75 +15,74 @@ #include "AutoCompleterDefaultImpl.h" -// #pragma mark - TextControlWrapper +// #pragma mark - TextViewWrapper -TextControlCompleter::TextControlWrapper::TextControlWrapper( - BTextControl* textControl) +TextViewCompleter::TextViewWrapper::TextViewWrapper(BTextView* textView) : - fTextControl(textControl) + fTextView(textView) { } void -TextControlCompleter::TextControlWrapper::GetEditViewState(BString& text, +TextViewCompleter::TextViewWrapper::GetEditViewState(BString& text, int32* caretPos) { - if (fTextControl && fTextControl->LockLooper()) { - text = fTextControl->Text(); + if (fTextView && fTextView->LockLooper()) { + text = fTextView->Text(); if (caretPos) { int32 end; - fTextControl->TextView()->GetSelection(caretPos, &end); + fTextView->GetSelection(caretPos, &end); } - fTextControl->UnlockLooper(); + fTextView->UnlockLooper(); } } void -TextControlCompleter::TextControlWrapper::SetEditViewState(const BString& text, +TextViewCompleter::TextViewWrapper::SetEditViewState(const BString& text, int32 caretPos, int32 selectionLength) { - if (fTextControl && fTextControl->LockLooper()) { - fTextControl->TextView()->SetText(text.String(), text.Length()); - fTextControl->TextView()->Select(caretPos, caretPos + selectionLength); - fTextControl->TextView()->ScrollToSelection(); - fTextControl->UnlockLooper(); + if (fTextView && fTextView->LockLooper()) { + fTextView->SetText(text.String(), text.Length()); + fTextView->Select(caretPos, caretPos + selectionLength); + fTextView->ScrollToSelection(); + fTextView->UnlockLooper(); } } BRect -TextControlCompleter::TextControlWrapper::GetAdjustmentFrame() +TextViewCompleter::TextViewWrapper::GetAdjustmentFrame() { - BRect frame = fTextControl->TextView()->Bounds(); - frame = fTextControl->TextView()->ConvertToScreen(frame); + BRect frame = fTextView->Bounds(); + frame = fTextView->ConvertToScreen(frame); frame.InsetBy(0, -3); return frame; } -TextControlCompleter::TextControlCompleter(BTextControl* textControl, - ChoiceModel* model, PatternSelector* patternSelector) +TextViewCompleter::TextViewCompleter(BTextView* textView, ChoiceModel* model, + PatternSelector* patternSelector) : - BAutoCompleter(new TextControlWrapper(textControl), model, + BAutoCompleter(new TextViewWrapper(textView), model, new BDefaultChoiceView(), patternSelector), BMessageFilter(B_KEY_DOWN), - fTextControl(textControl) + fTextView(textView) { - fTextControl->TextView()->AddFilter(this); + fTextView->AddFilter(this); } -TextControlCompleter::~TextControlCompleter() +TextViewCompleter::~TextViewCompleter() { - fTextControl->TextView()->RemoveFilter(this); + fTextView->RemoveFilter(this); } filter_result -TextControlCompleter::Filter(BMessage* message, BHandler** target) +TextViewCompleter::Filter(BMessage* message, BHandler** target) { const char* bytes; int32 modifiers; @@ -91,7 +90,7 @@ TextControlCompleter::Filter(BMessage* message, BHandler** target) || message->FindInt32("modifiers", &modifiers) != B_OK) { return B_DISPATCH_MESSAGE; } - + switch (bytes[0]) { case B_UP_ARROW: SelectPrevious(); diff --git a/src/apps/webpositive/autocompletion/TextControlCompleter.h b/src/apps/webpositive/autocompletion/TextViewCompleter.h similarity index 69% rename from src/apps/webpositive/autocompletion/TextControlCompleter.h rename to src/apps/webpositive/autocompletion/TextViewCompleter.h index 89c5125f2e..a325603309 100644 --- a/src/apps/webpositive/autocompletion/TextControlCompleter.h +++ b/src/apps/webpositive/autocompletion/TextViewCompleter.h @@ -13,31 +13,31 @@ #include "AutoCompleter.h" -class BTextControl; +class BTextView; -class TextControlCompleter : protected BAutoCompleter, public BMessageFilter { +class TextViewCompleter : protected BAutoCompleter, public BMessageFilter { public: - TextControlCompleter(BTextControl* textControl, + TextViewCompleter(BTextView* textView, ChoiceModel* choiceModel = NULL, PatternSelector* patternSelector = NULL); - virtual ~TextControlCompleter(); - + virtual ~TextViewCompleter(); + private: virtual filter_result Filter(BMessage* message, BHandler** target); - - class TextControlWrapper : public EditView { + + class TextViewWrapper : public EditView { public: - TextControlWrapper(BTextControl* textControl); + TextViewWrapper(BTextView* textView); virtual BRect GetAdjustmentFrame(); virtual void GetEditViewState(BString& text, int32* caretPos); virtual void SetEditViewState(const BString& text, int32 caretPos, int32 selectionLength = 0); private: - BTextControl* fTextControl; + BTextView* fTextView; }; private: - BTextControl* fTextControl; + BTextView* fTextView; }; #endif // TEXT_CONTROL_COMPLETER_H diff --git a/src/apps/webpositive/support/BaseURL.cpp b/src/apps/webpositive/support/BaseURL.cpp new file mode 100644 index 0000000000..4d2f47cd29 --- /dev/null +++ b/src/apps/webpositive/support/BaseURL.cpp @@ -0,0 +1,18 @@ +/* + * Copyright 2010 Stephan Aßmus + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#include "BaseURL.h" + + +BString +baseURL(const BString string) +{ + int32 baseURLStart = string.FindFirst("://") + 3; + int32 baseURLEnd = string.FindFirst("/", baseURLStart + 1); + BString result; + result.SetTo(string.String() + baseURLStart, baseURLEnd - baseURLStart); + return result; +} + diff --git a/src/apps/webpositive/support/BaseURL.h b/src/apps/webpositive/support/BaseURL.h new file mode 100644 index 0000000000..b4589ef58f --- /dev/null +++ b/src/apps/webpositive/support/BaseURL.h @@ -0,0 +1,14 @@ +/* + * Copyright 2010 Stephan Aßmus + * All rights reserved. Distributed under the terms of the MIT License. + */ +#ifndef BASE_URL_H +#define BASE_URL_H + +#include + + +BString baseURL(const BString string); + + +#endif // BASE_URL_H From ad7c99c0ca4493fe060f90ec7ee8aae72913e640 Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 8 Apr 2010 15:52:28 +0000 Subject: [PATCH 217/349] * Integrated the Go button into the URL text field. * Added a context menu to the URL input for integration with the system clipboard when you want to use the mouse only. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@403 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 14 +- src/apps/webpositive/BrowserWindow.h | 1 - src/apps/webpositive/URLInputGroup.cpp | 219 ++++++++++++++++++++++++- src/apps/webpositive/URLInputGroup.h | 6 +- src/apps/webpositive/WebPositive.rdef | 50 +++++- 5 files changed, 273 insertions(+), 17 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index ae574c6f80..2b5bce1fb3 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -243,11 +243,8 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fStopButton->SetIcon(204); fStopButton->TrimIcon(); - // URL - fURLInputGroup = new URLInputGroup(); - - // Go - fGoButton = new BButton("", "Go", new BMessage(GOTO_URL)); + // URL input group + fURLInputGroup = new URLInputGroup(new BMessage(GOTO_URL)); // Status Bar fStatusText = new BStringView("status", ""); @@ -291,7 +288,6 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, .Add(fForwardButton, 1, 0) .Add(fStopButton, 2, 0) .Add(fURLInputGroup, 3, 0) - .Add(fGoButton, 4, 0) .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) ) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) @@ -381,11 +377,11 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) // the text control just goes out of focus. if (bytes[0] == B_RETURN) { // Do it in such a way that the user sees the Go-button go down. - fGoButton->SetValue(B_CONTROL_ON); + fURLInputGroup->GoButton()->SetValue(B_CONTROL_ON); UpdateIfNeeded(); - fGoButton->Invoke(); + fURLInputGroup->GoButton()->Invoke(); snooze(1000); - fGoButton->SetValue(B_CONTROL_OFF); + fURLInputGroup->GoButton()->SetValue(B_CONTROL_OFF); } } else if (bytes[0] == B_LEFT_ARROW && (modifiers & B_COMMAND_KEY) != 0) { PostMessage(GO_BACK); diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 6146c8ecb2..c6c91a88c9 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -149,7 +149,6 @@ private: IconButton* fBackButton; IconButton* fForwardButton; IconButton* fStopButton; - BButton* fGoButton; URLInputGroup* fURLInputGroup; BStringView* fStatusText; BStatusBar* fLoadingProgressBar; diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index 07b4772c39..32cbffd55b 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -5,13 +5,18 @@ #include "URLInputGroup.h" +#include +#include #include +#include #include #include #include #include #include +#include #include +#include #include #include @@ -127,10 +132,14 @@ static const float kHorizontalTextRectInset = 3.0; class URLInputGroup::URLTextView : public BTextView { +private: + static const uint32 MSG_CLEAR = 'cler'; + public: URLTextView(URLInputGroup* parent); virtual ~URLTextView(); + virtual void MessageReceived(BMessage* message); virtual void FrameResized(float width, float height); virtual void MouseDown(BPoint where); virtual void KeyDown(const char* bytes, int32 numBytes); @@ -171,6 +180,20 @@ URLInputGroup::URLTextView::~URLTextView() } +void +URLInputGroup::URLTextView::MessageReceived(BMessage* message) +{ + switch (message->what) { + case MSG_CLEAR: + SetText(""); + break; + default: + BTextView::MessageReceived(message); + break; + } +} + + void URLInputGroup::URLTextView::FrameResized(float width, float height) { @@ -182,12 +205,52 @@ URLInputGroup::URLTextView::FrameResized(float width, float height) void URLInputGroup::URLTextView::MouseDown(BPoint where) { - if (!IsFocus()) { + bool wasFocus = IsFocus(); + if (!wasFocus) MakeFocus(true); + + int32 buttons; + if (Window()->CurrentMessage()->FindInt32("buttons", &buttons) != B_OK) + buttons = B_PRIMARY_MOUSE_BUTTON; + + if ((buttons & B_SECONDARY_MOUSE_BUTTON) != 0) { + // Display context menu + int32 selectionStart; + int32 selectionEnd; + GetSelection(&selectionStart, &selectionEnd); + bool canCutOrCopy = selectionEnd > selectionStart; + + bool canPaste = false; + if (be_clipboard->Lock()) { + if (BMessage* data = be_clipboard->Data()) + canPaste = data->HasData("text/plain", B_MIME_TYPE); + be_clipboard->Unlock(); + } + + BMenuItem* cutItem = new BMenuItem("Cut", new BMessage(B_CUT)); + BMenuItem* copyItem = new BMenuItem("Copy", new BMessage(B_COPY)); + BMenuItem* pasteItem = new BMenuItem("Paste", new BMessage(B_PASTE)); + BMenuItem* clearItem = new BMenuItem("Clear", new BMessage(MSG_CLEAR)); + cutItem->SetEnabled(canCutOrCopy); + copyItem->SetEnabled(canCutOrCopy); + pasteItem->SetEnabled(canPaste); + clearItem->SetEnabled(strlen(Text()) > 0); + + BPopUpMenu* menu = new BPopUpMenu("url context"); + menu->AddItem(cutItem); + menu->AddItem(copyItem); + menu->AddItem(pasteItem); + menu->AddItem(clearItem); + + menu->SetTargetForItems(this); + menu->Go(ConvertToScreen(where), true, true, true); return; } // Only pass through to base class if we already have focus. + if (!wasFocus) + return; + BTextView::MouseDown(where); } @@ -295,10 +358,145 @@ URLInputGroup::URLTextView::_AlignTextRect() } +// #pragma mark - GoButton + + +const uint32 kGoBitmapWidth = 14; +const uint32 kGoBitmapHeight = 14; +const color_space kGoBitmapFormat = B_RGBA32; + +const unsigned char kGoBitmapBits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xde, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x9c, 0xd5, 0xa6, 0xff, + 0x4a, 0x67, 0x50, 0xff, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xb6, 0xf9, 0xc2, 0xff, 0xb2, 0xf9, 0xc0, 0xff, 0x88, 0xbb, 0x91, 0xff, + 0x2e, 0x3d, 0x32, 0xff, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb6, 0xf9, 0xc2, 0xff, + 0x73, 0xfa, 0x8c, 0xff, 0x9f, 0xf9, 0xae, 0xff, 0xac, 0xed, 0xb7, 0xff, 0x63, 0x96, 0x6d, 0xff, + 0x00, 0x00, 0x00, 0xe9, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xb6, 0xf9, 0xc2, 0xff, 0x5d, 0xfc, 0x7b, 0xff, 0x5d, 0xfc, 0x7b, 0xff, + 0x72, 0xf9, 0x88, 0xff, 0x6d, 0xe5, 0x82, 0xff, 0x50, 0xbf, 0x65, 0xff, 0x27, 0x63, 0x32, 0xff, + 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb4, 0xf8, 0xc0, 0xff, + 0x59, 0xfc, 0x77, 0xff, 0x59, 0xfc, 0x77, 0xff, 0x59, 0xfc, 0x77, 0xff, 0x59, 0xfb, 0x76, 0xff, + 0x4a, 0xe8, 0x67, 0xff, 0x32, 0xcc, 0x50, 0xff, 0x27, 0x9e, 0x3d, 0xff, 0x15, 0x3d, 0x15, 0xff, + 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xa2, 0xf2, 0xb0, 0xff, 0x2e, 0xfa, 0x54, 0xff, 0x2e, 0xfa, 0x54, 0xff, + 0x2e, 0xfa, 0x54, 0xff, 0x2e, 0xf9, 0x54, 0xff, 0x27, 0xe4, 0x48, 0xff, 0x15, 0xc5, 0x38, 0xff, + 0x15, 0x98, 0x2e, 0xff, 0x00, 0x3b, 0x15, 0xff, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x26, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x88, 0xe9, 0x99, 0xff, + 0x15, 0xf9, 0x40, 0xff, 0x15, 0xf9, 0x40, 0xff, 0x15, 0xed, 0x3d, 0xff, 0x00, 0xc8, 0x2b, 0xff, + 0x00, 0xa5, 0x22, 0xff, 0x00, 0x57, 0x15, 0xff, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x63, + 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x72, 0xe0, 0x86, 0xff, 0x22, 0xf5, 0x42, 0xff, 0x27, 0xda, 0x46, 0xff, + 0x15, 0xb6, 0x32, 0xff, 0x00, 0x74, 0x1c, 0xff, 0x00, 0x00, 0x00, 0xe9, 0x00, 0x00, 0x00, 0x81, + 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x5f, 0xda, 0x76, 0xff, + 0x42, 0xd2, 0x5a, 0xff, 0x22, 0x95, 0x35, 0xff, 0x00, 0x2e, 0x00, 0xff, 0x00, 0x00, 0x00, 0xa2, + 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x46, 0xb6, 0x5c, 0xff, 0x1c, 0x54, 0x22, 0xff, 0x00, 0x00, 0x00, 0xc4, + 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0xde, + 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + + +class BitmapButton : public BButton { + static const float kFrameInset = 2; + +public: + BitmapButton(const char* resourceName, BMessage* message) + : + BButton("", message), + fBitmap(BTranslationUtils::GetBitmap(resourceName)) + { + } + + BitmapButton(const uint8* bits, uint32 width, uint32 height, + color_space format, BMessage* message) + : + BButton("", message), + fBitmap(new BBitmap(BRect(0, 0, width - 1, height - 1), 0, format)) + { + memcpy(fBitmap->Bits(), bits, fBitmap->BitsLength()); + } + + ~BitmapButton() + { + delete fBitmap; + } + + virtual BSize MinSize() + { + BSize min(0, 0); + if (fBitmap) { + min.width = fBitmap->Bounds().Width(); + min.height = fBitmap->Bounds().Height(); + } + min.width += kFrameInset * 2; + min.height += kFrameInset * 2; + return min; + } + + virtual BSize MaxSize() + { + return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED); + } + + virtual BSize PreferredSize() + { + return MinSize(); + } + + virtual void Draw(BRect updateRect) + { + BRect bounds(Bounds()); + rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); + uint32 flags = be_control_look->Flags(this); + + be_control_look->DrawButtonBackground(this, bounds, updateRect, base, + flags); + + SetDrawingMode(B_OP_ALPHA); + + if (!IsEnabled()) { + SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY); + SetHighColor(0, 0, 0, 120); + } + + BPoint bitmapLocation(kFrameInset, kFrameInset); + if (Value() == B_CONTROL_ON) + bitmapLocation += BPoint(1, 1); + + DrawBitmap(fBitmap, bitmapLocation); + } + +private: + BBitmap* fBitmap; +}; + + // #pragma mark - URLInputGroup -URLInputGroup::URLInputGroup() +URLInputGroup::URLInputGroup(BMessage* goMessage) : BGroupView(B_HORIZONTAL), fWindowActive(false) @@ -308,6 +506,15 @@ URLInputGroup::URLInputGroup() fTextView = new URLTextView(this); AddChild(fTextView); + AddChild(new BSeparatorView(B_VERTICAL, B_PLAIN_BORDER)); + +// TODO: Fix in Haiku, no in-built support for archived BBitmaps from +// resources? +// fGoButton = new BitmapButton("kActionGo", NULL); + fGoButton = new BitmapButton(kGoBitmapBits, kGoBitmapWidth, + kGoBitmapHeight, kGoBitmapFormat, goMessage); + GroupLayout()->AddView(fGoButton, 0.0); + SetFlags(Flags() | B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE); SetLowColor(ViewColor()); SetViewColor(B_TRANSPARENT_COLOR); @@ -382,3 +589,11 @@ URLInputGroup::Text() const return fTextView->Text(); } + +BButton* +URLInputGroup::GoButton() const +{ + return fGoButton; +} + + diff --git a/src/apps/webpositive/URLInputGroup.h b/src/apps/webpositive/URLInputGroup.h index 5f75590c6a..105b76d932 100644 --- a/src/apps/webpositive/URLInputGroup.h +++ b/src/apps/webpositive/URLInputGroup.h @@ -7,12 +7,13 @@ #include +class BButton; class BTextView; class URLInputGroup : public BGroupView { public: - URLInputGroup(); + URLInputGroup(BMessage* goMessage); virtual ~URLInputGroup(); virtual void AttachedToWindow(); @@ -24,10 +25,13 @@ public: void SetText(const char* text); const char* Text() const; + BButton* GoButton() const; + private: class URLTextView; URLTextView* fTextView; + BButton* fGoButton; bool fWindowActive; }; diff --git a/src/apps/webpositive/WebPositive.rdef b/src/apps/webpositive/WebPositive.rdef index f741a6a3e9..5734330206 100644 --- a/src/apps/webpositive/WebPositive.rdef +++ b/src/apps/webpositive/WebPositive.rdef @@ -252,7 +252,7 @@ resource vector_icon { $"44013402360000000000000000360000485000466000" }; -resource(201) #'VICN' array { +resource(201, "kActionBack") #'VICN' array { $"6E636966070500020006023B2FA63AC896BCCBD33D335A4A6980490D0B00ACE2" $"FFFF6ECDFF0200060236D841374D6EBD38553CC6154AA9DF4607770026A8EBFF" $"0694DE020006023729EA388C8FBC29073AAE614A51AF4A729A00035E8CFF0585" @@ -265,7 +265,7 @@ resource(201) #'VICN' array { $"05000A06020607100117812004" }; -resource(202) #'VICN' array { +resource(202, "kActionForward") #'VICN' array { $"6E636966050500020006023B2FA63AC896BCCBD33D335A4A6980490D0B00ACE2" $"FFFF6ECDFF0200060239AF2C39E19BBC89D83C68DC4AFA1247CFA20006A5F7FF" $"069EEC02000602B8EEBEB986C33C7FB4BC13FB46FA0C49FBDD000592DAFD3EBD" @@ -275,7 +275,7 @@ resource(202) #'VICN' array { $"0A020102000A030103000A040104100117812004" }; -resource(203) #'VICN' array { +resource(203, "kActionForward2") #'VICN' array { $"6E63696607050002000602396DF23A056B3B94FCBB09F547CD484AAB5F0090D9" $"FFFF6ECDFF02000602B5E5793878A83E023B3B2AC34893F147CC490060C8FFFF" $"44BEFD02000602B6F90538542D3C2FCA3ACA9249A8634A929A00034F77FF0468" @@ -288,7 +288,7 @@ resource(203) #'VICN' array { $"000A06020607100117812004" }; -resource(204) #'VICN' array { +resource(204, "kActionStop") #'VICN' array { $"6E63696606050102000602393D323BB602BEA28F3C4CC64B601449439F00FF3E" $"3EFFF70606020006033B27153C10C7BDF9893D088A4B2F634882C500C805057D" $"9D0404FFB4040403750303020006023B06EB3B5469BC08EB3BB31F4AB15D4478" @@ -301,3 +301,45 @@ resource(204) #'VICN' array { $"000A0503070809100117810004" }; +resource(205, "kActionGo") archive BBitmap { + "_frame" = rect { 0.0, 0.0, 15.0, 15.0 }, + "_cspace" = 8200, + "_bmflags" = 0, + "_rowbytes" = 64, + "_data" = array { + $"0000000000000000000000000000000000000000000000000000000000000000" + $"0000000000000000000000000000000000000000000000000000000000000000" + $"0000000000000000000000C1000000DE00000061000000070000000100000000" + $"0000000000000000000000000000000000000000000000000000000000000000" + $"0000000000000000000000FF9BD4A5FF48634EFF000000C00000003500000004" + $"0000000000000000000000000000000000000000000000000000000000000000" + $"0000000000000000000000FFB6F9C2FFB3F9C0FF84B68EFF263426FD0000009B" + $"0000001600000002000000000000000000000000000000000000000000000000" + $"0000000000000000000000FFB6F9C2FF7EF995FFA3F9B3FFAAE9B6FF69906FFF" + $"000000E200000064000000070000000100000000000000000000000000000000" + $"0000000000000000000000FFB6F9C2FF6AFB85FF6AFB85FF83FA98FFA4F5B2FF" + $"7CC88AFF325C3BFF000000C00000003500000004000000000000000000000000" + $"0000000000000000000000FFB6F9C2FF5DFC7BFF5DFC7BFF5DFC7BFF5DFB7CFF" + $"60ED7AFF54D76DFF389A48FF002A14FD0000009B000000160000000200000000" + $"0000000000000000000000FFB5F8C1FF59FC77FF59FC77FF59FC77FF59FC77FF" + $"59FC77FF55F674FF40DB5CFF2BBC48FF1C752BFF000000D00000002000000003" + $"0000000000000000000000FFA8F4B5FF2EFA54FF2EFA54FF2EFA54FF2EFA54FF" + $"2EFA54FF2BF350FF22D542FF1CB638FF157027FF000000D00000003D00000009" + $"0000000000000000000000FF92ECA2FF15F940FF15F940FF15F940FF15F740FF" + $"15DE35FF00BE2EFF008922FF002600FD0000009B000000430000002000000003" + $"0000000000000000000000FF7EE591FF15F83DFF15F83DFF1CEA3DFF00C732FF" + $"009E22FF004815FF000000BF000000560000002D0000000F0000000200000000" + $"0000000000000000000000FF6DDF81FF1CF340FF2BDA4AFF1CB638FF006D1CFF" + $"000000E200000074000000360000001900000004000000000000000000000000" + $"0000000000000000000000FF5DDA75FF44D25FFF229338FF002600FD0000009B" + $"0000004300000023000000070000000100000000000000000000000000000000" + $"0000000000000000000000FF46B65CFF1C5222FF000000BF000000560000002D" + $"0000000F00000002000000000000000000000000000000000000000000000000" + $"0000000000000000000000C2000000DE00000074000000360000001900000004" + $"0000000000000000000000000000000000000000000000000000000000000000" + $"0000000000000000000000030000001F00000020000000080000000100000000" + $"0000000000000000000000000000000000000000000000000000000000000000" + } +}; + + From 3aa3e03460eba4d65982ec900b065e69deacd643 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 9 Apr 2010 11:12:12 +0000 Subject: [PATCH 218/349] Adopt the URL also when requesting the URL, before it is commited. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@404 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 2b5bce1fb3..c397962a5f 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -836,6 +836,11 @@ BrowserWindow::CloseWindowRequested(BWebView* view) void BrowserWindow::LoadNegotiating(const BString& url, BWebView* view) { + if (view != CurrentWebView()) + return; + + fURLInputGroup->SetText(url.String()); + BString status("Requesting: "); status << url; view->WebPage()->SetStatusMessage(status); From 560610f70eb60020d17ec3c2889357b18aa4e322 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 11 Apr 2010 23:21:45 +0000 Subject: [PATCH 219/349] Don't overwrite memory when pressing return in the URL text input. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@405 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/URLInputGroup.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index 32cbffd55b..1f69f60538 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -320,10 +320,10 @@ URLInputGroup::URLTextView::InsertText(const char* inText, int32 inLength, char* buffer = NULL; if (strpbrk(inText, "\r\n") && inLength <= 1024) { - buffer = (char*)malloc(inLength); + buffer = (char*)malloc(inLength + 1); if (buffer) { - strcpy(buffer, inText); + strlcpy(buffer, inText, inLength); for (int32 i = 0; i < inLength; i++) { if (buffer[i] == '\r' || buffer[i] == '\n') From f9977c07c19bfe294637ac51b3c64aa237b9a300 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 12 Apr 2010 16:16:40 +0000 Subject: [PATCH 220/349] strlcpy() takes buffer size, not char count, and will copy buffer size - 1 chars at max and terminate the buffer. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@406 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/URLInputGroup.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index 1f69f60538..35a6130181 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -323,7 +323,7 @@ URLInputGroup::URLTextView::InsertText(const char* inText, int32 inLength, buffer = (char*)malloc(inLength + 1); if (buffer) { - strlcpy(buffer, inText, inLength); + strlcpy(buffer, inText, inLength + 1); for (int32 i = 0; i < inLength; i++) { if (buffer[i] == '\r' || buffer[i] == '\n') From a26e66b548662dc307869b11f411b6ce019ab3ae Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 12 Apr 2010 16:57:03 +0000 Subject: [PATCH 221/349] One more round of simplification and fixing. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@407 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/URLInputGroup.cpp | 30 +++++++++++--------------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index 35a6130181..57c1d8baa7 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -317,25 +317,19 @@ void URLInputGroup::URLTextView::InsertText(const char* inText, int32 inLength, int32 inOffset, const text_run_array* inRuns) { - char* buffer = NULL; - - if (strpbrk(inText, "\r\n") && inLength <= 1024) { - buffer = (char*)malloc(inLength + 1); - - if (buffer) { - strlcpy(buffer, inText, inLength + 1); - - for (int32 i = 0; i < inLength; i++) { - if (buffer[i] == '\r' || buffer[i] == '\n') - buffer[i] = ' '; - } - } + // Filter all line breaks, note that inText is not terminated. + if (inLength == 1) { + if (*inText == '\n' || *inText == '\r') + BTextView::InsertText(" ", 1, inOffset, inRuns); + else + BTextView::InsertText(inText, 1, inOffset, inRuns); + } else { + BString filteredText(inText, inLength); + filteredText.ReplaceAll('\n', ' '); + filteredText.ReplaceAll('\r', ' '); + BTextView::InsertText(filteredText.String(), inLength, inOffset, + inRuns); } - - BTextView::InsertText(buffer ? buffer : inText, inLength, inOffset, - inRuns); - - free(buffer); } From 0ef19ef7e12beb734510ed8bfd00a688300bdc9d Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 12 Apr 2010 17:44:22 +0000 Subject: [PATCH 222/349] Fix the cmd-arrow left/right for go back/forward actions. Truncate the modifiers to just the part that describes the modifier keys in general. What's left should be exactly B_COMMAND_KEY. This fixes the workspace switching short-cut to trigger page history navigation WebPositive. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@408 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index c397962a5f..5c8beb644e 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -366,15 +366,21 @@ void BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) { const char* bytes; - int32 modifiers; + uint32 modifiers; if ((message->what == B_KEY_DOWN || message->what == B_UNMAPPED_KEY_DOWN) && message->FindString("bytes", &bytes) == B_OK - && message->FindInt32("modifiers", &modifiers) == B_OK) { - if (target == fURLInputGroup->TextView()) { + && message->FindInt32("modifiers", (int32*)&modifiers) == B_OK) { + + modifiers = modifiers & 0x000000ff; + if (bytes[0] == B_LEFT_ARROW && modifiers == B_COMMAND_KEY) + PostMessage(GO_BACK); + else if (bytes[0] == B_RIGHT_ARROW && modifiers == B_COMMAND_KEY) + PostMessage(GO_FORWARD); + else if (target == fURLInputGroup->TextView()) { // Handle B_RETURN in the URL text control. This is the easiest // way to react *only* when the user presses the return key in the - // address bar, as opposed to trying to load whatever is in there when - // the text control just goes out of focus. + // address bar, as opposed to trying to load whatever is in there + // when the text control just goes out of focus. if (bytes[0] == B_RETURN) { // Do it in such a way that the user sees the Go-button go down. fURLInputGroup->GoButton()->SetValue(B_CONTROL_ON); @@ -383,10 +389,6 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) snooze(1000); fURLInputGroup->GoButton()->SetValue(B_CONTROL_OFF); } - } else if (bytes[0] == B_LEFT_ARROW && (modifiers & B_COMMAND_KEY) != 0) { - PostMessage(GO_BACK); - } else if (bytes[0] == B_RIGHT_ARROW && (modifiers & B_COMMAND_KEY) != 0) { - PostMessage(GO_FORWARD); } } BWebWindow::DispatchMessage(message, target); From 6d9387446962660835431fdf3b94d04884c49700 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 13 Apr 2010 23:15:23 +0000 Subject: [PATCH 223/349] * Add a flag "activate" to WindowFeatures and set it to true by default. It's supposed to allow specifying whether the new window/page shall be activated or not. * In ContextMenuController, when creating a new page from a link, specify that it shall not be activated. * Handle the new flag in the WebKit layer. -> "Open link in tab" from the context menu no longer selects the new tab, but opens it "in the background". git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@414 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 4 ++-- src/apps/webpositive/BrowserWindow.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 5c8beb644e..ac030f2f9d 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -810,14 +810,14 @@ BrowserWindow::NewWindowRequested(const BString& url, bool primaryAction) void BrowserWindow::NewPageCreated(BWebView* view, BRect windowFrame, - bool modalDialog, bool resizable) + bool modalDialog, bool resizable, bool activate) { if (windowFrame.IsValid()) { BrowserWindow* window = new BrowserWindow(windowFrame, fAppSettings, DoNotHaveToolbar, view); window->Show(); } else - CreateNewTab(BString(), true, view); + CreateNewTab(BString(), activate, view); } diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index c6c91a88c9..124144cffb 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -94,7 +94,7 @@ private: virtual void CloseWindowRequested(BWebView* view); virtual void NewPageCreated(BWebView* view, BRect windowFrame, bool modalDialog, - bool resizable); + bool resizable, bool activate); virtual void LoadNegotiating(const BString& url, BWebView* view); virtual void LoadCommitted(const BString& url, From 029353b44c63fa39a9135f36f225bfac5daed34b Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 15 Apr 2010 12:19:16 +0000 Subject: [PATCH 224/349] * Reworded defines in Jamfiles to make them more readable. * Split WebTabView into several files in a new sub-folder "tabview". * Implemented scrolling the tab view left/right when there are more tabs than fit into the view. * Fixed graphic glitches in the TabContainerView when the window is resized, the space behind the last tab was not managed properly. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@416 94f232f2-1747-11df-bad5-a5bfde151594 --- .../webpositive/tabview/TabContainerView.cpp | 520 ++++++++ .../webpositive/tabview/TabContainerView.h | 102 ++ .../TabManager.cpp} | 1052 ++++------------- .../{WebTabView.h => tabview/TabManager.h} | 3 +- src/apps/webpositive/tabview/TabView.cpp | 366 ++++++ src/apps/webpositive/tabview/TabView.h | 122 ++ 6 files changed, 1330 insertions(+), 835 deletions(-) create mode 100644 src/apps/webpositive/tabview/TabContainerView.cpp create mode 100644 src/apps/webpositive/tabview/TabContainerView.h rename src/apps/webpositive/{WebTabView.cpp => tabview/TabManager.cpp} (50%) rename src/apps/webpositive/{WebTabView.h => tabview/TabManager.h} (97%) create mode 100644 src/apps/webpositive/tabview/TabView.cpp create mode 100644 src/apps/webpositive/tabview/TabView.h diff --git a/src/apps/webpositive/tabview/TabContainerView.cpp b/src/apps/webpositive/tabview/TabContainerView.cpp new file mode 100644 index 0000000000..a4c26ddb2d --- /dev/null +++ b/src/apps/webpositive/tabview/TabContainerView.cpp @@ -0,0 +1,520 @@ +/* + * Copyright (C) 2010 Rene Gollent + * Copyright (C) 2010 Stephan Aßmus + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "TabContainerView.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "TabView.h" + + +static const float kLeftTabInset = 4; + + +TabContainerView::TabContainerView(Controller* controller) + : + BGroupView(B_HORIZONTAL), + fLastMouseEventTab(NULL), + fMouseDown(false), + fClickCount(0), + fSelectedTab(NULL), + fController(controller), + fFirstVisibleTabIndex(0) +{ + SetFlags(Flags() | B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE); + SetViewColor(B_TRANSPARENT_COLOR); + GroupLayout()->SetInsets(kLeftTabInset, 0, 0, 1); + GroupLayout()->AddItem(BSpaceLayoutItem::CreateGlue(), 0.0f); +} + + +TabContainerView::~TabContainerView() +{ +} + + +BSize +TabContainerView::MinSize() +{ + // Eventually, we want to be scrolling if the tabs don't fit. + BSize size(BGroupView::MinSize()); + size.width = 300; + return size; +} + + +void +TabContainerView::MessageReceived(BMessage* message) +{ + switch (message->what) { + default: + BGroupView::MessageReceived(message); + } +} + + +void +TabContainerView::Draw(BRect updateRect) +{ + // Stroke separator line at bottom. + rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); + BRect frame(Bounds()); + SetHighColor(tint_color(base, B_DARKEN_2_TINT)); + StrokeLine(frame.LeftBottom(), frame.RightBottom()); + frame.bottom--; + + // Draw empty area before first tab. + uint32 borders = BControlLook::B_TOP_BORDER | BControlLook::B_BOTTOM_BORDER; + BRect leftFrame(frame.left, frame.top, kLeftTabInset, frame.bottom); + be_control_look->DrawInactiveTab(this, leftFrame, updateRect, base, 0, + borders); + + // Draw all tabs, keeping track of where they end. + BGroupLayout* layout = GroupLayout(); + int32 count = layout->CountItems() - 1; + for (int32 i = 0; i < count; i++) { + TabLayoutItem* item = dynamic_cast( + layout->ItemAt(i)); + if (!item || !item->IsVisible()) + continue; + item->Parent()->Draw(updateRect); + frame.left = item->Frame().right + 1; + } + + // Draw empty area after last tab. + be_control_look->DrawInactiveTab(this, frame, updateRect, base, 0, borders); +} + + +void +TabContainerView::MouseDown(BPoint where) +{ + uint32 buttons; + if (Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons) != B_OK) + buttons = B_PRIMARY_MOUSE_BUTTON; + uint32 clicks; + if (Window()->CurrentMessage()->FindInt32("clicks", (int32*)&clicks) != B_OK) + clicks = 1; + fMouseDown = true; + SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); + if (fLastMouseEventTab) + fLastMouseEventTab->MouseDown(where, buttons); + else { + if (clicks > 1) + fClickCount++; + else + fClickCount = 1; + } +} + + +void +TabContainerView::MouseUp(BPoint where) +{ + fMouseDown = false; + if (fLastMouseEventTab) + fLastMouseEventTab->MouseUp(where); + else if (fClickCount > 1) { + fClickCount = 0; + fController->DoubleClickOutsideTabs(); + } +} + + +void +TabContainerView::MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMessage) +{ + _MouseMoved(where, transit, dragMessage); +} + + +void +TabContainerView::DoLayout() +{ + BGroupView::DoLayout(); + + _ValidateTabVisibility(); + _SendFakeMouseMoved(); +} + +void +TabContainerView::AddTab(const char* label, int32 index) +{ + TabView* tab; + if (fController) + tab = fController->CreateTabView(); + else + tab = new TabView(); + tab->SetLabel(label); + AddTab(tab, index); +} + + +void +TabContainerView::AddTab(TabView* tab, int32 index) +{ + tab->SetContainerView(this); + + if (index == -1) + index = GroupLayout()->CountItems() - 1; + + bool hasFrames = fController != NULL && fController->HasFrames(); + bool isFirst = index == 0 && hasFrames; + bool isLast = index == GroupLayout()->CountItems() - 1 && hasFrames; + bool isFront = fSelectedTab == NULL; + tab->Update(isFirst, isLast, isFront); + + GroupLayout()->AddItem(index, tab->LayoutItem()); + + if (isFront) + SelectTab(tab); + if (isLast) { + TabLayoutItem* item + = dynamic_cast(GroupLayout()->ItemAt(index - 1)); + if (item) + item->Parent()->SetIsLast(false); + } + + SetFirstVisibleTabIndex(MaxFirstVisibleTabIndex()); + _ValidateTabVisibility(); +} + +TabView* +TabContainerView::RemoveTab(int32 index) +{ + TabLayoutItem* item + = dynamic_cast(GroupLayout()->RemoveItem(index)); + + if (!item) + return NULL; + + BRect dirty(Bounds()); + dirty.left = item->Frame().left; + TabView* removedTab = item->Parent(); + removedTab->SetContainerView(NULL); + + if (removedTab == fLastMouseEventTab) + fLastMouseEventTab = NULL; + + // Update tabs after or before the removed tab. + bool hasFrames = fController != NULL && fController->HasFrames(); + item = dynamic_cast(GroupLayout()->ItemAt(index)); + if (item) { + // This tab is behind the removed tab. + TabView* tab = item->Parent(); + tab->Update(index == 0 && hasFrames, + index == GroupLayout()->CountItems() - 2 && hasFrames, + tab == fSelectedTab); + if (removedTab == fSelectedTab) { + fSelectedTab = NULL; + SelectTab(tab); + } else if (fController && tab == fSelectedTab) + fController->TabSelected(index); + } else { + // The removed tab was the last tab. + item = dynamic_cast(GroupLayout()->ItemAt(index - 1)); + if (item) { + TabView* tab = item->Parent(); + tab->Update(index == 0 && hasFrames, + index == GroupLayout()->CountItems() - 2 && hasFrames, + tab == fSelectedTab); + if (removedTab == fSelectedTab) { + fSelectedTab = NULL; + SelectTab(tab); + } + } + } + + Invalidate(dirty); + _ValidateTabVisibility(); + + return removedTab; +} + + +TabView* +TabContainerView::TabAt(int32 index) const +{ + TabLayoutItem* item = dynamic_cast( + GroupLayout()->ItemAt(index)); + if (item) + return item->Parent(); + return NULL; +} + + +int32 +TabContainerView::IndexOf(TabView* tab) const +{ + return GroupLayout()->IndexOfItem(tab->LayoutItem()); +} + + +void +TabContainerView::SelectTab(int32 index) +{ + TabView* tab = NULL; + TabLayoutItem* item = dynamic_cast( + GroupLayout()->ItemAt(index)); + if (item) + tab = item->Parent(); + + SelectTab(tab); +} + + +void +TabContainerView::SelectTab(TabView* tab) +{ + if (tab == fSelectedTab) + return; + + if (fSelectedTab) + fSelectedTab->SetIsFront(false); + + fSelectedTab = tab; + + if (fSelectedTab) + fSelectedTab->SetIsFront(true); + + if (fController != NULL) { + int32 index = -1; + if (fSelectedTab != NULL) + index = GroupLayout()->IndexOfItem(tab->LayoutItem()); + + fController->TabSelected(index); + } +} + + +void +TabContainerView::SetTabLabel(int32 tabIndex, const char* label) +{ + TabLayoutItem* item = dynamic_cast( + GroupLayout()->ItemAt(tabIndex)); + if (item == NULL) + return; + + item->Parent()->SetLabel(label); +} + + +void +TabContainerView::SetFirstVisibleTabIndex(int32 index) +{ + if (index < 0) + index = 0; + if (index > MaxFirstVisibleTabIndex()) + index = MaxFirstVisibleTabIndex(); + if (fFirstVisibleTabIndex == index) + return; + + fFirstVisibleTabIndex = index; + + _UpdateTabVisibility(); +} + + +int32 +TabContainerView::FirstVisibleTabIndex() const +{ + return fFirstVisibleTabIndex; +} + + +int32 +TabContainerView::MaxFirstVisibleTabIndex() const +{ + float availableWidth = _AvailableWidthForTabs(); + if (availableWidth < 0) + return 0; + float visibleTabsWidth = 0; + + BGroupLayout* layout = GroupLayout(); + int32 i = layout->CountItems() - 2; + for (; i >= 0; i--) { + TabLayoutItem* item = dynamic_cast( + layout->ItemAt(i)); + if (item == NULL) + continue; + + float itemWidth = item->MinSize().width; + if (availableWidth >= visibleTabsWidth + itemWidth) + visibleTabsWidth += itemWidth; + else { + // The tab before this tab is the last one that can be visible. + return i + 1; + } + } + + return 0; +} + + +bool +TabContainerView::CanScrollLeft() const +{ + return fFirstVisibleTabIndex < MaxFirstVisibleTabIndex(); +} + + +bool +TabContainerView::CanScrollRight() const +{ + BGroupLayout* layout = GroupLayout(); + int32 count = layout->CountItems() - 1; + if (count > 0) { + TabLayoutItem* item = dynamic_cast( + layout->ItemAt(count - 1)); + return !item->IsVisible(); + } + return false; +} + + +// #pragma mark - + + +TabView* +TabContainerView::_TabAt(const BPoint& where) const +{ + BGroupLayout* layout = GroupLayout(); + int32 count = layout->CountItems() - 1; + for (int32 i = 0; i < count; i++) { + TabLayoutItem* item = dynamic_cast( + layout->ItemAt(i)); + if (item && item->IsVisible() && item->Frame().Contains(where)) + return item->Parent(); + } + return NULL; +} + + +void +TabContainerView::_MouseMoved(BPoint where, uint32 _transit, + const BMessage* dragMessage) +{ + TabView* tab = _TabAt(where); + if (fMouseDown) { + uint32 transit = tab == fLastMouseEventTab + ? B_INSIDE_VIEW : B_OUTSIDE_VIEW; + if (fLastMouseEventTab) + fLastMouseEventTab->MouseMoved(where, transit, dragMessage); + return; + } + + if (fLastMouseEventTab && fLastMouseEventTab == tab) + fLastMouseEventTab->MouseMoved(where, B_INSIDE_VIEW, dragMessage); + else { + if (fLastMouseEventTab) + fLastMouseEventTab->MouseMoved(where, B_EXITED_VIEW, dragMessage); + fLastMouseEventTab = tab; + if (fLastMouseEventTab) + fLastMouseEventTab->MouseMoved(where, B_ENTERED_VIEW, dragMessage); + } +} + + +void +TabContainerView::_ValidateTabVisibility() +{ + if (fFirstVisibleTabIndex > MaxFirstVisibleTabIndex()) + SetFirstVisibleTabIndex(MaxFirstVisibleTabIndex()); + else + _UpdateTabVisibility(); +} + + +void +TabContainerView::_UpdateTabVisibility() +{ + float availableWidth = _AvailableWidthForTabs(); + if (availableWidth < 0) + return; + float visibleTabsWidth = 0; + + bool canScrollTabsLeft = fFirstVisibleTabIndex > 0; + bool canScrollTabsRight = false; + + BGroupLayout* layout = GroupLayout(); + int32 count = layout->CountItems() - 1; + for (int32 i = 0; i < count; i++) { + TabLayoutItem* item = dynamic_cast( + layout->ItemAt(i)); + if (i < fFirstVisibleTabIndex) + item->SetVisible(false); + else { + float itemWidth = item->MinSize().width; + bool visible = availableWidth >= visibleTabsWidth + itemWidth; + item->SetVisible(visible && !canScrollTabsRight); + visibleTabsWidth += itemWidth; + if (!visible) + canScrollTabsRight = true; + } + } + fController->UpdateTabScrollability(canScrollTabsLeft, canScrollTabsRight); +} + + +float +TabContainerView::_AvailableWidthForTabs() const +{ + float width = Bounds().Width() - 10; + // TODO: Don't really know why -10 is needed above. + + float left; + float right; + GroupLayout()->GetInsets(&left, NULL, &right, NULL); + width -= left + right; + + return width; +} + + +void +TabContainerView::_SendFakeMouseMoved() +{ + BPoint where; + uint32 buttons; + GetMouse(&where, &buttons, false); + if (Bounds().Contains(where)) + _MouseMoved(where, B_INSIDE_VIEW, NULL); +} + diff --git a/src/apps/webpositive/tabview/TabContainerView.h b/src/apps/webpositive/tabview/TabContainerView.h new file mode 100644 index 0000000000..13815d1592 --- /dev/null +++ b/src/apps/webpositive/tabview/TabContainerView.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TAB_CONTAINER_VIEW_H +#define TAB_CONTAINER_VIEW_H + +#include + + +class TabView; + + +class TabContainerView : public BGroupView { +public: + class Controller { + public: + virtual void TabSelected(int32 tabIndex) = 0; + virtual bool HasFrames() = 0; + virtual TabView* CreateTabView() = 0; + virtual void DoubleClickOutsideTabs() = 0; + virtual void UpdateTabScrollability(bool canScrollLeft, + bool canScrollRight) = 0; + }; + +public: + TabContainerView(Controller* controller); + virtual ~TabContainerView(); + + virtual BSize MinSize(); + + virtual void MessageReceived(BMessage*); + + virtual void Draw(BRect updateRect); + + virtual void MouseDown(BPoint where); + virtual void MouseUp(BPoint where); + virtual void MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMessage); + + virtual void DoLayout(); + + void AddTab(const char* label, int32 index = -1); + void AddTab(TabView* tab, int32 index = -1); + TabView* RemoveTab(int32 index); + TabView* TabAt(int32 index) const; + + int32 IndexOf(TabView* tab) const; + + void SelectTab(int32 tabIndex); + void SelectTab(TabView* tab); + + void SetTabLabel(int32 tabIndex, const char* label); + + void SetFirstVisibleTabIndex(int32 index); + int32 FirstVisibleTabIndex() const; + int32 MaxFirstVisibleTabIndex() const; + + bool CanScrollLeft() const; + bool CanScrollRight() const; + +private: + TabView* _TabAt(const BPoint& where) const; + void _MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMessage); + void _ValidateTabVisibility(); + void _UpdateTabVisibility(); + float _AvailableWidthForTabs() const; + void _SendFakeMouseMoved(); + +private: + TabView* fLastMouseEventTab; + bool fMouseDown; + uint32 fClickCount; + TabView* fSelectedTab; + Controller* fController; + int32 fFirstVisibleTabIndex; +}; + +#endif // TAB_CONTAINER_VIEW_H diff --git a/src/apps/webpositive/WebTabView.cpp b/src/apps/webpositive/tabview/TabManager.cpp similarity index 50% rename from src/apps/webpositive/WebTabView.cpp rename to src/apps/webpositive/tabview/TabManager.cpp index d953d2ee99..814496e582 100644 --- a/src/apps/webpositive/WebTabView.cpp +++ b/src/apps/webpositive/tabview/TabManager.cpp @@ -26,9 +26,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "WebTabView.h" +#include "TabManager.h" + +#include -#include "WebView.h" #include #include #include @@ -39,716 +40,245 @@ #include #include #include -#include + +#include "TabContainerView.h" +#include "TabView.h" -class TabView; -class TabContainerView; +// #pragma mark - Helper classes -class TabLayoutItem : public BAbstractLayoutItem { +class TabButton : public BButton { public: - TabLayoutItem(TabView* parent); + TabButton(BMessage* message) + : BButton("", message) + { + } - virtual bool IsVisible(); - virtual void SetVisible(bool visible); + virtual BSize MinSize() + { + return BSize(12, 12); + } - virtual BRect Frame(); - virtual void SetFrame(BRect frame); + virtual BSize MaxSize() + { + return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED); + } - virtual BView* View(); + virtual BSize PreferredSize() + { + return MinSize(); + } - virtual BSize BaseMinSize(); - virtual BSize BaseMaxSize(); - virtual BSize BasePreferredSize(); - virtual BAlignment BaseAlignment(); + virtual void Draw(BRect updateRect) + { + BRect bounds(Bounds()); + rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); + SetHighColor(tint_color(base, B_DARKEN_2_TINT)); + StrokeLine(bounds.LeftBottom(), bounds.RightBottom()); + bounds.bottom--; + uint32 flags = be_control_look->Flags(this); + uint32 borders = BControlLook::B_TOP_BORDER + | BControlLook::B_BOTTOM_BORDER; + be_control_look->DrawInactiveTab(this, bounds, updateRect, base, + 0, borders); + if (IsEnabled()) { + rgb_color button = tint_color(base, 1.07); + be_control_look->DrawButtonBackground(this, bounds, updateRect, + button, flags, 0); + } - TabView* Parent() const; + bounds.left = (bounds.left + bounds.right) / 2 - 6; + bounds.top = (bounds.top + bounds.bottom) / 2 - 6; + bounds.right = bounds.left + 12; + bounds.bottom = bounds.top + 12; + DrawSymbol(bounds, updateRect, base); + } -private: - TabView* fParent; - BRect fFrame; + virtual void DrawSymbol(BRect frame, const BRect& updateRect, + const rgb_color& base) + { + } }; -class TabView { +class ScrollLeftTabButton : public TabButton { public: - TabView(); - virtual ~TabView(); + ScrollLeftTabButton(BMessage* message) + : TabButton(message) + { + } - virtual BSize MinSize(); - virtual BSize PreferredSize(); - virtual BSize MaxSize(); - - void Draw(BRect updateRect); - virtual void DrawBackground(BView* owner, BRect frame, - const BRect& updateRect, bool isFirst, bool isLast, bool isFront); - virtual void DrawContents(BView* owner, BRect frame, - const BRect& updateRect, bool isFirst, bool isLast, bool isFront); - - virtual void MouseDown(BPoint where, uint32 buttons); - virtual void MouseUp(BPoint where); - virtual void MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage); - - void SetIsFront(bool isFront); - bool IsFront() const; - void SetIsLast(bool isLast); - virtual void Update(bool isFirst, bool isLast, bool isFront); - - BLayoutItem* LayoutItem() const; - void SetContainerView(TabContainerView* containerView); - TabContainerView* ContainerView() const; - - void SetLabel(const char* label); - const BString& Label() const; - - BRect Frame() const; - -private: - float _LabelHeight() const; - -private: - TabContainerView* fContainerView; - TabLayoutItem* fLayoutItem; - - BString fLabel; - - bool fIsFirst; - bool fIsLast; - bool fIsFront; + virtual void DrawSymbol(BRect frame, const BRect& updateRect, + const rgb_color& base) + { + float tint = IsEnabled() ? B_DARKEN_4_TINT : B_DARKEN_1_TINT; + be_control_look->DrawArrowShape(this, frame, updateRect, + base, BControlLook::B_LEFT_ARROW, 0, tint); + } }; -class TabContainerView : public BGroupView { +class ScrollRightTabButton : public TabButton { public: - class Controller { - public: - virtual void TabSelected(int32 tabIndex) = 0; - virtual bool HasFrames() = 0; - virtual TabView* CreateTabView() = 0; - virtual void DoubleClickOutsideTabs() = 0; - }; + ScrollRightTabButton(BMessage* message) + : TabButton(message) + { + } -public: - TabContainerView(Controller* controller); - virtual ~TabContainerView(); - - virtual BSize MinSize(); - - virtual void MessageReceived(BMessage*); - - virtual void Draw(BRect updateRect); - - virtual void MouseDown(BPoint where); - virtual void MouseUp(BPoint where); - virtual void MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage); - - virtual void DoLayout(); - - void AddTab(const char* label, int32 index = -1); - void AddTab(TabView* tab, int32 index = -1); - TabView* RemoveTab(int32 index); - TabView* TabAt(int32 index) const; - - int32 IndexOf(TabView* tab) const; - - void SelectTab(int32 tabIndex); - void SelectTab(TabView* tab); - - void SetTabLabel(int32 tabIndex, const char* label); - -private: - TabView* _TabAt(const BPoint& where) const; - void _MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage); - -private: - TabView* fLastMouseEventTab; - bool fMouseDown; - uint32 fClickCount; - TabView* fSelectedTab; - Controller* fController; + virtual void DrawSymbol(BRect frame, const BRect& updateRect, + const rgb_color& base) + { + frame.OffsetBy(1, 0); + float tint = IsEnabled() ? B_DARKEN_4_TINT : B_DARKEN_1_TINT; + be_control_look->DrawArrowShape(this, frame, updateRect, + base, BControlLook::B_RIGHT_ARROW, 0, tint); + } }; -// #pragma mark - TabContainerView - - -static const float kLeftTabInset = 4; - - -TabContainerView::TabContainerView(Controller* controller) - : - BGroupView(B_HORIZONTAL), - fLastMouseEventTab(NULL), - fMouseDown(false), - fClickCount(0), - fSelectedTab(NULL), - fController(controller) -{ - SetFlags(Flags() | B_WILL_DRAW); - SetViewColor(B_TRANSPARENT_COLOR); - GroupLayout()->SetInsets(kLeftTabInset, 0, 0, 1); - GroupLayout()->AddItem(BSpaceLayoutItem::CreateGlue(), 0.0f); -} - - -TabContainerView::~TabContainerView() -{ -} - - -BSize -TabContainerView::MinSize() -{ - // Eventually, we want to be scrolling if the tabs don't fit. - BSize size(BGroupView::MinSize()); - size.width = 300; - return size; -} - - -void -TabContainerView::MessageReceived(BMessage* message) -{ - switch (message->what) { - default: - BGroupView::MessageReceived(message); - } -} - - -void -TabContainerView::Draw(BRect updateRect) -{ - // Stroke separator line at bottom. - rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); - BRect frame(Bounds()); - SetHighColor(tint_color(base, B_DARKEN_2_TINT)); - StrokeLine(frame.LeftBottom(), frame.RightBottom()); - frame.bottom--; - - // Draw empty area before first tab. - uint32 borders = BControlLook::B_TOP_BORDER | BControlLook::B_BOTTOM_BORDER; - BRect leftFrame(frame.left, frame.top, kLeftTabInset, frame.bottom); - be_control_look->DrawInactiveTab(this, leftFrame, updateRect, base, 0, - borders); - - // Draw all tabs, keeping track of where they end. - BGroupLayout* layout = GroupLayout(); - int32 count = layout->CountItems() - 1; - for (int32 i = 0; i < count; i++) { - TabLayoutItem* item = dynamic_cast( - layout->ItemAt(i)); - if (!item) - continue; - item->Parent()->Draw(updateRect); - frame.left = item->Frame().right + 1; +class NewTabButton : public TabButton { +public: + NewTabButton(BMessage* message) + : TabButton(message) + { + SetToolTip("New tab (Cmd-T)"); } - // Draw empty area after last tab. - be_control_look->DrawInactiveTab(this, frame, updateRect, base, 0, borders); -} - - -void -TabContainerView::MouseDown(BPoint where) -{ - uint32 buttons; - if (Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons) != B_OK) - buttons = B_PRIMARY_MOUSE_BUTTON; - uint32 clicks; - if (Window()->CurrentMessage()->FindInt32("clicks", (int32*)&clicks) != B_OK) - clicks = 1; - fMouseDown = true; - SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); - if (fLastMouseEventTab) - fLastMouseEventTab->MouseDown(where, buttons); - else { - if (clicks > 1) - fClickCount++; - else - fClickCount = 1; + virtual BSize MinSize() + { + return BSize(18, 12); } -} - -void -TabContainerView::MouseUp(BPoint where) -{ - fMouseDown = false; - if (fLastMouseEventTab) - fLastMouseEventTab->MouseUp(where); - else if (fClickCount > 1) { - fClickCount = 0; - fController->DoubleClickOutsideTabs(); + virtual void DrawSymbol(BRect frame, const BRect& updateRect, + const rgb_color& base) + { + SetHighColor(tint_color(base, B_DARKEN_4_TINT)); + float inset = 3; + frame.InsetBy(2, 2); + frame.top++; + frame.left++; + FillRoundRect(BRect(frame.left, frame.top + inset, + frame.right, frame.bottom - inset), 1, 1); + FillRoundRect(BRect(frame.left + inset, frame.top, + frame.right - inset, frame.bottom), 1, 1); } -} +}; -void -TabContainerView::MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage) -{ - _MouseMoved(where, transit, dragMessage); -} - - -void -TabContainerView::DoLayout() -{ - BGroupView::DoLayout(); - - BPoint where; - uint32 buttons; - GetMouse(&where, &buttons, false); - if (Bounds().Contains(where)) - _MouseMoved(where, B_INSIDE_VIEW, NULL); -} - -void -TabContainerView::AddTab(const char* label, int32 index) -{ - TabView* tab; - if (fController) - tab = fController->CreateTabView(); - else - tab = new TabView(); - tab->SetLabel(label); - AddTab(tab, index); -} - - -void -TabContainerView::AddTab(TabView* tab, int32 index) -{ - tab->SetContainerView(this); - - if (index == -1) - index = GroupLayout()->CountItems() - 1; - - bool hasFrames = fController != NULL && fController->HasFrames(); - bool isFirst = index == 0 && hasFrames; - bool isLast = index == GroupLayout()->CountItems() - 1 && hasFrames; - bool isFront = fSelectedTab == NULL; - tab->Update(isFirst, isLast, isFront); - - GroupLayout()->AddItem(index, tab->LayoutItem()); - - if (isFront) - SelectTab(tab); - if (isLast) { - TabLayoutItem* item - = dynamic_cast(GroupLayout()->ItemAt(index - 1)); - if (item) - item->Parent()->SetIsLast(false); +class TabMenuTabButton : public TabButton { +public: + TabMenuTabButton(BMessage* message) + : TabButton(message) + { } -} -TabView* -TabContainerView::RemoveTab(int32 index) -{ - TabLayoutItem* item - = dynamic_cast(GroupLayout()->RemoveItem(index)); + virtual BSize MinSize() + { + return BSize(18, 12); + } - if (!item) - return NULL; + virtual void DrawSymbol(BRect frame, const BRect& updateRect, + const rgb_color& base) + { + be_control_look->DrawArrowShape(this, frame, updateRect, + base, BControlLook::B_DOWN_ARROW, 0, B_DARKEN_4_TINT); + } +}; - BRect dirty(Bounds()); - dirty.left = item->Frame().left; - TabView* removedTab = item->Parent(); - removedTab->SetContainerView(NULL); - if (removedTab == fLastMouseEventTab) - fLastMouseEventTab = NULL; +enum { + MSG_SCROLL_TABS_LEFT = 'stlt', + MSG_SCROLL_TABS_RIGHT = 'strt' +}; - // Update tabs after or before the removed tab. - bool hasFrames = fController != NULL && fController->HasFrames(); - item = dynamic_cast(GroupLayout()->ItemAt(index)); - if (item) { - // This tab is behind the removed tab. - TabView* tab = item->Parent(); - tab->Update(index == 0 && hasFrames, - index == GroupLayout()->CountItems() - 2 && hasFrames, - tab == fSelectedTab); - if (removedTab == fSelectedTab) { - fSelectedTab = NULL; - SelectTab(tab); - } else if (fController && tab == fSelectedTab) - fController->TabSelected(index); - } else { - // The removed tab was the last tab. - item = dynamic_cast(GroupLayout()->ItemAt(index - 1)); - if (item) { - TabView* tab = item->Parent(); - tab->Update(index == 0 && hasFrames, - index == GroupLayout()->CountItems() - 2 && hasFrames, - tab == fSelectedTab); - if (removedTab == fSelectedTab) { - fSelectedTab = NULL; - SelectTab(tab); - } + +class TabContainerGroup : public BGroupView { +public: + TabContainerGroup(TabContainerView* tabContainerView) + : + BGroupView(B_HORIZONTAL), + fTabContainerView(tabContainerView), + fScrollLeftTabButton(NULL), + fScrollRightTabButton(NULL) + { + } + + virtual void AttachedToWindow() + { + if (fScrollLeftTabButton != NULL) + fScrollLeftTabButton->SetTarget(this); + if (fScrollRightTabButton != NULL) + fScrollRightTabButton->SetTarget(this); + } + + virtual void MessageReceived(BMessage* message) + { + switch (message->what) { + case MSG_SCROLL_TABS_LEFT: + fTabContainerView->SetFirstVisibleTabIndex( + fTabContainerView->FirstVisibleTabIndex() - 1); + break; + case MSG_SCROLL_TABS_RIGHT: + fTabContainerView->SetFirstVisibleTabIndex( + fTabContainerView->FirstVisibleTabIndex() + 1); + break; + default: + BGroupView::MessageReceived(message); + break; } } - Invalidate(dirty); - - return removedTab; -} - - -TabView* -TabContainerView::TabAt(int32 index) const -{ - TabLayoutItem* item = dynamic_cast( - GroupLayout()->ItemAt(index)); - if (item) - return item->Parent(); - return NULL; -} - - -int32 -TabContainerView::IndexOf(TabView* tab) const -{ - return GroupLayout()->IndexOfItem(tab->LayoutItem()); -} - - -void -TabContainerView::SelectTab(int32 index) -{ - TabView* tab = NULL; - TabLayoutItem* item = dynamic_cast( - GroupLayout()->ItemAt(index)); - if (item) - tab = item->Parent(); - - SelectTab(tab); -} - - -void -TabContainerView::SelectTab(TabView* tab) -{ - if (tab == fSelectedTab) - return; - - if (fSelectedTab) - fSelectedTab->SetIsFront(false); - - fSelectedTab = tab; - - if (fSelectedTab) - fSelectedTab->SetIsFront(true); - - if (fController != NULL) { - int32 index = -1; - if (fSelectedTab != NULL) - index = GroupLayout()->IndexOfItem(tab->LayoutItem()); - - fController->TabSelected(index); - } -} - - -void -TabContainerView::SetTabLabel(int32 tabIndex, const char* label) -{ - TabLayoutItem* item = dynamic_cast( - GroupLayout()->ItemAt(tabIndex)); - if (item == NULL) - return; - - item->Parent()->SetLabel(label); -} - - -TabView* -TabContainerView::_TabAt(const BPoint& where) const -{ - BGroupLayout* layout = GroupLayout(); - int32 count = layout->CountItems() - 1; - for (int32 i = 0; i < count; i++) { - TabLayoutItem* item = dynamic_cast( - layout->ItemAt(i)); - if (item && item->Frame().Contains(where)) - return item->Parent(); - } - return NULL; -} - - -void -TabContainerView::_MouseMoved(BPoint where, uint32 _transit, - const BMessage* dragMessage) -{ - TabView* tab = _TabAt(where); - if (fMouseDown) { - uint32 transit = tab == fLastMouseEventTab - ? B_INSIDE_VIEW : B_OUTSIDE_VIEW; - if (fLastMouseEventTab) - fLastMouseEventTab->MouseMoved(where, transit, dragMessage); - return; + void AddScrollLeftButton(TabButton* button) + { + fScrollLeftTabButton = button; + GroupLayout()->AddView(button, 0.0f); } - if (fLastMouseEventTab && fLastMouseEventTab == tab) - fLastMouseEventTab->MouseMoved(where, B_INSIDE_VIEW, dragMessage); - else { - if (fLastMouseEventTab) - fLastMouseEventTab->MouseMoved(where, B_EXITED_VIEW, dragMessage); - fLastMouseEventTab = tab; - if (fLastMouseEventTab) - fLastMouseEventTab->MouseMoved(where, B_ENTERED_VIEW, dragMessage); + void AddScrollRightButton(TabButton* button) + { + fScrollRightTabButton = button; + GroupLayout()->AddView(button, 0.0f); } -} - -// #pragma mark - TabView - - -TabView::TabView() - : fContainerView(NULL) - , fLayoutItem(new TabLayoutItem(this)) - , fLabel() -{ -} - -TabView::~TabView() -{ - // The layout item is deleted for us by the layout which contains it. - if (!fContainerView) - delete fLayoutItem; -} - -BSize TabView::MinSize() -{ - BSize size(MaxSize()); - size.width = 100.0f; - return size; -} - -BSize TabView::PreferredSize() -{ - return MaxSize(); -} - -BSize TabView::MaxSize() -{ - float extra = be_control_look->DefaultLabelSpacing(); - float labelWidth = fContainerView->StringWidth(fLabel.String()) + 2 * extra; - labelWidth = min_c(300.0f, labelWidth); - return BSize(labelWidth, _LabelHeight() + extra); -} - -void TabView::Draw(BRect updateRect) -{ - BRect frame(fLayoutItem->Frame()); - if (fIsFront) { - // Extend the front tab outward left/right in order to merge - // the frames of adjacent tabs. - if (!fIsFirst) - frame.left--; - if (!fIsLast) - frame.right++; - - frame.bottom++; + void EnableScrollButtons(bool canScrollLeft, bool canScrollRight) + { + fScrollLeftTabButton->SetEnabled(canScrollLeft); + fScrollRightTabButton->SetEnabled(canScrollRight); + if (!canScrollLeft && !canScrollRight) { + // hide scroll buttons + } else { + // show scroll buttons + } } - DrawBackground(fContainerView, frame, updateRect, fIsFirst, fIsLast, - fIsFront); - if (fIsFront) { - frame.top += 3.0f; - if (!fIsFirst) - frame.left++; - if (!fIsLast) - frame.right--; - } else - frame.top += 6.0f; - float spacing = be_control_look->DefaultLabelSpacing(); - frame.InsetBy(spacing, spacing / 2); - DrawContents(fContainerView, frame, updateRect, fIsFirst, fIsLast, - fIsFront); -} -void TabView::DrawBackground(BView* owner, BRect frame, const BRect& updateRect, - bool isFirst, bool isLast, bool isFront) -{ - rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); - uint32 borders = BControlLook::B_TOP_BORDER - | BControlLook::B_BOTTOM_BORDER; - if (isFirst) - borders |= BControlLook::B_LEFT_BORDER; - if (isLast) - borders |= BControlLook::B_RIGHT_BORDER; - if (isFront) { - be_control_look->DrawActiveTab(owner, frame, updateRect, base, - 0, borders); - } else { - be_control_look->DrawInactiveTab(owner, frame, updateRect, base, - 0, borders); +private: + TabContainerView* fTabContainerView; + TabButton* fScrollLeftTabButton; + TabButton* fScrollRightTabButton; +}; + + +class TabButtonContainer : public BGroupView { +public: + TabButtonContainer() + : + BGroupView(B_HORIZONTAL) + { + SetFlags(Flags() | B_WILL_DRAW); + SetViewColor(B_TRANSPARENT_COLOR); + SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + GroupLayout()->SetInsets(0, 6, 0, 0); } -} -void TabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect, - bool isFirst, bool isLast, bool isFront) -{ - rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); - be_control_look->DrawLabel(owner, fLabel.String(), frame, updateRect, - base, 0, BAlignment(B_ALIGN_LEFT, B_ALIGN_MIDDLE)); -} - -void TabView::MouseDown(BPoint where, uint32 buttons) -{ - fContainerView->SelectTab(this); -} - -void TabView::MouseUp(BPoint where) -{ -} - -void TabView::MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage) -{ -} - -void TabView::SetIsFront(bool isFront) -{ - Update(fIsFirst, fIsLast, isFront); -} - -bool TabView::IsFront() const -{ - return fIsFront; -} - -void TabView::SetIsLast(bool isLast) -{ - Update(fIsFirst, isLast, fIsFront); -} - -void TabView::Update(bool isFirst, bool isLast, bool isFront) -{ - if (fIsFirst == isFirst && fIsLast == isLast && fIsFront == isFront) - return; - fIsFirst = isFirst; - fIsLast = isLast; - fIsFront = isFront; - BRect frame = fLayoutItem->Frame(); - frame.bottom++; - fContainerView->Invalidate(frame); -} - -void TabView::SetContainerView(TabContainerView* containerView) -{ - fContainerView = containerView; -} - -TabContainerView* TabView::ContainerView() const -{ - return fContainerView; -} - -BLayoutItem* TabView::LayoutItem() const -{ - return fLayoutItem; -} - -void TabView::SetLabel(const char* label) -{ - if (fLabel == label) - return; - fLabel = label; - fLayoutItem->InvalidateLayout(); -} - -const BString& TabView::Label() const -{ - return fLabel; -} - - -BRect -TabView::Frame() const -{ - return fLayoutItem->Frame(); -} - - -float TabView::_LabelHeight() const -{ - font_height fontHeight; - fContainerView->GetFontHeight(&fontHeight); - return ceilf(fontHeight.ascent) + ceilf(fontHeight.descent); -} - -// #pragma mark - TabLayoutItem - -TabLayoutItem::TabLayoutItem(TabView* parent) - : fParent(parent) -{ -} - -bool TabLayoutItem::IsVisible() -{ - return !fParent->ContainerView()->IsHidden(fParent->ContainerView()); -} - -void TabLayoutItem::SetVisible(bool visible) -{ - // not allowed -} - -BRect TabLayoutItem::Frame() -{ - return fFrame; -} - -void TabLayoutItem::SetFrame(BRect frame) -{ - BRect dirty = fFrame; - fFrame = frame; - dirty = dirty | fFrame; - // Invalidate more than necessary, to help the TabContainerView - // redraw the parts outside any tabs... - dirty.bottom++; - dirty.right++; - fParent->ContainerView()->Invalidate(dirty); -} - -BView* TabLayoutItem::View() -{ - return NULL; -} - -BSize TabLayoutItem::BaseMinSize() -{ - return fParent->MinSize(); -} - -BSize TabLayoutItem::BaseMaxSize() -{ - return fParent->MaxSize(); -} - -BSize TabLayoutItem::BasePreferredSize() -{ - return fParent->PreferredSize(); -} - -BAlignment TabLayoutItem::BaseAlignment() -{ - return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); -} - -TabView* TabLayoutItem::Parent() const -{ - return fParent; -} - - -// #pragma mark - TabManagerController + virtual void Draw(BRect updateRect) + { + BRect bounds(Bounds()); + rgb_color base = LowColor(); + be_control_look->DrawInactiveTab(this, bounds, updateRect, + base, 0, BControlLook::B_TOP_BORDER); + } +}; class TabManagerController : public TabContainerView::Controller { @@ -771,6 +301,12 @@ public: virtual void DoubleClickOutsideTabs(); + virtual void UpdateTabScrollability(bool canScrollLeft, + bool canScrollRight) + { + fTabContainerGroup->EnableScrollButtons(canScrollLeft, canScrollRight); + } + void CloseTab(int32 index); void SetCloseButtonsAvailable(bool available) @@ -786,11 +322,17 @@ public: void SetDoubleClickOutsideTabsMessage(const BMessage& message, const BMessenger& target); + void SetTabContainerGroup(TabContainerGroup* tabContainerGroup) + { + fTabContainerGroup = tabContainerGroup; + } + private: - TabManager* fManager; - bool fCloseButtonsAvailable; - BMessage* fDoubleClickOutsideTabsMessage; - BMessenger fTarget; + TabManager* fManager; + TabContainerGroup* fTabContainerGroup; + bool fCloseButtonsAvailable; + BMessage* fDoubleClickOutsideTabsMessage; + BMessenger fTarget; }; @@ -1021,6 +563,7 @@ void WebTabView::_DrawCloseButton(BView* owner, BRect& frame, TabManagerController::TabManagerController(TabManager* manager) : fManager(manager), + fTabContainerGroup(NULL), fCloseButtonsAvailable(false), fDoubleClickOutsideTabsMessage(NULL) { @@ -1064,169 +607,6 @@ TabManagerController::SetDoubleClickOutsideTabsMessage(const BMessage& message, } -// #pragma mark - TabButtonContainer - - -class TabButtonContainer : public BGroupView { -public: - TabButtonContainer() - : BGroupView(B_HORIZONTAL) - { - SetFlags(Flags() | B_WILL_DRAW); - SetViewColor(B_TRANSPARENT_COLOR); - SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); - GroupLayout()->SetInsets(0, 6, 0, 0); - } - - virtual void Draw(BRect updateRect) - { - BRect bounds(Bounds()); - rgb_color base = LowColor(); - be_control_look->DrawInactiveTab(this, bounds, updateRect, - base, 0, BControlLook::B_TOP_BORDER); - } -}; - - -// #pragma mark - TabButton - - -class TabButton : public BButton { -public: - TabButton(BMessage* message) - : BButton("", message) - { - } - - virtual BSize MinSize() - { - return BSize(12, 12); - } - - virtual BSize MaxSize() - { - return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED); - } - - virtual BSize PreferredSize() - { - return MinSize(); - } - - virtual void Draw(BRect updateRect) - { - BRect bounds(Bounds()); - rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); - SetHighColor(tint_color(base, B_DARKEN_2_TINT)); - StrokeLine(bounds.LeftBottom(), bounds.RightBottom()); - bounds.bottom--; - uint32 flags = be_control_look->Flags(this); - uint32 borders = BControlLook::B_TOP_BORDER - | BControlLook::B_BOTTOM_BORDER; - be_control_look->DrawInactiveTab(this, bounds, updateRect, base, - flags, borders); - if (IsEnabled()) { - rgb_color button = tint_color(base, 1.07); - be_control_look->DrawButtonBackground(this, bounds, updateRect, - button, flags, 0); - } - - bounds.left = (bounds.left + bounds.right) / 2 - 6; - bounds.top = (bounds.top + bounds.bottom) / 2 - 6; - bounds.right = bounds.left + 12; - bounds.bottom = bounds.top + 12; - DrawSymbol(bounds, updateRect, base); - } - - virtual void DrawSymbol(BRect frame, const BRect& updateRect, - const rgb_color& base) - { - } -}; - - -class ScrollLeftTabButton : public TabButton { -public: - ScrollLeftTabButton(BMessage* message) - : TabButton(message) - { - } - - virtual void DrawSymbol(BRect frame, const BRect& updateRect, - const rgb_color& base) - { - be_control_look->DrawArrowShape(this, frame, updateRect, - base, BControlLook::B_LEFT_ARROW, 0, B_DARKEN_4_TINT); - } -}; - - -class ScrollRightTabButton : public TabButton { -public: - ScrollRightTabButton(BMessage* message) - : TabButton(message) - { - } - - virtual void DrawSymbol(BRect frame, const BRect& updateRect, - const rgb_color& base) - { - be_control_look->DrawArrowShape(this, frame, updateRect, - base, BControlLook::B_RIGHT_ARROW, 0, B_DARKEN_4_TINT); - } -}; - - -class NewTabButton : public TabButton { -public: - NewTabButton(BMessage* message) - : TabButton(message) - { - SetToolTip("New tab (Cmd-T)"); - } - - virtual BSize MinSize() - { - return BSize(18, 12); - } - - virtual void DrawSymbol(BRect frame, const BRect& updateRect, - const rgb_color& base) - { - SetHighColor(tint_color(base, B_DARKEN_4_TINT)); - float inset = 3; - frame.InsetBy(2, 2); - frame.top++; - frame.left++; - FillRoundRect(BRect(frame.left, frame.top + inset, - frame.right, frame.bottom - inset), 1, 1); - FillRoundRect(BRect(frame.left + inset, frame.top, - frame.right - inset, frame.bottom), 1, 1); - } -}; - - -class TabMenuTabButton : public TabButton { -public: - TabMenuTabButton(BMessage* message) - : TabButton(message) - { - } - - virtual BSize MinSize() - { - return BSize(18, 12); - } - - virtual void DrawSymbol(BRect frame, const BRect& updateRect, - const rgb_color& base) - { - be_control_look->DrawArrowShape(this, frame, updateRect, - base, BControlLook::B_DOWN_ARROW, 0, B_DARKEN_4_TINT); - } -}; - - // #pragma mark - TabManager @@ -1243,9 +623,11 @@ TabManager::TabManager(const BMessenger& target, BMessage* newTabMessage) fContainerView->SetLayout(fCardLayout); fTabContainerView = new TabContainerView(fController); - fTabContainerGroup = new BGroupView(B_HORIZONTAL); + fTabContainerGroup = new TabContainerGroup(fTabContainerView); fTabContainerGroup->GroupLayout()->SetInsets(0, 3, 0, 0); + fController->SetTabContainerGroup(fTabContainerGroup); + #if INTEGRATE_MENU_INTO_TAB_BAR fMenu = new BMenu("Menu"); BMenuBar* menuBar = new BMenuBar("Menu bar"); @@ -1256,8 +638,10 @@ TabManager::TabManager(const BMessenger& target, BMessage* newTabMessage) #endif fTabContainerGroup->GroupLayout()->AddView(fTabContainerView); -// fTabContainerGroup->GroupLayout()->AddView(new ScrollLeftTabButton(NULL), 0.0f); -// fTabContainerGroup->GroupLayout()->AddView(new ScrollRightTabButton(NULL), 0.0f); + fTabContainerGroup->AddScrollLeftButton(new ScrollLeftTabButton( + new BMessage(MSG_SCROLL_TABS_LEFT))); + fTabContainerGroup->AddScrollRightButton(new ScrollRightTabButton( + new BMessage(MSG_SCROLL_TABS_RIGHT))); NewTabButton* newTabButton = new NewTabButton(newTabMessage); newTabButton->SetTarget(be_app); fTabContainerGroup->GroupLayout()->AddView(newTabButton, 0.0f); diff --git a/src/apps/webpositive/WebTabView.h b/src/apps/webpositive/tabview/TabManager.h similarity index 97% rename from src/apps/webpositive/WebTabView.h rename to src/apps/webpositive/tabview/TabManager.h index 23ea4cc62f..04f86062a2 100644 --- a/src/apps/webpositive/WebTabView.h +++ b/src/apps/webpositive/tabview/TabManager.h @@ -40,6 +40,7 @@ class BBitmap; class BCardLayout; class BGroupView; class BMenu; +class TabContainerGroup; class TabContainerView; class TabManagerController; @@ -81,7 +82,7 @@ private: #if INTEGRATE_MENU_INTO_TAB_BAR BMenu* fMenu; #endif - BGroupView* fTabContainerGroup; + TabContainerGroup* fTabContainerGroup; TabContainerView* fTabContainerView; BView* fContainerView; BCardLayout* fCardLayout; diff --git a/src/apps/webpositive/tabview/TabView.cpp b/src/apps/webpositive/tabview/TabView.cpp new file mode 100644 index 0000000000..bc5e2a6703 --- /dev/null +++ b/src/apps/webpositive/tabview/TabView.cpp @@ -0,0 +1,366 @@ +/* + * Copyright (C) 2010 Rene Gollent + * Copyright (C) 2010 Stephan Aßmus + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "TabView.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "TabContainerView.h" + + +// #pragma mark - TabView + + +TabView::TabView() + : + fContainerView(NULL), + fLayoutItem(new TabLayoutItem(this)), + fLabel() +{ +} + + +TabView::~TabView() +{ + // The layout item is deleted for us by the layout which contains it. + if (!fContainerView) + delete fLayoutItem; +} + + +BSize +TabView::MinSize() +{ + BSize size(MaxSize()); + size.width = 100.0f; + return size; +} + + +BSize +TabView::PreferredSize() +{ + return MaxSize(); +} + + +BSize +TabView::MaxSize() +{ + float extra = be_control_look->DefaultLabelSpacing(); + float labelWidth = fContainerView->StringWidth(fLabel.String()) + 2 * extra; + labelWidth = min_c(300.0f, labelWidth); + return BSize(labelWidth, _LabelHeight() + extra); +} + + +void +TabView::Draw(BRect updateRect) +{ + BRect frame(fLayoutItem->Frame()); + if (fIsFront) { + // Extend the front tab outward left/right in order to merge + // the frames of adjacent tabs. + if (!fIsFirst) + frame.left--; + if (!fIsLast) + frame.right++; + + frame.bottom++; + } + DrawBackground(fContainerView, frame, updateRect, fIsFirst, fIsLast, + fIsFront); + if (fIsFront) { + frame.top += 3.0f; + if (!fIsFirst) + frame.left++; + if (!fIsLast) + frame.right--; + } else + frame.top += 6.0f; + float spacing = be_control_look->DefaultLabelSpacing(); + frame.InsetBy(spacing, spacing / 2); + DrawContents(fContainerView, frame, updateRect, fIsFirst, fIsLast, + fIsFront); +} + + +void +TabView::DrawBackground(BView* owner, BRect frame, const BRect& updateRect, + bool isFirst, bool isLast, bool isFront) +{ + rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); + uint32 borders = BControlLook::B_TOP_BORDER + | BControlLook::B_BOTTOM_BORDER; + if (isFirst) + borders |= BControlLook::B_LEFT_BORDER; + if (isLast) + borders |= BControlLook::B_RIGHT_BORDER; + if (isFront) { + be_control_look->DrawActiveTab(owner, frame, updateRect, base, + 0, borders); + } else { + be_control_look->DrawInactiveTab(owner, frame, updateRect, base, + 0, borders); + } +} + + +void +TabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect, + bool isFirst, bool isLast, bool isFront) +{ + rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); + be_control_look->DrawLabel(owner, fLabel.String(), frame, updateRect, + base, 0, BAlignment(B_ALIGN_LEFT, B_ALIGN_MIDDLE)); +} + + +void +TabView::MouseDown(BPoint where, uint32 buttons) +{ + fContainerView->SelectTab(this); +} + + +void +TabView::MouseUp(BPoint where) +{ +} + + +void +TabView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage) +{ +} + + +void +TabView::SetIsFront(bool isFront) +{ + Update(fIsFirst, fIsLast, isFront); +} + + +bool +TabView::IsFront() const +{ + return fIsFront; +} + + +void +TabView::SetIsLast(bool isLast) +{ + Update(fIsFirst, isLast, fIsFront); +} + + +void +TabView::Update(bool isFirst, bool isLast, bool isFront) +{ + if (fIsFirst == isFirst && fIsLast == isLast && fIsFront == isFront) + return; + fIsFirst = isFirst; + fIsLast = isLast; + fIsFront = isFront; + + fLayoutItem->InvalidateContainer(); +} + + +void +TabView::SetContainerView(TabContainerView* containerView) +{ + fContainerView = containerView; +} + + +TabContainerView* +TabView::ContainerView() const +{ + return fContainerView; +} + + +BLayoutItem* +TabView::LayoutItem() const +{ + return fLayoutItem; +} + + +void +TabView::SetLabel(const char* label) +{ + if (fLabel == label) + return; + fLabel = label; + fLayoutItem->InvalidateLayout(); +} + + +const BString& +TabView::Label() const +{ + return fLabel; +} + + +BRect +TabView::Frame() const +{ + return fLayoutItem->Frame(); +} + + +float +TabView::_LabelHeight() const +{ + font_height fontHeight; + fContainerView->GetFontHeight(&fontHeight); + return ceilf(fontHeight.ascent) + ceilf(fontHeight.descent); +} + + +// #pragma mark - TabLayoutItem + + +TabLayoutItem::TabLayoutItem(TabView* parent) + : + fParent(parent), + fVisible(true) +{ +} + + +bool +TabLayoutItem::IsVisible() +{ + return fVisible; +} + + +void +TabLayoutItem::SetVisible(bool visible) +{ + if (fVisible == visible) + return; + + fVisible = visible; + + InvalidateContainer(); + fParent->ContainerView()->InvalidateLayout(); +} + + +BRect +TabLayoutItem::Frame() +{ + return fFrame; +} + + +void +TabLayoutItem::SetFrame(BRect frame) +{ + BRect dirty = fFrame; + fFrame = frame; + dirty = dirty | fFrame; + InvalidateContainer(dirty); +} + + +BView* +TabLayoutItem::View() +{ + return NULL; +} + + +BSize +TabLayoutItem::BaseMinSize() +{ + return fParent->MinSize(); +} + + +BSize +TabLayoutItem::BaseMaxSize() +{ + return fParent->MaxSize(); +} + + +BSize +TabLayoutItem::BasePreferredSize() +{ + return fParent->PreferredSize(); +} + + +BAlignment +TabLayoutItem::BaseAlignment() +{ + return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); +} + + +TabView* +TabLayoutItem::Parent() const +{ + return fParent; +} + + +void +TabLayoutItem::InvalidateContainer() +{ + InvalidateContainer(Frame()); +} + + +void +TabLayoutItem::InvalidateContainer(BRect frame) +{ + // Invalidate more than necessary, to help the TabContainerView + // redraw the parts outside any tabs... + frame.bottom++; + frame.right++; + fParent->ContainerView()->Invalidate(frame); +} diff --git a/src/apps/webpositive/tabview/TabView.h b/src/apps/webpositive/tabview/TabView.h new file mode 100644 index 0000000000..9f73c5a994 --- /dev/null +++ b/src/apps/webpositive/tabview/TabView.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef TAB_VIEW_H +#define TAB_VIEW_H + +#include +#include +#include + + +class BMessage; +class BView; +class TabContainerView; +class TabLayoutItem; + + +class TabView { +public: + TabView(); + virtual ~TabView(); + + virtual BSize MinSize(); + virtual BSize PreferredSize(); + virtual BSize MaxSize(); + + void Draw(BRect updateRect); + virtual void DrawBackground(BView* owner, BRect frame, + const BRect& updateRect, bool isFirst, + bool isLast, bool isFront); + virtual void DrawContents(BView* owner, BRect frame, + const BRect& updateRect, bool isFirst, + bool isLast, bool isFront); + + virtual void MouseDown(BPoint where, uint32 buttons); + virtual void MouseUp(BPoint where); + virtual void MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMessage); + + void SetIsFront(bool isFront); + bool IsFront() const; + void SetIsLast(bool isLast); + virtual void Update(bool isFirst, bool isLast, + bool isFront); + + BLayoutItem* LayoutItem() const; + void SetContainerView( + TabContainerView* containerView); + TabContainerView* ContainerView() const; + + void SetLabel(const char* label); + const BString& Label() const; + + BRect Frame() const; + +private: + float _LabelHeight() const; + +private: + TabContainerView* fContainerView; + TabLayoutItem* fLayoutItem; + + BString fLabel; + + bool fIsFirst; + bool fIsLast; + bool fIsFront; +}; + + +class TabLayoutItem : public BAbstractLayoutItem { +public: + TabLayoutItem(TabView* parent); + + virtual bool IsVisible(); + virtual void SetVisible(bool visible); + + virtual BRect Frame(); + virtual void SetFrame(BRect frame); + + virtual BView* View(); + + virtual BSize BaseMinSize(); + virtual BSize BaseMaxSize(); + virtual BSize BasePreferredSize(); + virtual BAlignment BaseAlignment(); + + TabView* Parent() const; + void InvalidateContainer(); + void InvalidateContainer(BRect frame); +private: + TabView* fParent; + BRect fFrame; + bool fVisible; +}; + + + +#endif // TAB_VIEW_H From a72e997ab0ab32f1afa97cd4378c4e8dc6b9f094 Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 15 Apr 2010 15:35:52 +0000 Subject: [PATCH 225/349] Improved the design of the Go button graphics. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@417 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/URLInputGroup.cpp | 80 +++++++++++++------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index 57c1d8baa7..99072acc15 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -364,50 +364,50 @@ const unsigned char kGoBitmapBits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xde, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x07, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x9c, 0xd5, 0xa6, 0xff, - 0x4a, 0x67, 0x50, 0xff, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0xb6, 0xf9, 0xc2, 0xff, 0xb2, 0xf9, 0xc0, 0xff, 0x88, 0xbb, 0x91, 0xff, - 0x2e, 0x3d, 0x32, 0xff, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb6, 0xf9, 0xc2, 0xff, - 0x73, 0xfa, 0x8c, 0xff, 0x9f, 0xf9, 0xae, 0xff, 0xac, 0xed, 0xb7, 0xff, 0x63, 0x96, 0x6d, 0xff, - 0x00, 0x00, 0x00, 0xe9, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0xb6, 0xf9, 0xc2, 0xff, 0x5d, 0xfc, 0x7b, 0xff, 0x5d, 0xfc, 0x7b, 0xff, - 0x72, 0xf9, 0x88, 0xff, 0x6d, 0xe5, 0x82, 0xff, 0x50, 0xbf, 0x65, 0xff, 0x27, 0x63, 0x32, 0xff, - 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xb4, 0xf8, 0xc0, 0xff, - 0x59, 0xfc, 0x77, 0xff, 0x59, 0xfc, 0x77, 0xff, 0x59, 0xfc, 0x77, 0xff, 0x59, 0xfb, 0x76, 0xff, - 0x4a, 0xe8, 0x67, 0xff, 0x32, 0xcc, 0x50, 0xff, 0x27, 0x9e, 0x3d, 0xff, 0x15, 0x3d, 0x15, 0xff, - 0x00, 0x00, 0x00, 0x75, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0xa2, 0xf2, 0xb0, 0xff, 0x2e, 0xfa, 0x54, 0xff, 0x2e, 0xfa, 0x54, 0xff, - 0x2e, 0xfa, 0x54, 0xff, 0x2e, 0xf9, 0x54, 0xff, 0x27, 0xe4, 0x48, 0xff, 0x15, 0xc5, 0x38, 0xff, - 0x15, 0x98, 0x2e, 0xff, 0x00, 0x3b, 0x15, 0xff, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x26, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x88, 0xe9, 0x99, 0xff, - 0x15, 0xf9, 0x40, 0xff, 0x15, 0xf9, 0x40, 0xff, 0x15, 0xed, 0x3d, 0xff, 0x00, 0xc8, 0x2b, 0xff, - 0x00, 0xa5, 0x22, 0xff, 0x00, 0x57, 0x15, 0xff, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x63, - 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0x72, 0xe0, 0x86, 0xff, 0x22, 0xf5, 0x42, 0xff, 0x27, 0xda, 0x46, 0xff, - 0x15, 0xb6, 0x32, 0xff, 0x00, 0x74, 0x1c, 0xff, 0x00, 0x00, 0x00, 0xe9, 0x00, 0x00, 0x00, 0x81, - 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x5f, 0xda, 0x76, 0xff, - 0x42, 0xd2, 0x5a, 0xff, 0x22, 0x95, 0x35, 0xff, 0x00, 0x2e, 0x00, 0xff, 0x00, 0x00, 0x00, 0xa2, - 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0x46, 0xb6, 0x5c, 0xff, 0x1c, 0x54, 0x22, 0xff, 0x00, 0x00, 0x00, 0xc4, - 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00, 0xde, - 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x17, 0x17, 0x17, 0x21, 0x49, 0x49, 0x49, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21, 0x49, 0x49, 0x49, 0xe0, 0x50, 0x50, 0x50, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21, 0x49, 0x49, 0x49, 0xe0, + 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2f, 0x2f, 0x2f, 0x56, 0x50, 0x50, 0x50, 0xff, 0x4d, 0x4d, 0x4d, 0xed, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21, + 0x49, 0x49, 0x49, 0xe0, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, + 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, + 0x50, 0x50, 0x50, 0xff, 0x37, 0x37, 0x37, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21, 0x49, 0x49, 0x49, 0xe0, 0x50, 0x50, 0x50, 0xff, + 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, + 0x50, 0x50, 0x50, 0xff, 0x4b, 0x4b, 0x4b, 0xec, 0x37, 0x37, 0x37, 0x77, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x17, 0x17, 0x17, 0x21, 0x49, 0x49, 0x49, 0xe1, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21, + 0x49, 0x49, 0x49, 0xe1, 0x50, 0x50, 0x50, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21, 0x49, 0x49, 0x49, 0xe1, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; From 8421f16ef1d8c3d1c46ea9f185625aed11cca711 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 16 Apr 2010 12:22:35 +0000 Subject: [PATCH 226/349] Fix the build. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@418 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index ac030f2f9d..3eedb566a7 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -41,9 +41,9 @@ #include "NavMenu.h" #include "SettingsKeys.h" #include "SettingsMessage.h" +#include "TabManager.h" #include "URLInputGroup.h" #include "WebPage.h" -#include "WebTabView.h" #include "WebView.h" #include "WebViewConstants.h" #include From 3e2f25ae9f8a9f827673589d8f328952d86d3282 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 17 Apr 2010 22:48:37 +0000 Subject: [PATCH 227/349] Fixed Maxime's name in the About window. Really sorry about that! git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@422 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index a32bbd04c0..a69cc84bea 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -88,7 +88,7 @@ void BrowserApp::AboutRequested() { BString aboutText("WebPositive\n\nby Ryan Leavengood, Andrea Anzani, " - "Maxime Simone, Michael Lotz, Rene Gollent and Stephan Aßmus"); + "Maxime Simon, Michael Lotz, Rene Gollent and Stephan Aßmus"); aboutText << "\n\nSVN revision: " << kSVNRevision; BAlert* alert = new BAlert("About WebPositive", aboutText.String(), From 62c697303a515d2efdd95845291c52ab96cc9bb5 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 20 Apr 2010 11:26:15 +0000 Subject: [PATCH 228/349] * Separated Text menu into Edit and View menus. * Added Cut/Copy/Paste items. Enabled status is updated when a text view has focus, but not yet with the selection of the BWebView, when that has focus. * Dispatch B_CUT/COPY/PASTE either to a focused BTextView or to the BWebView. * Enable the Find next/previous items according to contents of the Find text input. * Refactored MenusBeginning() hook. * Renamed Go menu to History. * Added Back/Forward menu items to History menu, now the shortcuts are visible. (Command key plus cursor left/right) * Added Reload item to View menu, now that shortcut is visible too. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@435 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 358 +++++++++++++++---------- src/apps/webpositive/BrowserWindow.h | 13 +- 2 files changed, 229 insertions(+), 142 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 3eedb566a7..d937501291 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -90,10 +91,11 @@ enum { ZOOM_FACTOR_RESET = 'zfrs', ZOOM_TEXT_ONLY = 'zfto', - TEXT_SHOW_FIND_GROUP = 'sfnd', - TEXT_HIDE_FIND_GROUP = 'hfnd', - TEXT_FIND_NEXT = 'fndn', - TEXT_FIND_PREVIOUS = 'fndp', + EDIT_SHOW_FIND_GROUP = 'sfnd', + EDIT_HIDE_FIND_GROUP = 'hfnd', + EDIT_FIND_NEXT = 'fndn', + EDIT_FIND_PREVIOUS = 'fndp', + FIND_TEXT_CHANGED = 'ftxt', SELECT_TAB = 'sltb', }; @@ -206,8 +208,26 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, quitItem->SetTarget(be_app); mainMenu->AddItem(menu); - menu = new BMenu("Text"); - menu->AddItem(new BMenuItem("Find", new BMessage(TEXT_SHOW_FIND_GROUP), 'F')); + menu = new BMenu("Edit"); + menu->AddItem(fCutMenuItem = new BMenuItem("Cut", new BMessage(B_CUT), + 'X')); + menu->AddItem(fCopyMenuItem = new BMenuItem("Copy", new BMessage(B_COPY), + 'C')); + menu->AddItem(fPasteMenuItem = new BMenuItem("Paste", new BMessage(B_PASTE), + 'V')); + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("Find", new BMessage(EDIT_SHOW_FIND_GROUP), + 'F')); + menu->AddItem(fFindPreviousMenuItem = new BMenuItem("Find previous", + new BMessage(EDIT_FIND_PREVIOUS), 'G', B_SHIFT_KEY)); + menu->AddItem(fFindNextMenuItem = new BMenuItem("Find next", + new BMessage(EDIT_FIND_NEXT), 'G')); + mainMenu->AddItem(menu); + fFindPreviousMenuItem->SetEnabled(false); + fFindNextMenuItem->SetEnabled(false); + + menu = new BMenu("View"); + menu->AddItem(new BMenuItem("Reload", new BMessage(RELOAD), 'R')); menu->AddSeparatorItem(); menu->AddItem(new BMenuItem("Increase size", new BMessage(ZOOM_FACTOR_INCREASE), '+')); menu->AddItem(new BMenuItem("Decrease size", new BMessage(ZOOM_FACTOR_DECREASE), '-')); @@ -218,8 +238,12 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, menu->AddItem(fZoomTextOnlyMenuItem); mainMenu->AddItem(menu); - fGoMenu = new BMenu("Go"); - mainMenu->AddItem(fGoMenu); + fHistoryMenu = new BMenu("History"); + fHistoryMenu->AddItem(new BMenuItem("Back", new BMessage(GO_BACK), B_LEFT_ARROW)); + fHistoryMenu->AddItem(new BMenuItem("Forward", new BMessage(GO_FORWARD), B_RIGHT_ARROW)); + fHistoryMenu->AddSeparatorItem(); + fHistoryMenuFixedItemCount = fHistoryMenu->CountItems(); + mainMenu->AddItem(fHistoryMenu); BPath bookmarkPath; entry_ref bookmarkRef; @@ -265,23 +289,26 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, const float kInsetSpacing = 3; const float kElementSpacing = 5; + // Find group fFindTextControl = new BTextControl("find", "Find:", "", - new BMessage(TEXT_FIND_NEXT)); + new BMessage(EDIT_FIND_NEXT)); + fFindTextControl->SetModificationMessage(new BMessage(FIND_TEXT_CHANGED)); fFindCaseSensitiveCheckBox = new BCheckBox("Match case"); BView* findGroup = BGroupLayoutBuilder(B_VERTICAL) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) .Add(fFindTextControl) - .Add(new BButton("Previous", new BMessage(TEXT_FIND_PREVIOUS))) - .Add(new BButton("Next", new BMessage(TEXT_FIND_NEXT))) + .Add(new BButton("Previous", new BMessage(EDIT_FIND_PREVIOUS))) + .Add(new BButton("Next", new BMessage(EDIT_FIND_NEXT))) .Add(fFindCaseSensitiveCheckBox) .Add(BSpaceLayoutItem::CreateGlue()) - .Add(new BButton("Close", new BMessage(TEXT_HIDE_FIND_GROUP))) + .Add(new BButton("Close", new BMessage(EDIT_HIDE_FIND_GROUP))) .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) ) ; + // Navigation group BView* navigationGroup = BGroupLayoutBuilder(B_VERTICAL) .Add(BGridLayoutBuilder(kElementSpacing, kElementSpacing) .Add(fBackButton, 0, 0) @@ -333,11 +360,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fNavigationGroup->SetVisible(false); } - AddShortcut('G', B_COMMAND_KEY, new BMessage(TEXT_FIND_NEXT)); - AddShortcut('G', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_FIND_PREVIOUS)); - AddShortcut('F', B_COMMAND_KEY, new BMessage(TEXT_SHOW_FIND_GROUP)); - AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(TEXT_HIDE_FIND_GROUP)); - AddShortcut('R', B_COMMAND_KEY, new BMessage(RELOAD)); + AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(EDIT_HIDE_FIND_GROUP)); // Add shortcuts to select a particular tab for (int32 i = 0; i <= 9; i++) { @@ -534,24 +557,43 @@ BrowserWindow::MessageReceived(BMessage* message) // already zoomed. break; - case TEXT_FIND_NEXT: + case EDIT_FIND_NEXT: CurrentWebView()->FindString(fFindTextControl->Text(), true, fFindCaseSensitiveCheckBox->Value()); break; - case TEXT_FIND_PREVIOUS: + case FIND_TEXT_CHANGED: + { + bool findTextAvailable = strlen(fFindTextControl->Text()) > 0; + fFindPreviousMenuItem->SetEnabled(findTextAvailable); + fFindNextMenuItem->SetEnabled(findTextAvailable); + break; + } + case EDIT_FIND_PREVIOUS: CurrentWebView()->FindString(fFindTextControl->Text(), false, fFindCaseSensitiveCheckBox->Value()); break; - case TEXT_SHOW_FIND_GROUP: + case EDIT_SHOW_FIND_GROUP: if (!fFindGroup->IsVisible()) fFindGroup->SetVisible(true); fFindTextControl->MakeFocus(true); break; - case TEXT_HIDE_FIND_GROUP: + case EDIT_HIDE_FIND_GROUP: if (fFindGroup->IsVisible()) fFindGroup->SetVisible(false); break; + case B_CUT: + case B_COPY: + case B_PASTE: + { + BTextView* textView = dynamic_cast(CurrentFocus()); + if (textView != NULL) + textView->MessageReceived(message); + else if (CurrentWebView() != NULL) + CurrentWebView()->MessageReceived(message); + break; + } + case SHOW_DOWNLOAD_WINDOW: case SHOW_SETTINGS_WINDOW: message->AddUInt32("workspaces", Workspaces()); @@ -633,129 +675,11 @@ BrowserWindow::QuitRequested() } -static void -addItemToMenuOrSubmenu(BMenu* menu, BMenuItem* newItem) -{ - BString baseURLLabel = baseURL(BString(newItem->Label())); - for (int32 i = menu->CountItems() - 1; i >= 0; i--) { - BMenuItem* item = menu->ItemAt(i); - BString label = item->Label(); - if (label.FindFirst(baseURLLabel) >= 0) { - if (item->Submenu()) { - // Submenu was already added in previous iteration. - item->Submenu()->AddItem(newItem); - return; - } else { - menu->RemoveItem(item); - BMenu* subMenu = new BMenu(baseURLLabel.String()); - subMenu->AddItem(item); - subMenu->AddItem(newItem); - // Add common submenu for this base URL, clickable. - BMessage* message = new BMessage(GOTO_URL); - message->AddString("url", baseURLLabel.String()); - menu->AddItem(new BMenuItem(subMenu, message), i); - return; - } - } - } - menu->AddItem(newItem); -} - - -static void -addOrDeleteMenu(BMenu* menu, BMenu* toMenu) -{ - if (menu->CountItems() > 0) - toMenu->AddItem(menu); - else - delete menu; -} - - void BrowserWindow::MenusBeginning() { - BMenuItem* menuItem; - while ((menuItem = fGoMenu->RemoveItem(0L))) - delete menuItem; - - BrowsingHistory* history = BrowsingHistory::DefaultInstance(); - if (!history->Lock()) - return; - - int32 count = history->CountItems(); - BMenuItem* clearHistoryItem = new BMenuItem("Clear history", - new BMessage(CLEAR_HISTORY)); - clearHistoryItem->SetEnabled(count > 0); - fGoMenu->AddItem(clearHistoryItem); - if (count == 0) { - history->Unlock(); - return; - } - fGoMenu->AddSeparatorItem(); - - BDateTime todayStart = BDateTime::CurrentDateTime(B_LOCAL_TIME); - todayStart.SetTime(BTime(0, 0, 0)); - - BDateTime oneDayAgoStart = todayStart; - oneDayAgoStart.Date().AddDays(-1); - - BDateTime twoDaysAgoStart = oneDayAgoStart; - twoDaysAgoStart.Date().AddDays(-1); - - BDateTime threeDaysAgoStart = twoDaysAgoStart; - threeDaysAgoStart.Date().AddDays(-1); - - BDateTime fourDaysAgoStart = threeDaysAgoStart; - fourDaysAgoStart.Date().AddDays(-1); - - BDateTime fiveDaysAgoStart = fourDaysAgoStart; - fiveDaysAgoStart.Date().AddDays(-1); - - BMenu* todayMenu = new BMenu("Today"); - BMenu* yesterdayMenu = new BMenu("Yesterday"); - BMenu* twoDaysAgoMenu = new BMenu( - twoDaysAgoStart.Date().LongDayName().String()); - BMenu* threeDaysAgoMenu = new BMenu( - threeDaysAgoStart.Date().LongDayName().String()); - BMenu* fourDaysAgoMenu = new BMenu( - fourDaysAgoStart.Date().LongDayName().String()); - BMenu* fiveDaysAgoMenu = new BMenu( - fiveDaysAgoStart.Date().LongDayName().String()); - BMenu* earlierMenu = new BMenu("Earlier"); - - for (int32 i = 0; i < count; i++) { - BrowsingHistoryItem historyItem = history->HistoryItemAt(i); - BMessage* message = new BMessage(GOTO_URL); - message->AddString("url", historyItem.URL().String()); - - BString truncatedUrl(historyItem.URL()); - be_plain_font->TruncateString(&truncatedUrl, B_TRUNCATE_END, 480); - menuItem = new BMenuItem(truncatedUrl, message); - - if (historyItem.DateTime() < fiveDaysAgoStart) - addItemToMenuOrSubmenu(earlierMenu, menuItem); - else if (historyItem.DateTime() < fourDaysAgoStart) - addItemToMenuOrSubmenu(fiveDaysAgoMenu, menuItem); - else if (historyItem.DateTime() < threeDaysAgoStart) - addItemToMenuOrSubmenu(fourDaysAgoMenu, menuItem); - else if (historyItem.DateTime() < twoDaysAgoStart) - addItemToMenuOrSubmenu(threeDaysAgoMenu, menuItem); - else if (historyItem.DateTime() < oneDayAgoStart) - addItemToMenuOrSubmenu(twoDaysAgoMenu, menuItem); - else if (historyItem.DateTime() < todayStart) - addItemToMenuOrSubmenu(yesterdayMenu, menuItem); - else - addItemToMenuOrSubmenu(todayMenu, menuItem); - } - history->Unlock(); - - addOrDeleteMenu(todayMenu, fGoMenu); - addOrDeleteMenu(yesterdayMenu, fGoMenu); - addOrDeleteMenu(twoDaysAgoMenu, fGoMenu); - addOrDeleteMenu(fourDaysAgoMenu, fGoMenu); - addOrDeleteMenu(fiveDaysAgoMenu, fGoMenu); - addOrDeleteMenu(earlierMenu, fGoMenu); + _UpdateHistoryMenu(); + _UpdateClipboardItems(); } @@ -1335,3 +1259,155 @@ BrowserWindow::_AddBookmarkURLsRecursively(BDirectory& directory, } +static void +addItemToMenuOrSubmenu(BMenu* menu, BMenuItem* newItem) +{ + BString baseURLLabel = baseURL(BString(newItem->Label())); + for (int32 i = menu->CountItems() - 1; i >= 0; i--) { + BMenuItem* item = menu->ItemAt(i); + BString label = item->Label(); + if (label.FindFirst(baseURLLabel) >= 0) { + if (item->Submenu()) { + // Submenu was already added in previous iteration. + item->Submenu()->AddItem(newItem); + return; + } else { + menu->RemoveItem(item); + BMenu* subMenu = new BMenu(baseURLLabel.String()); + subMenu->AddItem(item); + subMenu->AddItem(newItem); + // Add common submenu for this base URL, clickable. + BMessage* message = new BMessage(GOTO_URL); + message->AddString("url", baseURLLabel.String()); + menu->AddItem(new BMenuItem(subMenu, message), i); + return; + } + } + } + menu->AddItem(newItem); +} + + +static void +addOrDeleteMenu(BMenu* menu, BMenu* toMenu) +{ + if (menu->CountItems() > 0) + toMenu->AddItem(menu); + else + delete menu; +} + + +void +BrowserWindow::_UpdateHistoryMenu() +{ + BMenuItem* menuItem; + while ((menuItem = fHistoryMenu->RemoveItem(fHistoryMenuFixedItemCount))) + delete menuItem; + + BrowsingHistory* history = BrowsingHistory::DefaultInstance(); + if (!history->Lock()) + return; + + int32 count = history->CountItems(); + BMenuItem* clearHistoryItem = new BMenuItem("Clear history", + new BMessage(CLEAR_HISTORY)); + clearHistoryItem->SetEnabled(count > 0); + fHistoryMenu->AddItem(clearHistoryItem); + if (count == 0) { + history->Unlock(); + return; + } + fHistoryMenu->AddSeparatorItem(); + + BDateTime todayStart = BDateTime::CurrentDateTime(B_LOCAL_TIME); + todayStart.SetTime(BTime(0, 0, 0)); + + BDateTime oneDayAgoStart = todayStart; + oneDayAgoStart.Date().AddDays(-1); + + BDateTime twoDaysAgoStart = oneDayAgoStart; + twoDaysAgoStart.Date().AddDays(-1); + + BDateTime threeDaysAgoStart = twoDaysAgoStart; + threeDaysAgoStart.Date().AddDays(-1); + + BDateTime fourDaysAgoStart = threeDaysAgoStart; + fourDaysAgoStart.Date().AddDays(-1); + + BDateTime fiveDaysAgoStart = fourDaysAgoStart; + fiveDaysAgoStart.Date().AddDays(-1); + + BMenu* todayMenu = new BMenu("Today"); + BMenu* yesterdayMenu = new BMenu("Yesterday"); + BMenu* twoDaysAgoMenu = new BMenu( + twoDaysAgoStart.Date().LongDayName().String()); + BMenu* threeDaysAgoMenu = new BMenu( + threeDaysAgoStart.Date().LongDayName().String()); + BMenu* fourDaysAgoMenu = new BMenu( + fourDaysAgoStart.Date().LongDayName().String()); + BMenu* fiveDaysAgoMenu = new BMenu( + fiveDaysAgoStart.Date().LongDayName().String()); + BMenu* earlierMenu = new BMenu("Earlier"); + + for (int32 i = 0; i < count; i++) { + BrowsingHistoryItem historyItem = history->HistoryItemAt(i); + BMessage* message = new BMessage(GOTO_URL); + message->AddString("url", historyItem.URL().String()); + + BString truncatedUrl(historyItem.URL()); + be_plain_font->TruncateString(&truncatedUrl, B_TRUNCATE_END, 480); + menuItem = new BMenuItem(truncatedUrl, message); + + if (historyItem.DateTime() < fiveDaysAgoStart) + addItemToMenuOrSubmenu(earlierMenu, menuItem); + else if (historyItem.DateTime() < fourDaysAgoStart) + addItemToMenuOrSubmenu(fiveDaysAgoMenu, menuItem); + else if (historyItem.DateTime() < threeDaysAgoStart) + addItemToMenuOrSubmenu(fourDaysAgoMenu, menuItem); + else if (historyItem.DateTime() < twoDaysAgoStart) + addItemToMenuOrSubmenu(threeDaysAgoMenu, menuItem); + else if (historyItem.DateTime() < oneDayAgoStart) + addItemToMenuOrSubmenu(twoDaysAgoMenu, menuItem); + else if (historyItem.DateTime() < todayStart) + addItemToMenuOrSubmenu(yesterdayMenu, menuItem); + else + addItemToMenuOrSubmenu(todayMenu, menuItem); + } + history->Unlock(); + + addOrDeleteMenu(todayMenu, fHistoryMenu); + addOrDeleteMenu(yesterdayMenu, fHistoryMenu); + addOrDeleteMenu(twoDaysAgoMenu, fHistoryMenu); + addOrDeleteMenu(fourDaysAgoMenu, fHistoryMenu); + addOrDeleteMenu(fiveDaysAgoMenu, fHistoryMenu); + addOrDeleteMenu(earlierMenu, fHistoryMenu); +} + + +void +BrowserWindow::_UpdateClipboardItems() +{ + BTextView* focusTextView = dynamic_cast(CurrentFocus()); + if (focusTextView != NULL) { + int32 selectionStart; + int32 selectionEnd; + focusTextView->GetSelection(&selectionStart, &selectionEnd); + bool hasSelection = selectionStart < selectionEnd; + bool canPaste = false; + // A BTextView has the focus. + if (be_clipboard->Lock()) { + BMessage* data = be_clipboard->Data(); + if (data != NULL) + canPaste = data->HasData("text/plain", B_MIME_TYPE); + be_clipboard->Unlock(); + } + fCutMenuItem->SetEnabled(hasSelection); + fCopyMenuItem->SetEnabled(hasSelection); + fPasteMenuItem->SetEnabled(canPaste); + } else if (CurrentFocus() != CurrentWebView()) { + fCutMenuItem->SetEnabled(false); + fCopyMenuItem->SetEnabled(false); + fPasteMenuItem->SetEnabled(false); + } +} diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 124144cffb..03425cf43f 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -143,9 +143,20 @@ private: BMessage* message, uint32& addedCount) const; + void _UpdateHistoryMenu(); + void _UpdateClipboardItems(); + private: - BMenu* fGoMenu; + BMenu* fHistoryMenu; + int32 fHistoryMenuFixedItemCount; + + BMenuItem* fCutMenuItem; + BMenuItem* fCopyMenuItem; + BMenuItem* fPasteMenuItem; + BMenuItem* fFindPreviousMenuItem; + BMenuItem* fFindNextMenuItem; BMenuItem* fZoomTextOnlyMenuItem; + IconButton* fBackButton; IconButton* fForwardButton; IconButton* fStopButton; From 9b70fc27d27e13120c2d8566a020e8b124fd111e Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 20 Apr 2010 12:32:26 +0000 Subject: [PATCH 229/349] * Implemented a mechanism to ask the BWebPage about it's editing capabilities. This needs to be asynchronous, as always. BrowserWindow asks when menus are opened, but the result arrives so fast, that the user never sees invalid items. The Cut/Copy/Paste items are now always enabled according to what's currently really possible. * Enable and disable the Back/Forward History menu items along with the buttons. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@436 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 63 ++++++++++++++++++++++---- src/apps/webpositive/BrowserWindow.h | 3 ++ 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index d937501291..e23bc229da 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -239,8 +239,10 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, mainMenu->AddItem(menu); fHistoryMenu = new BMenu("History"); - fHistoryMenu->AddItem(new BMenuItem("Back", new BMessage(GO_BACK), B_LEFT_ARROW)); - fHistoryMenu->AddItem(new BMenuItem("Forward", new BMessage(GO_FORWARD), B_RIGHT_ARROW)); + fHistoryMenu->AddItem(fBackMenuItem = new BMenuItem("Back", + new BMessage(GO_BACK), B_LEFT_ARROW)); + fHistoryMenu->AddItem(fForwardMenuItem = new BMenuItem("Forward", + new BMessage(GO_FORWARD), B_RIGHT_ARROW)); fHistoryMenu->AddSeparatorItem(); fHistoryMenuFixedItemCount = fHistoryMenu->CountItems(); mainMenu->AddItem(fHistoryMenu); @@ -594,6 +596,29 @@ BrowserWindow::MessageReceived(BMessage* message) break; } + case B_EDITING_CAPABILITIES_RESULT: + { + BWebView* webView; + if (message->FindPointer("view", + reinterpret_cast(&webView)) != B_OK + || webView != CurrentWebView()) { + break; + } + bool canCut; + bool canCopy; + bool canPaste; + if (message->FindBool("can cut", &canCut) != B_OK) + canCut = false; + if (message->FindBool("can copy", &canCopy) != B_OK) + canCopy = false; + if (message->FindBool("can paste", &canPaste) != B_OK) + canPaste = false; + fCutMenuItem->SetEnabled(canCut); + fCopyMenuItem->SetEnabled(canCopy); + fPasteMenuItem->SetEnabled(canPaste); + break; + } + case SHOW_DOWNLOAD_WINDOW: case SHOW_SETTINGS_WINDOW: message->AddUInt32("workspaces", Workspaces()); @@ -683,6 +708,19 @@ BrowserWindow::MenusBeginning() } +void +BrowserWindow::MenusEnded() +{ + // Reenabled the clipboard items, since we don't update them when + // the capabilities really change, but only when the menu is opened. + // The shortcuts need to work when the capabilities change without + // the Edit menu being opened meanwhile. + fCutMenuItem->SetEnabled(true); + fCopyMenuItem->SetEnabled(true); + fPasteMenuItem->SetEnabled(true); +} + + void BrowserWindow::CreateNewTab(const BString& url, bool select, BWebView* webView) { @@ -957,12 +995,12 @@ BrowserWindow::NavigationCapabilitiesChanged(bool canGoBackward, if (view != CurrentWebView()) return; - if (fBackButton) - fBackButton->SetEnabled(canGoBackward); - if (fForwardButton) - fForwardButton->SetEnabled(canGoForward); - if (fStopButton) - fStopButton->SetEnabled(canStop); + fBackButton->SetEnabled(canGoBackward); + fForwardButton->SetEnabled(canGoForward); + fStopButton->SetEnabled(canStop); + + fBackMenuItem->SetEnabled(canGoBackward); + fForwardMenuItem->SetEnabled(canGoForward); } @@ -1405,9 +1443,16 @@ BrowserWindow::_UpdateClipboardItems() fCutMenuItem->SetEnabled(hasSelection); fCopyMenuItem->SetEnabled(hasSelection); fPasteMenuItem->SetEnabled(canPaste); - } else if (CurrentFocus() != CurrentWebView()) { + } else if (CurrentWebView() != NULL) { + // Trigger update of the clipboard items, even if the + // BWebView doesn't have focus, we'll dispatch these message + // there anyway. This works so fast that the user can never see + // the wrong enabled state when the menu opens until the result + // message arrives. fCutMenuItem->SetEnabled(false); fCopyMenuItem->SetEnabled(false); fPasteMenuItem->SetEnabled(false); + + CurrentWebView()->WebPage()->SendEditingCapabilities(); } } diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 03425cf43f..0eda3126dd 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -81,6 +81,7 @@ public: virtual void MessageReceived(BMessage* message); virtual bool QuitRequested(); virtual void MenusBeginning(); + virtual void MenusEnded(); void CreateNewTab(const BString& url, bool select, BWebView* webView = 0); @@ -156,6 +157,8 @@ private: BMenuItem* fFindPreviousMenuItem; BMenuItem* fFindNextMenuItem; BMenuItem* fZoomTextOnlyMenuItem; + BMenuItem* fBackMenuItem; + BMenuItem* fForwardMenuItem; IconButton* fBackButton; IconButton* fForwardButton; From ae82400bb4ff73fbc67c1d618ebf7fb53d1d83e3 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 20 Apr 2010 15:43:23 +0000 Subject: [PATCH 230/349] The return key is never supposed to reach the BTextView implementation, even if we don't have to invoke in the URLTextView. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@440 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/URLInputGroup.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index 99072acc15..b372fcfbdc 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -269,6 +269,10 @@ URLInputGroup::URLTextView::KeyDown(const char* bytes, int32 numBytes) SelectAll(); break; + case B_RETURN: + // Don't let this through to the text view. + break; + default: BTextView::KeyDown(bytes, numBytes); break; From a150602b0f1b17573d179f8b63e85f3467a8068d Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 20 Apr 2010 15:44:10 +0000 Subject: [PATCH 231/349] Return early in BrowserWindow::DispatchMessage(), if the message was already handled. This would also fix return keys ending up in the URLTextView. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@441 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index e23bc229da..8ed76b199d 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -397,11 +397,13 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) && message->FindInt32("modifiers", (int32*)&modifiers) == B_OK) { modifiers = modifiers & 0x000000ff; - if (bytes[0] == B_LEFT_ARROW && modifiers == B_COMMAND_KEY) + if (bytes[0] == B_LEFT_ARROW && modifiers == B_COMMAND_KEY) { PostMessage(GO_BACK); - else if (bytes[0] == B_RIGHT_ARROW && modifiers == B_COMMAND_KEY) + return; + } else if (bytes[0] == B_RIGHT_ARROW && modifiers == B_COMMAND_KEY) { PostMessage(GO_FORWARD); - else if (target == fURLInputGroup->TextView()) { + return; + } else if (target == fURLInputGroup->TextView()) { // Handle B_RETURN in the URL text control. This is the easiest // way to react *only* when the user presses the return key in the // address bar, as opposed to trying to load whatever is in there @@ -413,6 +415,7 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) fURLInputGroup->GoButton()->Invoke(); snooze(1000); fURLInputGroup->GoButton()->SetValue(B_CONTROL_OFF); + return; } } } From d5e2e814a417ed7606dcfd6c480c4db844f8acf9 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 20 Apr 2010 15:46:23 +0000 Subject: [PATCH 232/349] No need to block the BApplication thread when showing the About window. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@442 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index a69cc84bea..86bdfb1a75 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -93,7 +93,7 @@ BrowserApp::AboutRequested() BAlert* alert = new BAlert("About WebPositive", aboutText.String(), "Sweet!"); - alert->Go(); + alert->Go(NULL); } From 0e7170b49e6cfc864ea0f711485549b8bfcafb5c Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 20 Apr 2010 16:24:16 +0000 Subject: [PATCH 233/349] Handling shortcut is wrappedd inside MenusBeginning() and MenusEnded(), so we need to always enable the standard shortcut items in MenusBeginning(), if we would otherwise enable them only asynchronously. Fixes Cut/Copy/Paste via shortcuts. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@443 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 8ed76b199d..acffde3387 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1452,9 +1452,9 @@ BrowserWindow::_UpdateClipboardItems() // there anyway. This works so fast that the user can never see // the wrong enabled state when the menu opens until the result // message arrives. - fCutMenuItem->SetEnabled(false); - fCopyMenuItem->SetEnabled(false); - fPasteMenuItem->SetEnabled(false); + fCutMenuItem->SetEnabled(true); + fCopyMenuItem->SetEnabled(true); + fPasteMenuItem->SetEnabled(true); CurrentWebView()->WebPage()->SendEditingCapabilities(); } From c53bbc329d7e8a58eba8ec3edaf017c54334332e Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 20 Apr 2010 16:26:32 +0000 Subject: [PATCH 234/349] Implementing MenusEnded() is not needed anymore, since we enable Cut/Copy/Paste by default now. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@444 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 18 ++++-------------- src/apps/webpositive/BrowserWindow.h | 1 - 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index acffde3387..784d4a2f6a 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -711,19 +711,6 @@ BrowserWindow::MenusBeginning() } -void -BrowserWindow::MenusEnded() -{ - // Reenabled the clipboard items, since we don't update them when - // the capabilities really change, but only when the menu is opened. - // The shortcuts need to work when the capabilities change without - // the Edit menu being opened meanwhile. - fCutMenuItem->SetEnabled(true); - fCopyMenuItem->SetEnabled(true); - fPasteMenuItem->SetEnabled(true); -} - - void BrowserWindow::CreateNewTab(const BString& url, bool select, BWebView* webView) { @@ -1451,7 +1438,10 @@ BrowserWindow::_UpdateClipboardItems() // BWebView doesn't have focus, we'll dispatch these message // there anyway. This works so fast that the user can never see // the wrong enabled state when the menu opens until the result - // message arrives. + // message arrives. The initial state needs to be enabled, since + // standard shortcut handling is always wrapped inside MenusBeginning() + // and MenusEnded(), and since we update items asynchronously, we need + // to have them enabled to begin with. fCutMenuItem->SetEnabled(true); fCopyMenuItem->SetEnabled(true); fPasteMenuItem->SetEnabled(true); diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 0eda3126dd..73b6fdd48c 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -81,7 +81,6 @@ public: virtual void MessageReceived(BMessage* message); virtual bool QuitRequested(); virtual void MenusBeginning(); - virtual void MenusEnded(); void CreateNewTab(const BString& url, bool select, BWebView* webView = 0); From 9d150599741158a2e9efd09305020a73b5d0bd8f Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 20 Apr 2010 22:52:41 +0000 Subject: [PATCH 235/349] Make the base URL show in bold font in the URL input field, and the rest of the text in dark gray. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@445 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/URLInputGroup.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index b372fcfbdc..c1f9c999b9 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -171,6 +171,7 @@ URLInputGroup::URLTextView::URLTextView(URLInputGroup* parent) fPreviousText("") { MakeResizable(true); + SetStylable(true); } @@ -334,6 +335,31 @@ URLInputGroup::URLTextView::InsertText(const char* inText, int32 inLength, BTextView::InsertText(filteredText.String(), inLength, inOffset, inRuns); } + + // Make the base URL part bold. + BString text(Text(), TextLength()); + int32 baseUrlStart = text.FindFirst("://"); + if (baseUrlStart >= 0) + baseUrlStart += 3; + else + baseUrlStart = 0; + int32 baseUrlEnd = text.FindFirst("/", baseUrlStart); + if (baseUrlEnd < 0) + baseUrlEnd = TextLength(); + BFont font; + GetFont(&font); + const rgb_color black = (rgb_color){ 0, 0, 0, 255 }; + const rgb_color gray = (rgb_color){ 60, 60, 60, 255 }; + if (baseUrlStart > 0) + SetFontAndColor(0, baseUrlStart - 1, &font, B_FONT_ALL, &gray); + if (baseUrlEnd > baseUrlStart) { + font.SetFace(B_BOLD_FACE); + SetFontAndColor(baseUrlStart, baseUrlEnd, &font, B_FONT_ALL, &black); + } + if (baseUrlEnd < TextLength()) { + font.SetFace(B_REGULAR_FACE); + SetFontAndColor(baseUrlEnd, TextLength(), &font, B_FONT_ALL, &gray); + } } From 25057e59b7e5914185854eda2e33bc1fe49c6a31 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 21 Apr 2010 11:49:28 +0000 Subject: [PATCH 236/349] When selecting choices in the auto-completion pop-up, insert the current choice into the text view, so the user can continue typing from that choice, or modify it. For example, one can type "dev.haiku-os.org", select a choice "http://dev.haiku-os.org/ticket/1234" and then replace just the last chunk with another ticket number and press enter. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@447 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/autocompletion/TextViewCompleter.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp index 5ae515b529..9f0a90b065 100644 --- a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp +++ b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp @@ -94,9 +94,15 @@ TextViewCompleter::Filter(BMessage* message, BHandler** target) switch (bytes[0]) { case B_UP_ARROW: SelectPrevious(); + // Insert the current choice into the text view, so the user can + // continue typing. This will not trigger another evaluation, since + // we don't invoke EditViewStateChanged(). + ApplyChoice(false); return B_SKIP_MESSAGE; case B_DOWN_ARROW: SelectNext(); + // See above. + ApplyChoice(false); return B_SKIP_MESSAGE; case B_ESCAPE: CancelChoice(); From fa485bda233dbf3fc885816b6b0f4e95fe034ab7 Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 22 Apr 2010 21:01:42 +0000 Subject: [PATCH 237/349] When removing the currently selected tab, temporarily unset the current BWebView, since we did not delete the BWebView directly, but in the application thread, this was a race condition that would only crash sometimes (in _TabChanged(), when we tried to attach user data to the current tab before switching it). This should fix the last known (to me) crash. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@452 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 784d4a2f6a..cd13d89309 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -694,7 +694,7 @@ BrowserWindow::QuitRequested() // Do this here, so WebKit tear down happens earlier. while (fTabManager->CountTabs() > 0) _ShutdownTab(0); - SetCurrentWebView(0); + SetCurrentWebView(NULL); BMessage message(WINDOW_CLOSED); message.AddRect("window frame", Frame()); @@ -1056,6 +1056,8 @@ BrowserWindow::_ShutdownTab(int32 index) { BView* view = fTabManager->RemoveTab(index); BWebView* webView = dynamic_cast(view); + if (webView == CurrentWebView()) + SetCurrentWebView(NULL); if (webView != NULL) webView->Shutdown(); else From 88b25a7da970e034e24ec8f7fb7ad232344f7872 Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 22 Apr 2010 21:22:06 +0000 Subject: [PATCH 238/349] Add a small hack to fix the invalidation glitches in the menu bar when resizing the window. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@453 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index cd13d89309..a3a4043495 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -342,6 +342,10 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, .Add(statusGroup) ); + // TODO: Small hack for fixing some invalidation problems with BMenuBar... + mainMenu->SetFlags(mainMenu->Flags() | B_FULL_UPDATE_ON_RESIZE); + mainMenu->SetViewColor(B_TRANSPARENT_COLOR); + fURLInputGroup->MakeFocus(true); fMenuGroup = layoutItemFor(mainMenu); From f7530134b1b87dc483f6d62309433ce4e22188fe Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 22 Apr 2010 22:19:41 +0000 Subject: [PATCH 239/349] Don't set the text if it's the same, allows to keep selection. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@454 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/URLInputGroup.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index c1f9c999b9..6fb51e498c 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -603,7 +603,8 @@ URLInputGroup::TextView() const void URLInputGroup::SetText(const char* text) { - fTextView->SetText(text); + if (!text || !Text() || strcmp(Text(), text) != 0) + fTextView->SetText(text); } From a8d1c85daab2129c69f4f91131f543460cc80d20 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 23 Apr 2010 15:02:17 +0000 Subject: [PATCH 240/349] Fixed looking up uint32 values. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@455 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/support/SettingsMessage.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/support/SettingsMessage.cpp b/src/apps/webpositive/support/SettingsMessage.cpp index e11900b1b5..15dc12394c 100644 --- a/src/apps/webpositive/support/SettingsMessage.cpp +++ b/src/apps/webpositive/support/SettingsMessage.cpp @@ -363,10 +363,10 @@ SettingsMessage::GetValue(const char* name, int32 defaultValue) const uint32 SettingsMessage::GetValue(const char* name, uint32 defaultValue) const { - int32 value; - if (FindInt32(name, &value) != B_OK) + uint32 value; + if (FindUInt32(name, &value) != B_OK) return defaultValue; - return (uint32)value; + return value; } From 1547f92b8ea875c3a0c15f4c78fd473720ec95d0 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 23 Apr 2010 15:07:53 +0000 Subject: [PATCH 241/349] * Improved the layout of the Settings window general page. * Allow specifying a start and a search page in the Settings window. * Separated the "New page" policy into "New window" and "New tab" policies. For a new window, the user can chose to "Open start page", "Open search page" and "Open blank page". The default changed to "Open start page" and the default start page points to the "Welcome" readme. For new tabs, there is an additional choice "Clone current page". The default stayed with opening a blank page. * Implemented the new page policies in BrowserWindow. * Listen for changes of the new settings in BrowserWindow. * Added the new settings keys and default values to SettingsKeys. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@456 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 52 ++++++- src/apps/webpositive/BrowserWindow.h | 12 ++ src/apps/webpositive/SettingsKeys.cpp | 12 ++ src/apps/webpositive/SettingsKeys.h | 8 ++ src/apps/webpositive/SettingsWindow.cpp | 177 +++++++++++++++++++----- src/apps/webpositive/SettingsWindow.h | 21 ++- 6 files changed, 236 insertions(+), 46 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index a3a4043495..f4d0e58a4c 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -166,11 +166,22 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fZoomTextOnly(true), fShowTabsIfSinglePageOpen(true) { + // Begin listening to settings changes and read some current values. fAppSettings->AddListener(BMessenger(this)); // fZoomTextOnly = fAppSettings->GetValue("zoom text only", fZoomTextOnly); fShowTabsIfSinglePageOpen = fAppSettings->GetValue( kSettingsKeyShowTabsIfSinglePageOpen, fShowTabsIfSinglePageOpen); + fNewWindowPolicy = fAppSettings->GetValue(kSettingsKeyNewWindowPolicy, + (uint32)OpenStartPage); + fNewTabPolicy = fAppSettings->GetValue(kSettingsKeyNewTabPolicy, + (uint32)OpenBlankPage); + fStartPageURL = fAppSettings->GetValue(kSettingsKeyStartPageURL, + kDefaultStartPageURL); + fSearchPageURL = fAppSettings->GetValue(kSettingsKeySearchPageURL, + kDefaultSearchPageURL); + + // Create the interface elements BMessage* newTabMessage = new BMessage(NEW_TAB); newTabMessage->AddString("url", ""); newTabMessage->AddPointer("window", this); @@ -672,12 +683,26 @@ BrowserWindow::MessageReceived(BMessage* message) if (message->FindString("name", &name) != B_OK) break; bool flag; + BString string; + uint32 value; if (name == kSettingsKeyShowTabsIfSinglePageOpen && message->FindBool("value", &flag) == B_OK) { if (fShowTabsIfSinglePageOpen != flag) { fShowTabsIfSinglePageOpen = flag; _UpdateTabGroupVisibility(); } + } else if (name == kSettingsKeyStartPageURL + && message->FindString("value", &string) == B_OK) { + fStartPageURL = string; + } else if (name == kSettingsKeySearchPageURL + && message->FindString("value", &string) == B_OK) { + fSearchPageURL = string; + } else if (name == kSettingsKeyNewWindowPolicy + && message->FindUInt32("value", &value) == B_OK) { + fNewWindowPolicy = value; + } else if (name == kSettingsKeyNewTabPolicy + && message->FindUInt32("value", &value) == B_OK) { + fNewTabPolicy = value; } break; } @@ -716,15 +741,38 @@ BrowserWindow::MenusBeginning() void -BrowserWindow::CreateNewTab(const BString& url, bool select, BWebView* webView) +BrowserWindow::CreateNewTab(const BString& _url, bool select, BWebView* webView) { // Executed in app thread (new BWebPage needs to be created in app thread). if (!webView) webView = new BWebView("web view"); + bool isNewWindow = fTabManager->CountTabs() == 0; + fTabManager->AddTab(webView, "New tab"); - if (url.Length()) + BString url(_url); + if (url.Length() == 0) { + uint32 policy = isNewWindow ? fNewWindowPolicy : fNewTabPolicy; + // Implement new page policy + switch (policy) { + case OpenStartPage: + url = fStartPageURL; + break; + case OpenSearchPage: + url = fSearchPageURL; + break; + case CloneCurrentPage: + if (CurrentWebView() != NULL) + url = CurrentWebView()->MainFrameURL(); + break; + default: + case OpenBlankPage: + break; + } + } + + if (url.Length() > 0) webView->LoadURL(url.String()); if (select) { diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 73b6fdd48c..31886fa045 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -56,6 +56,13 @@ enum ToolbarPolicy { DoNotHaveToolbar }; +enum NewPagePolicy { + OpenBlankPage = 0, + OpenStartPage = 1, + OpenSearchPage = 2, + CloneCurrentPage = 3 +}; + enum { NEW_WINDOW = 'nwnd', NEW_TAB = 'ntab', @@ -176,9 +183,14 @@ private: BCheckBox* fFindCaseSensitiveCheckBox; TabManager* fTabManager; + // cached settings SettingsMessage* fAppSettings; bool fZoomTextOnly; bool fShowTabsIfSinglePageOpen; + uint32 fNewWindowPolicy; + uint32 fNewTabPolicy; + BString fStartPageURL; + BString fSearchPageURL; }; diff --git a/src/apps/webpositive/SettingsKeys.cpp b/src/apps/webpositive/SettingsKeys.cpp index 7fe0c4e1e2..5df66469ca 100644 --- a/src/apps/webpositive/SettingsKeys.cpp +++ b/src/apps/webpositive/SettingsKeys.cpp @@ -30,3 +30,15 @@ const char* kSettingsKeyDownloadPath = "download path"; const char* kSettingsKeyShowTabsIfSinglePageOpen = "show tabs if single page open"; + +const char* kSettingsKeyNewWindowPolicy = "new window policy"; +const char* kSettingsKeyNewTabPolicy = "new tab policy"; +const char* kSettingsKeyStartPageURL = "start page url"; +const char* kSettingsKeySearchPageURL = "search page url"; + + +const char* kDefaultDownloadPath = "/boot/home/Desktop/"; +const char* kDefaultStartPageURL + = "file:///boot/system/documentation/welcome/welcome_en.html"; +const char* kDefaultSearchPageURL = "http://www.google.com"; + diff --git a/src/apps/webpositive/SettingsKeys.h b/src/apps/webpositive/SettingsKeys.h index 584a320e86..112e903e81 100644 --- a/src/apps/webpositive/SettingsKeys.h +++ b/src/apps/webpositive/SettingsKeys.h @@ -33,5 +33,13 @@ extern const char* kSettingsKeyDownloadPath; extern const char* kSettingsKeyShowTabsIfSinglePageOpen; +extern const char* kSettingsKeyNewWindowPolicy; +extern const char* kSettingsKeyNewTabPolicy; +extern const char* kSettingsKeyStartPageURL; +extern const char* kSettingsKeySearchPageURL; + +extern const char* kDefaultDownloadPath; +extern const char* kDefaultStartPageURL; +extern const char* kDefaultSearchPageURL; #endif // SETTINGS_KEYS_H diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 8591fd8c6a..c24b0b1d0a 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -48,6 +48,7 @@ #include "BrowserApp.h" #include "BrowsingHistory.h" +#include "BrowserWindow.h" #include "FontSelectionView.h" #include "SettingsKeys.h" #include "SettingsMessage.h" @@ -63,9 +64,12 @@ enum { MSG_REVERT = 'rvrt', MSG_STANDARD_FONT_SIZE_SELECTED = 'sfss', MSG_FIXED_FONT_SIZE_SELECTED = 'ffss', + MSG_START_PAGE_CHANGED = 'hpch', + MSG_SEARCH_PAGE_CHANGED = 'spch', MSG_DOWNLOAD_FOLDER_CHANGED = 'dnfc', - MSG_NEW_PAGE_BEHAVIOR_CHANGED = 'npbc', - MSG_GO_MENU_DAYS_CHANGED = 'digm', + MSG_NEW_WINDOWS_BEHAVIOR_CHANGED = 'nwbc', + MSG_NEW_TABS_BEHAVIOR_CHANGED = 'ntbc', + MSG_HISTORY_MENU_DAYS_CHANGED = 'digm', MSG_TAB_DISPLAY_BEHAVIOR_CHANGED = 'tdbc', }; @@ -209,61 +213,94 @@ SettingsWindow::Show() BView* SettingsWindow::_CreateGeneralPage(float spacing) { + fStartPageControl = new BTextControl("start page", + TR("Start page:"), "", new BMessage(MSG_START_PAGE_CHANGED)); + fStartPageControl->SetText( + fSettings->GetValue(kSettingsKeyStartPageURL, kDefaultStartPageURL)); + + fSearchPageControl = new BTextControl("search page", + TR("Search page:"), "", new BMessage(MSG_SEARCH_PAGE_CHANGED)); + fSearchPageControl->SetText( + fSettings->GetValue(kSettingsKeySearchPageURL, kDefaultSearchPageURL)); + fDownloadFolderControl = new BTextControl("download folder", TR("Download folder:"), "", new BMessage(MSG_DOWNLOAD_FOLDER_CHANGED)); fDownloadFolderControl->SetText( - fSettings->GetValue(kSettingsKeyDownloadPath, "")); + fSettings->GetValue(kSettingsKeyDownloadPath, kDefaultDownloadPath)); - fNewPageBehaviorCloneCurrentItem = new BMenuItem(TR("Clone current page"), + fNewWindowBehaviorOpenHomeItem = new BMenuItem(TR("Open start page"), NULL); - fNewPageBehaviorCloneCurrentItem->SetEnabled(false); - fNewPageBehaviorOpenHomeItem = new BMenuItem(TR("Open home page"), NULL); - fNewPageBehaviorOpenHomeItem->SetEnabled(false); - fNewPageBehaviorOpenSearchItem = new BMenuItem(TR("Open search page"), + fNewWindowBehaviorOpenSearchItem = new BMenuItem(TR("Open search page"), + NULL); + fNewWindowBehaviorOpenBlankItem = new BMenuItem(TR("Open blank page"), NULL); - fNewPageBehaviorOpenSearchItem->SetEnabled(false); - fNewPageBehaviorOpenBlankItem = new BMenuItem(TR("Open blank page"), NULL); - fNewPageBehaviorOpenBlankItem->SetMarked(true); - BPopUpMenu* newPageBehaviorMenu = new BPopUpMenu("New pages"); - newPageBehaviorMenu->AddItem(fNewPageBehaviorCloneCurrentItem); - newPageBehaviorMenu->AddItem(fNewPageBehaviorOpenHomeItem); - newPageBehaviorMenu->AddItem(fNewPageBehaviorOpenSearchItem); - newPageBehaviorMenu->AddItem(fNewPageBehaviorOpenBlankItem); - fNewPageBehaviorMenu = new BMenuField("new page behavior", - TR("New pages:"), newPageBehaviorMenu, - new BMessage(MSG_NEW_PAGE_BEHAVIOR_CHANGED)); -fNewPageBehaviorMenu->SetEnabled(false); + fNewTabBehaviorCloneCurrentItem = new BMenuItem(TR("Clone current page"), + NULL); + fNewTabBehaviorOpenHomeItem = new BMenuItem(TR("Open start page"), NULL); + fNewTabBehaviorOpenSearchItem = new BMenuItem(TR("Open search page"), + NULL); + fNewTabBehaviorOpenBlankItem = new BMenuItem(TR("Open blank page"), NULL); - fDaysInGoMenuControl = new BTextControl("days in go menu", - TR("Number of days to keep links in Go menu:"), "", - new BMessage(MSG_GO_MENU_DAYS_CHANGED)); + fNewWindowBehaviorOpenHomeItem->SetMarked(true); + fNewTabBehaviorOpenBlankItem->SetMarked(true); + + BPopUpMenu* newWindowBehaviorMenu = new BPopUpMenu("New windows"); + newWindowBehaviorMenu->AddItem(fNewWindowBehaviorOpenHomeItem); + newWindowBehaviorMenu->AddItem(fNewWindowBehaviorOpenSearchItem); + newWindowBehaviorMenu->AddItem(fNewWindowBehaviorOpenBlankItem); + fNewWindowBehaviorMenu = new BMenuField("new window behavior", + TR("New windows:"), newWindowBehaviorMenu, + new BMessage(MSG_NEW_WINDOWS_BEHAVIOR_CHANGED)); + + BPopUpMenu* newTabBehaviorMenu = new BPopUpMenu("New tabs"); + newTabBehaviorMenu->AddItem(fNewTabBehaviorOpenBlankItem); + newTabBehaviorMenu->AddItem(fNewTabBehaviorOpenHomeItem); + newTabBehaviorMenu->AddItem(fNewTabBehaviorOpenSearchItem); + newTabBehaviorMenu->AddItem(fNewTabBehaviorCloneCurrentItem); + fNewTabBehaviorMenu = new BMenuField("new tab behavior", + TR("New tabs:"), newTabBehaviorMenu, + new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED)); + + fDaysInHistoryMenuControl = new BTextControl("days in history", + TR("Number of days to keep links in History menu:"), "", + new BMessage(MSG_HISTORY_MENU_DAYS_CHANGED)); BString maxHistoryAge; maxHistoryAge << BrowsingHistory::DefaultInstance()->MaxHistoryItemAge(); - fDaysInGoMenuControl->SetText(maxHistoryAge.String()); + fDaysInHistoryMenuControl->SetText(maxHistoryAge.String()); for (uchar i = 0; i < '0'; i++) - fDaysInGoMenuControl->TextView()->DisallowChar(i); + fDaysInHistoryMenuControl->TextView()->DisallowChar(i); for (uchar i = '9' + 1; i <= 128; i++) - fDaysInGoMenuControl->TextView()->DisallowChar(i); + fDaysInHistoryMenuControl->TextView()->DisallowChar(i); fShowTabsIfOnlyOnePage = new BCheckBox("show tabs if only one page", TR("Show tabs if only one page is open."), new BMessage(MSG_TAB_DISPLAY_BEHAVIOR_CHANGED)); fShowTabsIfOnlyOnePage->SetValue(B_CONTROL_ON); - BView* view = BGridLayoutBuilder(spacing / 2, spacing / 2) - .Add(fDownloadFolderControl->CreateLabelLayoutItem(), 0, 1) - .Add(fDownloadFolderControl->CreateTextViewLayoutItem(), 1, 1) + BView* view = BGroupLayoutBuilder(B_VERTICAL, spacing / 2) + .Add(BGridLayoutBuilder(spacing / 2, spacing / 2) + .Add(fStartPageControl->CreateLabelLayoutItem(), 0, 0) + .Add(fStartPageControl->CreateTextViewLayoutItem(), 1, 0) - .Add(fNewPageBehaviorMenu->CreateLabelLayoutItem(), 0, 2) - .Add(fNewPageBehaviorMenu->CreateMenuBarLayoutItem(), 1, 2) + .Add(fSearchPageControl->CreateLabelLayoutItem(), 0, 1) + .Add(fSearchPageControl->CreateTextViewLayoutItem(), 1, 1) - .Add(fDaysInGoMenuControl->CreateLabelLayoutItem(), 0, 3) - .Add(fDaysInGoMenuControl->CreateTextViewLayoutItem(), 1, 3) + .Add(fDownloadFolderControl->CreateLabelLayoutItem(), 0, 2) + .Add(fDownloadFolderControl->CreateTextViewLayoutItem(), 1, 2) - .Add(fShowTabsIfOnlyOnePage, 0, 4, 2) + .Add(fNewWindowBehaviorMenu->CreateLabelLayoutItem(), 0, 3) + .Add(fNewWindowBehaviorMenu->CreateMenuBarLayoutItem(), 1, 3) - .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 5, 2) + .Add(fNewTabBehaviorMenu->CreateLabelLayoutItem(), 0, 4) + .Add(fNewTabBehaviorMenu->CreateMenuBarLayoutItem(), 1, 4) + ) + .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing)) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing)) + .Add(fShowTabsIfOnlyOnePage) + .Add(fDaysInHistoryMenuControl) + .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing)) .SetInsets(spacing, spacing, spacing, spacing) ; @@ -330,20 +367,42 @@ void SettingsWindow::_ApplySettings() { // Store general settings - int32 maxHistoryAge = atoi(fDaysInGoMenuControl->Text()); + int32 maxHistoryAge = atoi(fDaysInHistoryMenuControl->Text()); if (maxHistoryAge <= 0) maxHistoryAge = 1; if (maxHistoryAge >= 35) maxHistoryAge = 35; BString text; text << maxHistoryAge; - fDaysInGoMenuControl->SetText(text.String()); + fDaysInHistoryMenuControl->SetText(text.String()); BrowsingHistory::DefaultInstance()->SetMaxHistoryItemAge(maxHistoryAge); + fSettings->SetValue(kSettingsKeyStartPageURL, fStartPageControl->Text()); + fSettings->SetValue(kSettingsKeySearchPageURL, fSearchPageControl->Text()); fSettings->SetValue(kSettingsKeyDownloadPath, fDownloadFolderControl->Text()); fSettings->SetValue(kSettingsKeyShowTabsIfSinglePageOpen, fShowTabsIfOnlyOnePage->Value() == B_CONTROL_ON); + // New window policy + uint32 newWindowPolicy = OpenStartPage; + BMenuItem* markedItem = fNewWindowBehaviorMenu->Menu()->FindMarked(); + if (markedItem == fNewWindowBehaviorOpenSearchItem) + newWindowPolicy = OpenSearchPage; + else if (markedItem == fNewWindowBehaviorOpenBlankItem) + newWindowPolicy = OpenBlankPage; + fSettings->SetValue(kSettingsKeyNewWindowPolicy, newWindowPolicy); + + // New tab policy + uint32 newTabPolicy = OpenBlankPage; + markedItem = fNewTabBehaviorMenu->Menu()->FindMarked(); + if (markedItem == fNewTabBehaviorCloneCurrentItem) + newTabPolicy = CloneCurrentPage; + else if (markedItem == fNewTabBehaviorOpenHomeItem) + newTabPolicy = OpenStartPage; + else if (markedItem == fNewTabBehaviorOpenSearchItem) + newTabPolicy = OpenSearchPage; + fSettings->SetValue(kSettingsKeyNewTabPolicy, newTabPolicy); + // Store fond settings fSettings->SetValue("standard font", fStandardFontView->Font()); fSettings->SetValue("serif font", fSerifFontView->Font()); @@ -373,11 +432,53 @@ SettingsWindow::_ApplySettings() void SettingsWindow::_RevertSettings() { + fStartPageControl->SetText( + fSettings->GetValue(kSettingsKeyStartPageURL, kDefaultStartPageURL)); + + fSearchPageControl->SetText( + fSettings->GetValue(kSettingsKeySearchPageURL, kDefaultSearchPageURL)); + fDownloadFolderControl->SetText( - fSettings->GetValue(kSettingsKeyDownloadPath, "")); + fSettings->GetValue(kSettingsKeyDownloadPath, kDefaultDownloadPath)); fShowTabsIfOnlyOnePage->SetValue( fSettings->GetValue(kSettingsKeyShowTabsIfSinglePageOpen, true)); + // New window policy + uint32 newWindowPolicy = fSettings->GetValue(kSettingsKeyNewWindowPolicy, + (uint32)OpenStartPage); + switch (newWindowPolicy) { + default: + case OpenStartPage: + fNewWindowBehaviorOpenHomeItem->SetMarked(true); + break; + case OpenSearchPage: + fNewWindowBehaviorOpenSearchItem->SetMarked(true); + break; + case OpenBlankPage: + fNewWindowBehaviorOpenBlankItem->SetMarked(true); + break; + } + + // New tab policy + uint32 newTabPolicy = fSettings->GetValue(kSettingsKeyNewTabPolicy, + (uint32)OpenBlankPage); + switch (newTabPolicy) { + default: + case OpenBlankPage: + fNewTabBehaviorOpenBlankItem->SetMarked(true); + break; + case OpenStartPage: + fNewTabBehaviorOpenHomeItem->SetMarked(true); + break; + case OpenSearchPage: + fNewTabBehaviorOpenSearchItem->SetMarked(true); + break; + case CloneCurrentPage: + fNewTabBehaviorCloneCurrentItem->SetMarked(true); + break; + } + + // Font settings int32 defaultFontSize = fSettings->GetValue("standard font size", kDefaultFontSize); int32 defaultFixedFontSize = fSettings->GetValue("fixed font size", diff --git a/src/apps/webpositive/SettingsWindow.h b/src/apps/webpositive/SettingsWindow.h index 1e9d7e3421..1824471541 100644 --- a/src/apps/webpositive/SettingsWindow.h +++ b/src/apps/webpositive/SettingsWindow.h @@ -67,13 +67,22 @@ private: private: SettingsMessage* fSettings; + BTextControl* fStartPageControl; + BTextControl* fSearchPageControl; BTextControl* fDownloadFolderControl; - BMenuField* fNewPageBehaviorMenu; - BMenuItem* fNewPageBehaviorCloneCurrentItem; - BMenuItem* fNewPageBehaviorOpenHomeItem; - BMenuItem* fNewPageBehaviorOpenSearchItem; - BMenuItem* fNewPageBehaviorOpenBlankItem; - BTextControl* fDaysInGoMenuControl; + + BMenuField* fNewWindowBehaviorMenu; + BMenuItem* fNewWindowBehaviorOpenHomeItem; + BMenuItem* fNewWindowBehaviorOpenSearchItem; + BMenuItem* fNewWindowBehaviorOpenBlankItem; + + BMenuField* fNewTabBehaviorMenu; + BMenuItem* fNewTabBehaviorCloneCurrentItem; + BMenuItem* fNewTabBehaviorOpenHomeItem; + BMenuItem* fNewTabBehaviorOpenSearchItem; + BMenuItem* fNewTabBehaviorOpenBlankItem; + + BTextControl* fDaysInHistoryMenuControl; BCheckBox* fShowTabsIfOnlyOnePage; FontSelectionView* fStandardFontView; From b0240c4936c561e4e964f35663f1b7344110ac42 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 23 Apr 2010 16:07:22 +0000 Subject: [PATCH 242/349] Allow setting a listener target and a modification message. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@457 94f232f2-1747-11df-bad5-a5bfde151594 --- .../webpositive/support/FontSelectionView.cpp | 36 ++++++++++++++++++- .../webpositive/support/FontSelectionView.h | 8 +++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/support/FontSelectionView.cpp b/src/apps/webpositive/support/FontSelectionView.cpp index 24fcd248fb..c463a8c9ef 100644 --- a/src/apps/webpositive/support/FontSelectionView.cpp +++ b/src/apps/webpositive/support/FontSelectionView.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -43,7 +44,9 @@ static const int32 kMsgSetSize = 'size'; FontSelectionView::FontSelectionView(const char* name, const char* label, bool separateStyles, const BFont* currentFont) : - BHandler(name) + BHandler(name), + fMessage(NULL), + fTarget(NULL) { if (currentFont == NULL) fCurrentFont = _DefaultFont(); @@ -96,6 +99,8 @@ FontSelectionView::~FontSelectionView() delete fStylesMenuField; if (!fFontsMenuField->Window()) delete fFontsMenuField; + + delete fMessage; } @@ -120,6 +125,7 @@ FontSelectionView::MessageReceived(BMessage* message) fCurrentFont.SetSize(size); _UpdateFontPreview(); + _Invoke(); break; } @@ -153,6 +159,8 @@ FontSelectionView::MessageReceived(BMessage* message) if (fStylesMenuField != NULL) _AddStylesToMenu(fCurrentFont, fStylesMenuField->Menu()); } + + _Invoke(); break; } @@ -173,6 +181,7 @@ FontSelectionView::MessageReceived(BMessage* message) fCurrentFont.SetFamilyAndStyle(family, style); _UpdateFontPreview(); + _Invoke(); break; } @@ -182,6 +191,21 @@ FontSelectionView::MessageReceived(BMessage* message) } +void +FontSelectionView::SetMessage(BMessage* message) +{ + delete fMessage; + fMessage = message; +} + + +void +FontSelectionView::SetTarget(BHandler* target) +{ + fTarget = target; +} + + // #pragma mark - @@ -379,6 +403,16 @@ FontSelectionView::PreviewBox() const // #pragma mark - private +void +FontSelectionView::_Invoke() +{ + if (fTarget != NULL && fTarget->Looper() != NULL && fMessage != NULL) { + BMessage message(*fMessage); + fTarget->Looper()->PostMessage(&message, fTarget); + } +} + + BFont FontSelectionView::_DefaultFont() const { diff --git a/src/apps/webpositive/support/FontSelectionView.h b/src/apps/webpositive/support/FontSelectionView.h index f25801a840..8ee630b448 100644 --- a/src/apps/webpositive/support/FontSelectionView.h +++ b/src/apps/webpositive/support/FontSelectionView.h @@ -35,6 +35,9 @@ public: void AttachedToLooper(); virtual void MessageReceived(BMessage* message); + void SetMessage(BMessage* message); + void SetTarget(BHandler* target); + void SetFont(const BFont& font, float size); void SetFont(const BFont& font); void SetSize(float size); @@ -59,6 +62,8 @@ public: BView* PreviewBox() const; private: + void _Invoke(); + BFont _DefaultFont() const; void _SelectCurrentFont(bool select); void _SelectCurrentSize(bool select); @@ -78,6 +83,9 @@ protected: BFont fSavedFont; BFont fCurrentFont; + + BMessage* fMessage; + BHandler* fTarget; }; #endif // FONT_SELECTION_VIEW_H From b1957a61f69eec02dbd2636f4cdb94aa5869445c Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 23 Apr 2010 16:09:04 +0000 Subject: [PATCH 243/349] * The current max history age was not read from the BrowsingHistory in SettingsWindow::_RevertSettings(). * Made all necessary refactoring in order to support _CanApplySettings(). * Adjust the Apply and Revert button enabled state whenever settings change. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@458 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/SettingsWindow.cpp | 270 ++++++++++++++++++------ src/apps/webpositive/SettingsWindow.h | 19 +- 2 files changed, 219 insertions(+), 70 deletions(-) diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index c24b0b1d0a..c5a5577800 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -62,8 +62,7 @@ enum { MSG_APPLY = 'aply', MSG_CANCEL = 'cncl', MSG_REVERT = 'rvrt', - MSG_STANDARD_FONT_SIZE_SELECTED = 'sfss', - MSG_FIXED_FONT_SIZE_SELECTED = 'ffss', + MSG_START_PAGE_CHANGED = 'hpch', MSG_SEARCH_PAGE_CHANGED = 'spch', MSG_DOWNLOAD_FOLDER_CHANGED = 'dnfc', @@ -71,6 +70,14 @@ enum { MSG_NEW_TABS_BEHAVIOR_CHANGED = 'ntbc', MSG_HISTORY_MENU_DAYS_CHANGED = 'digm', MSG_TAB_DISPLAY_BEHAVIOR_CHANGED = 'tdbc', + + MSG_STANDARD_FONT_CHANGED = 'stfc', + MSG_SERIF_FONT_CHANGED = 'sefc', + MSG_SANS_SERIF_FONT_CHANGED = 'ssfc', + MSG_FIXED_FONT_CHANGED = 'ffch', + + MSG_STANDARD_FONT_SIZE_SELECTED = 'sfss', + MSG_FIXED_FONT_SIZE_SELECTED = 'ffss', }; static const int32 kDefaultFontSize = 14; @@ -106,17 +113,14 @@ SettingsWindow::SettingsWindow(BRect frame, SettingsMessage* settings) tabView->AddTab(_CreateGeneralPage(spacing)); tabView->AddTab(_CreateFontsPage(spacing)); - AddHandler(fStandardFontView); - fStandardFontView->AttachedToLooper(); - - AddHandler(fSerifFontView); - fSerifFontView->AttachedToLooper(); - - AddHandler(fSansSerifFontView); - fSansSerifFontView->AttachedToLooper(); - - AddHandler(fFixedFontView); - fFixedFontView->AttachedToLooper(); + _SetupFontSelectionView(fStandardFontView, + new BMessage(MSG_STANDARD_FONT_CHANGED)); + _SetupFontSelectionView(fSerifFontView, + new BMessage(MSG_SERIF_FONT_CHANGED)); + _SetupFontSelectionView(fSansSerifFontView, + new BMessage(MSG_SANS_SERIF_FONT_CHANGED)); + _SetupFontSelectionView(fFixedFontView, + new BMessage(MSG_FIXED_FONT_CHANGED)); fApplyButton->MakeDefault(true); @@ -168,17 +172,30 @@ SettingsWindow::MessageReceived(BMessage* message) fStandardFontView->SetSize(size); fSerifFontView->SetSize(size); fSansSerifFontView->SetSize(size); + _ValidateButtonsEnabled(); break; } case MSG_FIXED_FONT_SIZE_SELECTED: { int32 size = _SizesMenuValue(fFixedSizesMenu->Menu()); fFixedFontView->SetSize(size); + _ValidateButtonsEnabled(); break; } + case MSG_START_PAGE_CHANGED: + case MSG_SEARCH_PAGE_CHANGED: + case MSG_DOWNLOAD_FOLDER_CHANGED: + case MSG_NEW_WINDOWS_BEHAVIOR_CHANGED: + case MSG_NEW_TABS_BEHAVIOR_CHANGED: + case MSG_HISTORY_MENU_DAYS_CHANGED: case MSG_TAB_DISPLAY_BEHAVIOR_CHANGED: + case MSG_STANDARD_FONT_CHANGED: + case MSG_SERIF_FONT_CHANGED: + case MSG_SANS_SERIF_FONT_CHANGED: + case MSG_FIXED_FONT_CHANGED: // TODO: Some settings could change live, some others not? + _ValidateButtonsEnabled(); break; default: @@ -215,32 +232,40 @@ SettingsWindow::_CreateGeneralPage(float spacing) { fStartPageControl = new BTextControl("start page", TR("Start page:"), "", new BMessage(MSG_START_PAGE_CHANGED)); + fStartPageControl->SetModificationMessage( + new BMessage(MSG_START_PAGE_CHANGED)); fStartPageControl->SetText( fSettings->GetValue(kSettingsKeyStartPageURL, kDefaultStartPageURL)); fSearchPageControl = new BTextControl("search page", TR("Search page:"), "", new BMessage(MSG_SEARCH_PAGE_CHANGED)); + fSearchPageControl->SetModificationMessage( + new BMessage(MSG_SEARCH_PAGE_CHANGED)); fSearchPageControl->SetText( fSettings->GetValue(kSettingsKeySearchPageURL, kDefaultSearchPageURL)); fDownloadFolderControl = new BTextControl("download folder", TR("Download folder:"), "", new BMessage(MSG_DOWNLOAD_FOLDER_CHANGED)); + fDownloadFolderControl->SetModificationMessage( + new BMessage(MSG_DOWNLOAD_FOLDER_CHANGED)); fDownloadFolderControl->SetText( fSettings->GetValue(kSettingsKeyDownloadPath, kDefaultDownloadPath)); fNewWindowBehaviorOpenHomeItem = new BMenuItem(TR("Open start page"), - NULL); + new BMessage(MSG_NEW_WINDOWS_BEHAVIOR_CHANGED)); fNewWindowBehaviorOpenSearchItem = new BMenuItem(TR("Open search page"), - NULL); + new BMessage(MSG_NEW_WINDOWS_BEHAVIOR_CHANGED)); fNewWindowBehaviorOpenBlankItem = new BMenuItem(TR("Open blank page"), - NULL); + new BMessage(MSG_NEW_WINDOWS_BEHAVIOR_CHANGED)); fNewTabBehaviorCloneCurrentItem = new BMenuItem(TR("Clone current page"), - NULL); - fNewTabBehaviorOpenHomeItem = new BMenuItem(TR("Open start page"), NULL); + new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED)); + fNewTabBehaviorOpenHomeItem = new BMenuItem(TR("Open start page"), + new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED)); fNewTabBehaviorOpenSearchItem = new BMenuItem(TR("Open search page"), - NULL); - fNewTabBehaviorOpenBlankItem = new BMenuItem(TR("Open blank page"), NULL); + new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED)); + fNewTabBehaviorOpenBlankItem = new BMenuItem(TR("Open blank page"), + new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED)); fNewWindowBehaviorOpenHomeItem->SetMarked(true); fNewTabBehaviorOpenBlankItem->SetMarked(true); @@ -250,8 +275,7 @@ SettingsWindow::_CreateGeneralPage(float spacing) newWindowBehaviorMenu->AddItem(fNewWindowBehaviorOpenSearchItem); newWindowBehaviorMenu->AddItem(fNewWindowBehaviorOpenBlankItem); fNewWindowBehaviorMenu = new BMenuField("new window behavior", - TR("New windows:"), newWindowBehaviorMenu, - new BMessage(MSG_NEW_WINDOWS_BEHAVIOR_CHANGED)); + TR("New windows:"), newWindowBehaviorMenu); BPopUpMenu* newTabBehaviorMenu = new BPopUpMenu("New tabs"); newTabBehaviorMenu->AddItem(fNewTabBehaviorOpenBlankItem); @@ -259,12 +283,13 @@ SettingsWindow::_CreateGeneralPage(float spacing) newTabBehaviorMenu->AddItem(fNewTabBehaviorOpenSearchItem); newTabBehaviorMenu->AddItem(fNewTabBehaviorCloneCurrentItem); fNewTabBehaviorMenu = new BMenuField("new tab behavior", - TR("New tabs:"), newTabBehaviorMenu, - new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED)); + TR("New tabs:"), newTabBehaviorMenu); fDaysInHistoryMenuControl = new BTextControl("days in history", TR("Number of days to keep links in History menu:"), "", new BMessage(MSG_HISTORY_MENU_DAYS_CHANGED)); + fDaysInHistoryMenuControl->SetModificationMessage( + new BMessage(MSG_HISTORY_MENU_DAYS_CHANGED)); BString maxHistoryAge; maxHistoryAge << BrowsingHistory::DefaultInstance()->MaxHistoryItemAge(); fDaysInHistoryMenuControl->SetText(maxHistoryAge.String()); @@ -363,15 +388,109 @@ SettingsWindow::_CreateFontsPage(float spacing) } +void +SettingsWindow::_BuildSizesMenu(BMenu* menu, uint32 messageWhat) +{ + const float kMinSize = 8.0; + const float kMaxSize = 18.0; + + const int32 kSizes[] = {7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 21, 24, 0}; + + for (int32 i = 0; kSizes[i]; i++) { + int32 size = kSizes[i]; + if (size < kMinSize || size > kMaxSize) + continue; + + char label[32]; + snprintf(label, sizeof(label), "%ld", size); + + BMessage* message = new BMessage(messageWhat); + message->AddInt32("size", size); + + BMenuItem* item = new BMenuItem(label, message); + + menu->AddItem(item); + item->SetTarget(this); + } +} + + +void +SettingsWindow::_SetupFontSelectionView(FontSelectionView* view, + BMessage* message) +{ + AddHandler(view); + view->AttachedToLooper(); + view->SetMessage(message); + view->SetTarget(this); +} + + +// #pragma mark - + + +bool +SettingsWindow::_CanApplySettings() const +{ + bool canApply = false; + + // General settings + canApply = canApply || (strcmp(fStartPageControl->Text(), + fSettings->GetValue(kSettingsKeyStartPageURL, + kDefaultStartPageURL)) != 0); + + canApply = canApply || (strcmp(fSearchPageControl->Text(), + fSettings->GetValue(kSettingsKeySearchPageURL, + kDefaultSearchPageURL)) != 0); + + canApply = canApply || (strcmp(fDownloadFolderControl->Text(), + fSettings->GetValue(kSettingsKeyDownloadPath, + kDefaultDownloadPath)) != 0); + + canApply = canApply || ((fShowTabsIfOnlyOnePage->Value() == B_CONTROL_ON) + != fSettings->GetValue(kSettingsKeyShowTabsIfSinglePageOpen, true)); + + canApply = canApply || (_MaxHistoryAge() + != BrowsingHistory::DefaultInstance()->MaxHistoryItemAge()); + + // New window policy + canApply = canApply || (_NewWindowPolicy() + != fSettings->GetValue(kSettingsKeyNewWindowPolicy, + (uint32)OpenStartPage)); + + // New tab policy + canApply = canApply || (_NewTabPolicy() + != fSettings->GetValue(kSettingsKeyNewTabPolicy, + (uint32)OpenBlankPage)); + + // Font settings + canApply = canApply || (fStandardFontView->Font() + != fSettings->GetValue("standard font", *be_plain_font)); + + canApply = canApply || (fSerifFontView->Font() + != fSettings->GetValue("serif font", _FindDefaultSerifFont())); + + canApply = canApply || (fSansSerifFontView->Font() + != fSettings->GetValue("sans serif font", *be_plain_font)); + + canApply = canApply || (fFixedFontView->Font() + != fSettings->GetValue("fixed font", *be_fixed_font)); + + canApply = canApply || (_SizesMenuValue(fStandardSizesMenu->Menu()) + != fSettings->GetValue("standard font size", kDefaultFontSize)); + + canApply = canApply || (_SizesMenuValue(fFixedSizesMenu->Menu()) + != fSettings->GetValue("fixed font size", kDefaultFontSize)); + + return canApply; +} + + void SettingsWindow::_ApplySettings() { // Store general settings - int32 maxHistoryAge = atoi(fDaysInHistoryMenuControl->Text()); - if (maxHistoryAge <= 0) - maxHistoryAge = 1; - if (maxHistoryAge >= 35) - maxHistoryAge = 35; + int32 maxHistoryAge = _MaxHistoryAge(); BString text; text << maxHistoryAge; fDaysInHistoryMenuControl->SetText(text.String()); @@ -383,25 +502,9 @@ SettingsWindow::_ApplySettings() fSettings->SetValue(kSettingsKeyShowTabsIfSinglePageOpen, fShowTabsIfOnlyOnePage->Value() == B_CONTROL_ON); - // New window policy - uint32 newWindowPolicy = OpenStartPage; - BMenuItem* markedItem = fNewWindowBehaviorMenu->Menu()->FindMarked(); - if (markedItem == fNewWindowBehaviorOpenSearchItem) - newWindowPolicy = OpenSearchPage; - else if (markedItem == fNewWindowBehaviorOpenBlankItem) - newWindowPolicy = OpenBlankPage; - fSettings->SetValue(kSettingsKeyNewWindowPolicy, newWindowPolicy); - - // New tab policy - uint32 newTabPolicy = OpenBlankPage; - markedItem = fNewTabBehaviorMenu->Menu()->FindMarked(); - if (markedItem == fNewTabBehaviorCloneCurrentItem) - newTabPolicy = CloneCurrentPage; - else if (markedItem == fNewTabBehaviorOpenHomeItem) - newTabPolicy = OpenStartPage; - else if (markedItem == fNewTabBehaviorOpenSearchItem) - newTabPolicy = OpenSearchPage; - fSettings->SetValue(kSettingsKeyNewTabPolicy, newTabPolicy); + // New page policies + fSettings->SetValue(kSettingsKeyNewWindowPolicy, _NewWindowPolicy()); + fSettings->SetValue(kSettingsKeyNewTabPolicy, _NewTabPolicy()); // Store fond settings fSettings->SetValue("standard font", fStandardFontView->Font()); @@ -426,6 +529,9 @@ SettingsWindow::_ApplySettings() // This will find all currently instantiated page settings and apply // the default values, unless the page settings have local overrides. BWebSettings::Default()->Apply(); + + + _ValidateButtonsEnabled(); } @@ -443,6 +549,10 @@ SettingsWindow::_RevertSettings() fShowTabsIfOnlyOnePage->SetValue( fSettings->GetValue(kSettingsKeyShowTabsIfSinglePageOpen, true)); + BString text; + text << BrowsingHistory::DefaultInstance()->MaxHistoryItemAge(); + fDaysInHistoryMenuControl->SetText(text.String()); + // New window policy uint32 newWindowPolicy = fSettings->GetValue(kSettingsKeyNewWindowPolicy, (uint32)OpenStartPage); @@ -495,33 +605,63 @@ SettingsWindow::_RevertSettings() *be_plain_font), defaultFontSize); fFixedFontView->SetFont(fSettings->GetValue("fixed font", *be_fixed_font), defaultFixedFontSize); + + _ValidateButtonsEnabled(); } void -SettingsWindow::_BuildSizesMenu(BMenu* menu, uint32 messageWhat) +SettingsWindow::_ValidateButtonsEnabled() { - const float kMinSize = 8.0; - const float kMaxSize = 18.0; + bool canApply = _CanApplySettings(); + fApplyButton->SetEnabled(canApply); + fRevertButton->SetEnabled(canApply); + // Let the Cancel button be enabled always, as another way to close the + // window... + fCancelButton->SetEnabled(true); +} - const int32 kSizes[] = {7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 21, 24, 0}; - for (int32 i = 0; kSizes[i]; i++) { - int32 size = kSizes[i]; - if (size < kMinSize || size > kMaxSize) - continue; +// #pragma mark - - char label[32]; - snprintf(label, sizeof(label), "%ld", size); - BMessage* message = new BMessage(messageWhat); - message->AddInt32("size", size); +uint32 +SettingsWindow::_NewWindowPolicy() const +{ + uint32 newWindowPolicy = OpenStartPage; + BMenuItem* markedItem = fNewWindowBehaviorMenu->Menu()->FindMarked(); + if (markedItem == fNewWindowBehaviorOpenSearchItem) + newWindowPolicy = OpenSearchPage; + else if (markedItem == fNewWindowBehaviorOpenBlankItem) + newWindowPolicy = OpenBlankPage; + return newWindowPolicy; +} - BMenuItem* item = new BMenuItem(label, message); - menu->AddItem(item); - item->SetTarget(this); - } +uint32 +SettingsWindow::_NewTabPolicy() const +{ + uint32 newTabPolicy = OpenBlankPage; + BMenuItem* markedItem = fNewTabBehaviorMenu->Menu()->FindMarked(); + if (markedItem == fNewTabBehaviorCloneCurrentItem) + newTabPolicy = CloneCurrentPage; + else if (markedItem == fNewTabBehaviorOpenHomeItem) + newTabPolicy = OpenStartPage; + else if (markedItem == fNewTabBehaviorOpenSearchItem) + newTabPolicy = OpenSearchPage; + return newTabPolicy; +} + + +int32 +SettingsWindow::_MaxHistoryAge() const +{ + int32 maxHistoryAge = atoi(fDaysInHistoryMenuControl->Text()); + if (maxHistoryAge <= 0) + maxHistoryAge = 1; + if (maxHistoryAge >= 35) + maxHistoryAge = 35; + return maxHistoryAge; } @@ -541,7 +681,7 @@ SettingsWindow::_SetSizesMenuValue(BMenu* menu, int32 value) int32 -SettingsWindow::_SizesMenuValue(BMenu* menu) +SettingsWindow::_SizesMenuValue(BMenu* menu) const { if (BMenuItem* item = menu->FindMarked()) { if (BMessage* message = item->Message()) { diff --git a/src/apps/webpositive/SettingsWindow.h b/src/apps/webpositive/SettingsWindow.h index 1824471541..a3b6417ec9 100644 --- a/src/apps/webpositive/SettingsWindow.h +++ b/src/apps/webpositive/SettingsWindow.h @@ -53,14 +53,23 @@ public: private: BView* _CreateGeneralPage(float spacing); BView* _CreateFontsPage(float spacing); - - void _ApplySettings(); - void _RevertSettings(); - void _BuildSizesMenu(BMenu* menu, uint32 messageWhat); + void _SetupFontSelectionView( + FontSelectionView* view, + BMessage* message); + + bool _CanApplySettings() const; + void _ApplySettings(); + void _RevertSettings(); + void _ValidateButtonsEnabled(); + + uint32 _NewWindowPolicy() const; + uint32 _NewTabPolicy() const; + int32 _MaxHistoryAge() const; + void _SetSizesMenuValue(BMenu* menu, int32 value); - int32 _SizesMenuValue(BMenu* menu); + int32 _SizesMenuValue(BMenu* menu) const; BFont _FindDefaultSerifFont() const; From 3cba4f1616fda0ea8c8b6890b086799d00df7525 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 23 Apr 2010 17:00:08 +0000 Subject: [PATCH 244/349] Optimize default window size for 1024x768. Actually I would like to optimize for 800x600 by default, but then the Welcome page opens with horizontal scroll bar. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@459 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 86bdfb1a75..e9976d0c5d 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -62,7 +62,7 @@ BrowserApp::BrowserApp() : BApplication(kApplicationSignature), fWindowCount(0), - fLastWindowFrame(100, 100, 700, 750), + fLastWindowFrame(50, 50, 950, 750), fLaunchRefsMessage(0), fInitialized(false), fSettings(NULL), From a0fcf3c05ee1c8e410fca75868ead94aa99682f1 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 24 Apr 2010 00:46:24 +0000 Subject: [PATCH 245/349] Never apply the new page policy if we already have the BWebView. If we already have it, it was created by the ChromeClient and navigation is soon going to happen with it. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@460 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index f4d0e58a4c..8b0a15d526 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -743,8 +743,9 @@ BrowserWindow::MenusBeginning() void BrowserWindow::CreateNewTab(const BString& _url, bool select, BWebView* webView) { + bool applyNewPagePolicy = webView == NULL; // Executed in app thread (new BWebPage needs to be created in app thread). - if (!webView) + if (webView == NULL) webView = new BWebView("web view"); bool isNewWindow = fTabManager->CountTabs() == 0; @@ -752,7 +753,7 @@ BrowserWindow::CreateNewTab(const BString& _url, bool select, BWebView* webView) fTabManager->AddTab(webView, "New tab"); BString url(_url); - if (url.Length() == 0) { + if (applyNewPagePolicy && url.Length() == 0) { uint32 policy = isNewWindow ? fNewWindowPolicy : fNewTabPolicy; // Implement new page policy switch (policy) { From 54cc547050faded7e2b9918cf0c8839360add704 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 25 Apr 2010 13:45:05 +0000 Subject: [PATCH 246/349] Make sure a filename derived from a bookmark title does not contain invalid characters for a filename. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@461 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 8b0a15d526..e5988d1833 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1193,6 +1193,9 @@ BrowserWindow::_CreateBookmark() if (leafPos >= 0) bookmarkName.Remove(0, leafPos + 1); } + // Make sure the bookmark title does not contain chars that are not + // allowed in file names. + bookmarkName.ReplaceAll('/', '-'); // Check that the bookmark exists nowhere in the bookmark hierarchy, // though the intended file name must match, we don't search the stored From 34da9596562803b4d8369f0cf41948d638d3fdb7 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 26 Apr 2010 15:13:57 +0000 Subject: [PATCH 247/349] Cleanup the supported types. Claiming support for image/jpeg, gif and png is not really useful. Neither is claiming support for text/*. Added support for image/svg+xml, since I don't think anything else would handle it as good as WebPositive (which will do better once BView supports affine transformations). git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@462 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/WebPositive.rdef | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/apps/webpositive/WebPositive.rdef b/src/apps/webpositive/WebPositive.rdef index 5734330206..1079ab970a 100644 --- a/src/apps/webpositive/WebPositive.rdef +++ b/src/apps/webpositive/WebPositive.rdef @@ -14,11 +14,8 @@ resource app_flags B_SINGLE_LAUNCH; resource file_types message { "types" = "text/html", - "types" = "image/gif", - "types" = "image/jpeg", - "types" = "image/png", + "types" = "image/svg+xml", "types" = "application/x-vnd.Be-bookmark", - "types" = "text", "types" = "application/x-vnd.Be-doc_bookmark", "types" = "application/x-vnd.Be.URL.file", "types" = "application/x-vnd.Be.URL.ftp", From 969b9a9669b105cb809c1d2315800160204519bb Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 26 Apr 2010 15:44:32 +0000 Subject: [PATCH 248/349] Give focus back to the web view when hiding the Find controls. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@463 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index e5988d1833..552b2ee885 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -598,8 +598,11 @@ BrowserWindow::MessageReceived(BMessage* message) fFindTextControl->MakeFocus(true); break; case EDIT_HIDE_FIND_GROUP: - if (fFindGroup->IsVisible()) + if (fFindGroup->IsVisible()) { fFindGroup->SetVisible(false); + if (CurrentWebView() != NULL) + CurrentWebView()->MakeFocus(true); + } break; case B_CUT: From 50c66f38576be9af6e806361871107f51405de1a Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 30 Apr 2010 14:05:35 +0000 Subject: [PATCH 249/349] * Store the favicon in the PageUserData of any BWebView instance. * Refactored setting the page icon so it always goes through the new BrowserWindow::_SetPageIcon(). * Don't replace the PageUserData in _TabChanged() if it already exists (which would forget the favicon). * Write the favicon to the Bookmark file. At the moment, it writes the 32x32 icon as upscaled version of the 16x16 icon. Color reduction makes the icons look not so nice, since Haiku does not yet support PNG icons... git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@464 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 112 +++++++++++++++++++++++-- src/apps/webpositive/BrowserWindow.h | 3 + 2 files changed, 108 insertions(+), 7 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 552b2ee885..9699ca2bd7 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -139,17 +139,43 @@ class PageUserData : public BWebView::UserData { public: PageUserData(BView* focusedView) : - fFocusedView(focusedView) + fFocusedView(focusedView), + fPageIcon(NULL) { } + ~PageUserData() + { + delete fPageIcon; + } + + void SetFocusedView(BView* focusedView) + { + fFocusedView = focusedView; + } + BView* FocusedView() const { return fFocusedView; } + void SetPageIcon(const BBitmap* icon) + { + delete fPageIcon; + if (icon) + fPageIcon = new BBitmap(icon); + else + fPageIcon = NULL; + } + + const BBitmap* PageIcon() const + { + return fPageIcon; + } + private: - BView* fFocusedView; + BView* fFocusedView; + BBitmap* fPageIcon; }; @@ -456,7 +482,7 @@ BrowserWindow::MessageReceived(BMessage* message) BString url; if (message->FindString("url", &url) != B_OK) url = fURLInputGroup->Text(); - fTabManager->SetTabIcon(CurrentWebView(), NULL); + _SetPageIcon(CurrentWebView(), NULL); CurrentWebView()->LoadURL(url.String()); break; } @@ -1019,7 +1045,7 @@ BrowserWindow::TitleChanged(const BString& title, BWebView* view) void BrowserWindow::IconReceived(const BBitmap* icon, BWebView* view) { - fTabManager->SetTabIcon(view, icon); + _SetPageIcon(view, icon); } @@ -1128,14 +1154,24 @@ BrowserWindow::_TabChanged(int32 index) if (webView == CurrentWebView()) return; - if (CurrentWebView() != NULL) - CurrentWebView()->SetUserData(new PageUserData(CurrentFocus())); + if (CurrentWebView() != NULL) { + // Remember the currently focused view before switching tabs, + // so that we can revert the focus when switching back to this tab + // later. + PageUserData* userData = static_cast( + webView->GetUserData()); + if (userData) + userData->SetFocusedView(CurrentFocus()); + else + CurrentWebView()->SetUserData(new PageUserData(CurrentFocus())); + } SetCurrentWebView(webView); if (webView != NULL) { _UpdateTitle(webView->MainFrameTitle()); + // Restore the previous focus or focus the web view. PageUserData* userData = static_cast( webView->GetUserData()); if (userData != NULL && userData->FocusedView() != NULL) @@ -1247,8 +1283,53 @@ BrowserWindow::_CreateBookmark() } BNodeInfo nodeInfo(&bookmarkFile); - if (status == B_OK) + if (status == B_OK) { status = nodeInfo.SetType("application/x-vnd.Be-bookmark"); + if (status == B_OK) { + PageUserData* userData = static_cast( + webView->GetUserData()); + if (userData != NULL && userData->PageIcon() != NULL) { + BBitmap miniIcon(BRect(0, 0, 15, 15), B_BITMAP_NO_SERVER_LINK, + B_CMAP8); + status_t ret = miniIcon.ImportBits(userData->PageIcon()); + if (ret == B_OK) + ret = nodeInfo.SetIcon(&miniIcon, B_MINI_ICON); + if (ret != B_OK) { + fprintf(stderr, "Failed to store mini icon for bookmark: " + "%s\n", strerror(ret)); + } + BBitmap largeIcon(BRect(0, 0, 31, 31), B_BITMAP_NO_SERVER_LINK, + B_CMAP8); + // TODO: Store 32x32 favicon which is often provided by sites. + const uint8* src = (const uint8*)miniIcon.Bits(); + uint32 srcBPR = miniIcon.BytesPerRow(); + uint8* dst = (uint8*)largeIcon.Bits(); + uint32 dstBPR = largeIcon.BytesPerRow(); + for (uint32 y = 0; y < 16; y++) { + const uint8* s = src; + uint8* d = dst; + for (uint32 x = 0; x < 16; x++) { + *d++ = *s; + *d++ = *s++; + } + dst += dstBPR; + s = src; + for (uint32 x = 0; x < 16; x++) { + *d++ = *s; + *d++ = *s++; + } + dst += dstBPR; + src += srcBPR; + } + if (ret == B_OK) + ret = nodeInfo.SetIcon(&largeIcon, B_LARGE_ICON); + if (ret != B_OK) { + fprintf(stderr, "Failed to store large icon for bookmark: " + "%s\n", strerror(ret)); + } + } + } + } if (status != B_OK) { BString message("There was an error creating the bookmark " @@ -1348,6 +1429,23 @@ BrowserWindow::_AddBookmarkURLsRecursively(BDirectory& directory, } +void +BrowserWindow::_SetPageIcon(BWebView* view, const BBitmap* icon) +{ + PageUserData* userData = static_cast(view->GetUserData()); + if (userData == NULL) { + userData = new(std::nothrow) PageUserData(NULL); + if (userData == NULL) + return; + view->SetUserData(userData); + } + // The PageUserData makes a copy of the icon, which we pass on to + // the TabManager for display in the respective tab. + userData->SetPageIcon(icon); + fTabManager->SetTabIcon(view, userData->PageIcon()); +} + + static void addItemToMenuOrSubmenu(BMenu* menu, BMenuItem* newItem) { diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 31886fa045..9f3937257b 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -150,6 +150,9 @@ private: BMessage* message, uint32& addedCount) const; + void _SetPageIcon(BWebView* view, + const BBitmap* icon); + void _UpdateHistoryMenu(); void _UpdateClipboardItems(); From 65cc5e49ee22e22dae9204db37a33ab636f39bf3 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 30 Apr 2010 15:08:05 +0000 Subject: [PATCH 250/349] The favicon is now also displayed in the URL input view. Mostly because one is used to it, but also when only one page is open and tabs are not displayed as per the user settings, the favicon would then not be visible. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@465 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 12 +++- src/apps/webpositive/URLInputGroup.cpp | 94 ++++++++++++++++++++++++-- src/apps/webpositive/URLInputGroup.h | 4 ++ 3 files changed, 103 insertions(+), 7 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 9699ca2bd7..c5f9ce96e4 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1174,8 +1174,14 @@ BrowserWindow::_TabChanged(int32 index) // Restore the previous focus or focus the web view. PageUserData* userData = static_cast( webView->GetUserData()); - if (userData != NULL && userData->FocusedView() != NULL) - userData->FocusedView()->MakeFocus(true); + BView* focusedView = NULL; + if (userData != NULL) { + focusedView = userData->FocusedView(); + fURLInputGroup->SetPageIcon(userData->PageIcon()); + } + + if (focusedView != NULL) + focusedView->MakeFocus(true); else webView->MakeFocus(true); @@ -1443,6 +1449,8 @@ BrowserWindow::_SetPageIcon(BWebView* view, const BBitmap* icon) // the TabManager for display in the respective tab. userData->SetPageIcon(icon); fTabManager->SetTabIcon(view, userData->PageIcon()); + if (view == CurrentWebView()) + fURLInputGroup->SetPageIcon(icon); } diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index 6fb51e498c..4e252855b3 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -128,7 +128,7 @@ private: // #pragma mark - URLTextView -static const float kHorizontalTextRectInset = 3.0; +static const float kHorizontalTextRectInset = 4.0; class URLInputGroup::URLTextView : public BTextView { @@ -505,9 +505,14 @@ public: SetHighColor(0, 0, 0, 120); } - BPoint bitmapLocation(kFrameInset, kFrameInset); - if (Value() == B_CONTROL_ON) - bitmapLocation += BPoint(1, 1); + if (fBitmap == NULL) + return; + BRect bitmapBounds(fBitmap->Bounds()); + BPoint bitmapLocation( + floorf((bounds.left + bounds.right + - (bitmapBounds.left + bitmapBounds.right)) / 2 + 0.5f), + floorf((bounds.top + bounds.bottom + - (bitmapBounds.top + bitmapBounds.bottom)) / 2 + 0.5f)); DrawBitmap(fBitmap, bitmapLocation); } @@ -517,6 +522,76 @@ private: }; +// #pragma mark - IconView + + +class URLInputGroup::PageIconView : public BView { +public: + PageIconView() + : + BView("page icon view", B_WILL_DRAW), + fIcon(NULL) + { + SetDrawingMode(B_OP_OVER); + } + + ~PageIconView() + { + delete fIcon; + } + + virtual void Draw(BRect updateRect) + { + if (fIcon == NULL) + return; + + BRect bounds(Bounds()); + BRect iconBounds(fIcon->Bounds()); + BPoint iconPos( + floorf((bounds.left + bounds.right + - (iconBounds.left + iconBounds.right)) / 2 + 0.5f), + floorf((bounds.top + bounds.bottom + - (iconBounds.top + iconBounds.bottom)) / 2 + 0.5f)); + DrawBitmap(fIcon, iconPos); + } + + virtual BSize MinSize() + { + if (fIcon != NULL) { + return BSize(fIcon->Bounds().Width() + 3, + fIcon->Bounds().Height() + 3); + } + return BSize(0, 0); + } + + virtual BSize MaxSize() + { + return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED); + } + + virtual BSize PreferredSize() + { + return MinSize(); + } + + void SetIcon(const BBitmap* icon) + { + if (icon == NULL && fIcon == NULL) + return; + delete fIcon; + if (icon) + fIcon = new BBitmap(icon); + else + fIcon = NULL; + Invalidate(); + InvalidateLayout(); + } + +private: + BBitmap* fIcon; +}; + + // #pragma mark - URLInputGroup @@ -527,6 +602,9 @@ URLInputGroup::URLInputGroup(BMessage* goMessage) { GroupLayout()->SetInsets(2, 2, 2, 2); + fIconView = new PageIconView(); + GroupLayout()->AddView(fIconView, 0.0f); + fTextView = new URLTextView(this); AddChild(fTextView); @@ -537,7 +615,7 @@ URLInputGroup::URLInputGroup(BMessage* goMessage) // fGoButton = new BitmapButton("kActionGo", NULL); fGoButton = new BitmapButton(kGoBitmapBits, kGoBitmapWidth, kGoBitmapHeight, kGoBitmapFormat, goMessage); - GroupLayout()->AddView(fGoButton, 0.0); + GroupLayout()->AddView(fGoButton, 0.0f); SetFlags(Flags() | B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE); SetLowColor(ViewColor()); @@ -622,3 +700,9 @@ URLInputGroup::GoButton() const } +void +URLInputGroup::SetPageIcon(const BBitmap* icon) +{ + fIconView->SetIcon(icon); +} + diff --git a/src/apps/webpositive/URLInputGroup.h b/src/apps/webpositive/URLInputGroup.h index 105b76d932..d71f713ca7 100644 --- a/src/apps/webpositive/URLInputGroup.h +++ b/src/apps/webpositive/URLInputGroup.h @@ -27,9 +27,13 @@ public: BButton* GoButton() const; + void SetPageIcon(const BBitmap* icon); + private: + class PageIconView; class URLTextView; + PageIconView* fIconView; URLTextView* fTextView; BButton* fGoButton; bool fWindowActive; From a4c1f6783dbe0ebd25a5699c648a26794574c9e0 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 30 Apr 2010 15:40:36 +0000 Subject: [PATCH 251/349] * After a recent commit, _TabChanged() was accessing "webView" when it really meant CurrentWebView(). This also fixed the focus restoration, since it remembered the current focus for the wrong web view when the user data was already stored. * Refactored _TabChanged() so that this code is now executed in the now virtual SetCurrentWebView(), which makes the features also work for new tabs. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@466 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 107 +++++++++++++++---------- src/apps/webpositive/BrowserWindow.h | 2 + 2 files changed, 67 insertions(+), 42 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index c5f9ce96e4..d1ee857392 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -750,9 +750,9 @@ BrowserWindow::QuitRequested() // Iterate over all tabs to delete all BWebViews. // Do this here, so WebKit tear down happens earlier. + SetCurrentWebView(NULL); while (fTabManager->CountTabs() > 0) _ShutdownTab(0); - SetCurrentWebView(NULL); BMessage message(WINDOW_CLOSED); message.AddRect("window frame", Frame()); @@ -769,6 +769,69 @@ BrowserWindow::MenusBeginning() } +static bool +viewIsChild(const BView* parent, const BView* view) +{ + if (parent == view) + return true; + + int32 count = parent->CountChildren(); + for (int32 i = 0; i < count; i++) { + BView* child = parent->ChildAt(i); + if (viewIsChild(child, view)) + return true; + } + return false; +} + + +void +BrowserWindow::SetCurrentWebView(BWebView* webView) +{ + if (webView == CurrentWebView()) + return; + + if (CurrentWebView() != NULL) { + // Remember the currently focused view before switching tabs, + // so that we can revert the focus when switching back to this tab + // later. + PageUserData* userData = static_cast( + CurrentWebView()->GetUserData()); + if (userData) + userData->SetFocusedView(CurrentFocus()); + else + CurrentWebView()->SetUserData(new PageUserData(CurrentFocus())); + } + + BWebWindow::SetCurrentWebView(webView); + + if (webView != NULL) { + _UpdateTitle(webView->MainFrameTitle()); + + // Restore the previous focus or focus the web view. + PageUserData* userData = static_cast( + webView->GetUserData()); + BView* focusedView = NULL; + if (userData != NULL) { + focusedView = userData->FocusedView(); + fURLInputGroup->SetPageIcon(userData->PageIcon()); + } + + if (focusedView != NULL + && viewIsChild(GetLayout()->View(), focusedView)) { + focusedView->MakeFocus(true); + } else + webView->MakeFocus(true); + + fURLInputGroup->SetText(webView->MainFrameURL()); + // Trigger update of the interface to the new page, by requesting + // to resend all notifications. + webView->WebPage()->ResendNotifications(); + } else + _UpdateTitle(""); +} + + void BrowserWindow::CreateNewTab(const BString& _url, bool select, BWebView* webView) { @@ -1150,47 +1213,7 @@ BrowserWindow::_ShutdownTab(int32 index) void BrowserWindow::_TabChanged(int32 index) { - BWebView* webView = dynamic_cast(fTabManager->ViewForTab(index)); - if (webView == CurrentWebView()) - return; - - if (CurrentWebView() != NULL) { - // Remember the currently focused view before switching tabs, - // so that we can revert the focus when switching back to this tab - // later. - PageUserData* userData = static_cast( - webView->GetUserData()); - if (userData) - userData->SetFocusedView(CurrentFocus()); - else - CurrentWebView()->SetUserData(new PageUserData(CurrentFocus())); - } - - SetCurrentWebView(webView); - - if (webView != NULL) { - _UpdateTitle(webView->MainFrameTitle()); - - // Restore the previous focus or focus the web view. - PageUserData* userData = static_cast( - webView->GetUserData()); - BView* focusedView = NULL; - if (userData != NULL) { - focusedView = userData->FocusedView(); - fURLInputGroup->SetPageIcon(userData->PageIcon()); - } - - if (focusedView != NULL) - focusedView->MakeFocus(true); - else - webView->MakeFocus(true); - - fURLInputGroup->SetText(webView->MainFrameURL()); - // Trigger update of the interface to the new page, by requesting - // to resend all notifications. - webView->WebPage()->ResendNotifications(); - } else - _UpdateTitle(""); + SetCurrentWebView(dynamic_cast(fTabManager->ViewForTab(index))); } diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 9f3937257b..0e2769db49 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -89,6 +89,8 @@ public: virtual bool QuitRequested(); virtual void MenusBeginning(); + virtual void SetCurrentWebView(BWebView* view); + void CreateNewTab(const BString& url, bool select, BWebView* webView = 0); From 5913d4a98b5c55e91bb9327e89d748747e439ffd Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 30 Apr 2010 16:33:17 +0000 Subject: [PATCH 252/349] * Invalidate layout only when necessary. * Icon view needs to update completely on resize. -> Fixes graphics glitch when switching between icon and no icon. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@467 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/URLInputGroup.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index 4e252855b3..40805943fc 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -529,7 +529,7 @@ class URLInputGroup::PageIconView : public BView { public: PageIconView() : - BView("page icon view", B_WILL_DRAW), + BView("page icon view", B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE), fIcon(NULL) { SetDrawingMode(B_OP_OVER); @@ -578,13 +578,14 @@ public: { if (icon == NULL && fIcon == NULL) return; + if (!(fIcon != NULL && icon != NULL)) + InvalidateLayout(); delete fIcon; if (icon) fIcon = new BBitmap(icon); else fIcon = NULL; Invalidate(); - InvalidateLayout(); } private: From 99006ca0ae2b9ef0e9d33ce69bf97894c6e86f3d Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 30 Apr 2010 17:49:21 +0000 Subject: [PATCH 253/349] * Added page for proxy server configuration to the Settings window. * Added necessary wiring in BWebSettings for proxy server configuration. Actual proxy server usage untested, feedback welcome. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@468 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/SettingsKeys.cpp | 3 + src/apps/webpositive/SettingsKeys.h | 4 + src/apps/webpositive/SettingsWindow.cpp | 112 ++++++++++++++++++++++-- src/apps/webpositive/SettingsWindow.h | 9 +- 4 files changed, 119 insertions(+), 9 deletions(-) diff --git a/src/apps/webpositive/SettingsKeys.cpp b/src/apps/webpositive/SettingsKeys.cpp index 5df66469ca..d525ba6aeb 100644 --- a/src/apps/webpositive/SettingsKeys.cpp +++ b/src/apps/webpositive/SettingsKeys.cpp @@ -42,3 +42,6 @@ const char* kDefaultStartPageURL = "file:///boot/system/documentation/welcome/welcome_en.html"; const char* kDefaultSearchPageURL = "http://www.google.com"; +const char* kSettingsKeyUseProxy = "use http proxy"; +const char* kSettingsKeyProxyAddress = "http proxy address"; +const char* kSettingsKeyProxyPort = "http proxy port"; diff --git a/src/apps/webpositive/SettingsKeys.h b/src/apps/webpositive/SettingsKeys.h index 112e903e81..6be0e5e15c 100644 --- a/src/apps/webpositive/SettingsKeys.h +++ b/src/apps/webpositive/SettingsKeys.h @@ -42,4 +42,8 @@ extern const char* kDefaultDownloadPath; extern const char* kDefaultStartPageURL; extern const char* kDefaultSearchPageURL; +extern const char* kSettingsKeyUseProxy; +extern const char* kSettingsKeyProxyAddress; +extern const char* kSettingsKeyProxyPort; + #endif // SETTINGS_KEYS_H diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index c5a5577800..b9fa66136a 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -78,6 +78,10 @@ enum { MSG_STANDARD_FONT_SIZE_SELECTED = 'sfss', MSG_FIXED_FONT_SIZE_SELECTED = 'ffss', + + MSG_USE_PROXY_CHANGED = 'upsc', + MSG_PROXY_ADDRESS_CHANGED = 'psac', + MSG_PROXY_PORT_CHANGED = 'pspc', }; static const int32 kDefaultFontSize = 14; @@ -112,6 +116,7 @@ SettingsWindow::SettingsWindow(BRect frame, SettingsMessage* settings) tabView->AddTab(_CreateGeneralPage(spacing)); tabView->AddTab(_CreateFontsPage(spacing)); + tabView->AddTab(_CreateProxyPage(spacing)); _SetupFontSelectionView(fStandardFontView, new BMessage(MSG_STANDARD_FONT_CHANGED)); @@ -172,14 +177,14 @@ SettingsWindow::MessageReceived(BMessage* message) fStandardFontView->SetSize(size); fSerifFontView->SetSize(size); fSansSerifFontView->SetSize(size); - _ValidateButtonsEnabled(); + _ValidateControlsEnabledStatus(); break; } case MSG_FIXED_FONT_SIZE_SELECTED: { int32 size = _SizesMenuValue(fFixedSizesMenu->Menu()); fFixedFontView->SetSize(size); - _ValidateButtonsEnabled(); + _ValidateControlsEnabledStatus(); break; } @@ -194,8 +199,11 @@ SettingsWindow::MessageReceived(BMessage* message) case MSG_SERIF_FONT_CHANGED: case MSG_SANS_SERIF_FONT_CHANGED: case MSG_FIXED_FONT_CHANGED: + case MSG_USE_PROXY_CHANGED: + case MSG_PROXY_ADDRESS_CHANGED: + case MSG_PROXY_PORT_CHANGED: // TODO: Some settings could change live, some others not? - _ValidateButtonsEnabled(); + _ValidateControlsEnabledStatus(); break; default: @@ -329,7 +337,7 @@ SettingsWindow::_CreateGeneralPage(float spacing) .SetInsets(spacing, spacing, spacing, spacing) ; - view->SetName("General"); + view->SetName(TR("General")); return view; } @@ -383,7 +391,48 @@ SettingsWindow::_CreateFontsPage(float spacing) .SetInsets(spacing, spacing, spacing, spacing) ; - view->SetName("Fonts"); + view->SetName(TR("Fonts")); + return view; +} + + +BView* +SettingsWindow::_CreateProxyPage(float spacing) +{ + fUseProxyCheckBox = new BCheckBox("use proxy", + TR("Use proxy server to connect to the internet."), + new BMessage(MSG_USE_PROXY_CHANGED)); + fUseProxyCheckBox->SetValue(B_CONTROL_ON); + + fProxyAddressControl = new BTextControl("proxy address", + TR("Proxy server address:"), "", + new BMessage(MSG_PROXY_ADDRESS_CHANGED)); + fProxyAddressControl->SetModificationMessage( + new BMessage(MSG_PROXY_ADDRESS_CHANGED)); + fProxyAddressControl->SetText( + fSettings->GetValue(kSettingsKeyProxyAddress, "")); + + fProxyPortControl = new BTextControl("proxy port", + TR("Proxy server port:"), "", new BMessage(MSG_PROXY_PORT_CHANGED)); + fProxyPortControl->SetModificationMessage( + new BMessage(MSG_PROXY_PORT_CHANGED)); + fProxyPortControl->SetText( + fSettings->GetValue(kSettingsKeyProxyAddress, "")); + + BView* view = BGroupLayoutBuilder(B_VERTICAL, spacing / 2) + .Add(fUseProxyCheckBox) + .Add(BGridLayoutBuilder(spacing / 2, spacing / 2) + .Add(fProxyAddressControl->CreateLabelLayoutItem(), 0, 0) + .Add(fProxyAddressControl->CreateTextViewLayoutItem(), 1, 0) + + .Add(fProxyPortControl->CreateLabelLayoutItem(), 0, 1) + .Add(fProxyPortControl->CreateTextViewLayoutItem(), 1, 1) + ) + .Add(BSpaceLayoutItem::CreateGlue()) + + .SetInsets(spacing, spacing, spacing, spacing) + ; + view->SetName(TR("Proxy server")); return view; } @@ -482,6 +531,16 @@ SettingsWindow::_CanApplySettings() const canApply = canApply || (_SizesMenuValue(fFixedSizesMenu->Menu()) != fSettings->GetValue("fixed font size", kDefaultFontSize)); + // Proxy settings + canApply = canApply || ((fUseProxyCheckBox->Value() == B_CONTROL_ON) + != fSettings->GetValue(kSettingsKeyUseProxy, false)); + + canApply = canApply || (strcmp(fProxyAddressControl->Text(), + fSettings->GetValue(kSettingsKeyProxyAddress, "")) != 0); + + canApply = canApply || (_ProxyPort() + != fSettings->GetValue(kSettingsKeyProxyPort, (uint32)0)); + return canApply; } @@ -516,6 +575,15 @@ SettingsWindow::_ApplySettings() fSettings->SetValue("standard font size", standardFontSize); fSettings->SetValue("fixed font size", fixedFontSize); + // Store proxy settings + + fSettings->SetValue(kSettingsKeyUseProxy, + fUseProxyCheckBox->Value() == B_CONTROL_ON); + fSettings->SetValue(kSettingsKeyProxyAddress, + fProxyAddressControl->Text()); + uint32 proxyPort = _ProxyPort(); + fSettings->SetValue(kSettingsKeyProxyPort, proxyPort); + fSettings->Save(); // Apply settings to default web page settings. @@ -526,12 +594,18 @@ SettingsWindow::_ApplySettings() BWebSettings::Default()->SetDefaultStandardFontSize(standardFontSize); BWebSettings::Default()->SetDefaultFixedFontSize(fixedFontSize); + if (fUseProxyCheckBox->Value() == B_CONTROL_ON) { + BWebSettings::Default()->SetProxyInfo(fProxyAddressControl->Text(), + proxyPort, B_PROXY_TYPE_HTTP, "", ""); + } else + BWebSettings::Default()->SetProxyInfo(); + // This will find all currently instantiated page settings and apply // the default values, unless the page settings have local overrides. BWebSettings::Default()->Apply(); - _ValidateButtonsEnabled(); + _ValidateControlsEnabledStatus(); } @@ -606,12 +680,21 @@ SettingsWindow::_RevertSettings() fFixedFontView->SetFont(fSettings->GetValue("fixed font", *be_fixed_font), defaultFixedFontSize); - _ValidateButtonsEnabled(); + // Proxy settings + fUseProxyCheckBox->SetValue(fSettings->GetValue(kSettingsKeyUseProxy, + false)); + fProxyAddressControl->SetText(fSettings->GetValue(kSettingsKeyProxyAddress, + "")); + text = ""; + text << fSettings->GetValue(kSettingsKeyProxyPort, (uint32)0); + fProxyPortControl->SetText(text.String()); + + _ValidateControlsEnabledStatus(); } void -SettingsWindow::_ValidateButtonsEnabled() +SettingsWindow::_ValidateControlsEnabledStatus() { bool canApply = _CanApplySettings(); fApplyButton->SetEnabled(canApply); @@ -619,6 +702,10 @@ SettingsWindow::_ValidateButtonsEnabled() // Let the Cancel button be enabled always, as another way to close the // window... fCancelButton->SetEnabled(true); + + bool useProxy = fUseProxyCheckBox->Value() == B_CONTROL_ON; + fProxyAddressControl->SetEnabled(useProxy); + fProxyPortControl->SetEnabled(useProxy); } @@ -714,3 +801,12 @@ SettingsWindow::_FindDefaultSerifFont() const } return serifFont; } + + +uint32 +SettingsWindow::_ProxyPort() const +{ + return atoul(fProxyPortControl->Text()); +} + + diff --git a/src/apps/webpositive/SettingsWindow.h b/src/apps/webpositive/SettingsWindow.h index a3b6417ec9..c595632f8e 100644 --- a/src/apps/webpositive/SettingsWindow.h +++ b/src/apps/webpositive/SettingsWindow.h @@ -53,6 +53,7 @@ public: private: BView* _CreateGeneralPage(float spacing); BView* _CreateFontsPage(float spacing); + BView* _CreateProxyPage(float spacing); void _BuildSizesMenu(BMenu* menu, uint32 messageWhat); void _SetupFontSelectionView( @@ -62,7 +63,7 @@ private: bool _CanApplySettings() const; void _ApplySettings(); void _RevertSettings(); - void _ValidateButtonsEnabled(); + void _ValidateControlsEnabledStatus(); uint32 _NewWindowPolicy() const; uint32 _NewTabPolicy() const; @@ -73,6 +74,8 @@ private: BFont _FindDefaultSerifFont() const; + uint32 _ProxyPort() const; + private: SettingsMessage* fSettings; @@ -99,6 +102,10 @@ private: FontSelectionView* fSansSerifFontView; FontSelectionView* fFixedFontView; + BCheckBox* fUseProxyCheckBox; + BTextControl* fProxyAddressControl; + BTextControl* fProxyPortControl; + BButton* fApplyButton; BButton* fCancelButton; BButton* fRevertButton; From 464aca712fec2d1d0db5200721e5acc0529e6a0b Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 1 May 2010 18:07:40 +0000 Subject: [PATCH 254/349] Fix a bug with closing tabs by pressing the tertiary mouse button. fMouseDown would be true, but the fLastMouseEventTab would have been reset when removing the tab. Rather than fixing this problem, behave the same as Firefox and close the tab on mouse up (when the mouse is still over the tab, which allows the user a way back out). Avoids the above problem as a side effect. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@469 94f232f2-1747-11df-bad5-a5bfde151594 --- .../webpositive/tabview/TabContainerView.cpp | 2 +- src/apps/webpositive/tabview/TabManager.cpp | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/apps/webpositive/tabview/TabContainerView.cpp b/src/apps/webpositive/tabview/TabContainerView.cpp index a4c26ddb2d..6f502b2850 100644 --- a/src/apps/webpositive/tabview/TabContainerView.cpp +++ b/src/apps/webpositive/tabview/TabContainerView.cpp @@ -440,7 +440,7 @@ TabContainerView::_MouseMoved(BPoint where, uint32 _transit, return; } - if (fLastMouseEventTab && fLastMouseEventTab == tab) + if (fLastMouseEventTab != NULL && fLastMouseEventTab == tab) fLastMouseEventTab->MouseMoved(where, B_INSIDE_VIEW, dragMessage); else { if (fLastMouseEventTab) diff --git a/src/apps/webpositive/tabview/TabManager.cpp b/src/apps/webpositive/tabview/TabManager.cpp index 814496e582..bdde273b04 100644 --- a/src/apps/webpositive/tabview/TabManager.cpp +++ b/src/apps/webpositive/tabview/TabManager.cpp @@ -366,6 +366,7 @@ private: TabManagerController* fController; bool fOverCloseRect; bool fClicked; + bool fCloseOnMouseUp; }; @@ -375,7 +376,8 @@ WebTabView::WebTabView(TabManagerController* controller) fIcon(NULL), fController(controller), fOverCloseRect(false), - fClicked(false) + fClicked(false), + fCloseOnMouseUp(false) { } @@ -449,7 +451,7 @@ void WebTabView::MouseDown(BPoint where, uint32 buttons) { if (buttons & B_TERTIARY_MOUSE_BUTTON) { - fController->CloseTab(ContainerView()->IndexOf(this)); + fCloseOnMouseUp = true; return; } @@ -467,12 +469,20 @@ WebTabView::MouseDown(BPoint where, uint32 buttons) void WebTabView::MouseUp(BPoint where) { - if (!fClicked) { + if (!fClicked && !fCloseOnMouseUp) { TabView::MouseUp(where); return; } + if (fCloseOnMouseUp && Frame().Contains(where)) { + fCloseOnMouseUp = false; + fController->CloseTab(ContainerView()->IndexOf(this)); + // Probably this object is toast now, better return here. + return; + } + fClicked = false; + fCloseOnMouseUp = false; if (_CloseRectFrame(Frame()).Contains(where)) fController->CloseTab(ContainerView()->IndexOf(this)); From 06ea485752153d9dd4bd8d02e617b28758dd7229 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 1 May 2010 19:20:53 +0000 Subject: [PATCH 255/349] Add a context menu to the download progress view. It allows to open the containing folder (and selects the file in it), and to copy the download URL to the clipboard. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@470 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadProgressView.cpp | 112 +++++++++++++++++- src/apps/webpositive/DownloadProgressView.h | 2 + 2 files changed, 110 insertions(+), 4 deletions(-) diff --git a/src/apps/webpositive/DownloadProgressView.cpp b/src/apps/webpositive/DownloadProgressView.cpp index ddee6317c5..54ca1797e6 100644 --- a/src/apps/webpositive/DownloadProgressView.cpp +++ b/src/apps/webpositive/DownloadProgressView.cpp @@ -32,12 +32,15 @@ #include #include #include +#include #include #include #include #include +#include #include #include +#include #include #include #include @@ -49,10 +52,12 @@ enum { - OPEN_DOWNLOAD = 'opdn', - RESTART_DOWNLOAD = 'rsdn', - CANCEL_DOWNLOAD = 'cndn', - REMOVE_DOWNLOAD = 'rmdn', + OPEN_DOWNLOAD = 'opdn', + RESTART_DOWNLOAD = 'rsdn', + CANCEL_DOWNLOAD = 'cndn', + REMOVE_DOWNLOAD = 'rmdn', + COPY_URL_TO_CLIPBOARD = 'curl', + OPEN_CONTAINING_FOLDER = 'opfd', }; const bigtime_t kMaxUpdateInterval = 100000LL; @@ -203,6 +208,10 @@ DownloadProgressView::DownloadProgressView(const BMessage* archive) bool DownloadProgressView::Init(BMessage* archive) { + // We need to receive mouse events even for the areas of children views, + // so we can pop up a context menu. + SetEventMask(B_POINTER_EVENTS); + fCurrentSize = 0; fExpectedSize = 0; fLastUpdateTime = 0; @@ -330,6 +339,35 @@ DownloadProgressView::AllAttached() } +void +DownloadProgressView::MouseDown(BPoint where) +{ + if (!Bounds().Contains(where)) + return; + + int32 buttons; + if (Window()->CurrentMessage()->FindInt32("buttons", &buttons) != B_OK) + return; + + if ((buttons & B_SECONDARY_MOUSE_BUTTON) == 0) + return; + + where = ConvertToScreen(where) + BPoint(2, 2); + + BPopUpMenu* contextMenu = new BPopUpMenu("download context"); + BMenuItem* copyURL = new BMenuItem("Copy URL to clipboard", + new BMessage(COPY_URL_TO_CLIPBOARD)); + copyURL->SetEnabled(fURL.Length() > 0); + contextMenu->AddItem(copyURL); + BMenuItem* openFolder = new BMenuItem("Open containing folder", + new BMessage(OPEN_CONTAINING_FOLDER)); + contextMenu->AddItem(openFolder); + + contextMenu->SetTargetForItems(this); + contextMenu->Go(where, true, true, true); +} + + void DownloadProgressView::Draw(BRect updateRect) { @@ -477,6 +515,71 @@ DownloadProgressView::MessageReceived(BMessage* message) } break; } + + // Context menu messages + case COPY_URL_TO_CLIPBOARD: + if (be_clipboard->Lock()) { + BMessage* data = be_clipboard->Data(); + if (data != NULL) { + be_clipboard->Clear(); + data->AddData("text/plain", B_MIME_TYPE, fURL.String(), + fURL.Length()); + } + be_clipboard->Commit(); + be_clipboard->Unlock(); + } + break; + case OPEN_CONTAINING_FOLDER: + if (fPath.InitCheck() == B_OK) { + BPath containingFolder; + if (fPath.GetParent(&containingFolder) != B_OK) + break; + BEntry entry(containingFolder.Path()); + if (!entry.Exists()) + break; + entry_ref ref; + if (entry.GetRef(&ref) != B_OK) + break; + be_roster->Launch(&ref); + + // Use Tracker scripting and select the download pose + // in the window. + // TODO: We should somehow get the window that just openend. + // Using the name like this is broken when there are multiple + // windows open with this name. Also Tracker does not scroll + // to this entry. + BString windowName = ref.name; + BString fullWindowName = containingFolder.Path(); + + BMessenger trackerMessenger("application/x-vnd.Be-TRAK"); + if (trackerMessenger.IsValid() + && get_ref_for_path(fPath.Path(), &ref) == B_OK) { + // We need to wait a bit until the folder is open. + // TODO: This is also too fragile... we should be able + // to wait for the roster message. + snooze(250000); + int32 tries = 2; + while (tries > 0) { + BMessage selectionCommand(B_SET_PROPERTY); + selectionCommand.AddSpecifier("Selection"); + selectionCommand.AddSpecifier("Poses"); + selectionCommand.AddSpecifier("Window", + windowName.String()); + selectionCommand.AddRef("data", &ref); + BMessage reply; + trackerMessenger.SendMessage(&selectionCommand, &reply); + int32 error; + if (reply.FindInt32("error", &error) != B_OK + || error == B_OK) { + break; + } + windowName = fullWindowName; + tries--; + } + } + } + break; + default: BGroupView::MessageReceived(message); } @@ -534,6 +637,7 @@ DownloadProgressView::DownloadCanceled() fBottomButton->SetMessage(new BMessage(REMOVE_DOWNLOAD)); fBottomButton->SetEnabled(true); fInfoView->SetText(""); + fPath.Unset(); } diff --git a/src/apps/webpositive/DownloadProgressView.h b/src/apps/webpositive/DownloadProgressView.h index 4c4ae7e48f..256245442d 100644 --- a/src/apps/webpositive/DownloadProgressView.h +++ b/src/apps/webpositive/DownloadProgressView.h @@ -57,6 +57,8 @@ public: virtual void DetachedFromWindow(); virtual void AllAttached(); + virtual void MouseDown(BPoint where); + virtual void Draw(BRect updateRect); virtual void MessageReceived(BMessage* message); From ef4f1b553391ba664a1ef6a287b1afc6039f4f61 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 3 May 2010 11:02:05 +0000 Subject: [PATCH 256/349] Since fLastMouseEventTab is never updated in _MouseMoved() while fMouseDown is true, we need to recheck it in MouseUp(). This would fix the problem with the middle mouse button click to close tabs if we didn't move closing to the mouse up event, and it also fixes other situations, like clicking on one tab, moving the mouse over another tab's close button, releasing the mouse and clicking again without moving it inbetween. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@471 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/tabview/TabContainerView.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/apps/webpositive/tabview/TabContainerView.cpp b/src/apps/webpositive/tabview/TabContainerView.cpp index 6f502b2850..70badaf3d1 100644 --- a/src/apps/webpositive/tabview/TabContainerView.cpp +++ b/src/apps/webpositive/tabview/TabContainerView.cpp @@ -151,9 +151,16 @@ TabContainerView::MouseUp(BPoint where) if (fLastMouseEventTab) fLastMouseEventTab->MouseUp(where); else if (fClickCount > 1) { + // NOTE: fClickCount is >= 1 only if the first click was outside + // any tab. So even if fLastMouseEventTab has been reset to NULL + // because this tab was removed during mouse down, we wouldn't + // run the "outside tabs" code below. fClickCount = 0; fController->DoubleClickOutsideTabs(); } + // Always check the tab under the mouse again, since we don't update + // it with fMouseDown == true. + _SendFakeMouseMoved(); } From b9d4b634f6406790a909a0a1c4a3770e3d8620fb Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 3 May 2010 11:45:22 +0000 Subject: [PATCH 257/349] Use BStatusBar properly. The text in a BStatusBar is composed of four parts. Label and trailing label are only specified in the constructor or in Reset(). By using SetText(), we were modifying another part of the text, while we meant to set the label. This fixes updates on node monitor messages. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@472 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadProgressView.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/DownloadProgressView.cpp b/src/apps/webpositive/DownloadProgressView.cpp index 54ca1797e6..e7914e8736 100644 --- a/src/apps/webpositive/DownloadProgressView.cpp +++ b/src/apps/webpositive/DownloadProgressView.cpp @@ -501,7 +501,9 @@ DownloadProgressView::MessageReceived(BMessage* message) } } - fStatusBar->SetText(name); + float value = fStatusBar->CurrentValue(); + fStatusBar->Reset(name); + fStatusBar->SetTo(value); Window()->PostMessage(SAVE_SETTINGS); break; } From d5c4471790572a33a47d80317f523aac096c216e Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 3 May 2010 12:20:37 +0000 Subject: [PATCH 258/349] * Fixed double click outside tabs to only be recognized when the first click was outside as well. * Single tertiary click outside tabs opens new tab on mouse up. * Reset fClickCount always when the click was inside a tab. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@474 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/tabview/TabContainerView.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/apps/webpositive/tabview/TabContainerView.cpp b/src/apps/webpositive/tabview/TabContainerView.cpp index 70badaf3d1..fc0f41b8bc 100644 --- a/src/apps/webpositive/tabview/TabContainerView.cpp +++ b/src/apps/webpositive/tabview/TabContainerView.cpp @@ -136,8 +136,11 @@ TabContainerView::MouseDown(BPoint where) if (fLastMouseEventTab) fLastMouseEventTab->MouseDown(where, buttons); else { - if (clicks > 1) - fClickCount++; + if ((buttons & B_TERTIARY_MOUSE_BUTTON) != 0) { + // Middle click outside tabs should always open a new tab. + fClickCount = 2; + } else if (clicks > 1) + fClickCount = fClickCount++; else fClickCount = 1; } @@ -148,15 +151,16 @@ void TabContainerView::MouseUp(BPoint where) { fMouseDown = false; - if (fLastMouseEventTab) + if (fLastMouseEventTab) { fLastMouseEventTab->MouseUp(where); - else if (fClickCount > 1) { + fClickCount = 0; + } else if (fClickCount > 1) { // NOTE: fClickCount is >= 1 only if the first click was outside // any tab. So even if fLastMouseEventTab has been reset to NULL // because this tab was removed during mouse down, we wouldn't // run the "outside tabs" code below. - fClickCount = 0; fController->DoubleClickOutsideTabs(); + fClickCount = 0; } // Always check the tab under the mouse again, since we don't update // it with fMouseDown == true. From 1a2246ccf975d3f45c6ee4e9606ca80b843be60d Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 3 May 2010 13:09:54 +0000 Subject: [PATCH 259/349] Avoid loading the start page before loading the requested URL in new windows by passing the url to the constructor already. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@476 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 8 ++++---- src/apps/webpositive/BrowserWindow.cpp | 6 +++--- src/apps/webpositive/BrowserWindow.h | 1 + 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index e9976d0c5d..b6f1cc349e 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -169,7 +169,8 @@ BrowserApp::ReadyToRun() fLaunchRefsMessage = 0; } if (pagesCreated == 0) { - BrowserWindow* window = new BrowserWindow(fLastWindowFrame, fSettings); + BrowserWindow* window = new BrowserWindow(fLastWindowFrame, fSettings, + ""); window->Show(); } PostMessage(PRELOAD_BROWSING_HISTORY); @@ -347,10 +348,9 @@ BrowserApp::_CreateNewWindow(const BString& url) if (!BScreen().Frame().Contains(fLastWindowFrame)) fLastWindowFrame.OffsetTo(50, 50); - BrowserWindow* window = new BrowserWindow(fLastWindowFrame, fSettings); + BrowserWindow* window = new BrowserWindow(fLastWindowFrame, fSettings, + url); window->Show(); - if (url.Length()) - window->CurrentWebView()->LoadURL(url.String()); } diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index d1ee857392..d1835a7544 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -183,7 +183,7 @@ private: BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, - ToolbarPolicy toolbarPolicy, BWebView* webView) + const BString& url, ToolbarPolicy toolbarPolicy, BWebView* webView) : BWebWindow(frame, kApplicationName, B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, @@ -391,7 +391,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fFindGroup = layoutItemFor(findGroup); fStatusGroup = layoutItemFor(statusGroup); - CreateNewTab("", true, webView); + CreateNewTab(url, true, webView); fFindGroup->SetVisible(false); @@ -911,7 +911,7 @@ BrowserWindow::NewPageCreated(BWebView* view, BRect windowFrame, { if (windowFrame.IsValid()) { BrowserWindow* window = new BrowserWindow(windowFrame, fAppSettings, - DoNotHaveToolbar, view); + BString(), DoNotHaveToolbar, view); window->Show(); } else CreateNewTab(BString(), activate, view); diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 0e2769db49..1dd2951410 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -79,6 +79,7 @@ class BrowserWindow : public BWebWindow { public: BrowserWindow(BRect frame, SettingsMessage* appSettings, + const BString& url, ToolbarPolicy = HaveToolbar, BWebView* webView = NULL); virtual ~BrowserWindow(); From ea992272d768de9784c9154976fe984d1d408f94 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 3 May 2010 16:52:02 +0000 Subject: [PATCH 260/349] Added a few utility classes from Haiku. To be removed when WebPositive moves into Haiku. Added new file HashKeys.h which implements commonly used HashKey classes. Additionally to the ones found in HashMap.h, it has a HashKeyString class, which wraps a BString and provides the GetHashCode() method. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@477 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/support/AutoLocker.h | 178 +++++++ src/apps/webpositive/support/HashKeys.h | 124 +++++ src/apps/webpositive/support/HashMap.h | 481 +++++++++++++++++ src/apps/webpositive/support/HashSet.h | 342 ++++++++++++ src/apps/webpositive/support/OpenHashTable.h | 514 +++++++++++++++++++ 5 files changed, 1639 insertions(+) create mode 100644 src/apps/webpositive/support/AutoLocker.h create mode 100644 src/apps/webpositive/support/HashKeys.h create mode 100644 src/apps/webpositive/support/HashMap.h create mode 100644 src/apps/webpositive/support/HashSet.h create mode 100644 src/apps/webpositive/support/OpenHashTable.h diff --git a/src/apps/webpositive/support/AutoLocker.h b/src/apps/webpositive/support/AutoLocker.h new file mode 100644 index 0000000000..9baa7aa7a5 --- /dev/null +++ b/src/apps/webpositive/support/AutoLocker.h @@ -0,0 +1,178 @@ +/* + * Copyright 2005-2007, Ingo Weinhold, bonefish@users.sf.net. + * All rights reserved. Distributed under the terms of the MIT License. + */ +#ifndef _AUTO_LOCKER_H +#define _AUTO_LOCKER_H + + +#include + + +namespace BPrivate { + +// AutoLockerStandardLocking +template +class AutoLockerStandardLocking { +public: + inline bool Lock(Lockable* lockable) + { + return lockable->Lock(); + } + + inline void Unlock(Lockable* lockable) + { + lockable->Unlock(); + } +}; + +// AutoLockerReadLocking +template +class AutoLockerReadLocking { +public: + inline bool Lock(Lockable* lockable) + { + return lockable->ReadLock(); + } + + inline void Unlock(Lockable* lockable) + { + lockable->ReadUnlock(); + } +}; + +// AutoLockerWriteLocking +template +class AutoLockerWriteLocking { +public: + inline bool Lock(Lockable* lockable) + { + return lockable->WriteLock(); + } + + inline void Unlock(Lockable* lockable) + { + lockable->WriteUnlock(); + } +}; + +// AutoLocker +template > +class AutoLocker { +private: + typedef AutoLocker ThisClass; +public: + inline AutoLocker() + : + fLockable(NULL), + fLocked(false) + { + } + + inline AutoLocker(const Locking& locking) + : + fLockable(NULL), + fLocking(locking), + fLocked(false) + { + } + + inline AutoLocker(Lockable* lockable, bool alreadyLocked = false, + bool lockIfNotLocked = true) + : + fLockable(lockable), + fLocked(fLockable && alreadyLocked) + { + if (!alreadyLocked && lockIfNotLocked) + Lock(); + } + + inline AutoLocker(Lockable& lockable, bool alreadyLocked = false, + bool lockIfNotLocked = true) + : + fLockable(&lockable), + fLocked(fLockable && alreadyLocked) + { + if (!alreadyLocked && lockIfNotLocked) + Lock(); + } + + inline ~AutoLocker() + { + Unlock(); + } + + inline void SetTo(Lockable* lockable, bool alreadyLocked, + bool lockIfNotLocked = true) + { + Unlock(); + fLockable = lockable; + fLocked = (lockable && alreadyLocked); + if (!alreadyLocked && lockIfNotLocked) + Lock(); + } + + inline void SetTo(Lockable& lockable, bool alreadyLocked, + bool lockIfNotLocked = true) + { + SetTo(&lockable, alreadyLocked, lockIfNotLocked); + } + + inline void Unset() + { + Unlock(); + Detach(); + } + + inline bool Lock() + { + if (fLockable && !fLocked) + fLocked = fLocking.Lock(fLockable); + return fLocked; + } + + inline void Unlock() + { + if (fLockable && fLocked) { + fLocking.Unlock(fLockable); + fLocked = false; + } + } + + inline void Detach() + { + fLockable = NULL; + fLocked = false; + } + + inline AutoLocker& operator=(Lockable* lockable) + { + SetTo(lockable); + return *this; + } + + inline AutoLocker& operator=(Lockable& lockable) + { + SetTo(&lockable); + return *this; + } + + inline bool IsLocked() const { return fLocked; } + + inline operator bool() const { return fLocked; } + +protected: + Lockable* fLockable; + Locking fLocking; + bool fLocked; +}; + + +} // namespace BPrivate + +using BPrivate::AutoLocker; +using BPrivate::AutoLockerReadLocking; +using BPrivate::AutoLockerWriteLocking; + +#endif // _AUTO_LOCKER_H diff --git a/src/apps/webpositive/support/HashKeys.h b/src/apps/webpositive/support/HashKeys.h new file mode 100644 index 0000000000..3480b56492 --- /dev/null +++ b/src/apps/webpositive/support/HashKeys.h @@ -0,0 +1,124 @@ +/* + * Copyright 2010, Stephan Aßmus . All rights reserved. + * Copyright 2004-2007, Ingo Weinhold . All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef HASH_KEYS_H +#define HASH_KEYS_H + +#include + + +namespace BPrivate { + +#if 0 +// TODO: Move here from HashMap.h and adapt all clients. +// HashKey32 +template +struct HashKey32 { + HashKey32() {} + HashKey32(const Value& value) : value(value) {} + + uint32 GetHashCode() const + { + return (uint32)value; + } + + HashKey32 operator=(const HashKey32& other) + { + value = other.value; + return *this; + } + + bool operator==(const HashKey32& other) const + { + return (value == other.value); + } + + bool operator!=(const HashKey32& other) const + { + return (value != other.value); + } + + Value value; +}; + + +// HashKey64 +template +struct HashKey64 { + HashKey64() {} + HashKey64(const Value& value) : value(value) {} + + uint32 GetHashCode() const + { + uint64 v = (uint64)value; + return (uint32)(v >> 32) ^ (uint32)v; + } + + HashKey64 operator=(const HashKey64& other) + { + value = other.value; + return *this; + } + + bool operator==(const HashKey64& other) const + { + return (value == other.value); + } + + bool operator!=(const HashKey64& other) const + { + return (value != other.value); + } + + Value value; +}; +#endif + + +struct HashKeyString { + HashKeyString() {} + HashKeyString(const BString& value) : value(value) {} + HashKeyString(const char* string) : value(string) {} + + uint32 GetHashCode() const + { + // from the Dragon Book: a slightly modified hashpjw() + uint32 hash = 0; + const char* string = value.String(); + if (string != NULL) { + for (; *string; string++) { + uint32 g = hash & 0xf0000000; + if (g != 0) + hash ^= g >> 24; + hash = (hash << 4) + *string; + } + } + return hash; + } + + HashKeyString operator=(const HashKeyString& other) + { + value = other.value; + return *this; + } + + bool operator==(const HashKeyString& other) const + { + return (value == other.value); + } + + bool operator!=(const HashKeyString& other) const + { + return (value != other.value); + } + + BString value; +}; + +} // namespace BPrivate + +using BPrivate::HashKeyString; + +#endif // HASH_KEYS_H diff --git a/src/apps/webpositive/support/HashMap.h b/src/apps/webpositive/support/HashMap.h new file mode 100644 index 0000000000..36b321f2b8 --- /dev/null +++ b/src/apps/webpositive/support/HashMap.h @@ -0,0 +1,481 @@ +// HashMap.h +// +// Copyright (c) 2004-2007, Ingo Weinhold (bonefish@cs.tu-berlin.de) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// Except as contained in this notice, the name of a copyright holder shall +// not be used in advertising or otherwise to promote the sale, use or other +// dealings in this Software without prior written authorization of the +// copyright holder. + +#ifndef HASH_MAP_H +#define HASH_MAP_H + + +#include + +#include "AutoLocker.h" +#include "OpenHashTable.h" + + +namespace BPrivate { + +// HashMapElement +template +class HashMapElement : public OpenHashElement { +private: + typedef HashMapElement Element; +public: + + HashMapElement() : OpenHashElement(), fKey(), fValue() + { + fNext = -1; + } + + inline uint32 Hash() const + { + return fKey.GetHashCode(); + } + + inline bool operator==(const OpenHashElement &_element) const + { + const Element &element = static_cast(_element); + return (fKey == element.fKey); + } + + inline void Adopt(Element &element) + { + fKey = element.fKey; + fValue = element.fValue; + } + + Key fKey; + Value fValue; +}; + +// HashMap +template +class HashMap { +public: + class Entry { + public: + Entry() {} + Entry(const Key& key, Value value) : key(key), value(value) {} + + Key key; + Value value; + }; + + class Iterator { + private: + typedef HashMapElement Element; + public: + Iterator(const Iterator& other) + : + fMap(other.fMap), + fIndex(other.fIndex), + fElement(other.fElement), + fLastElement(other.fElement) + { + } + + bool HasNext() const + { + return fElement; + } + + Entry Next() + { + if (!fElement) + return Entry(); + Entry result(fElement->fKey, fElement->fValue); + _FindNext(); + return result; + } + + Value* NextValue() + { + if (fElement == NULL) + return NULL; + + Value* value = &fElement->fValue; + _FindNext(); + return value; + } + + Entry Remove() + { + if (!fLastElement) + return Entry(); + Entry result(fLastElement->fKey, fLastElement->fValue); + fMap->fTable.Remove(fLastElement, true); + fLastElement = NULL; + return result; + } + + Iterator& operator=(const Iterator& other) + { + fMap = other.fMap; + fIndex = other.fIndex; + fElement = other.fElement; + fLastElement = other.fLastElement; + return *this; + } + + private: + Iterator(const HashMap* map) + : + fMap(const_cast*>(map)), + fIndex(0), + fElement(NULL), + fLastElement(NULL) + { + // find first + _FindNext(); + } + + void _FindNext() + { + fLastElement = fElement; + if (fElement && fElement->fNext >= 0) { + fElement = fMap->fTable.ElementAt(fElement->fNext); + return; + } + fElement = NULL; + int32 arraySize = fMap->fTable.ArraySize(); + for (; !fElement && fIndex < arraySize; fIndex++) + fElement = fMap->fTable.FindFirst(fIndex); + } + + private: + friend class HashMap; + + HashMap* fMap; + int32 fIndex; + Element* fElement; + Element* fLastElement; + }; + + HashMap(); + ~HashMap(); + + status_t InitCheck() const; + + status_t Put(const Key& key, Value value); + Value Remove(const Key& key); + void Clear(); + Value Get(const Key& key) const; + bool Get(const Key& key, Value*& _value) const; + + bool ContainsKey(const Key& key) const; + + int32 Size() const; + + Iterator GetIterator() const; + +protected: + typedef HashMapElement Element; + friend class Iterator; + +private: + Element *_FindElement(const Key& key) const; + +protected: + OpenHashElementArray fElementArray; + OpenHashTable > fTable; +}; + +// SynchronizedHashMap +template +class SynchronizedHashMap : public BLocker { +public: + typedef struct HashMap::Entry Entry; + typedef struct HashMap::Iterator Iterator; + + SynchronizedHashMap() : BLocker("synchronized hash map") {} + ~SynchronizedHashMap() { Lock(); } + + status_t InitCheck() const + { + return fMap.InitCheck(); + } + + status_t Put(const Key& key, Value value) + { + MapLocker locker(this); + if (!locker.IsLocked()) + return B_ERROR; + return fMap.Put(key, value); + } + + Value Remove(const Key& key) + { + MapLocker locker(this); + if (!locker.IsLocked()) + return Value(); + return fMap.Remove(key); + } + + void Clear() + { + MapLocker locker(this); + return fMap.Clear(); + } + + Value Get(const Key& key) const + { + const BLocker* lock = this; + MapLocker locker(const_cast(lock)); + if (!locker.IsLocked()) + return Value(); + return fMap.Get(key); + } + + bool ContainsKey(const Key& key) const + { + const BLocker* lock = this; + MapLocker locker(const_cast(lock)); + if (!locker.IsLocked()) + return false; + return fMap.ContainsKey(key); + } + + int32 Size() const + { + const BLocker* lock = this; + MapLocker locker(const_cast(lock)); + return fMap.Size(); + } + + Iterator GetIterator() + { + return fMap.GetIterator(); + } + + // for debugging only + const HashMap& GetUnsynchronizedMap() const { return fMap; } + HashMap& GetUnsynchronizedMap() { return fMap; } + +protected: + typedef AutoLocker MapLocker; + + HashMap fMap; +}; + +// HashKey32 +template +struct HashKey32 { + HashKey32() {} + HashKey32(const Value& value) : value(value) {} + + uint32 GetHashCode() const + { + return (uint32)value; + } + + HashKey32 operator=(const HashKey32& other) + { + value = other.value; + return *this; + } + + bool operator==(const HashKey32& other) const + { + return (value == other.value); + } + + bool operator!=(const HashKey32& other) const + { + return (value != other.value); + } + + Value value; +}; + + +// HashKey64 +template +struct HashKey64 { + HashKey64() {} + HashKey64(const Value& value) : value(value) {} + + uint32 GetHashCode() const + { + uint64 v = (uint64)value; + return (uint32)(v >> 32) ^ (uint32)v; + } + + HashKey64 operator=(const HashKey64& other) + { + value = other.value; + return *this; + } + + bool operator==(const HashKey64& other) const + { + return (value == other.value); + } + + bool operator!=(const HashKey64& other) const + { + return (value != other.value); + } + + Value value; +}; + + +// HashMap + +// constructor +template +HashMap::HashMap() + : + fElementArray(1000), + fTable(1000, &fElementArray) +{ +} + +// destructor +template +HashMap::~HashMap() +{ +} + +// InitCheck +template +status_t +HashMap::InitCheck() const +{ + return (fTable.InitCheck() && fElementArray.InitCheck() + ? B_OK : B_NO_MEMORY); +} + +// Put +template +status_t +HashMap::Put(const Key& key, Value value) +{ + Element* element = _FindElement(key); + if (element) { + // already contains the key: just set the new value + element->fValue = value; + return B_OK; + } + // does not contain the key yet: add an element + element = fTable.Add(key.GetHashCode()); + if (!element) + return B_NO_MEMORY; + element->fKey = key; + element->fValue = value; + return B_OK; +} + +// Remove +template +Value +HashMap::Remove(const Key& key) +{ + Value value = Value(); + if (Element* element = _FindElement(key)) { + value = element->fValue; + fTable.Remove(element); + } + return value; +} + +// Clear +template +void +HashMap::Clear() +{ + fTable.RemoveAll(); +} + +// Get +template +Value +HashMap::Get(const Key& key) const +{ + if (Element* element = _FindElement(key)) + return element->fValue; + return Value(); +} + +// Get +template +bool +HashMap::Get(const Key& key, Value*& _value) const +{ + if (Element* element = _FindElement(key)) { + _value = &element->fValue; + return true; + } + + return false; +} + +// ContainsKey +template +bool +HashMap::ContainsKey(const Key& key) const +{ + return _FindElement(key); +} + +// Size +template +int32 +HashMap::Size() const +{ + return fTable.CountElements(); +} + +// GetIterator +template +struct HashMap::Iterator +HashMap::GetIterator() const +{ + return Iterator(this); +} + +// _FindElement +template +struct HashMap::Element * +HashMap::_FindElement(const Key& key) const +{ + Element* element = fTable.FindFirst(key.GetHashCode()); + while (element && element->fKey != key) { + if (element->fNext >= 0) + element = fTable.ElementAt(element->fNext); + else + element = NULL; + } + return element; +} + +} // namespace BPrivate + +using BPrivate::HashMap; +using BPrivate::HashKey32; +using BPrivate::HashKey64; +using BPrivate::SynchronizedHashMap; + +#endif // HASH_MAP_H diff --git a/src/apps/webpositive/support/HashSet.h b/src/apps/webpositive/support/HashSet.h new file mode 100644 index 0000000000..ee7be71288 --- /dev/null +++ b/src/apps/webpositive/support/HashSet.h @@ -0,0 +1,342 @@ +// HashSet.h +// +// Copyright (c) 2004, Ingo Weinhold (bonefish@cs.tu-berlin.de) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// Except as contained in this notice, the name of a copyright holder shall +// not be used in advertising or otherwise to promote the sale, use or other +// dealings in this Software without prior written authorization of the +// copyright holder. + +#ifndef HASH_SET_H +#define HASH_SET_H + +#include + +#include "AutoLocker.h" +#include "OpenHashTable.h" + + +namespace BPrivate { + +// HashSetElement +template +class HashSetElement : public OpenHashElement { +private: + typedef HashSetElement Element; +public: + + HashSetElement() : OpenHashElement(), fKey() + { + fNext = -1; + } + + inline uint32 Hash() const + { + return fKey.GetHashCode(); + } + + inline bool operator==(const OpenHashElement &_element) const + { + const Element &element = static_cast(_element); + return (fKey == element.fKey); + } + + inline void Adopt(Element &element) + { + fKey = element.fKey; + } + + Key fKey; +}; + +// HashSet +template +class HashSet { +public: + class Iterator { + private: + typedef HashSetElement Element; + public: + Iterator(const Iterator& other) + : fSet(other.fSet), + fIndex(other.fIndex), + fElement(other.fElement), + fLastElement(other.fElement) + { + } + + bool HasNext() const + { + return fElement; + } + + Key Next() + { + if (!fElement) + return Key(); + Key result(fElement->fKey); + _FindNext(); + return result; + } + + bool Remove() + { + if (!fLastElement) + return false; + fSet->fTable.Remove(fLastElement); + fLastElement = NULL; + return true; + } + + Iterator& operator=(const Iterator& other) + { + fSet = other.fSet; + fIndex = other.fIndex; + fElement = other.fElement; + fLastElement = other.fLastElement; + return *this; + } + + private: + Iterator(HashSet* map) + : fSet(map), + fIndex(0), + fElement(NULL), + fLastElement(NULL) + { + // find first + _FindNext(); + } + + void _FindNext() + { + fLastElement = fElement; + if (fElement && fElement->fNext >= 0) { + fElement = fSet->fTable.ElementAt(fElement->fNext); + return; + } + fElement = NULL; + int32 arraySize = fSet->fTable.ArraySize(); + for (; !fElement && fIndex < arraySize; fIndex++) + fElement = fSet->fTable.FindFirst(fIndex); + } + + private: + friend class HashSet; + + HashSet* fSet; + int32 fIndex; + Element* fElement; + Element* fLastElement; + }; + + HashSet(); + ~HashSet(); + + status_t InitCheck() const; + + status_t Add(const Key& key); + bool Remove(const Key& key); + void Clear(); + bool Contains(const Key& key) const; + + int32 Size() const; + bool IsEmpty() const { return Size() == 0; } + + Iterator GetIterator(); + +protected: + typedef HashSetElement Element; + friend class Iterator; + +private: + Element *_FindElement(const Key& key) const; + +protected: + OpenHashElementArray fElementArray; + OpenHashTable > fTable; +}; + +// SynchronizedHashSet +template +class SynchronizedHashSet : public BLocker { +public: + typedef struct HashSet::Iterator Iterator; + + SynchronizedHashSet() : BLocker("synchronized hash set") {} + ~SynchronizedHashSet() { Lock(); } + + status_t InitCheck() const + { + return fSet.InitCheck(); + } + + status_t Add(const Key& key) + { + MapLocker locker(this); + if (!locker.IsLocked()) + return B_ERROR; + return fSet.Add(key); + } + + bool Remove(const Key& key) + { + MapLocker locker(this); + if (!locker.IsLocked()) + return false; + return fSet.Remove(key); + } + + bool Contains(const Key& key) const + { + const BLocker* lock = this; + MapLocker locker(const_cast(lock)); + if (!locker.IsLocked()) + return false; + return fSet.Contains(key); + } + + int32 Size() const + { + const BLocker* lock = this; + MapLocker locker(const_cast(lock)); + return fSet.Size(); + } + + Iterator GetIterator() + { + return fSet.GetIterator(); + } + + // for debugging only + const HashSet& GetUnsynchronizedSet() const { return fSet; } + HashSet& GetUnsynchronizedSet() { return fSet; } + +protected: + typedef AutoLocker MapLocker; + + HashSet fSet; +}; + +// HashSet + +// constructor +template +HashSet::HashSet() + : fElementArray(1000), + fTable(1000, &fElementArray) +{ +} + +// destructor +template +HashSet::~HashSet() +{ +} + +// InitCheck +template +status_t +HashSet::InitCheck() const +{ + return (fTable.InitCheck() && fElementArray.InitCheck() + ? B_OK : B_NO_MEMORY); +} + +// Add +template +status_t +HashSet::Add(const Key& key) +{ + if (Contains(key)) + return B_OK; + Element* element = fTable.Add(key.GetHashCode()); + if (!element) + return B_NO_MEMORY; + element->fKey = key; + return B_OK; +} + +// Remove +template +bool +HashSet::Remove(const Key& key) +{ + if (Element* element = _FindElement(key)) { + fTable.Remove(element); + return true; + } + return false; +} + +// Clear +template +void +HashSet::Clear() +{ + fTable.RemoveAll(); +} + +// Contains +template +bool +HashSet::Contains(const Key& key) const +{ + return _FindElement(key); +} + +// Size +template +int32 +HashSet::Size() const +{ + return fTable.CountElements(); +} + +// GetIterator +template +struct HashSet::Iterator +HashSet::GetIterator() +{ + return Iterator(this); +} + +// _FindElement +template +struct HashSet::Element * +HashSet::_FindElement(const Key& key) const +{ + Element* element = fTable.FindFirst(key.GetHashCode()); + while (element && element->fKey != key) { + if (element->fNext >= 0) + element = fTable.ElementAt(element->fNext); + else + element = NULL; + } + return element; +} + +} // namespace BPrivate + +using BPrivate::HashSet; +using BPrivate::SynchronizedHashSet; + +#endif // HASH_SET_H diff --git a/src/apps/webpositive/support/OpenHashTable.h b/src/apps/webpositive/support/OpenHashTable.h new file mode 100644 index 0000000000..437fbed170 --- /dev/null +++ b/src/apps/webpositive/support/OpenHashTable.h @@ -0,0 +1,514 @@ +/* +Open Tracker License + +Terms and Conditions + +Copyright (c) 1991-2000, Be Incorporated. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice applies to all licensees +and shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Be Incorporated shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from Be Incorporated. + +Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks +of Be Incorporated in the United States and other countries. Other brand product +names are registered trademarks or trademarks of their respective holders. +All rights reserved. +*/ + +// bonefish: +// * removed need for exceptions +// * fixed warnings +// * implemented rehashing +// * added RemoveAll() +// TODO: +// * shrinking of element vectors + +// Hash table with open addresssing + +#ifndef __OPEN_HASH_TABLE__ +#define __OPEN_HASH_TABLE__ + +#include +#include + +// don't include +#ifndef ASSERT +# define ASSERT(E) (void)0 +#endif +#ifndef TRESPASS +# define TRESPASS() (void)0 +#endif + +namespace BPrivate { + +template +class ElementVector { + // element vector for OpenHashTable needs to implement this + // interface +public: + Element &At(int32 index); + Element *Add(); + int32 IndexOf(const Element &) const; + void Remove(int32 index); +}; + +class OpenHashElement { +public: + uint32 Hash() const; + bool operator==(const OpenHashElement &) const; + void Adopt(OpenHashElement &); + // low overhead copy, original element is in undefined state + // after call (calls Adopt on BString members, etc.) + int32 fNext; +}; + +const uint32 kPrimes [] = { + 509, 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071, 262139, + 524287, 1048573, 2097143, 4194301, 8388593, 16777213, 33554393, 67108859, + 134217689, 268435399, 536870909, 1073741789, 2147483647, 0 +}; + +template > +class OpenHashTable { +public: + OpenHashTable(int32 minSize, ElementVec *elementVector = 0, + float maxLoadFactor = 0.8); + // it is up to the subclass of OpenHashTable to supply + // elementVector + ~OpenHashTable(); + + bool InitCheck() const; + + void SetElementVector(ElementVec *elementVector); + + Element *FindFirst(uint32 elementHash) const; + Element *Add(uint32 elementHash); + + void Remove(Element *element, bool dontRehash = false); + void RemoveAll(); + + // when calling Add, any outstanding element pointer may become + // invalid; to deal with this, get the element index and restore + // it after the add + int32 ElementIndex(const Element *) const; + Element *ElementAt(int32 index) const; + + int32 ArraySize() const; + int32 VectorSize() const; + int32 CountElements() const; + +protected: + static int32 OptimalSize(int32 minSize); + +private: + bool _RehashIfNeeded(); + bool _Rehash(); + + int32 fArraySize; + int32 fInitialSize; + int32 fElementCount; + int32 *fHashArray; + ElementVec *fElementVector; + float fMaxLoadFactor; +}; + +template +class OpenHashElementArray : public ElementVector { + // this is a straightforward implementation of an element vector + // deleting is handled by linking deleted elements into a free list + // the vector never shrinks +public: + OpenHashElementArray(int32 initialSize); + ~OpenHashElementArray(); + + bool InitCheck() const; + + Element &At(int32 index); + const Element &At(int32 index) const; + Element *Add(const Element &); + Element *Add(); + void Remove(int32 index); + int32 IndexOf(const Element &) const; + int32 Size() const; + +private: + Element *fData; + int32 fSize; + int32 fNextFree; + int32 fNextDeleted; +}; + + +//----------------------------------- + +template +OpenHashTable::OpenHashTable(int32 minSize, + ElementVec *elementVector, float maxLoadFactor) + : fArraySize(OptimalSize(minSize)), + fInitialSize(fArraySize), + fElementCount(0), + fElementVector(elementVector), + fMaxLoadFactor(maxLoadFactor) +{ + // sanity check the maximal load factor + if (fMaxLoadFactor < 0.5) + fMaxLoadFactor = 0.5; + // allocate and init the array + fHashArray = (int32*)calloc(fArraySize, sizeof(int32)); + if (fHashArray) { + for (int32 index = 0; index < fArraySize; index++) + fHashArray[index] = -1; + } +} + +template +OpenHashTable::~OpenHashTable() +{ + RemoveAll(); + free(fHashArray); +} + +template +bool +OpenHashTable::InitCheck() const +{ + return (fHashArray && fElementVector); +} + +template +int32 +OpenHashTable::OptimalSize(int32 minSize) +{ + for (int32 index = 0; ; index++) + if (!kPrimes[index] || kPrimes[index] >= (uint32)minSize) + return (int32)kPrimes[index]; + + return 0; +} + +template +Element * +OpenHashTable::FindFirst(uint32 hash) const +{ + ASSERT(fElementVector); + hash %= fArraySize; + if (fHashArray[hash] < 0) + return 0; + + return &fElementVector->At(fHashArray[hash]); +} + +template +int32 +OpenHashTable::ElementIndex(const Element *element) const +{ + return fElementVector->IndexOf(*element); +} + +template +Element * +OpenHashTable::ElementAt(int32 index) const +{ + return &fElementVector->At(index); +} + +template +int32 +OpenHashTable::ArraySize() const +{ + return fArraySize; +} + +template +int32 +OpenHashTable::VectorSize() const +{ + return fElementVector->Size(); +} + +template +int32 +OpenHashTable::CountElements() const +{ + return fElementCount; +} + + +template +Element * +OpenHashTable::Add(uint32 hash) +{ + ASSERT(fElementVector); + _RehashIfNeeded(); + hash %= fArraySize; + Element *result = fElementVector->Add(); + if (result) { + result->fNext = fHashArray[hash]; + fHashArray[hash] = fElementVector->IndexOf(*result); + fElementCount++; + } + return result; +} + +template +void +OpenHashTable::Remove(Element *element, bool dontRehash) +{ + if (!dontRehash) + _RehashIfNeeded(); + uint32 hash = element->Hash() % fArraySize; + int32 next = fHashArray[hash]; + ASSERT(next >= 0); + + if (&fElementVector->At(next) == element) { + fHashArray[hash] = element->fNext; + fElementVector->Remove(next); + fElementCount--; + return; + } + + for (int32 index = next; index >= 0; ) { + // look for an existing match in table + next = fElementVector->At(index).fNext; + if (next < 0) { + TRESPASS(); + return; + } + + if (&fElementVector->At(next) == element) { + fElementVector->At(index).fNext = element->fNext; + fElementVector->Remove(next); + fElementCount--; + return; + } + index = next; + } +} + +template +void +OpenHashTable::RemoveAll() +{ + for (int32 i = 0; fElementCount > 0 && i < fArraySize; i++) { + int32 index = fHashArray[i]; + while (index >= 0) { + Element* element = &fElementVector->At(index); + int32 next = element->fNext; + fElementVector->Remove(index); + fElementCount--; + index = next; + } + fHashArray[i] = -1; + } + _RehashIfNeeded(); +} + +template +void +OpenHashTable::SetElementVector(ElementVec *elementVector) +{ + fElementVector = elementVector; +} + +// _RehashIfNeeded +template +bool +OpenHashTable::_RehashIfNeeded() +{ + // The load factor range [fMaxLoadFactor / 3, fMaxLoadFactor] is fine, + // I think. After rehashing the load factor will be about + // fMaxLoadFactor * 2 / 3, respectively fMaxLoadFactor / 2. + float loadFactor = (float)fElementCount / (float)fArraySize; + if (loadFactor > fMaxLoadFactor + || (fArraySize > fInitialSize && loadFactor < fMaxLoadFactor / 3)) { + return _Rehash(); + } + return true; +} + +// _Rehash +template +bool +OpenHashTable::_Rehash() +{ + bool result = true; + int32 newSize = int32(fElementCount * 1.73 * fMaxLoadFactor); + newSize = (fInitialSize > newSize ? fInitialSize : newSize); + if (newSize != fArraySize) { + // allocate a new array + int32 *newHashArray = (int32*)calloc(newSize, sizeof(int32)); + if (newHashArray) { + // init the new hash array + for (int32 index = 0; index < newSize; index++) + newHashArray[index] = -1; + // iterate through all elements and put them into the new + // hash array + for (int i = 0; i < fArraySize; i++) { + int32 index = fHashArray[i]; + while (index >= 0) { + // insert the element in the new array + Element &element = fElementVector->At(index); + int32 next = element.fNext; + uint32 hash = (element.Hash() % newSize); + element.fNext = newHashArray[hash]; + newHashArray[hash] = index; + // next element in old list + index = next; + } + } + // delete the old array and set the new one + free(fHashArray); + fHashArray = newHashArray; + fArraySize = newSize; + } else + result = false; + } + return result; +} + + +template +OpenHashElementArray::OpenHashElementArray(int32 initialSize) + : fSize(initialSize), + fNextFree(0), + fNextDeleted(-1) +{ + fData = (Element*)calloc((size_t)initialSize, sizeof(Element)); +} + +template +OpenHashElementArray::~OpenHashElementArray() +{ + free(fData); +} + +template +bool +OpenHashElementArray::InitCheck() const +{ + return fData; +} + +template +Element & +OpenHashElementArray::At(int32 index) +{ + ASSERT(index < fSize); + return fData[index]; +} + +template +const Element & +OpenHashElementArray::At(int32 index) const +{ + ASSERT(index < fSize); + return fData[index]; +} + +template +int32 +OpenHashElementArray::IndexOf(const Element &element) const +{ + int32 result = &element - fData; + if (result < 0 || result > fSize) + return -1; + + return result; +} + +template +int32 +OpenHashElementArray::Size() const +{ + return fSize; +} + + +template +Element * +OpenHashElementArray::Add(const Element &newElement) +{ + Element *element = Add(); + if (element) + element.Adopt(newElement); + return element; +} + +#if DEBUG +const int32 kGrowChunk = 10; +#else +const int32 kGrowChunk = 1024; +#endif + +template +Element * +OpenHashElementArray::Add() +{ + int32 index = fNextFree; + if (fNextDeleted >= 0) { + index = fNextDeleted; + fNextDeleted = At(index).fNext; + } else if (fNextFree >= fSize - 1) { + int32 newSize = fSize + kGrowChunk; +/* + Element *newData = (Element *)calloc((size_t)newSize , sizeof(Element)); + if (!newData) + return NULL; + memcpy(newData, fData, fSize * sizeof(Element)); + free(fData); +*/ + Element *newData = (Element*)realloc(fData, + (size_t)newSize * sizeof(Element)); + if (!newData) + return NULL; + + fData = newData; + fSize = newSize; + index = fNextFree; + fNextFree++; + } else + fNextFree++; + + new (&At(index)) Element; + // call placement new to initialize the element properly + ASSERT(At(index).fNext == -1); + + return &At(index); +} + +template +void +OpenHashElementArray::Remove(int32 index) +{ + // delete by chaining empty elements in a single linked + // list, reusing the next field + ASSERT(index < fSize); + At(index).~Element(); + // call the destructor explicitly to destroy the element + // properly + At(index).fNext = fNextDeleted; + fNextDeleted = index; +} + +} // namespace BPrivate + +using BPrivate::OpenHashTable; + +#endif // __OPEN_HASH_TABLE__ From 9f30678a6772a544fc0c1d7c14bd329ba5c040cd Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 3 May 2010 16:56:54 +0000 Subject: [PATCH 261/349] Implemented a CredentialsStorage class with optional persistency. Two global objects are used for session and persistent storage of credentials with the appropriate locking. Passwords are stored on disk insecurely. If the user uses the checkmark in the authentication window to remember the credentials, the persistent storage will be used, otherwise the session storage. In another words, even if not asked to remember the credentials, the same user/pass never needs to be entered more than once per session, unlike before. WebCore already contains a CredentialStorage class, but we don't use it. It could be used via the CURL networking backend implementation, only the CF backend uses it at all. Since we don't have a "keyring" OS level service, this solution was more convenient for the time being. Note all this has nothing to do with storage of form data entered by the user. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@478 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 32 ++- src/apps/webpositive/BrowserWindow.h | 2 + src/apps/webpositive/CredentialsStorage.cpp | 275 ++++++++++++++++++++ src/apps/webpositive/CredentialsStorage.h | 98 +++++++ 4 files changed, 406 insertions(+), 1 deletion(-) create mode 100644 src/apps/webpositive/CredentialsStorage.cpp create mode 100644 src/apps/webpositive/CredentialsStorage.h diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index d1835a7544..e64906eaf7 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -37,6 +37,7 @@ #include "BaseURL.h" #include "BrowserApp.h" #include "BrowsingHistory.h" +#include "CredentialsStorage.h" #include "IconButton.h" #include "NavMenu.h" #include "SettingsKeys.h" @@ -1151,6 +1152,27 @@ BrowserWindow::AuthenticationChallenge(BString message, BString& inOutUser, BString& inOutPassword, bool& inOutRememberCredentials, uint32 failureCount, BWebView* view) { + CredentialsStorage* persistentStorage + = CredentialsStorage::PersistentInstance(); + CredentialsStorage* sessionStorage + = CredentialsStorage::SessionInstance(); + + // TODO: Using the message as key here is not so smart. + HashKeyString key(message); + + if (failureCount == 0) { + if (persistentStorage->Contains(key)) { + Credentials credentials = persistentStorage->GetCredentials(key); + inOutUser = credentials.Username(); + inOutPassword = credentials.Password(); + return true; + } else if (sessionStorage->Contains(key)) { + Credentials credentials = sessionStorage->GetCredentials(key); + inOutUser = credentials.Username(); + inOutPassword = credentials.Password(); + return true; + } + } // Switch to the page for which this authentication is required. if (view != CurrentWebView()) { int32 tabIndex = fTabManager->TabForView(view); @@ -1164,9 +1186,17 @@ BrowserWindow::AuthenticationChallenge(BString message, BString& inOutUser, } AuthenticationPanel* panel = new AuthenticationPanel(Frame()); // Panel auto-destructs. - return panel->getAuthentication(message, inOutUser, inOutPassword, + bool success = panel->getAuthentication(message, inOutUser, inOutPassword, inOutRememberCredentials, failureCount > 0, inOutUser, inOutPassword, &inOutRememberCredentials); + if (success) { + Credentials credentials(inOutUser, inOutPassword); + if (inOutRememberCredentials) + persistentStorage->PutCredentials(key, credentials); + else + sessionStorage->PutCredentials(key, credentials); + } + return success; } diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 1dd2951410..0c78abd48a 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -30,6 +30,8 @@ #define BROWSER_WINDOW_H +#include "HashKeys.h" +#include "HashMap.h" #include "WebWindow.h" #include #include diff --git a/src/apps/webpositive/CredentialsStorage.cpp b/src/apps/webpositive/CredentialsStorage.cpp new file mode 100644 index 0000000000..ab5f8eae8d --- /dev/null +++ b/src/apps/webpositive/CredentialsStorage.cpp @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "CredentialsStorage.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "BrowserApp.h" + + +Credentials::Credentials() + : + fUsername(), + fPassword() +{ +} + + +Credentials::Credentials(const BString& username, const BString& password) + : + fUsername(username), + fPassword(password) +{ +} + + +Credentials::Credentials(const Credentials& other) +{ + *this = other; +} + + +Credentials::Credentials(const BMessage* archive) +{ + if (archive == NULL) + return; + archive->FindString("username", &fUsername); + archive->FindString("password", &fPassword); +} + + +Credentials::~Credentials() +{ +} + + +status_t +Credentials::Archive(BMessage* archive) const +{ + if (archive == NULL) + return B_BAD_VALUE; + status_t status = archive->AddString("username", fUsername); + if (status == B_OK) + status = archive->AddString("password", fPassword); + return status; +} + + +Credentials& +Credentials::operator=(const Credentials& other) +{ + if (this == &other) + return *this; + + fUsername = other.fUsername; + fPassword = other.fPassword; + + return *this; +} + + +bool +Credentials::operator==(const Credentials& other) const +{ + if (this == &other) + return true; + + return fUsername == other.fUsername && fPassword == other.fPassword; +} + + +bool +Credentials::operator!=(const Credentials& other) const +{ + return !(*this == other); +} + + +const BString& +Credentials::Username() const +{ + return fUsername; +} + + +const BString& +Credentials::Password() const +{ + return fPassword; +} + + +// #pragma mark - CredentialsStorage + + +CredentialsStorage +CredentialsStorage::sPersistentInstance(true); + + +CredentialsStorage +CredentialsStorage::sSessionInstance(false); + + +CredentialsStorage::CredentialsStorage(bool persistent) + : + BLocker(persistent ? "persistent credential storage" + : "credential storage"), + fCredentialMap(), + fSettingsLoaded(false), + fPersistent(persistent) +{ +} + + +CredentialsStorage::~CredentialsStorage() +{ + _SaveSettings(); +} + + +/*static*/ CredentialsStorage* +CredentialsStorage::SessionInstance() +{ + return &sSessionInstance; +} + + +/*static*/ CredentialsStorage* +CredentialsStorage::PersistentInstance() +{ + if (sPersistentInstance.Lock()) { + sPersistentInstance._LoadSettings(); + sPersistentInstance.Unlock(); + } + return &sPersistentInstance; +} + + +bool +CredentialsStorage::Contains(const HashKeyString& key) +{ + BAutolock _(this); + + return fCredentialMap.ContainsKey(key); +} + + +status_t +CredentialsStorage::PutCredentials(const HashKeyString& key, + const Credentials& credentials) +{ + BAutolock _(this); + + return fCredentialMap.Put(key, credentials); +} + + +Credentials +CredentialsStorage::GetCredentials(const HashKeyString& key) +{ + BAutolock _(this); + + return fCredentialMap.Get(key); +} + + +// #pragma mark - private + + +void +CredentialsStorage::_LoadSettings() +{ + if (!fPersistent || fSettingsLoaded) + return; + + fSettingsLoaded = true; + + BFile settingsFile; + if (_OpenSettingsFile(settingsFile, B_READ_ONLY)) { + BMessage settingsArchive; + settingsArchive.Unflatten(&settingsFile); + BMessage credentialsArchive; + for (int32 i = 0; settingsArchive.FindMessage("credentials", i, + &credentialsArchive) == B_OK; i++) { + BString key; + if (credentialsArchive.FindString("key", &key) == B_OK) { + Credentials credentials(&credentialsArchive); + fCredentialMap.Put(key, credentials); + } + } + } +} + + +void +CredentialsStorage::_SaveSettings() const +{ + BFile settingsFile; + if (_OpenSettingsFile(settingsFile, + B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) { + BMessage settingsArchive; + BMessage credentialsArchive; + CredentialMap::Iterator iterator = fCredentialMap.GetIterator(); + while (iterator.HasNext()) { + const CredentialMap::Entry& entry = iterator.Next(); + if (entry.value.Archive(&credentialsArchive) != B_OK + || credentialsArchive.AddString("key", + entry.key.value) != B_OK) { + break; + } + if (settingsArchive.AddMessage("credentials", + &credentialsArchive) != B_OK) { + break; + } + credentialsArchive.MakeEmpty(); + } + settingsArchive.Flatten(&settingsFile); + } +} + + +bool +CredentialsStorage::_OpenSettingsFile(BFile& file, uint32 mode) const +{ + BPath path; + if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK + || path.Append(kApplicationName) != B_OK + || path.Append("CredentialsStorage") != B_OK) { + return false; + } + return file.SetTo(path.Path(), mode) == B_OK; +} + diff --git a/src/apps/webpositive/CredentialsStorage.h b/src/apps/webpositive/CredentialsStorage.h new file mode 100644 index 0000000000..214c36b371 --- /dev/null +++ b/src/apps/webpositive/CredentialsStorage.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2010 Stephan Aßmus + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef CREDENTIAL_STORAGE_H +#define CREDENTIAL_STORAGE_H + +#include "HashKeys.h" +#include "HashMap.h" +#include +#include + + +class BFile; +class BMessage; +class BString; + + +class Credentials { +public: + Credentials(); + Credentials(const BString& username, + const BString& password); + Credentials( + const Credentials& other); + Credentials(const BMessage* archive); + ~Credentials(); + + status_t Archive(BMessage* archive) const; + + Credentials& operator=(const Credentials& other); + + bool operator==(const Credentials& other) const; + bool operator!=(const Credentials& other) const; + + const BString& Username() const; + const BString& Password() const; + +private: + BString fUsername; + BString fPassword; +}; + + +class CredentialsStorage : public BLocker { +public: + static CredentialsStorage* SessionInstance(); + static CredentialsStorage* PersistentInstance(); + + bool Contains(const HashKeyString& key); + status_t PutCredentials(const HashKeyString& key, + const Credentials& credentials); + Credentials GetCredentials(const HashKeyString& key); + +private: + CredentialsStorage(bool persistent); + virtual ~CredentialsStorage(); + + void _LoadSettings(); + void _SaveSettings() const; + bool _OpenSettingsFile(BFile& file, + uint32 mode) const; + +private: + typedef HashMap CredentialMap; + CredentialMap fCredentialMap; + + static CredentialsStorage sPersistentInstance; + static CredentialsStorage sSessionInstance; + bool fSettingsLoaded; + bool fPersistent; +}; + + +#endif // CREDENTIAL_STORAGE_H + From 27dab3e5fe5e7f8115d8db88f82508168faf27e9 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 3 May 2010 18:01:38 +0000 Subject: [PATCH 262/349] Make sure never to draw the favicon too big, in case we only got a big one from the page, and use the proper drawing mode and filtering. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@479 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/URLInputGroup.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index 40805943fc..d5f4888234 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -532,7 +532,8 @@ public: BView("page icon view", B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE), fIcon(NULL) { - SetDrawingMode(B_OP_OVER); + SetDrawingMode(B_OP_ALPHA); + SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); } ~PageIconView() @@ -546,21 +547,20 @@ public: return; BRect bounds(Bounds()); - BRect iconBounds(fIcon->Bounds()); - BPoint iconPos( + BRect iconBounds(0, 0, 15, 15); + iconBounds.OffsetTo( floorf((bounds.left + bounds.right - (iconBounds.left + iconBounds.right)) / 2 + 0.5f), floorf((bounds.top + bounds.bottom - (iconBounds.top + iconBounds.bottom)) / 2 + 0.5f)); - DrawBitmap(fIcon, iconPos); + DrawBitmap(fIcon, fIcon->Bounds(), iconBounds, + B_FILTER_BITMAP_BILINEAR); } virtual BSize MinSize() { - if (fIcon != NULL) { - return BSize(fIcon->Bounds().Width() + 3, - fIcon->Bounds().Height() + 3); - } + if (fIcon != NULL) + return BSize(18, 18); return BSize(0, 0); } From 9adbaa437850184544cd54aaf5c45e91b573a02f Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 4 May 2010 10:49:16 +0000 Subject: [PATCH 263/349] Removed unneeded headers. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@480 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 0c78abd48a..1dd2951410 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -30,8 +30,6 @@ #define BROWSER_WINDOW_H -#include "HashKeys.h" -#include "HashMap.h" #include "WebWindow.h" #include #include From 9a6307059ae614b24fb17805b0ed916aa09d6a9f Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 4 May 2010 12:02:24 +0000 Subject: [PATCH 264/349] Moved handling/display of "main site error" alert into client. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@481 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 90 ++++++++++++++++---------- src/apps/webpositive/BrowserWindow.h | 5 ++ 2 files changed, 62 insertions(+), 33 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index e64906eaf7..742b910562 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1009,6 +1009,43 @@ BrowserWindow::LoadFinished(const BString& url, BWebView* view) } +void +BrowserWindow::MainDocumentError(const BString& failingURL, + const BString& localizedDescription, BWebView* view) +{ + // Make sure we show the page that contains the view. + if (!_ShowPage(view)) + return; + + BWebWindow::MainDocumentError(failingURL, localizedDescription, view); + + // TODO: Remove the failing URL from the BrowsingHistory! +} + + +void +BrowserWindow::TitleChanged(const BString& title, BWebView* view) +{ + for (int32 i = 0; i < fTabManager->CountTabs(); i++) { + if (fTabManager->ViewForTab(i) == view) { + fTabManager->SetTabLabel(i, title); + break; + } + } + if (view != CurrentWebView()) + return; + + _UpdateTitle(title); +} + + +void +BrowserWindow::IconReceived(const BBitmap* icon, BWebView* view) +{ + _SetPageIcon(view, icon); +} + + void BrowserWindow::ResizeRequested(float width, float height, BWebView* view) { @@ -1090,29 +1127,6 @@ BrowserWindow::SetResizable(bool flag, BWebView* view) } -void -BrowserWindow::TitleChanged(const BString& title, BWebView* view) -{ - for (int32 i = 0; i < fTabManager->CountTabs(); i++) { - if (fTabManager->ViewForTab(i) == view) { - fTabManager->SetTabLabel(i, title); - break; - } - } - if (view != CurrentWebView()) - return; - - _UpdateTitle(title); -} - - -void -BrowserWindow::IconReceived(const BBitmap* icon, BWebView* view) -{ - _SetPageIcon(view, icon); -} - - void BrowserWindow::StatusChanged(const BString& statusText, BWebView* view) { @@ -1174,16 +1188,9 @@ BrowserWindow::AuthenticationChallenge(BString message, BString& inOutUser, } } // Switch to the page for which this authentication is required. - if (view != CurrentWebView()) { - int32 tabIndex = fTabManager->TabForView(view); - if (tabIndex < 0) { - // Page seems to be gone already? - return false; - } - fTabManager->SelectTab(tabIndex); - _TabChanged(tabIndex); - UpdateIfNeeded(); - } + if (!_ShowPage(view)) + return false; + AuthenticationPanel* panel = new AuthenticationPanel(Frame()); // Panel auto-destructs. bool success = panel->getAuthentication(message, inOutUser, inOutPassword, @@ -1669,3 +1676,20 @@ BrowserWindow::_UpdateClipboardItems() CurrentWebView()->WebPage()->SendEditingCapabilities(); } } + + +bool +BrowserWindow::_ShowPage(BWebView* view) +{ + if (view != CurrentWebView()) { + int32 tabIndex = fTabManager->TabForView(view); + if (tabIndex < 0) { + // Page seems to be gone already? + return false; + } + fTabManager->SelectTab(tabIndex); + _TabChanged(tabIndex); + UpdateIfNeeded(); + } + return true; +} diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 1dd2951410..610029ac3d 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -113,6 +113,9 @@ private: virtual void LoadFailed(const BString& url, BWebView* view); virtual void LoadFinished(const BString& url, BWebView* view); + virtual void MainDocumentError(const BString& failingURL, + const BString& localizedDescription, + BWebView* view); virtual void TitleChanged(const BString& title, BWebView* view); virtual void IconReceived(const BBitmap* icon, @@ -159,6 +162,8 @@ private: void _UpdateHistoryMenu(); void _UpdateClipboardItems(); + bool _ShowPage(BWebView* view); + private: BMenu* fHistoryMenu; int32 fHistoryMenuFixedItemCount; From f157030d2e6f467b0ce61cfca868051fb3868078 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 4 May 2010 12:23:56 +0000 Subject: [PATCH 265/349] Implemented most basic fullscreen feature. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@482 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 106 ++++++++++++++++++++----- src/apps/webpositive/BrowserWindow.h | 13 +++ 2 files changed, 100 insertions(+), 19 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 742b910562..44abfb4534 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -76,29 +76,31 @@ enum { - OPEN_LOCATION = 'open', - GO_BACK = 'goba', - GO_FORWARD = 'gofo', - STOP = 'stop', - GOTO_URL = 'goul', - RELOAD = 'reld', - CLEAR_HISTORY = 'clhs', + OPEN_LOCATION = 'open', + GO_BACK = 'goba', + GO_FORWARD = 'gofo', + STOP = 'stop', + GOTO_URL = 'goul', + RELOAD = 'reld', + CLEAR_HISTORY = 'clhs', - CREATE_BOOKMARK = 'crbm', - SHOW_BOOKMARKS = 'shbm', + CREATE_BOOKMARK = 'crbm', + SHOW_BOOKMARKS = 'shbm', - ZOOM_FACTOR_INCREASE = 'zfin', - ZOOM_FACTOR_DECREASE = 'zfdc', - ZOOM_FACTOR_RESET = 'zfrs', - ZOOM_TEXT_ONLY = 'zfto', + ZOOM_FACTOR_INCREASE = 'zfin', + ZOOM_FACTOR_DECREASE = 'zfdc', + ZOOM_FACTOR_RESET = 'zfrs', + ZOOM_TEXT_ONLY = 'zfto', - EDIT_SHOW_FIND_GROUP = 'sfnd', - EDIT_HIDE_FIND_GROUP = 'hfnd', - EDIT_FIND_NEXT = 'fndn', - EDIT_FIND_PREVIOUS = 'fndp', - FIND_TEXT_CHANGED = 'ftxt', + TOGGLE_FULLSCREEN = 'tgfs', - SELECT_TAB = 'sltb', + EDIT_SHOW_FIND_GROUP = 'sfnd', + EDIT_HIDE_FIND_GROUP = 'hfnd', + EDIT_FIND_NEXT = 'fndn', + EDIT_FIND_PREVIOUS = 'fndp', + FIND_TEXT_CHANGED = 'ftxt', + + SELECT_TAB = 'sltb', }; @@ -189,6 +191,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, BWebWindow(frame, kApplicationName, B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS), + fIsFullscreen(false), fAppSettings(appSettings), fZoomTextOnly(true), fShowTabsIfSinglePageOpen(true) @@ -274,6 +277,12 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, new BMessage(ZOOM_TEXT_ONLY)); fZoomTextOnlyMenuItem->SetMarked(fZoomTextOnly); menu->AddItem(fZoomTextOnlyMenuItem); + + menu->AddSeparatorItem(); + fFullscreenItem = new BMenuItem("Fullscreen", + new BMessage(TOGGLE_FULLSCREEN), B_RETURN); + menu->AddItem(fFullscreenItem); + mainMenu->AddItem(menu); fHistoryMenu = new BMenu("History"); @@ -604,6 +613,10 @@ BrowserWindow::MessageReceived(BMessage* message) // already zoomed. break; + case TOGGLE_FULLSCREEN: + _ToggleFullscreen(); + break; + case EDIT_FIND_NEXT: CurrentWebView()->FindString(fFindTextControl->Text(), true, fFindCaseSensitiveCheckBox->Value()); @@ -770,6 +783,29 @@ BrowserWindow::MenusBeginning() } +void +BrowserWindow::Zoom(BPoint origin, float width, float height) +{ + _ToggleFullscreen(); +} + + +void +BrowserWindow::ScreenChanged(BRect screenSize, color_space format) +{ + if (fIsFullscreen) + _ResizeToScreen(); +} + + +void +BrowserWindow::WorkspacesChanged(uint32 oldWorkspaces, uint32 newWorkspaces) +{ + if (fIsFullscreen) + _ResizeToScreen(); +} + + static bool viewIsChild(const BView* parent, const BView* view) { @@ -1693,3 +1729,35 @@ BrowserWindow::_ShowPage(BWebView* view) } return true; } + + +void +BrowserWindow::_ToggleFullscreen() +{ + if (fIsFullscreen) { + MoveTo(fNonFullscreenWindowFrame.LeftTop()); + ResizeTo(fNonFullscreenWindowFrame.Width(), + fNonFullscreenWindowFrame.Height()); + + SetFlags(Flags() & ~(B_NOT_RESIZABLE | B_NOT_MOVABLE)); + SetLook(B_DOCUMENT_WINDOW_LOOK); + } else { + fNonFullscreenWindowFrame = Frame(); + _ResizeToScreen(); + + SetFlags(Flags() | (B_NOT_RESIZABLE | B_NOT_MOVABLE)); + SetLook(B_TITLED_WINDOW_LOOK); + } + fIsFullscreen = !fIsFullscreen; + fFullscreenItem->SetMarked(fIsFullscreen); +} + + +void +BrowserWindow::_ResizeToScreen() +{ + BScreen screen(this); + MoveTo(0, 0); + ResizeTo(screen.Frame().Width(), screen.Frame().Height()); +} + diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 610029ac3d..3ae549af66 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -90,6 +90,12 @@ public: virtual bool QuitRequested(); virtual void MenusBeginning(); + virtual void Zoom(BPoint origin, float width, float height); + virtual void ScreenChanged(BRect screenSize, + color_space format); + virtual void WorkspacesChanged(uint32 oldWorkspaces, + uint32 newWorkspaces); + virtual void SetCurrentWebView(BWebView* view); void CreateNewTab(const BString& url, bool select, @@ -164,6 +170,9 @@ private: bool _ShowPage(BWebView* view); + void _ToggleFullscreen(); + void _ResizeToScreen(); + private: BMenu* fHistoryMenu; int32 fHistoryMenuFixedItemCount; @@ -174,6 +183,7 @@ private: BMenuItem* fFindPreviousMenuItem; BMenuItem* fFindNextMenuItem; BMenuItem* fZoomTextOnlyMenuItem; + BMenuItem* fFullscreenItem; BMenuItem* fBackMenuItem; BMenuItem* fForwardMenuItem; @@ -194,6 +204,9 @@ private: BCheckBox* fFindCaseSensitiveCheckBox; TabManager* fTabManager; + bool fIsFullscreen; + BRect fNonFullscreenWindowFrame; + // cached settings SettingsMessage* fAppSettings; bool fZoomTextOnly; From 095c4241efc817337f8662d832a6634f74146db3 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 4 May 2010 16:10:39 +0000 Subject: [PATCH 266/349] Moved BitmapButton into it's own file. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@483 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/URLInputGroup.cpp | 87 +------------ src/apps/webpositive/support/BitmapButton.cpp | 116 ++++++++++++++++++ src/apps/webpositive/support/BitmapButton.h | 44 +++++++ 3 files changed, 162 insertions(+), 85 deletions(-) create mode 100644 src/apps/webpositive/support/BitmapButton.cpp create mode 100644 src/apps/webpositive/support/BitmapButton.h diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index d5f4888234..7fec10caaf 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -16,13 +16,13 @@ #include #include #include -#include #include #include #include #include "BaseURL.h" +#include "BitmapButton.h" #include "BrowsingHistory.h" #include "IconButton.h" #include "TextViewCompleter.h" @@ -382,9 +382,6 @@ URLInputGroup::URLTextView::_AlignTextRect() } -// #pragma mark - GoButton - - const uint32 kGoBitmapWidth = 14; const uint32 kGoBitmapHeight = 14; const color_space kGoBitmapFormat = B_RGBA32; @@ -442,87 +439,7 @@ const unsigned char kGoBitmapBits[] = { }; -class BitmapButton : public BButton { - static const float kFrameInset = 2; - -public: - BitmapButton(const char* resourceName, BMessage* message) - : - BButton("", message), - fBitmap(BTranslationUtils::GetBitmap(resourceName)) - { - } - - BitmapButton(const uint8* bits, uint32 width, uint32 height, - color_space format, BMessage* message) - : - BButton("", message), - fBitmap(new BBitmap(BRect(0, 0, width - 1, height - 1), 0, format)) - { - memcpy(fBitmap->Bits(), bits, fBitmap->BitsLength()); - } - - ~BitmapButton() - { - delete fBitmap; - } - - virtual BSize MinSize() - { - BSize min(0, 0); - if (fBitmap) { - min.width = fBitmap->Bounds().Width(); - min.height = fBitmap->Bounds().Height(); - } - min.width += kFrameInset * 2; - min.height += kFrameInset * 2; - return min; - } - - virtual BSize MaxSize() - { - return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED); - } - - virtual BSize PreferredSize() - { - return MinSize(); - } - - virtual void Draw(BRect updateRect) - { - BRect bounds(Bounds()); - rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); - uint32 flags = be_control_look->Flags(this); - - be_control_look->DrawButtonBackground(this, bounds, updateRect, base, - flags); - - SetDrawingMode(B_OP_ALPHA); - - if (!IsEnabled()) { - SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY); - SetHighColor(0, 0, 0, 120); - } - - if (fBitmap == NULL) - return; - BRect bitmapBounds(fBitmap->Bounds()); - BPoint bitmapLocation( - floorf((bounds.left + bounds.right - - (bitmapBounds.left + bitmapBounds.right)) / 2 + 0.5f), - floorf((bounds.top + bounds.bottom - - (bitmapBounds.top + bitmapBounds.bottom)) / 2 + 0.5f)); - - DrawBitmap(fBitmap, bitmapLocation); - } - -private: - BBitmap* fBitmap; -}; - - -// #pragma mark - IconView +// #pragma mark - PageIconView class URLInputGroup::PageIconView : public BView { diff --git a/src/apps/webpositive/support/BitmapButton.cpp b/src/apps/webpositive/support/BitmapButton.cpp new file mode 100644 index 0000000000..1b4a22cee0 --- /dev/null +++ b/src/apps/webpositive/support/BitmapButton.cpp @@ -0,0 +1,116 @@ +/* + * Copyright 2010 Stephan Aßmus . All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#include "BitmapButton.h" + +#include + +#include +#include +#include + + +static const float kFrameInset = 2; + + +BitmapButton::BitmapButton(const char* resourceName, BMessage* message) + : + BButton("", message), + fBitmap(BTranslationUtils::GetBitmap(resourceName)), + fBackgroundMode(BUTTON_BACKGROUND) +{ +} + + +BitmapButton::BitmapButton(const uint8* bits, uint32 width, uint32 height, + color_space format, BMessage* message) + : + BButton("", message), + fBitmap(new BBitmap(BRect(0, 0, width - 1, height - 1), 0, format)), + fBackgroundMode(BUTTON_BACKGROUND) +{ + memcpy(fBitmap->Bits(), bits, fBitmap->BitsLength()); +} + + +BitmapButton::~BitmapButton() +{ + delete fBitmap; +} + + +BSize +BitmapButton::MinSize() +{ + BSize min(0, 0); + if (fBitmap) { + min.width = fBitmap->Bounds().Width(); + min.height = fBitmap->Bounds().Height(); + } + min.width += kFrameInset * 2; + min.height += kFrameInset * 2; + return min; +} + + +BSize +BitmapButton::MaxSize() +{ + return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED); +} + + +BSize +BitmapButton::PreferredSize() +{ + return MinSize(); +} + + +void +BitmapButton::Draw(BRect updateRect) +{ + BRect bounds(Bounds()); + rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); + uint32 flags = be_control_look->Flags(this); + + if (fBackgroundMode == BUTTON_BACKGROUND || Value() == B_CONTROL_ON) { + be_control_look->DrawButtonBackground(this, bounds, updateRect, base, + flags); + } else { + be_control_look->DrawMenuBarBackground(this, bounds, updateRect, base, + flags); + } + + if (fBitmap == NULL) + return; + + SetDrawingMode(B_OP_ALPHA); + + if (!IsEnabled()) { + SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY); + SetHighColor(0, 0, 0, 120); + } + + BRect bitmapBounds(fBitmap->Bounds()); + BPoint bitmapLocation( + floorf((bounds.left + bounds.right + - (bitmapBounds.left + bitmapBounds.right)) / 2 + 0.5f), + floorf((bounds.top + bounds.bottom + - (bitmapBounds.top + bitmapBounds.bottom)) / 2 + 0.5f)); + + DrawBitmap(fBitmap, bitmapLocation); +} + + +void +BitmapButton::SetBackgroundMode(uint32 mode) +{ + if (fBackgroundMode != mode) { + fBackgroundMode = mode; + Invalidate(); + } +} + diff --git a/src/apps/webpositive/support/BitmapButton.h b/src/apps/webpositive/support/BitmapButton.h new file mode 100644 index 0000000000..432adcb34e --- /dev/null +++ b/src/apps/webpositive/support/BitmapButton.h @@ -0,0 +1,44 @@ +/* + * Copyright 2010 Stephan Aßmus . All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef BITMAP_BUTTON_H +#define BITMAP_BUTTON_H + +#include + + +class BBitmap; + + +class BitmapButton : public BButton { +public: + enum { + BUTTON_BACKGROUND = 0, + MENUBAR_BACKGROUND, + }; + + BitmapButton(const char* resourceName, + BMessage* message); + + BitmapButton(const uint8* bits, uint32 width, + uint32 height, color_space format, + BMessage* message); + + virtual ~BitmapButton(); + + virtual BSize MinSize(); + virtual BSize MaxSize(); + virtual BSize PreferredSize(); + + virtual void Draw(BRect updateRect); + + void SetBackgroundMode(uint32 mode); + +private: + BBitmap* fBitmap; + uint32 fBackgroundMode; +}; + + +#endif // BITMAP_BUTTON_H From c0f79c032172efa3649b0902d1ffbf2411f1e467 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 4 May 2010 19:34:13 +0000 Subject: [PATCH 267/349] Added button besides main menu bar which is only visible in fullscreen mode and allows to go back to window'ed mode. The icon is the window icon which Deskbar uses also. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@484 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 19 +++++-- src/apps/webpositive/BrowserWindow.h | 1 + src/apps/webpositive/support/BitmapButton.cpp | 3 ++ src/apps/webpositive/support/WindowIcon.h | 54 +++++++++++++++++++ 4 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 src/apps/webpositive/support/WindowIcon.h diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 44abfb4534..173f947577 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -35,6 +35,7 @@ #include "AuthenticationPanel.h" #include "BaseURL.h" +#include "BitmapButton.h" #include "BrowserApp.h" #include "BrowsingHistory.h" #include "CredentialsStorage.h" @@ -47,6 +48,7 @@ #include "WebPage.h" #include "WebView.h" #include "WebViewConstants.h" +#include "WindowIcon.h" #include #include #include @@ -376,10 +378,18 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, .SetInsets(kInsetSpacing, 0, kInsetSpacing, 0) ; + BitmapButton* toggleFullscreenButton = new BitmapButton(kWindowIconBits, + kWindowIconWidth, kWindowIconHeight, kWindowIconFormat, + new BMessage(TOGGLE_FULLSCREEN)); + toggleFullscreenButton->SetBackgroundMode(BitmapButton::MENUBAR_BACKGROUND); + // Layout AddChild(BGroupLayoutBuilder(B_VERTICAL) #if !INTEGRATE_MENU_INTO_TAB_BAR - .Add(mainMenu) + .Add(BGroupLayoutBuilder(B_HORIZONTAL) + .Add(mainMenu) + .Add(toggleFullscreenButton, 0.0f) + ) #endif .Add(fTabManager->TabGroup()) .Add(navigationGroup) @@ -400,10 +410,12 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fNavigationGroup = layoutItemFor(navigationGroup); fFindGroup = layoutItemFor(findGroup); fStatusGroup = layoutItemFor(statusGroup); - - CreateNewTab(url, true, webView); + fToggleFullscreenButton = layoutItemFor(toggleFullscreenButton); fFindGroup->SetVisible(false); + fToggleFullscreenButton->SetVisible(false); + + CreateNewTab(url, true, webView); if (toolbarPolicy == DoNotHaveToolbar) { #if !INTEGRATE_MENU_INTO_TAB_BAR @@ -1750,6 +1762,7 @@ BrowserWindow::_ToggleFullscreen() } fIsFullscreen = !fIsFullscreen; fFullscreenItem->SetMarked(fIsFullscreen); + fToggleFullscreenButton->SetVisible(fIsFullscreen); } diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 3ae549af66..c7d230c2f0 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -199,6 +199,7 @@ private: BLayoutItem* fNavigationGroup; BLayoutItem* fFindGroup; BLayoutItem* fStatusGroup; + BLayoutItem* fToggleFullscreenButton; BTextControl* fFindTextControl; BCheckBox* fFindCaseSensitiveCheckBox; diff --git a/src/apps/webpositive/support/BitmapButton.cpp b/src/apps/webpositive/support/BitmapButton.cpp index 1b4a22cee0..009079969c 100644 --- a/src/apps/webpositive/support/BitmapButton.cpp +++ b/src/apps/webpositive/support/BitmapButton.cpp @@ -80,6 +80,9 @@ BitmapButton::Draw(BRect updateRect) be_control_look->DrawButtonBackground(this, bounds, updateRect, base, flags); } else { + SetHighColor(tint_color(base, B_DARKEN_2_TINT)); + StrokeLine(bounds.LeftBottom(), bounds.RightBottom()); + bounds.bottom--; be_control_look->DrawMenuBarBackground(this, bounds, updateRect, base, flags); } diff --git a/src/apps/webpositive/support/WindowIcon.h b/src/apps/webpositive/support/WindowIcon.h new file mode 100644 index 0000000000..30d1622058 --- /dev/null +++ b/src/apps/webpositive/support/WindowIcon.h @@ -0,0 +1,54 @@ + +const uint32 kWindowIconWidth = 13; +const uint32 kWindowIconHeight = 14; +const color_space kWindowIconFormat = B_RGBA32; + +const unsigned char kWindowIconBits[] = { + 0x78, 0x78, 0x78, 0xff, 0x78, 0x78, 0x78, 0xff, 0x78, 0x78, 0x78, 0xff, 0x78, 0x78, 0x78, 0xff, + 0x78, 0x78, 0x78, 0xff, 0x78, 0x78, 0x78, 0xff, 0x78, 0x78, 0x78, 0xff, 0x78, 0x78, 0x78, 0xff, + 0x78, 0x78, 0x78, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x78, 0x78, 0xff, 0x66, 0xff, 0xff, 0xff, 0x66, 0xff, 0xff, 0xff, + 0x66, 0xff, 0xff, 0xff, 0x66, 0xff, 0xff, 0xff, 0x66, 0xff, 0xff, 0xff, 0x66, 0xff, 0xff, 0xff, + 0x66, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x78, 0x78, 0xff, 0x13, 0xaf, 0xff, 0xff, + 0x13, 0xaf, 0xff, 0xff, 0x13, 0xaf, 0xff, 0xff, 0x13, 0xaf, 0xff, 0xff, 0x13, 0xaf, 0xff, 0xff, + 0x13, 0xaf, 0xff, 0xff, 0x13, 0xaf, 0xff, 0xff, 0x78, 0x78, 0x78, 0xff, 0x78, 0x78, 0x78, 0xff, + 0x78, 0x78, 0x78, 0xff, 0x78, 0x78, 0x78, 0xff, 0x78, 0x78, 0x78, 0xff, 0x78, 0x78, 0x78, 0xff, + 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, + 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, + 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x78, 0x78, 0x78, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc8, 0xc8, 0xc8, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xc8, 0xc8, 0xc8, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0xff, 0xc8, 0xc8, 0xc8, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0xff, + 0xc8, 0xc8, 0xc8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x78, 0x78, 0x78, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc8, 0xc8, 0xc8, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xc8, 0xc8, 0xc8, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0xff, 0xc8, 0xc8, 0xc8, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0x00, 0x00, 0x00, 0xff, 0x78, 0x78, 0x78, 0xff, + 0xc8, 0xc8, 0xc8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x78, 0x78, 0x78, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, + 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, + 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff +}; + From c2227feb1e1b34c9d9a7025e16fb8ac30302fde6 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 4 May 2010 21:54:10 +0000 Subject: [PATCH 268/349] Implemented an "auto-hide the interface" feature for the full-screen mode. The mouse cursor will automatically hide if you don't move it, unless it's over the interface. The interface will disappear after three seconds if the cursor is not above it. It will re-appear when you touch the top of the screen with the mouse. I find this the best solution, since the mouse is also used for navigation in the page, and showing the interface based on some virtual area of the interface would just get in the way. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@485 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 209 +++++++++++++++++++------ src/apps/webpositive/BrowserWindow.h | 43 +++-- src/apps/webpositive/SettingsKeys.cpp | 3 + src/apps/webpositive/SettingsKeys.h | 2 + 4 files changed, 192 insertions(+), 65 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 173f947577..68febf2eff 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -64,6 +64,7 @@ #include #include #include +#include #include #include #include @@ -78,31 +79,33 @@ enum { - OPEN_LOCATION = 'open', - GO_BACK = 'goba', - GO_FORWARD = 'gofo', - STOP = 'stop', - GOTO_URL = 'goul', - RELOAD = 'reld', - CLEAR_HISTORY = 'clhs', + OPEN_LOCATION = 'open', + GO_BACK = 'goba', + GO_FORWARD = 'gofo', + STOP = 'stop', + GOTO_URL = 'goul', + RELOAD = 'reld', + CLEAR_HISTORY = 'clhs', - CREATE_BOOKMARK = 'crbm', - SHOW_BOOKMARKS = 'shbm', + CREATE_BOOKMARK = 'crbm', + SHOW_BOOKMARKS = 'shbm', - ZOOM_FACTOR_INCREASE = 'zfin', - ZOOM_FACTOR_DECREASE = 'zfdc', - ZOOM_FACTOR_RESET = 'zfrs', - ZOOM_TEXT_ONLY = 'zfto', + ZOOM_FACTOR_INCREASE = 'zfin', + ZOOM_FACTOR_DECREASE = 'zfdc', + ZOOM_FACTOR_RESET = 'zfrs', + ZOOM_TEXT_ONLY = 'zfto', - TOGGLE_FULLSCREEN = 'tgfs', + TOGGLE_FULLSCREEN = 'tgfs', + TOGGLE_AUTO_HIDE_INTERFACE_IN_FULLSCREEN = 'tgah', + CHECK_AUTO_HIDE_INTERFACE = 'cahi', - EDIT_SHOW_FIND_GROUP = 'sfnd', - EDIT_HIDE_FIND_GROUP = 'hfnd', - EDIT_FIND_NEXT = 'fndn', - EDIT_FIND_PREVIOUS = 'fndp', - FIND_TEXT_CHANGED = 'ftxt', + EDIT_SHOW_FIND_GROUP = 'sfnd', + EDIT_HIDE_FIND_GROUP = 'hfnd', + EDIT_FIND_NEXT = 'fndn', + EDIT_FIND_PREVIOUS = 'fndp', + FIND_TEXT_CHANGED = 'ftxt', - SELECT_TAB = 'sltb', + SELECT_TAB = 'sltb', }; @@ -188,15 +191,18 @@ private: BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, - const BString& url, ToolbarPolicy toolbarPolicy, BWebView* webView) + const BString& url, uint32 interfaceElements, BWebView* webView) : BWebWindow(frame, kApplicationName, B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS), fIsFullscreen(false), + fPulseRunner(NULL), + fVisibleInterfaceElements(interfaceElements), fAppSettings(appSettings), fZoomTextOnly(true), - fShowTabsIfSinglePageOpen(true) + fShowTabsIfSinglePageOpen(true), + fAutoHideInterfaceInFullscreenMode(false) { // Begin listening to settings changes and read some current values. fAppSettings->AddListener(BMessenger(this)); @@ -284,6 +290,10 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fFullscreenItem = new BMenuItem("Fullscreen", new BMessage(TOGGLE_FULLSCREEN), B_RETURN); menu->AddItem(fFullscreenItem); + fAutoHideInterfaceInFullscreenItem = new BMenuItem("Auto hide interface " + "in fullscreen mode", + new BMessage(TOGGLE_AUTO_HIDE_INTERFACE_IN_FULLSCREEN)); + menu->AddItem(fAutoHideInterfaceInFullscreenItem); mainMenu->AddItem(menu); @@ -371,11 +381,15 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) ; - BView* statusGroup = BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) - .Add(fStatusText) - .Add(fLoadingProgressBar, 0.2) - .AddStrut(12 - kElementSpacing) - .SetInsets(kInsetSpacing, 0, kInsetSpacing, 0) + // Status bar group + BView* statusGroup = BGroupLayoutBuilder(B_VERTICAL) + .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) + .Add(fStatusText) + .Add(fLoadingProgressBar, 0.2) + .AddStrut(12 - kElementSpacing) + .SetInsets(kInsetSpacing, 0, kInsetSpacing, 0) + ) ; BitmapButton* toggleFullscreenButton = new BitmapButton(kWindowIconBits, @@ -383,19 +397,20 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, new BMessage(TOGGLE_FULLSCREEN)); toggleFullscreenButton->SetBackgroundMode(BitmapButton::MENUBAR_BACKGROUND); + BView* menuBarGroup = BGroupLayoutBuilder(B_HORIZONTAL) + .Add(mainMenu) + .Add(toggleFullscreenButton, 0.0f) + ; + // Layout AddChild(BGroupLayoutBuilder(B_VERTICAL) #if !INTEGRATE_MENU_INTO_TAB_BAR - .Add(BGroupLayoutBuilder(B_HORIZONTAL) - .Add(mainMenu) - .Add(toggleFullscreenButton, 0.0f) - ) + .Add(menuBarGroup) #endif .Add(fTabManager->TabGroup()) .Add(navigationGroup) .Add(fTabManager->ContainerView()) .Add(findGroup) - .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(statusGroup) ); @@ -405,7 +420,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fURLInputGroup->MakeFocus(true); - fMenuGroup = layoutItemFor(mainMenu); + fMenuGroup = layoutItemFor(menuBarGroup); fTabGroup = layoutItemFor(fTabManager->TabGroup()); fNavigationGroup = layoutItemFor(navigationGroup); fFindGroup = layoutItemFor(findGroup); @@ -416,14 +431,10 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fToggleFullscreenButton->SetVisible(false); CreateNewTab(url, true, webView); - - if (toolbarPolicy == DoNotHaveToolbar) { -#if !INTEGRATE_MENU_INTO_TAB_BAR - fMenuGroup->SetVisible(false); -#endif - fTabGroup->SetVisible(false); - fNavigationGroup->SetVisible(false); - } + _ShowInterface(true); + _SetAutoHideInterfaceInFullscreen(fAppSettings->GetValue( + kAutoHideInterfaceInFullscreenMode, + fAutoHideInterfaceInFullscreenMode)); AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(EDIT_HIDE_FIND_GROUP)); @@ -447,6 +458,7 @@ BrowserWindow::~BrowserWindow() { fAppSettings->RemoveListener(BMessenger(this)); delete fTabManager; + delete fPulseRunner; } @@ -482,6 +494,13 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) } } } + if (message->what == B_MOUSE_MOVED || message->what == B_MOUSE_DOWN + || message->what == B_MOUSE_UP) { + message->FindPoint("where", &fLastMousePos); + if (message->FindInt64("when", &fLastMouseMovedTime) != B_OK) + fLastMouseMovedTime = system_time(); + _CheckAutoHideInterface(); + } BWebWindow::DispatchMessage(message, target); } @@ -629,6 +648,15 @@ BrowserWindow::MessageReceived(BMessage* message) _ToggleFullscreen(); break; + case TOGGLE_AUTO_HIDE_INTERFACE_IN_FULLSCREEN: + _SetAutoHideInterfaceInFullscreen( + !fAutoHideInterfaceInFullscreenMode); + break; + + case CHECK_AUTO_HIDE_INTERFACE: + _CheckAutoHideInterface(); + break; + case EDIT_FIND_NEXT: CurrentWebView()->FindString(fFindTextControl->Text(), true, fFindCaseSensitiveCheckBox->Value()); @@ -758,6 +786,9 @@ BrowserWindow::MessageReceived(BMessage* message) } else if (name == kSettingsKeyNewTabPolicy && message->FindUInt32("value", &value) == B_OK) { fNewTabPolicy = value; + } else if (name == kAutoHideInterfaceInFullscreenMode + && message->FindBool("value", &flag) == B_OK) { + _SetAutoHideInterfaceInFullscreen(flag); } break; } @@ -960,7 +991,7 @@ BrowserWindow::NewPageCreated(BWebView* view, BRect windowFrame, { if (windowFrame.IsValid()) { BrowserWindow* window = new BrowserWindow(windowFrame, fAppSettings, - BString(), DoNotHaveToolbar, view); + BString(), INTERFACE_ELEMENT_STATUS, view); window->Show(); } else CreateNewTab(BString(), activate, view); @@ -1016,13 +1047,11 @@ BrowserWindow::LoadProgress(float progress, BWebView* view) if (view != CurrentWebView()) return; - if (fLoadingProgressBar) { - if (progress < 100 && fLoadingProgressBar->IsHidden()) - fLoadingProgressBar->Show(); - else if (progress == 100 && !fLoadingProgressBar->IsHidden()) - fLoadingProgressBar->Hide(); - fLoadingProgressBar->SetTo(progress); - } + if (progress < 100 && fLoadingProgressBar->IsHidden()) + fLoadingProgressBar->Show(); + else if (progress == 100 && !fLoadingProgressBar->IsHidden()) + fLoadingProgressBar->Hide(); + fLoadingProgressBar->SetTo(progress); } @@ -1035,7 +1064,7 @@ BrowserWindow::LoadFailed(const BString& url, BWebView* view) BString status(url); status << " failed."; view->WebPage()->SetStatusMessage(status); - if (fLoadingProgressBar && !fLoadingProgressBar->IsHidden()) + if (!fLoadingProgressBar->IsHidden()) fLoadingProgressBar->Hide(); } @@ -1049,7 +1078,7 @@ BrowserWindow::LoadFinished(const BString& url, BWebView* view) BString status(url); status << " finished."; view->WebPage()->SetStatusMessage(status); - if (fLoadingProgressBar && !fLoadingProgressBar->IsHidden()) + if (!fLoadingProgressBar->IsHidden()) fLoadingProgressBar->Hide(); NavigationCapabilitiesChanged(fBackButton->IsEnabled(), @@ -1753,6 +1782,8 @@ BrowserWindow::_ToggleFullscreen() SetFlags(Flags() & ~(B_NOT_RESIZABLE | B_NOT_MOVABLE)); SetLook(B_DOCUMENT_WINDOW_LOOK); + + _ShowInterface(true); } else { fNonFullscreenWindowFrame = Frame(); _ResizeToScreen(); @@ -1774,3 +1805,79 @@ BrowserWindow::_ResizeToScreen() ResizeTo(screen.Frame().Width(), screen.Frame().Height()); } + +void +BrowserWindow::_SetAutoHideInterfaceInFullscreen(bool doIt) +{ + if (fAutoHideInterfaceInFullscreenMode == doIt) + return; + + fAutoHideInterfaceInFullscreenMode = doIt; + fAutoHideInterfaceInFullscreenItem->SetMarked(doIt); + if (fAppSettings->GetValue(kAutoHideInterfaceInFullscreenMode, doIt) + != doIt) { + fAppSettings->SetValue(kAutoHideInterfaceInFullscreenMode, doIt); + } + + if (fAutoHideInterfaceInFullscreenMode) { + BMessage message(CHECK_AUTO_HIDE_INTERFACE); + fPulseRunner = new BMessageRunner(BMessenger(this), &message, 300000); + } else { + delete fPulseRunner; + fPulseRunner = NULL; + } +} + + +void +BrowserWindow::_CheckAutoHideInterface() +{ + if (!fIsFullscreen || !fAutoHideInterfaceInFullscreenMode) + return; + + bigtime_t now = system_time(); + float navigationGroupBottom = fNavigationGroup->IsVisible() ? + fNavigationGroup->Frame().bottom : 0; + if (fLastMousePos.y > navigationGroupBottom + && now - fLastMouseMovedTime > 1500000) { + be_app->ObscureCursor(); + } + + if (fLastMousePos.y == 0) + _ShowInterface(true); + else if (fNavigationGroup->IsVisible() + && fLastMousePos.y > fNavigationGroup->Frame().bottom + && now - fLastMouseMovedTime > 3000000) { + // NOTE: Do not re-use navigationGroupBottom in the above + // check, since we only want to hide the interface when it is visible. + _ShowInterface(false); + } +} + + +void +BrowserWindow::_ShowInterface(bool show) +{ + if (show) { +#if !INTEGRATE_MENU_INTO_TAB_BAR + fMenuGroup->SetVisible( + (fVisibleInterfaceElements & INTERFACE_ELEMENT_MENU) != 0); +#endif + fTabGroup->SetVisible( + (fVisibleInterfaceElements & INTERFACE_ELEMENT_TABS) != 0); + fNavigationGroup->SetVisible( + (fVisibleInterfaceElements & INTERFACE_ELEMENT_NAVIGATION) != 0); + fStatusGroup->SetVisible( + (fVisibleInterfaceElements & INTERFACE_ELEMENT_STATUS) != 0); + } else { + fMenuGroup->SetVisible(false); + fTabGroup->SetVisible(false); + fNavigationGroup->SetVisible(false); + fStatusGroup->SetVisible(false); + } + // TODO: Setting the group visible seems to unhide the status bar. + // Fix in Haiku? + if (!fLoadingProgressBar->IsHidden()) + fLoadingProgressBar->Hide(); +} + diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index c7d230c2f0..8956bffa2d 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -41,6 +41,7 @@ class BFile; class BLayoutItem; class BMenu; class BMenuItem; +class BMessageRunner; class BPath; class BStatusBar; class BStringView; @@ -51,25 +52,29 @@ class SettingsMessage; class TabManager; class URLInputGroup; -enum ToolbarPolicy { - HaveToolbar, - DoNotHaveToolbar +enum { + INTERFACE_ELEMENT_MENU = 1 << 0, + INTERFACE_ELEMENT_TABS = 1 << 1, + INTERFACE_ELEMENT_NAVIGATION = 1 << 2, + INTERFACE_ELEMENT_STATUS = 1 << 3, + + INTERFACE_ELEMENT_ALL = 0xffff }; enum NewPagePolicy { - OpenBlankPage = 0, - OpenStartPage = 1, - OpenSearchPage = 2, - CloneCurrentPage = 3 + OpenBlankPage = 0, + OpenStartPage = 1, + OpenSearchPage = 2, + CloneCurrentPage = 3 }; enum { - NEW_WINDOW = 'nwnd', - NEW_TAB = 'ntab', - WINDOW_OPENED = 'wndo', - WINDOW_CLOSED = 'wndc', - SHOW_DOWNLOAD_WINDOW = 'sdwd', - SHOW_SETTINGS_WINDOW = 'sswd' + NEW_WINDOW = 'nwnd', + NEW_TAB = 'ntab', + WINDOW_OPENED = 'wndo', + WINDOW_CLOSED = 'wndc', + SHOW_DOWNLOAD_WINDOW = 'sdwd', + SHOW_SETTINGS_WINDOW = 'sswd' }; #define INTEGRATE_MENU_INTO_TAB_BAR 0 @@ -80,7 +85,8 @@ public: BrowserWindow(BRect frame, SettingsMessage* appSettings, const BString& url, - ToolbarPolicy = HaveToolbar, + uint32 interfaceElements + = INTERFACE_ELEMENT_ALL, BWebView* webView = NULL); virtual ~BrowserWindow(); @@ -172,6 +178,9 @@ private: void _ToggleFullscreen(); void _ResizeToScreen(); + void _SetAutoHideInterfaceInFullscreen(bool doIt); + void _CheckAutoHideInterface(); + void _ShowInterface(bool show); private: BMenu* fHistoryMenu; @@ -184,6 +193,7 @@ private: BMenuItem* fFindNextMenuItem; BMenuItem* fZoomTextOnlyMenuItem; BMenuItem* fFullscreenItem; + BMenuItem* fAutoHideInterfaceInFullscreenItem; BMenuItem* fBackMenuItem; BMenuItem* fForwardMenuItem; @@ -207,11 +217,16 @@ private: bool fIsFullscreen; BRect fNonFullscreenWindowFrame; + BMessageRunner* fPulseRunner; + uint32 fVisibleInterfaceElements; + bigtime_t fLastMouseMovedTime; + BPoint fLastMousePos; // cached settings SettingsMessage* fAppSettings; bool fZoomTextOnly; bool fShowTabsIfSinglePageOpen; + bool fAutoHideInterfaceInFullscreenMode; uint32 fNewWindowPolicy; uint32 fNewTabPolicy; BString fStartPageURL; diff --git a/src/apps/webpositive/SettingsKeys.cpp b/src/apps/webpositive/SettingsKeys.cpp index d525ba6aeb..f9e3de942f 100644 --- a/src/apps/webpositive/SettingsKeys.cpp +++ b/src/apps/webpositive/SettingsKeys.cpp @@ -45,3 +45,6 @@ const char* kDefaultSearchPageURL = "http://www.google.com"; const char* kSettingsKeyUseProxy = "use http proxy"; const char* kSettingsKeyProxyAddress = "http proxy address"; const char* kSettingsKeyProxyPort = "http proxy port"; + +const char* kAutoHideInterfaceInFullscreenMode + = "auto hide interface in full screen mode"; diff --git a/src/apps/webpositive/SettingsKeys.h b/src/apps/webpositive/SettingsKeys.h index 6be0e5e15c..87abb6be7d 100644 --- a/src/apps/webpositive/SettingsKeys.h +++ b/src/apps/webpositive/SettingsKeys.h @@ -46,4 +46,6 @@ extern const char* kSettingsKeyUseProxy; extern const char* kSettingsKeyProxyAddress; extern const char* kSettingsKeyProxyPort; +extern const char* kAutoHideInterfaceInFullscreenMode; + #endif // SETTINGS_KEYS_H From ea40bbf2d1618534fa28d8a977a21a60cb073ca0 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 4 May 2010 22:36:04 +0000 Subject: [PATCH 269/349] * Moved "Auto-hide" menu item into Settings window, as a check box along the "show tabs if single page only" option. * Fixed problems with showing tabs when opening new tabs while the interface was hidden. Introduced a new flag which tracks the hidden state to make this easier. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@486 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 35 ++++++++++++++----------- src/apps/webpositive/BrowserWindow.h | 2 +- src/apps/webpositive/SettingsKeys.cpp | 5 ++-- src/apps/webpositive/SettingsKeys.h | 3 +-- src/apps/webpositive/SettingsWindow.cpp | 18 +++++++++++++ src/apps/webpositive/SettingsWindow.h | 1 + 6 files changed, 43 insertions(+), 21 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 68febf2eff..75f1757ace 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -197,6 +197,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS), fIsFullscreen(false), + fInterfaceVisible(false), fPulseRunner(NULL), fVisibleInterfaceElements(interfaceElements), fAppSettings(appSettings), @@ -290,11 +291,6 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fFullscreenItem = new BMenuItem("Fullscreen", new BMessage(TOGGLE_FULLSCREEN), B_RETURN); menu->AddItem(fFullscreenItem); - fAutoHideInterfaceInFullscreenItem = new BMenuItem("Auto hide interface " - "in fullscreen mode", - new BMessage(TOGGLE_AUTO_HIDE_INTERFACE_IN_FULLSCREEN)); - menu->AddItem(fAutoHideInterfaceInFullscreenItem); - mainMenu->AddItem(menu); fHistoryMenu = new BMenu("History"); @@ -433,7 +429,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, CreateNewTab(url, true, webView); _ShowInterface(true); _SetAutoHideInterfaceInFullscreen(fAppSettings->GetValue( - kAutoHideInterfaceInFullscreenMode, + kSettingsKeyAutoHideInterfaceInFullscreenMode, fAutoHideInterfaceInFullscreenMode)); AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(EDIT_HIDE_FIND_GROUP)); @@ -786,7 +782,7 @@ BrowserWindow::MessageReceived(BMessage* message) } else if (name == kSettingsKeyNewTabPolicy && message->FindUInt32("value", &value) == B_OK) { fNewTabPolicy = value; - } else if (name == kAutoHideInterfaceInFullscreenMode + } else if (name == kSettingsKeyAutoHideInterfaceInFullscreenMode && message->FindBool("value", &flag) == B_OK) { _SetAutoHideInterfaceInFullscreen(flag); } @@ -956,6 +952,7 @@ BrowserWindow::CreateNewTab(const BString& _url, bool select, BWebView* webView) fURLInputGroup->MakeFocus(true); } + _ShowInterface(true); _UpdateTabGroupVisibility(); } @@ -1302,8 +1299,10 @@ void BrowserWindow::_UpdateTabGroupVisibility() { if (Lock()) { - fTabGroup->SetVisible(fShowTabsIfSinglePageOpen - || fTabManager->CountTabs() > 1); + if (fInterfaceVisible) { + fTabGroup->SetVisible(fShowTabsIfSinglePageOpen + || fTabManager->CountTabs() > 1); + } fTabManager->SetCloseButtonsAvailable(fTabManager->CountTabs() > 1); Unlock(); } @@ -1813,10 +1812,10 @@ BrowserWindow::_SetAutoHideInterfaceInFullscreen(bool doIt) return; fAutoHideInterfaceInFullscreenMode = doIt; - fAutoHideInterfaceInFullscreenItem->SetMarked(doIt); - if (fAppSettings->GetValue(kAutoHideInterfaceInFullscreenMode, doIt) - != doIt) { - fAppSettings->SetValue(kAutoHideInterfaceInFullscreenMode, doIt); + if (fAppSettings->GetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode, + doIt) != doIt) { + fAppSettings->SetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode, + doIt); } if (fAutoHideInterfaceInFullscreenMode) { @@ -1858,13 +1857,19 @@ BrowserWindow::_CheckAutoHideInterface() void BrowserWindow::_ShowInterface(bool show) { + if (fInterfaceVisible == show) + return; + + fInterfaceVisible = show; + if (show) { #if !INTEGRATE_MENU_INTO_TAB_BAR fMenuGroup->SetVisible( (fVisibleInterfaceElements & INTERFACE_ELEMENT_MENU) != 0); #endif - fTabGroup->SetVisible( - (fVisibleInterfaceElements & INTERFACE_ELEMENT_TABS) != 0); + fTabGroup->SetVisible((fShowTabsIfSinglePageOpen + || fTabManager->CountTabs() > 1) + && (fVisibleInterfaceElements & INTERFACE_ELEMENT_TABS) != 0); fNavigationGroup->SetVisible( (fVisibleInterfaceElements & INTERFACE_ELEMENT_NAVIGATION) != 0); fStatusGroup->SetVisible( diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 8956bffa2d..1750584fb3 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -193,7 +193,6 @@ private: BMenuItem* fFindNextMenuItem; BMenuItem* fZoomTextOnlyMenuItem; BMenuItem* fFullscreenItem; - BMenuItem* fAutoHideInterfaceInFullscreenItem; BMenuItem* fBackMenuItem; BMenuItem* fForwardMenuItem; @@ -216,6 +215,7 @@ private: TabManager* fTabManager; bool fIsFullscreen; + bool fInterfaceVisible; BRect fNonFullscreenWindowFrame; BMessageRunner* fPulseRunner; uint32 fVisibleInterfaceElements; diff --git a/src/apps/webpositive/SettingsKeys.cpp b/src/apps/webpositive/SettingsKeys.cpp index f9e3de942f..b65abd8da0 100644 --- a/src/apps/webpositive/SettingsKeys.cpp +++ b/src/apps/webpositive/SettingsKeys.cpp @@ -30,6 +30,8 @@ const char* kSettingsKeyDownloadPath = "download path"; const char* kSettingsKeyShowTabsIfSinglePageOpen = "show tabs if single page open"; +const char* kSettingsKeyAutoHideInterfaceInFullscreenMode + = "auto hide interface in full screen mode"; const char* kSettingsKeyNewWindowPolicy = "new window policy"; const char* kSettingsKeyNewTabPolicy = "new tab policy"; @@ -45,6 +47,3 @@ const char* kDefaultSearchPageURL = "http://www.google.com"; const char* kSettingsKeyUseProxy = "use http proxy"; const char* kSettingsKeyProxyAddress = "http proxy address"; const char* kSettingsKeyProxyPort = "http proxy port"; - -const char* kAutoHideInterfaceInFullscreenMode - = "auto hide interface in full screen mode"; diff --git a/src/apps/webpositive/SettingsKeys.h b/src/apps/webpositive/SettingsKeys.h index 87abb6be7d..08fc6077be 100644 --- a/src/apps/webpositive/SettingsKeys.h +++ b/src/apps/webpositive/SettingsKeys.h @@ -32,6 +32,7 @@ extern const char* kSettingsKeyDownloadPath; extern const char* kSettingsKeyShowTabsIfSinglePageOpen; +extern const char* kSettingsKeyAutoHideInterfaceInFullscreenMode; extern const char* kSettingsKeyNewWindowPolicy; extern const char* kSettingsKeyNewTabPolicy; @@ -46,6 +47,4 @@ extern const char* kSettingsKeyUseProxy; extern const char* kSettingsKeyProxyAddress; extern const char* kSettingsKeyProxyPort; -extern const char* kAutoHideInterfaceInFullscreenMode; - #endif // SETTINGS_KEYS_H diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index b9fa66136a..5026f867dc 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -70,6 +70,7 @@ enum { MSG_NEW_TABS_BEHAVIOR_CHANGED = 'ntbc', MSG_HISTORY_MENU_DAYS_CHANGED = 'digm', MSG_TAB_DISPLAY_BEHAVIOR_CHANGED = 'tdbc', + MSG_AUTO_HIDE_BEHAVIOR_CHANGED = 'ahbc', MSG_STANDARD_FONT_CHANGED = 'stfc', MSG_SERIF_FONT_CHANGED = 'sefc', @@ -195,6 +196,7 @@ SettingsWindow::MessageReceived(BMessage* message) case MSG_NEW_TABS_BEHAVIOR_CHANGED: case MSG_HISTORY_MENU_DAYS_CHANGED: case MSG_TAB_DISPLAY_BEHAVIOR_CHANGED: + case MSG_AUTO_HIDE_BEHAVIOR_CHANGED: case MSG_STANDARD_FONT_CHANGED: case MSG_SERIF_FONT_CHANGED: case MSG_SANS_SERIF_FONT_CHANGED: @@ -311,6 +313,11 @@ SettingsWindow::_CreateGeneralPage(float spacing) new BMessage(MSG_TAB_DISPLAY_BEHAVIOR_CHANGED)); fShowTabsIfOnlyOnePage->SetValue(B_CONTROL_ON); + fAutoHideInterfaceInFullscreenMode = new BCheckBox("auto-hide interface", + TR("Auto-hide interface in fullscreen mode."), + new BMessage(MSG_AUTO_HIDE_BEHAVIOR_CHANGED)); + fAutoHideInterfaceInFullscreenMode->SetValue(B_CONTROL_OFF); + BView* view = BGroupLayoutBuilder(B_VERTICAL, spacing / 2) .Add(BGridLayoutBuilder(spacing / 2, spacing / 2) .Add(fStartPageControl->CreateLabelLayoutItem(), 0, 0) @@ -332,6 +339,7 @@ SettingsWindow::_CreateGeneralPage(float spacing) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing)) .Add(fShowTabsIfOnlyOnePage) + .Add(fAutoHideInterfaceInFullscreenMode) .Add(fDaysInHistoryMenuControl) .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing)) @@ -499,6 +507,11 @@ SettingsWindow::_CanApplySettings() const canApply = canApply || ((fShowTabsIfOnlyOnePage->Value() == B_CONTROL_ON) != fSettings->GetValue(kSettingsKeyShowTabsIfSinglePageOpen, true)); + canApply = canApply || ( + (fAutoHideInterfaceInFullscreenMode->Value() == B_CONTROL_ON) + != fSettings->GetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode, + false)); + canApply = canApply || (_MaxHistoryAge() != BrowsingHistory::DefaultInstance()->MaxHistoryItemAge()); @@ -560,6 +573,8 @@ SettingsWindow::_ApplySettings() fSettings->SetValue(kSettingsKeyDownloadPath, fDownloadFolderControl->Text()); fSettings->SetValue(kSettingsKeyShowTabsIfSinglePageOpen, fShowTabsIfOnlyOnePage->Value() == B_CONTROL_ON); + fSettings->SetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode, + fAutoHideInterfaceInFullscreenMode->Value() == B_CONTROL_ON); // New page policies fSettings->SetValue(kSettingsKeyNewWindowPolicy, _NewWindowPolicy()); @@ -622,6 +637,9 @@ SettingsWindow::_RevertSettings() fSettings->GetValue(kSettingsKeyDownloadPath, kDefaultDownloadPath)); fShowTabsIfOnlyOnePage->SetValue( fSettings->GetValue(kSettingsKeyShowTabsIfSinglePageOpen, true)); + fAutoHideInterfaceInFullscreenMode->SetValue( + fSettings->GetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode, + false)); BString text; text << BrowsingHistory::DefaultInstance()->MaxHistoryItemAge(); diff --git a/src/apps/webpositive/SettingsWindow.h b/src/apps/webpositive/SettingsWindow.h index c595632f8e..cfd8f54ce9 100644 --- a/src/apps/webpositive/SettingsWindow.h +++ b/src/apps/webpositive/SettingsWindow.h @@ -96,6 +96,7 @@ private: BTextControl* fDaysInHistoryMenuControl; BCheckBox* fShowTabsIfOnlyOnePage; + BCheckBox* fAutoHideInterfaceInFullscreenMode; FontSelectionView* fStandardFontView; FontSelectionView* fSerifFontView; From e7c6e9f7476fbcf4524baa322f4b831ff81e94c6 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 5 May 2010 10:24:38 +0000 Subject: [PATCH 270/349] Reset the page icon in the URL input for new tabs. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@487 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 75f1757ace..ee72d6b890 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -935,8 +935,8 @@ BrowserWindow::CreateNewTab(const BString& _url, bool select, BWebView* webView) if (CurrentWebView() != NULL) url = CurrentWebView()->MainFrameURL(); break; - default: case OpenBlankPage: + default: break; } } @@ -948,6 +948,7 @@ BrowserWindow::CreateNewTab(const BString& _url, bool select, BWebView* webView) fTabManager->SelectTab(fTabManager->CountTabs() - 1); SetCurrentWebView(webView); webView->WebPage()->ResendNotifications(); + fURLInputGroup->SetPageIcon(NULL); fURLInputGroup->SetText(url.String()); fURLInputGroup->MakeFocus(true); } From e07fc6b71df68266b262583b4d9ca43138ea6c9f Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 5 May 2010 11:04:24 +0000 Subject: [PATCH 271/349] * Changed the implementation of context menus in DownloadProgressViews. The views were intercepting mouse messages even if the window was not showing. Now secondary clicks are intercepted in DownloadWindow and the target view is found, which makes this much cheaper. * Offset context menus by 2 pixels, so the mouse does not start directly over an item. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@488 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 18 ++++--- src/apps/webpositive/BrowserWindow.h | 1 + src/apps/webpositive/DownloadProgressView.cpp | 52 +++++++------------ src/apps/webpositive/DownloadProgressView.h | 4 +- src/apps/webpositive/DownloadWindow.cpp | 30 +++++++++++ src/apps/webpositive/DownloadWindow.h | 2 + 6 files changed, 65 insertions(+), 42 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index ee72d6b890..92873f1d97 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1300,16 +1300,22 @@ void BrowserWindow::_UpdateTabGroupVisibility() { if (Lock()) { - if (fInterfaceVisible) { - fTabGroup->SetVisible(fShowTabsIfSinglePageOpen - || fTabManager->CountTabs() > 1); - } + if (fInterfaceVisible) + fTabGroup->SetVisible(_TabGroupShouldBeVisible()); fTabManager->SetCloseButtonsAvailable(fTabManager->CountTabs() > 1); Unlock(); } } +bool +BrowserWindow::_TabGroupShouldBeVisible() const +{ + return (fShowTabsIfSinglePageOpen || fTabManager->CountTabs() > 1) + && (fVisibleInterfaceElements & INTERFACE_ELEMENT_TABS) != 0; +} + + void BrowserWindow::_ShutdownTab(int32 index) { @@ -1868,9 +1874,7 @@ BrowserWindow::_ShowInterface(bool show) fMenuGroup->SetVisible( (fVisibleInterfaceElements & INTERFACE_ELEMENT_MENU) != 0); #endif - fTabGroup->SetVisible((fShowTabsIfSinglePageOpen - || fTabManager->CountTabs() > 1) - && (fVisibleInterfaceElements & INTERFACE_ELEMENT_TABS) != 0); + fTabGroup->SetVisible(_TabGroupShouldBeVisible()); fNavigationGroup->SetVisible( (fVisibleInterfaceElements & INTERFACE_ELEMENT_NAVIGATION) != 0); fStatusGroup->SetVisible( diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 1750584fb3..5d272b2eb8 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -152,6 +152,7 @@ private: private: void _UpdateTitle(const BString &title); void _UpdateTabGroupVisibility(); + bool _TabGroupShouldBeVisible() const; void _ShutdownTab(int32 index); void _TabChanged(int32 index); diff --git a/src/apps/webpositive/DownloadProgressView.cpp b/src/apps/webpositive/DownloadProgressView.cpp index e7914e8736..f0c4e5bb3b 100644 --- a/src/apps/webpositive/DownloadProgressView.cpp +++ b/src/apps/webpositive/DownloadProgressView.cpp @@ -208,10 +208,6 @@ DownloadProgressView::DownloadProgressView(const BMessage* archive) bool DownloadProgressView::Init(BMessage* archive) { - // We need to receive mouse events even for the areas of children views, - // so we can pop up a context menu. - SetEventMask(B_POINTER_EVENTS); - fCurrentSize = 0; fExpectedSize = 0; fLastUpdateTime = 0; @@ -339,35 +335,6 @@ DownloadProgressView::AllAttached() } -void -DownloadProgressView::MouseDown(BPoint where) -{ - if (!Bounds().Contains(where)) - return; - - int32 buttons; - if (Window()->CurrentMessage()->FindInt32("buttons", &buttons) != B_OK) - return; - - if ((buttons & B_SECONDARY_MOUSE_BUTTON) == 0) - return; - - where = ConvertToScreen(where) + BPoint(2, 2); - - BPopUpMenu* contextMenu = new BPopUpMenu("download context"); - BMenuItem* copyURL = new BMenuItem("Copy URL to clipboard", - new BMessage(COPY_URL_TO_CLIPBOARD)); - copyURL->SetEnabled(fURL.Length() > 0); - contextMenu->AddItem(copyURL); - BMenuItem* openFolder = new BMenuItem("Open containing folder", - new BMessage(OPEN_CONTAINING_FOLDER)); - contextMenu->AddItem(openFolder); - - contextMenu->SetTargetForItems(this); - contextMenu->Go(where, true, true, true); -} - - void DownloadProgressView::Draw(BRect updateRect) { @@ -588,6 +555,25 @@ DownloadProgressView::MessageReceived(BMessage* message) } +void +DownloadProgressView::ShowContextMenu(BPoint screenWhere) +{ + screenWhere += BPoint(2, 2); + + BPopUpMenu* contextMenu = new BPopUpMenu("download context"); + BMenuItem* copyURL = new BMenuItem("Copy URL to clipboard", + new BMessage(COPY_URL_TO_CLIPBOARD)); + copyURL->SetEnabled(fURL.Length() > 0); + contextMenu->AddItem(copyURL); + BMenuItem* openFolder = new BMenuItem("Open containing folder", + new BMessage(OPEN_CONTAINING_FOLDER)); + contextMenu->AddItem(openFolder); + + contextMenu->SetTargetForItems(this); + contextMenu->Go(screenWhere, true, true, true); +} + + BWebDownload* DownloadProgressView::Download() const { diff --git a/src/apps/webpositive/DownloadProgressView.h b/src/apps/webpositive/DownloadProgressView.h index 256245442d..32a021b169 100644 --- a/src/apps/webpositive/DownloadProgressView.h +++ b/src/apps/webpositive/DownloadProgressView.h @@ -57,12 +57,12 @@ public: virtual void DetachedFromWindow(); virtual void AllAttached(); - virtual void MouseDown(BPoint where); - virtual void Draw(BRect updateRect); virtual void MessageReceived(BMessage* message); + void ShowContextMenu(BPoint screenWhere); + BWebDownload* Download() const; const BString& URL() const; bool IsMissing() const; diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 7fa39a6b0a..00d57dc50f 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -198,6 +198,36 @@ DownloadWindow::~DownloadWindow() } +void +DownloadWindow::DispatchMessage(BMessage* message, BHandler* target) +{ + // We need to intercept mouse down events inside the area of download + // progress views (regardless of whether they have children at the click), + // so that they may display a context menu. + BPoint where; + int32 buttons; + if (message->what == B_MOUSE_DOWN + && message->FindPoint("screen_where", &where) == B_OK + && message->FindInt32("buttons", &buttons) == B_OK + && (buttons & B_SECONDARY_MOUSE_BUTTON) != 0) { + for (int32 i = fDownloadViewsLayout->CountItems() - 1; + BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) { + DownloadProgressView* view = dynamic_cast( + item->View()); + if (!view) + continue; + BPoint viewWhere(where); + view->ConvertFromScreen(&viewWhere); + if (view->Bounds().Contains(viewWhere)) { + view->ShowContextMenu(where); + return; + } + } + } + BWindow::DispatchMessage(message, target); +} + + void DownloadWindow::MessageReceived(BMessage* message) { diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index 92d299c89b..e4e62bfecc 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -45,6 +45,8 @@ public: SettingsMessage* settings); virtual ~DownloadWindow(); + virtual void DispatchMessage(BMessage* message, + BHandler* target); virtual void MessageReceived(BMessage* message); virtual bool QuitRequested(); From 17813bda8c2c42afa1505e51340833183cf0c407 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 11 May 2010 12:01:39 +0000 Subject: [PATCH 272/349] Do not advertize support for types we don't actually support. These are handled by the urlwrapper anyway. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@489 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/WebPositive.rdef | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/apps/webpositive/WebPositive.rdef b/src/apps/webpositive/WebPositive.rdef index 1079ab970a..5b89991cc9 100644 --- a/src/apps/webpositive/WebPositive.rdef +++ b/src/apps/webpositive/WebPositive.rdef @@ -15,8 +15,6 @@ resource app_flags B_SINGLE_LAUNCH; resource file_types message { "types" = "text/html", "types" = "image/svg+xml", - "types" = "application/x-vnd.Be-bookmark", - "types" = "application/x-vnd.Be-doc_bookmark", "types" = "application/x-vnd.Be.URL.file", "types" = "application/x-vnd.Be.URL.ftp", "types" = "application/x-vnd.Be.URL.http", From 59b99c122942d421d4f37bedcda7112ca96222e0 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 11 May 2010 12:15:22 +0000 Subject: [PATCH 273/349] Upated to use new B_TRANSLATE macros. Rene also send me a patch for this (thanks!), but I've redone it to keep the 80 char/line limit. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@493 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/SettingsWindow.cpp | 92 +++++++++++-------- .../webpositive/support/FontSelectionView.cpp | 18 ++-- 2 files changed, 65 insertions(+), 45 deletions(-) diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 5026f867dc..64a75a7117 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -55,8 +55,8 @@ #include "WebSettings.h" -#undef TR_CONTEXT -#define TR_CONTEXT "Settings Window" +#undef B_TRANSLATE_CONTEXT +#define B_TRANSLATE_CONTEXT "Settings Window" enum { MSG_APPLY = 'aply', @@ -90,15 +90,18 @@ static const int32 kDefaultFontSize = 14; SettingsWindow::SettingsWindow(BRect frame, SettingsMessage* settings) : - BWindow(frame, TR("Settings"), B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, - B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE), + BWindow(frame, B_TRANSLATE("Settings"), B_TITLED_WINDOW_LOOK, + B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS + | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE), fSettings(settings) { SetLayout(new BGroupLayout(B_VERTICAL)); - fApplyButton = new BButton(TR("Apply"), new BMessage(MSG_APPLY)); - fCancelButton = new BButton(TR("Cancel"), new BMessage(MSG_CANCEL)); - fRevertButton = new BButton(TR("Revert"), new BMessage(MSG_REVERT)); + fApplyButton = new BButton(B_TRANSLATE("Apply"), new BMessage(MSG_APPLY)); + fCancelButton = new BButton(B_TRANSLATE("Cancel"), + new BMessage(MSG_CANCEL)); + fRevertButton = new BButton(B_TRANSLATE("Revert"), + new BMessage(MSG_REVERT)); float spacing = be_control_look->DefaultItemSpacing(); @@ -241,40 +244,49 @@ BView* SettingsWindow::_CreateGeneralPage(float spacing) { fStartPageControl = new BTextControl("start page", - TR("Start page:"), "", new BMessage(MSG_START_PAGE_CHANGED)); + B_TRANSLATE("Start page:"), "", new BMessage(MSG_START_PAGE_CHANGED)); fStartPageControl->SetModificationMessage( new BMessage(MSG_START_PAGE_CHANGED)); fStartPageControl->SetText( fSettings->GetValue(kSettingsKeyStartPageURL, kDefaultStartPageURL)); fSearchPageControl = new BTextControl("search page", - TR("Search page:"), "", new BMessage(MSG_SEARCH_PAGE_CHANGED)); + B_TRANSLATE("Search page:"), "", + new BMessage(MSG_SEARCH_PAGE_CHANGED)); fSearchPageControl->SetModificationMessage( new BMessage(MSG_SEARCH_PAGE_CHANGED)); fSearchPageControl->SetText( fSettings->GetValue(kSettingsKeySearchPageURL, kDefaultSearchPageURL)); fDownloadFolderControl = new BTextControl("download folder", - TR("Download folder:"), "", new BMessage(MSG_DOWNLOAD_FOLDER_CHANGED)); + B_TRANSLATE("Download folder:"), "", + new BMessage(MSG_DOWNLOAD_FOLDER_CHANGED)); fDownloadFolderControl->SetModificationMessage( new BMessage(MSG_DOWNLOAD_FOLDER_CHANGED)); fDownloadFolderControl->SetText( fSettings->GetValue(kSettingsKeyDownloadPath, kDefaultDownloadPath)); - fNewWindowBehaviorOpenHomeItem = new BMenuItem(TR("Open start page"), + fNewWindowBehaviorOpenHomeItem = new BMenuItem( + B_TRANSLATE("Open start page"), new BMessage(MSG_NEW_WINDOWS_BEHAVIOR_CHANGED)); - fNewWindowBehaviorOpenSearchItem = new BMenuItem(TR("Open search page"), + fNewWindowBehaviorOpenSearchItem = new BMenuItem( + B_TRANSLATE("Open search page"), new BMessage(MSG_NEW_WINDOWS_BEHAVIOR_CHANGED)); - fNewWindowBehaviorOpenBlankItem = new BMenuItem(TR("Open blank page"), + fNewWindowBehaviorOpenBlankItem = new BMenuItem( + B_TRANSLATE("Open blank page"), new BMessage(MSG_NEW_WINDOWS_BEHAVIOR_CHANGED)); - fNewTabBehaviorCloneCurrentItem = new BMenuItem(TR("Clone current page"), + fNewTabBehaviorCloneCurrentItem = new BMenuItem( + B_TRANSLATE("Clone current page"), new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED)); - fNewTabBehaviorOpenHomeItem = new BMenuItem(TR("Open start page"), + fNewTabBehaviorOpenHomeItem = new BMenuItem( + B_TRANSLATE("Open start page"), new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED)); - fNewTabBehaviorOpenSearchItem = new BMenuItem(TR("Open search page"), + fNewTabBehaviorOpenSearchItem = new BMenuItem( + B_TRANSLATE("Open search page"), new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED)); - fNewTabBehaviorOpenBlankItem = new BMenuItem(TR("Open blank page"), + fNewTabBehaviorOpenBlankItem = new BMenuItem( + B_TRANSLATE("Open blank page"), new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED)); fNewWindowBehaviorOpenHomeItem->SetMarked(true); @@ -285,7 +297,7 @@ SettingsWindow::_CreateGeneralPage(float spacing) newWindowBehaviorMenu->AddItem(fNewWindowBehaviorOpenSearchItem); newWindowBehaviorMenu->AddItem(fNewWindowBehaviorOpenBlankItem); fNewWindowBehaviorMenu = new BMenuField("new window behavior", - TR("New windows:"), newWindowBehaviorMenu); + B_TRANSLATE("New windows:"), newWindowBehaviorMenu); BPopUpMenu* newTabBehaviorMenu = new BPopUpMenu("New tabs"); newTabBehaviorMenu->AddItem(fNewTabBehaviorOpenBlankItem); @@ -293,10 +305,10 @@ SettingsWindow::_CreateGeneralPage(float spacing) newTabBehaviorMenu->AddItem(fNewTabBehaviorOpenSearchItem); newTabBehaviorMenu->AddItem(fNewTabBehaviorCloneCurrentItem); fNewTabBehaviorMenu = new BMenuField("new tab behavior", - TR("New tabs:"), newTabBehaviorMenu); + B_TRANSLATE("New tabs:"), newTabBehaviorMenu); fDaysInHistoryMenuControl = new BTextControl("days in history", - TR("Number of days to keep links in History menu:"), "", + B_TRANSLATE("Number of days to keep links in History menu:"), "", new BMessage(MSG_HISTORY_MENU_DAYS_CHANGED)); fDaysInHistoryMenuControl->SetModificationMessage( new BMessage(MSG_HISTORY_MENU_DAYS_CHANGED)); @@ -309,12 +321,12 @@ SettingsWindow::_CreateGeneralPage(float spacing) fDaysInHistoryMenuControl->TextView()->DisallowChar(i); fShowTabsIfOnlyOnePage = new BCheckBox("show tabs if only one page", - TR("Show tabs if only one page is open."), + B_TRANSLATE("Show tabs if only one page is open."), new BMessage(MSG_TAB_DISPLAY_BEHAVIOR_CHANGED)); fShowTabsIfOnlyOnePage->SetValue(B_CONTROL_ON); fAutoHideInterfaceInFullscreenMode = new BCheckBox("auto-hide interface", - TR("Auto-hide interface in fullscreen mode."), + B_TRANSLATE("Auto-hide interface in fullscreen mode."), new BMessage(MSG_AUTO_HIDE_BEHAVIOR_CHANGED)); fAutoHideInterfaceInFullscreenMode->SetValue(B_CONTROL_OFF); @@ -345,7 +357,7 @@ SettingsWindow::_CreateGeneralPage(float spacing) .SetInsets(spacing, spacing, spacing, spacing) ; - view->SetName(TR("General")); + view->SetName(B_TRANSLATE("General")); return view; } @@ -353,22 +365,25 @@ SettingsWindow::_CreateGeneralPage(float spacing) BView* SettingsWindow::_CreateFontsPage(float spacing) { - fStandardFontView = new FontSelectionView("standard", TR("Standard font:"), - true, be_plain_font); + fStandardFontView = new FontSelectionView("standard", + B_TRANSLATE("Standard font:"), true, be_plain_font); BFont defaultSerifFont = _FindDefaultSerifFont(); - fSerifFontView = new FontSelectionView("serif", TR("Serif font:"), true, - &defaultSerifFont); + fSerifFontView = new FontSelectionView("serif", + B_TRANSLATE("Serif font:"), true, &defaultSerifFont); fSansSerifFontView = new FontSelectionView("sans serif", - TR("Sans serif font:"), true, be_plain_font); - fFixedFontView = new FontSelectionView("fixed", TR("Fixed font:"), true, - be_fixed_font); + B_TRANSLATE("Sans serif font:"), true, be_plain_font); + fFixedFontView = new FontSelectionView("fixed", + B_TRANSLATE("Fixed font:"), true, be_fixed_font); fStandardSizesMenu = new BMenuField("standard font size", - TR("Default standard font size:"), new BPopUpMenu("sizes"), NULL); - _BuildSizesMenu(fStandardSizesMenu->Menu(), MSG_STANDARD_FONT_SIZE_SELECTED); + B_TRANSLATE("Default standard font size:"), new BPopUpMenu("sizes"), + NULL); + _BuildSizesMenu(fStandardSizesMenu->Menu(), + MSG_STANDARD_FONT_SIZE_SELECTED); fFixedSizesMenu = new BMenuField("fixed font size", - TR("Default fixed font size:"), new BPopUpMenu("sizes"), NULL); + B_TRANSLATE("Default fixed font size:"), new BPopUpMenu("sizes"), + NULL); _BuildSizesMenu(fFixedSizesMenu->Menu(), MSG_FIXED_FONT_SIZE_SELECTED); BView* view = BGridLayoutBuilder(spacing / 2, spacing / 2) @@ -399,7 +414,7 @@ SettingsWindow::_CreateFontsPage(float spacing) .SetInsets(spacing, spacing, spacing, spacing) ; - view->SetName(TR("Fonts")); + view->SetName(B_TRANSLATE("Fonts")); return view; } @@ -408,12 +423,12 @@ BView* SettingsWindow::_CreateProxyPage(float spacing) { fUseProxyCheckBox = new BCheckBox("use proxy", - TR("Use proxy server to connect to the internet."), + B_TRANSLATE("Use proxy server to connect to the internet."), new BMessage(MSG_USE_PROXY_CHANGED)); fUseProxyCheckBox->SetValue(B_CONTROL_ON); fProxyAddressControl = new BTextControl("proxy address", - TR("Proxy server address:"), "", + B_TRANSLATE("Proxy server address:"), "", new BMessage(MSG_PROXY_ADDRESS_CHANGED)); fProxyAddressControl->SetModificationMessage( new BMessage(MSG_PROXY_ADDRESS_CHANGED)); @@ -421,7 +436,8 @@ SettingsWindow::_CreateProxyPage(float spacing) fSettings->GetValue(kSettingsKeyProxyAddress, "")); fProxyPortControl = new BTextControl("proxy port", - TR("Proxy server port:"), "", new BMessage(MSG_PROXY_PORT_CHANGED)); + B_TRANSLATE("Proxy server port:"), "", + new BMessage(MSG_PROXY_PORT_CHANGED)); fProxyPortControl->SetModificationMessage( new BMessage(MSG_PROXY_PORT_CHANGED)); fProxyPortControl->SetText( @@ -440,7 +456,7 @@ SettingsWindow::_CreateProxyPage(float spacing) .SetInsets(spacing, spacing, spacing, spacing) ; - view->SetName(TR("Proxy server")); + view->SetName(B_TRANSLATE("Proxy server")); return view; } diff --git a/src/apps/webpositive/support/FontSelectionView.cpp b/src/apps/webpositive/support/FontSelectionView.cpp index c463a8c9ef..81ce76bcb0 100644 --- a/src/apps/webpositive/support/FontSelectionView.cpp +++ b/src/apps/webpositive/support/FontSelectionView.cpp @@ -26,8 +26,8 @@ #include -#undef TR_CONTEXT -#define TR_CONTEXT "Font Selection view" +#undef B_TRANSLATE_CONTEXT +#define B_TRANSLATE_CONTEXT "Font Selection view" static const float kMinSize = 8.0; @@ -65,22 +65,26 @@ FontSelectionView::FontSelectionView(const char* name, const char* label, // styles menu, if desired if (separateStyles) { fStylesMenu = new BPopUpMenu("styles menu"); - fStylesMenuField = new BMenuField("styles", TR("Style:"), fStylesMenu, - NULL); + fStylesMenuField = new BMenuField("styles", B_TRANSLATE("Style:"), + fStylesMenu, NULL); } else { fStylesMenu = NULL; fStylesMenuField = NULL; } // size menu - fSizesMenuField = new BMenuField("size", TR("Size:"), fSizesMenu, NULL); + fSizesMenuField = new BMenuField("size", B_TRANSLATE("Size:"), fSizesMenu, + NULL); fSizesMenuField->SetAlignment(B_ALIGN_RIGHT); // preview fPreviewText = new BStringView("preview text", - TR_CMT("The quick brown fox jumps over the lazy dog.","Don't translate this literally ! Use a phrase showing all chars from A to Z.")); + B_TRANSLATE_COMMENT("The quick brown fox jumps over the lazy dog.", + "Don't translate this literally ! Use a phrase showing all " + "chars from A to Z.")); - fPreviewText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED)); + fPreviewText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, + B_SIZE_UNLIMITED)); fPreviewText->SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 1.65)); fPreviewText->SetAlignment(B_ALIGN_RIGHT); From 208ecbcad581862d4fa35d792180cad8cc46195e Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 16 May 2010 19:37:33 +0000 Subject: [PATCH 274/349] * Moved auto-hiding the mouse pointer into BWebView::Pulse(). * Unhide the interface when the user invokes CMD-L (Open location). * Make sure the progress bar is really hidden, sometimes it would be visible again after unhiding the rest of the interface. * Added a setting for the auto-hiding the mouse pointer feature. It defaults to true, since I think it's useful for an app where the pointer would usually be in the way. * Hide the mouse pointer in any case as soon as the user begins typing, also hide potentially showing tool tips in that case. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@496 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 28 +++++++----- src/apps/webpositive/BrowserWindow.h | 1 + src/apps/webpositive/SettingsKeys.cpp | 1 + src/apps/webpositive/SettingsKeys.h | 1 + src/apps/webpositive/SettingsWindow.cpp | 60 ++++++++++++++++--------- src/apps/webpositive/SettingsWindow.h | 1 + 6 files changed, 59 insertions(+), 33 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 92873f1d97..bc588402db 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -203,7 +203,8 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fAppSettings(appSettings), fZoomTextOnly(true), fShowTabsIfSinglePageOpen(true), - fAutoHideInterfaceInFullscreenMode(false) + fAutoHideInterfaceInFullscreenMode(false), + fAutoHidePointer(true) { // Begin listening to settings changes and read some current values. fAppSettings->AddListener(BMessenger(this)); @@ -211,6 +212,9 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fShowTabsIfSinglePageOpen = fAppSettings->GetValue( kSettingsKeyShowTabsIfSinglePageOpen, fShowTabsIfSinglePageOpen); + fAutoHidePointer = fAppSettings->GetValue(kSettingsKeyAutoHidePointer, + fAutoHidePointer); + fNewWindowPolicy = fAppSettings->GetValue(kSettingsKeyNewWindowPolicy, (uint32)OpenStartPage); fNewTabPolicy = fAppSettings->GetValue(kSettingsKeyNewTabPolicy, @@ -506,6 +510,7 @@ BrowserWindow::MessageReceived(BMessage* message) { switch (message->what) { case OPEN_LOCATION: + _ShowInterface(true); if (fURLInputGroup->TextView()->IsFocus()) fURLInputGroup->TextView()->SelectAll(); else @@ -770,6 +775,11 @@ BrowserWindow::MessageReceived(BMessage* message) fShowTabsIfSinglePageOpen = flag; _UpdateTabGroupVisibility(); } + } else if (name == kSettingsKeyAutoHidePointer + && message->FindBool("value", &flag) == B_OK) { + fAutoHidePointer = flag; + if (CurrentWebView()) + CurrentWebView()->SetAutoHidePointer(fAutoHidePointer); } else if (name == kSettingsKeyStartPageURL && message->FindString("value", &string) == B_OK) { fStartPageURL = string; @@ -882,6 +892,8 @@ BrowserWindow::SetCurrentWebView(BWebView* webView) BWebWindow::SetCurrentWebView(webView); if (webView != NULL) { + webView->SetAutoHidePointer(fAutoHidePointer); + _UpdateTitle(webView->MainFrameTitle()); // Restore the previous focus or focus the web view. @@ -1838,22 +1850,16 @@ BrowserWindow::_SetAutoHideInterfaceInFullscreen(bool doIt) void BrowserWindow::_CheckAutoHideInterface() { - if (!fIsFullscreen || !fAutoHideInterfaceInFullscreenMode) + if (!fIsFullscreen || !fAutoHideInterfaceInFullscreenMode + || (CurrentWebView() != NULL && !CurrentWebView()->IsFocus())) { return; - - bigtime_t now = system_time(); - float navigationGroupBottom = fNavigationGroup->IsVisible() ? - fNavigationGroup->Frame().bottom : 0; - if (fLastMousePos.y > navigationGroupBottom - && now - fLastMouseMovedTime > 1500000) { - be_app->ObscureCursor(); } if (fLastMousePos.y == 0) _ShowInterface(true); else if (fNavigationGroup->IsVisible() && fLastMousePos.y > fNavigationGroup->Frame().bottom - && now - fLastMouseMovedTime > 3000000) { + && system_time() - fLastMouseMovedTime > 3000000) { // NOTE: Do not re-use navigationGroupBottom in the above // check, since we only want to hide the interface when it is visible. _ShowInterface(false); @@ -1887,7 +1893,7 @@ BrowserWindow::_ShowInterface(bool show) } // TODO: Setting the group visible seems to unhide the status bar. // Fix in Haiku? - if (!fLoadingProgressBar->IsHidden()) + while (!fLoadingProgressBar->IsHidden()) fLoadingProgressBar->Hide(); } diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 5d272b2eb8..4fd972fcce 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -228,6 +228,7 @@ private: bool fZoomTextOnly; bool fShowTabsIfSinglePageOpen; bool fAutoHideInterfaceInFullscreenMode; + bool fAutoHidePointer; uint32 fNewWindowPolicy; uint32 fNewTabPolicy; BString fStartPageURL; diff --git a/src/apps/webpositive/SettingsKeys.cpp b/src/apps/webpositive/SettingsKeys.cpp index b65abd8da0..5bd2f32cb9 100644 --- a/src/apps/webpositive/SettingsKeys.cpp +++ b/src/apps/webpositive/SettingsKeys.cpp @@ -32,6 +32,7 @@ const char* kSettingsKeyShowTabsIfSinglePageOpen = "show tabs if single page open"; const char* kSettingsKeyAutoHideInterfaceInFullscreenMode = "auto hide interface in full screen mode"; +const char* kSettingsKeyAutoHidePointer = "auto hide pointer"; const char* kSettingsKeyNewWindowPolicy = "new window policy"; const char* kSettingsKeyNewTabPolicy = "new tab policy"; diff --git a/src/apps/webpositive/SettingsKeys.h b/src/apps/webpositive/SettingsKeys.h index 08fc6077be..8f2b96de35 100644 --- a/src/apps/webpositive/SettingsKeys.h +++ b/src/apps/webpositive/SettingsKeys.h @@ -33,6 +33,7 @@ extern const char* kSettingsKeyDownloadPath; extern const char* kSettingsKeyShowTabsIfSinglePageOpen; extern const char* kSettingsKeyAutoHideInterfaceInFullscreenMode; +extern const char* kSettingsKeyAutoHidePointer; extern const char* kSettingsKeyNewWindowPolicy; extern const char* kSettingsKeyNewTabPolicy; diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 64a75a7117..8cfece44f9 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -59,30 +59,31 @@ #define B_TRANSLATE_CONTEXT "Settings Window" enum { - MSG_APPLY = 'aply', - MSG_CANCEL = 'cncl', - MSG_REVERT = 'rvrt', + MSG_APPLY = 'aply', + MSG_CANCEL = 'cncl', + MSG_REVERT = 'rvrt', - MSG_START_PAGE_CHANGED = 'hpch', - MSG_SEARCH_PAGE_CHANGED = 'spch', - MSG_DOWNLOAD_FOLDER_CHANGED = 'dnfc', - MSG_NEW_WINDOWS_BEHAVIOR_CHANGED = 'nwbc', - MSG_NEW_TABS_BEHAVIOR_CHANGED = 'ntbc', - MSG_HISTORY_MENU_DAYS_CHANGED = 'digm', - MSG_TAB_DISPLAY_BEHAVIOR_CHANGED = 'tdbc', - MSG_AUTO_HIDE_BEHAVIOR_CHANGED = 'ahbc', + MSG_START_PAGE_CHANGED = 'hpch', + MSG_SEARCH_PAGE_CHANGED = 'spch', + MSG_DOWNLOAD_FOLDER_CHANGED = 'dnfc', + MSG_NEW_WINDOWS_BEHAVIOR_CHANGED = 'nwbc', + MSG_NEW_TABS_BEHAVIOR_CHANGED = 'ntbc', + MSG_HISTORY_MENU_DAYS_CHANGED = 'digm', + MSG_TAB_DISPLAY_BEHAVIOR_CHANGED = 'tdbc', + MSG_AUTO_HIDE_INTERFACE_BEHAVIOR_CHANGED = 'ahic', + MSG_AUTO_HIDE_POINTER_BEHAVIOR_CHANGED = 'ahpc', - MSG_STANDARD_FONT_CHANGED = 'stfc', - MSG_SERIF_FONT_CHANGED = 'sefc', - MSG_SANS_SERIF_FONT_CHANGED = 'ssfc', - MSG_FIXED_FONT_CHANGED = 'ffch', + MSG_STANDARD_FONT_CHANGED = 'stfc', + MSG_SERIF_FONT_CHANGED = 'sefc', + MSG_SANS_SERIF_FONT_CHANGED = 'ssfc', + MSG_FIXED_FONT_CHANGED = 'ffch', - MSG_STANDARD_FONT_SIZE_SELECTED = 'sfss', - MSG_FIXED_FONT_SIZE_SELECTED = 'ffss', + MSG_STANDARD_FONT_SIZE_SELECTED = 'sfss', + MSG_FIXED_FONT_SIZE_SELECTED = 'ffss', - MSG_USE_PROXY_CHANGED = 'upsc', - MSG_PROXY_ADDRESS_CHANGED = 'psac', - MSG_PROXY_PORT_CHANGED = 'pspc', + MSG_USE_PROXY_CHANGED = 'upsc', + MSG_PROXY_ADDRESS_CHANGED = 'psac', + MSG_PROXY_PORT_CHANGED = 'pspc', }; static const int32 kDefaultFontSize = 14; @@ -199,7 +200,8 @@ SettingsWindow::MessageReceived(BMessage* message) case MSG_NEW_TABS_BEHAVIOR_CHANGED: case MSG_HISTORY_MENU_DAYS_CHANGED: case MSG_TAB_DISPLAY_BEHAVIOR_CHANGED: - case MSG_AUTO_HIDE_BEHAVIOR_CHANGED: + case MSG_AUTO_HIDE_INTERFACE_BEHAVIOR_CHANGED: + case MSG_AUTO_HIDE_POINTER_BEHAVIOR_CHANGED: case MSG_STANDARD_FONT_CHANGED: case MSG_SERIF_FONT_CHANGED: case MSG_SANS_SERIF_FONT_CHANGED: @@ -327,9 +329,14 @@ SettingsWindow::_CreateGeneralPage(float spacing) fAutoHideInterfaceInFullscreenMode = new BCheckBox("auto-hide interface", B_TRANSLATE("Auto-hide interface in fullscreen mode."), - new BMessage(MSG_AUTO_HIDE_BEHAVIOR_CHANGED)); + new BMessage(MSG_AUTO_HIDE_INTERFACE_BEHAVIOR_CHANGED)); fAutoHideInterfaceInFullscreenMode->SetValue(B_CONTROL_OFF); + fAutoHidePointer = new BCheckBox("auto-hide pointer", + B_TRANSLATE("Auto-hide mouse pointer."), + new BMessage(MSG_AUTO_HIDE_POINTER_BEHAVIOR_CHANGED)); + fAutoHidePointer->SetValue(B_CONTROL_ON); + BView* view = BGroupLayoutBuilder(B_VERTICAL, spacing / 2) .Add(BGridLayoutBuilder(spacing / 2, spacing / 2) .Add(fStartPageControl->CreateLabelLayoutItem(), 0, 0) @@ -352,6 +359,7 @@ SettingsWindow::_CreateGeneralPage(float spacing) .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing)) .Add(fShowTabsIfOnlyOnePage) .Add(fAutoHideInterfaceInFullscreenMode) + .Add(fAutoHidePointer) .Add(fDaysInHistoryMenuControl) .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing)) @@ -528,6 +536,10 @@ SettingsWindow::_CanApplySettings() const != fSettings->GetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode, false)); + canApply = canApply || ( + (fAutoHidePointer->Value() == B_CONTROL_ON) + != fSettings->GetValue(kSettingsKeyAutoHidePointer, true)); + canApply = canApply || (_MaxHistoryAge() != BrowsingHistory::DefaultInstance()->MaxHistoryItemAge()); @@ -591,6 +603,8 @@ SettingsWindow::_ApplySettings() fShowTabsIfOnlyOnePage->Value() == B_CONTROL_ON); fSettings->SetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode, fAutoHideInterfaceInFullscreenMode->Value() == B_CONTROL_ON); + fSettings->SetValue(kSettingsKeyAutoHidePointer, + fAutoHidePointer->Value() == B_CONTROL_ON); // New page policies fSettings->SetValue(kSettingsKeyNewWindowPolicy, _NewWindowPolicy()); @@ -656,6 +670,8 @@ SettingsWindow::_RevertSettings() fAutoHideInterfaceInFullscreenMode->SetValue( fSettings->GetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode, false)); + fAutoHidePointer->SetValue( + fSettings->GetValue(kSettingsKeyAutoHidePointer, true)); BString text; text << BrowsingHistory::DefaultInstance()->MaxHistoryItemAge(); diff --git a/src/apps/webpositive/SettingsWindow.h b/src/apps/webpositive/SettingsWindow.h index cfd8f54ce9..9648860bff 100644 --- a/src/apps/webpositive/SettingsWindow.h +++ b/src/apps/webpositive/SettingsWindow.h @@ -97,6 +97,7 @@ private: BTextControl* fDaysInHistoryMenuControl; BCheckBox* fShowTabsIfOnlyOnePage; BCheckBox* fAutoHideInterfaceInFullscreenMode; + BCheckBox* fAutoHidePointer; FontSelectionView* fStandardFontView; FontSelectionView* fSerifFontView; From 0e4207931358115f232a09f5cf5b3e49efaee387 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 16 May 2010 20:41:50 +0000 Subject: [PATCH 275/349] Remember the current URL input contents and selection when switching away from a tab, and restore them when switching back. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@498 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 66 ++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 9 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index bc588402db..98068501b5 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -148,7 +148,9 @@ public: PageUserData(BView* focusedView) : fFocusedView(focusedView), - fPageIcon(NULL) + fPageIcon(NULL), + fURLInputSelectionStart(-1), + fURLInputSelectionEnd(-1) { } @@ -181,9 +183,38 @@ public: return fPageIcon; } + void SetURLInputContents(const char* text) + { + fURLInputContents = text; + } + + const char* URLInputContents() const + { + return fURLInputContents.String(); + } + + void SetURLInputSelection(int32 selectionStart, int32 selectionEnd) + { + fURLInputSelectionStart = selectionStart; + fURLInputSelectionEnd = selectionEnd; + } + + int32 URLInputSelectionStart() const + { + return fURLInputSelectionStart; + } + + int32 URLInputSelectionEnd() const + { + return fURLInputSelectionEnd; + } + private: BView* fFocusedView; BBitmap* fPageIcon; + BString fURLInputContents; + int32 fURLInputSelectionStart; + int32 fURLInputSelectionEnd; }; @@ -883,10 +914,17 @@ BrowserWindow::SetCurrentWebView(BWebView* webView) // later. PageUserData* userData = static_cast( CurrentWebView()->GetUserData()); - if (userData) - userData->SetFocusedView(CurrentFocus()); - else - CurrentWebView()->SetUserData(new PageUserData(CurrentFocus())); + if (userData == NULL) { + userData = new PageUserData(CurrentFocus()); + CurrentWebView()->SetUserData(userData); + } + userData->SetFocusedView(CurrentFocus()); + userData->SetURLInputContents(fURLInputGroup->Text()); + int32 selectionStart; + int32 selectionEnd; + fURLInputGroup->TextView()->GetSelection(&selectionStart, + &selectionEnd); + userData->SetURLInputSelection(selectionStart, selectionEnd); } BWebWindow::SetCurrentWebView(webView); @@ -900,10 +938,8 @@ BrowserWindow::SetCurrentWebView(BWebView* webView) PageUserData* userData = static_cast( webView->GetUserData()); BView* focusedView = NULL; - if (userData != NULL) { + if (userData != NULL) focusedView = userData->FocusedView(); - fURLInputGroup->SetPageIcon(userData->PageIcon()); - } if (focusedView != NULL && viewIsChild(GetLayout()->View(), focusedView)) { @@ -911,7 +947,19 @@ BrowserWindow::SetCurrentWebView(BWebView* webView) } else webView->MakeFocus(true); - fURLInputGroup->SetText(webView->MainFrameURL()); + if (userData != NULL) { + fURLInputGroup->SetPageIcon(userData->PageIcon()); + fURLInputGroup->SetText(userData->URLInputContents()); + if (userData->URLInputSelectionStart() >= 0) { + fURLInputGroup->TextView()->Select( + userData->URLInputSelectionStart(), + userData->URLInputSelectionEnd()); + } + } else { + fURLInputGroup->SetPageIcon(NULL); + fURLInputGroup->SetText(webView->MainFrameURL()); + } + // Trigger update of the interface to the new page, by requesting // to resend all notifications. webView->WebPage()->ResendNotifications(); From eb44597cd09e566abafdf55ed3e03efd03d6a963 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 16 May 2010 20:56:35 +0000 Subject: [PATCH 276/349] Revert r250, since CMD-0 for changing to the tenth tab conflicts with the shortcut for resetting the page zoom, but that is also an established shortcut from Firefox. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@499 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 98068501b5..49a0dc3a11 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -470,12 +470,9 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(EDIT_HIDE_FIND_GROUP)); // Add shortcuts to select a particular tab - for (int32 i = 0; i <= 9; i++) { + for (int32 i = 1; i <= 9; i++) { BMessage *selectTab = new BMessage(SELECT_TAB); - if (i == 0) - selectTab->AddInt32("tab index", 9); - else - selectTab->AddInt32("tab index", i - 1); + selectTab->AddInt32("tab index", i - 1); char numStr[2]; snprintf(numStr, sizeof(numStr), "%d", (int) i); AddShortcut(numStr[0], B_COMMAND_KEY, selectTab); From 90a69c8e1d42bbe82b16a9caadad3fefca92f655 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 18 May 2010 16:59:34 +0000 Subject: [PATCH 277/349] The mechanism with which the TextViewCompleter detected changes (attaching a BMessageFilter to the BTextView to pre-process key down events) missed changes to the BTextView via other means, for example by pasting, or simply when SetText() is invoked on the BTextView. -> Introduced an alternative method of making the TextViewCompleter aware of changes, by invoking new method TextModified(). To bypass the old method, one has to call SetModificationsReported(true). URLInput::URLTextView now uses the new method in InsertText() and DeleteText(), which catches any and all changes to the text. Since the BAutoCompleter framework also controls the editor view contents, it needs to protect against re-entering some methods when the editor view reports the changes (fIgnoreEditViewStateChanges). Since we want the BAutoCompleter to always be aware of the current editor view contents, but not necessarily also running the choice mechanism (i.e. when you enter "www.google.com", you don't want the auto-completion kick back in when it is programmatically changed to "http://www.google.com" later on), the EditViewStateChange() method gets a boolean now "updateChoices". All programmatic changes to the URL will then not trigger displaying the choice pop-up, but the BAutoCompleter is always aware of the current editor view contents. All this fixes numerous issues and inconsistencies with entering text in the URL text view. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@500 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/URLInputGroup.cpp | 32 +++++++++++++++-- .../autocompletion/AutoCompleter.cpp | 4 +-- .../autocompletion/AutoCompleter.h | 5 +-- .../AutoCompleterDefaultImpl.cpp | 29 ++++++++++++---- .../autocompletion/AutoCompleterDefaultImpl.h | 3 +- .../autocompletion/TextViewCompleter.cpp | 34 +++++++++++++++---- .../autocompletion/TextViewCompleter.h | 5 +++ 7 files changed, 92 insertions(+), 20 deletions(-) diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index 7fec10caaf..e5d5c9ecb3 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -148,10 +148,14 @@ public: virtual BSize MinSize(); virtual BSize MaxSize(); + void SetUpdateAutoCompleterChoices(bool update); + protected: virtual void InsertText(const char* inText, int32 inLength, int32 inOffset, const text_run_array* inRuns); + virtual void DeleteText(int32 fromOffset, int32 toOffset); + private: void _AlignTextRect(); @@ -159,6 +163,7 @@ private: URLInputGroup* fURLInputGroup; TextViewCompleter* fURLAutoCompleter; BString fPreviousText; + bool fUpdateAutoCompleterChoices; }; @@ -168,10 +173,12 @@ URLInputGroup::URLTextView::URLTextView(URLInputGroup* parent) fURLInputGroup(parent), fURLAutoCompleter(new TextViewCompleter(this, new BrowsingHistoryChoiceModel())), - fPreviousText("") + fPreviousText(""), + fUpdateAutoCompleterChoices(true) { MakeResizable(true); SetStylable(true); + fURLAutoCompleter->SetModificationsReported(true); } @@ -318,6 +325,13 @@ URLInputGroup::URLTextView::MaxSize() } +void +URLInputGroup::URLTextView::SetUpdateAutoCompleterChoices(bool update) +{ + fUpdateAutoCompleterChoices = update; +} + + void URLInputGroup::URLTextView::InsertText(const char* inText, int32 inLength, int32 inOffset, const text_run_array* inRuns) @@ -360,6 +374,17 @@ URLInputGroup::URLTextView::InsertText(const char* inText, int32 inLength, font.SetFace(B_REGULAR_FACE); SetFontAndColor(baseUrlEnd, TextLength(), &font, B_FONT_ALL, &gray); } + + fURLAutoCompleter->TextModified(fUpdateAutoCompleterChoices); +} + + +void +URLInputGroup::URLTextView::DeleteText(int32 fromOffset, int32 toOffset) +{ + BTextView::DeleteText(fromOffset, toOffset); + + fURLAutoCompleter->TextModified(fUpdateAutoCompleterChoices); } @@ -599,8 +624,11 @@ URLInputGroup::TextView() const void URLInputGroup::SetText(const char* text) { - if (!text || !Text() || strcmp(Text(), text) != 0) + if (!text || !Text() || strcmp(Text(), text) != 0) { + fTextView->SetUpdateAutoCompleterChoices(false); fTextView->SetText(text); + fTextView->SetUpdateAutoCompleterChoices(true); + } } diff --git a/src/apps/webpositive/autocompletion/AutoCompleter.cpp b/src/apps/webpositive/autocompletion/AutoCompleter.cpp index 98b659da40..2e5d45e164 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleter.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleter.cpp @@ -175,10 +175,10 @@ BAutoCompleter::CancelChoice() void -BAutoCompleter::EditViewStateChanged() +BAutoCompleter::EditViewStateChanged(bool updateChoices) { if (fCompletionStyle) - fCompletionStyle->EditViewStateChanged(); + fCompletionStyle->EditViewStateChanged(updateChoices); } diff --git a/src/apps/webpositive/autocompletion/AutoCompleter.h b/src/apps/webpositive/autocompletion/AutoCompleter.h index 8b5cb7be37..16a94559b4 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleter.h +++ b/src/apps/webpositive/autocompletion/AutoCompleter.h @@ -101,7 +101,7 @@ public: virtual void ApplyChoice(bool hideChoices = true) = 0; virtual void CancelChoice() = 0; - virtual void EditViewStateChanged() = 0; + virtual void EditViewStateChanged(bool updateChoices) = 0; void SetEditView(EditView* view); void SetPatternSelector(PatternSelector* selector); @@ -130,7 +130,8 @@ protected: PatternSelector* patternSelector); virtual ~BAutoCompleter(); - void EditViewStateChanged(); + void EditViewStateChanged( + bool updateChoices = true); bool Select(int32 index); bool SelectNext(bool wrap = false); diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp index 95ce32c7a0..5760852400 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp @@ -15,6 +15,7 @@ // #pragma mark - BDefaultPatternSelector + void BDefaultPatternSelector::SelectPatternBounds(const BString& text, int32 caretPos, int32* start, int32* length) @@ -38,7 +39,8 @@ BDefaultCompletionStyle::BDefaultCompletionStyle( CompletionStyle(editView, choiceModel, choiceView, patternSelector), fSelectedIndex(-1), fPatternStartPos(0), - fPatternLength(0) + fPatternLength(0), + fIgnoreEditViewStateChanges(false) { } @@ -114,15 +116,19 @@ BDefaultCompletionStyle::ApplyChoice(bool hideChoices) const BString& choiceStr = fChoiceModel->ChoiceAt(fSelectedIndex)->Text(); completedText.Insert(choiceStr, fPatternStartPos); + fIgnoreEditViewStateChanges = true; + fFullEnteredText = completedText; fPatternLength = choiceStr.Length(); fEditView->SetEditViewState(completedText, - fPatternStartPos+choiceStr.Length()); + fPatternStartPos + choiceStr.Length()); if (hideChoices) { fChoiceView->HideChoices(); Select(-1); } + + fIgnoreEditViewStateChanges = false; } @@ -132,25 +138,36 @@ BDefaultCompletionStyle::CancelChoice() if (!fChoiceView || !fEditView) return; if (fChoiceView->ChoicesAreShown()) { - fEditView->SetEditViewState(fFullEnteredText, - fPatternStartPos+fPatternLength); + fIgnoreEditViewStateChanges = true; + + fEditView->SetEditViewState(fFullEnteredText, + fPatternStartPos + fPatternLength); fChoiceView->HideChoices(); Select(-1); + + fIgnoreEditViewStateChanges = false; } } void -BDefaultCompletionStyle::EditViewStateChanged() +BDefaultCompletionStyle::EditViewStateChanged(bool updateChoices) { - if (!fChoiceModel || !fChoiceView || !fEditView) + if (fIgnoreEditViewStateChanges || !fChoiceModel || !fChoiceView + || !fEditView) { return; + } BString text; int32 caretPos; fEditView->GetEditViewState(text, &caretPos); if (fFullEnteredText == text) return; + fFullEnteredText = text; + + if (!updateChoices) + return; + fPatternSelector->SelectPatternBounds(text, caretPos, &fPatternStartPos, &fPatternLength); BString pattern(text.String() + fPatternStartPos, fPatternLength); diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h index cf01dbbad1..216a2d7f78 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h @@ -39,13 +39,14 @@ public: virtual void ApplyChoice(bool hideChoices = true); virtual void CancelChoice(); - virtual void EditViewStateChanged(); + virtual void EditViewStateChanged(bool updateChoices); private: BString fFullEnteredText; int32 fSelectedIndex; int32 fPatternStartPos; int32 fPatternLength; + bool fIgnoreEditViewStateChanges; }; diff --git a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp index 9f0a90b065..3f83e884d8 100644 --- a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp +++ b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp @@ -63,13 +63,17 @@ TextViewCompleter::TextViewWrapper::GetAdjustmentFrame() } +// #pragma mark - + + TextViewCompleter::TextViewCompleter(BTextView* textView, ChoiceModel* model, PatternSelector* patternSelector) : BAutoCompleter(new TextViewWrapper(textView), model, new BDefaultChoiceView(), patternSelector), BMessageFilter(B_KEY_DOWN), - fTextView(textView) + fTextView(textView), + fModificationsReported(false) { fTextView->AddFilter(this); } @@ -81,6 +85,20 @@ TextViewCompleter::~TextViewCompleter() } +void +TextViewCompleter::SetModificationsReported(bool reported) +{ + fModificationsReported = reported; +} + + +void +TextViewCompleter::TextModified(bool updateChoices) +{ + EditViewStateChanged(updateChoices); +} + + filter_result TextViewCompleter::Filter(BMessage* message, BHandler** target) { @@ -120,11 +138,13 @@ TextViewCompleter::Filter(BMessage* message, BHandler** target) return B_DISPATCH_MESSAGE; } default: - // dispatch message to textview manually... - Looper()->DispatchMessage(message, *target); - // ...and propagate the new state to the auto-completer: - EditViewStateChanged(); - return B_SKIP_MESSAGE; + if (!fModificationsReported) { + // dispatch message to textview manually... + Looper()->DispatchMessage(message, *target); + // ...and propagate the new state to the auto-completer: + EditViewStateChanged(); + return B_SKIP_MESSAGE; + } + return B_DISPATCH_MESSAGE; } - return B_DISPATCH_MESSAGE; } diff --git a/src/apps/webpositive/autocompletion/TextViewCompleter.h b/src/apps/webpositive/autocompletion/TextViewCompleter.h index a325603309..1a2955f6d7 100644 --- a/src/apps/webpositive/autocompletion/TextViewCompleter.h +++ b/src/apps/webpositive/autocompletion/TextViewCompleter.h @@ -22,6 +22,9 @@ public: PatternSelector* patternSelector = NULL); virtual ~TextViewCompleter(); + void SetModificationsReported(bool reported); + void TextModified(bool updateChoices); + private: virtual filter_result Filter(BMessage* message, BHandler** target); @@ -36,8 +39,10 @@ private: private: BTextView* fTextView; }; + private: BTextView* fTextView; + bool fModificationsReported; }; #endif // TEXT_CONTROL_COMPLETER_H From 37876e4b33ddb7258e98d6b5af42529f6dfc46b8 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 18 May 2010 18:59:34 +0000 Subject: [PATCH 278/349] Extend the auto-completion framework in order to support using page-up/down to navigate the choices list. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@501 94f232f2-1747-11df-bad5-a5bfde151594 --- .../autocompletion/AutoCompleter.cpp | 30 +++++++++++ .../autocompletion/AutoCompleter.h | 5 ++ .../AutoCompleterDefaultImpl.cpp | 50 ++++++++++++++++--- .../autocompletion/AutoCompleterDefaultImpl.h | 7 +++ .../autocompletion/TextViewCompleter.cpp | 17 +++++++ 5 files changed, 102 insertions(+), 7 deletions(-) diff --git a/src/apps/webpositive/autocompletion/AutoCompleter.cpp b/src/apps/webpositive/autocompletion/AutoCompleter.cpp index 2e5d45e164..09060512f6 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleter.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleter.cpp @@ -158,6 +158,36 @@ BAutoCompleter::IsChoiceSelected() const } +int32 +BAutoCompleter::CountChoices() const +{ + if (fCompletionStyle && fCompletionStyle->GetChoiceModel()) + return fCompletionStyle->GetChoiceModel()->CountChoices(); + else + return 0; +} + + +int32 +BAutoCompleter::CountVisibleChoices() const +{ + if (fCompletionStyle && fCompletionStyle->GetChoiceView()) + return fCompletionStyle->GetChoiceView()->CountVisibleChoices(); + else + return 0; +} + + +int32 +BAutoCompleter::SelectedChoiceIndex() const +{ + if (fCompletionStyle) + return fCompletionStyle->SelectedChoiceIndex(); + else + return -1; +} + + void BAutoCompleter::ApplyChoice(bool hideChoices) { diff --git a/src/apps/webpositive/autocompletion/AutoCompleter.h b/src/apps/webpositive/autocompletion/AutoCompleter.h index 16a94559b4..dab8268db2 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleter.h +++ b/src/apps/webpositive/autocompletion/AutoCompleter.h @@ -83,6 +83,7 @@ public: = 0; virtual void HideChoices() = 0; virtual bool ChoicesAreShown() = 0; + virtual int32 CountVisibleChoices() const = 0; }; class CompletionStyle { @@ -97,6 +98,7 @@ public: virtual bool SelectNext(bool wrap = false) = 0; virtual bool SelectPrevious(bool wrap = false) = 0; virtual bool IsChoiceSelected() const = 0; + virtual int32 SelectedChoiceIndex() const = 0; virtual void ApplyChoice(bool hideChoices = true) = 0; virtual void CancelChoice() = 0; @@ -137,6 +139,9 @@ protected: bool SelectNext(bool wrap = false); bool SelectPrevious(bool wrap = false); bool IsChoiceSelected() const; + int32 CountChoices() const; + int32 CountVisibleChoices() const; + int32 SelectedChoiceIndex() const; void ApplyChoice(bool hideChoices = true); void CancelChoice(); diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp index 5760852400..1f7f27c3ea 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp @@ -105,6 +105,13 @@ BDefaultCompletionStyle::IsChoiceSelected() const } +int32 +BDefaultCompletionStyle::SelectedChoiceIndex() const +{ + return fSelectedIndex; +} + + void BDefaultCompletionStyle::ApplyChoice(bool hideChoices) { @@ -187,13 +194,13 @@ BDefaultCompletionStyle::EditViewStateChanged(bool updateChoices) // #pragma mark - BDefaultChoiceView::ListView -static const int32 BM_INVOKED = 'bmin'; +static const int32 MSG_INVOKED = 'invk'; BDefaultChoiceView::ListView::ListView( BAutoCompleter::CompletionStyle* completer) : - BListView(BRect(0,0,100,100), "ChoiceViewList"), + BListView(BRect(0, 0, 100, 100), "ChoiceViewList"), fCompleter(completer) { // we need to check if user clicks outside of window-bounds: @@ -205,7 +212,7 @@ void BDefaultChoiceView::ListView::AttachedToWindow() { SetTarget(this); - SetInvocationMessage(new BMessage(BM_INVOKED)); + SetInvocationMessage(new BMessage(MSG_INVOKED)); BListView::AttachedToWindow(); } @@ -221,7 +228,7 @@ void BDefaultChoiceView::ListView::MessageReceived(BMessage* message) { switch(message->what) { - case BM_INVOKED: + case MSG_INVOKED: fCompleter->ApplyChoice(); break; default: @@ -316,7 +323,8 @@ BDefaultChoiceView::ListItem::DrawItem(BView* owner, BRect frame, BDefaultChoiceView::BDefaultChoiceView() : fWindow(NULL), - fListView(NULL) + fListView(NULL), + fMaxVisibleChoices(5) { } @@ -359,7 +367,7 @@ BDefaultChoiceView::ShowChoices(BAutoCompleter::CompletionStyle* completer) fListView = new ListView(completer); int32 count = choiceModel->CountChoices(); - for(int32 i=0; iAddItem( new ListItem(choiceModel->ChoiceAt(i)) ); @@ -370,7 +378,7 @@ BDefaultChoiceView::ShowChoices(BAutoCompleter::CompletionStyle* completer) | B_AVOID_FOCUS | B_ASYNCHRONOUS_CONTROLS); fWindow->AddChild(fListView); - int32 visibleCount = min_c(count, 5); + int32 visibleCount = min_c(count, fMaxVisibleChoices); float listHeight = fListView->ItemFrame(visibleCount - 1).bottom + 1; BRect pvRect = editView->GetAdjustmentFrame(); @@ -407,3 +415,31 @@ BDefaultChoiceView::ChoicesAreShown() return (fWindow != NULL); } + +int32 +BDefaultChoiceView::CountVisibleChoices() const +{ + return min_c(fMaxVisibleChoices, fListView->CountItems()); +} + + +void +BDefaultChoiceView::SetMaxVisibleChoices(int32 choices) +{ + if (choices < 1) + choices = 1; + if (choices == fMaxVisibleChoices) + return; + + fMaxVisibleChoices = choices; + + // TODO: Update live? +} + + +int32 +BDefaultChoiceView::MaxVisibleChoices() const +{ + return fMaxVisibleChoices; +} + diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h index 216a2d7f78..6c3e50e8f5 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h @@ -35,6 +35,7 @@ public: virtual bool SelectNext(bool wrap = false); virtual bool SelectPrevious(bool wrap = false); virtual bool IsChoiceSelected() const; + virtual int32 SelectedChoiceIndex() const; virtual void ApplyChoice(bool hideChoices = true); virtual void CancelChoice(); @@ -60,6 +61,7 @@ protected: virtual void MessageReceived(BMessage* msg); virtual void MouseDown(BPoint point); virtual void AttachedToWindow(); + private: BAutoCompleter::CompletionStyle* fCompleter; }; @@ -84,10 +86,15 @@ public: BAutoCompleter::CompletionStyle* completer); virtual void HideChoices(); virtual bool ChoicesAreShown(); + virtual int32 CountVisibleChoices() const; + + void SetMaxVisibleChoices(int32 choices); + int32 MaxVisibleChoices() const; private: BWindow* fWindow; ListView* fListView; + int32 fMaxVisibleChoices; }; #endif // _AUTO_COMPLETER_DEFAULT_IMPL_H diff --git a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp index 3f83e884d8..66e95e9ae6 100644 --- a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp +++ b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp @@ -122,6 +122,23 @@ TextViewCompleter::Filter(BMessage* message, BHandler** target) // See above. ApplyChoice(false); return B_SKIP_MESSAGE; + case B_PAGE_UP: + { + int32 index = SelectedChoiceIndex() - CountVisibleChoices(); + index = max_c(index, 0); + Select(index); + ApplyChoice(false); + return B_SKIP_MESSAGE; + } + case B_PAGE_DOWN: + { + int32 index = SelectedChoiceIndex() + CountVisibleChoices(); + index = min_c(index, CountChoices() - 1); + Select(index); + ApplyChoice(false); + return B_SKIP_MESSAGE; + } + case B_ESCAPE: CancelChoice(); return B_SKIP_MESSAGE; From 1f009b1e11c283ce1c13ce0c03d3b943c4015fb9 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 18 May 2010 19:13:58 +0000 Subject: [PATCH 279/349] Tweaked the delays for the auto-hiding of the mouse pointer and the interface in full-screen mode. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@502 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 49a0dc3a11..3ff7e2d9f3 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1904,7 +1904,7 @@ BrowserWindow::_CheckAutoHideInterface() _ShowInterface(true); else if (fNavigationGroup->IsVisible() && fLastMousePos.y > fNavigationGroup->Frame().bottom - && system_time() - fLastMouseMovedTime > 3000000) { + && system_time() - fLastMouseMovedTime > 1000000) { // NOTE: Do not re-use navigationGroupBottom in the above // check, since we only want to hide the interface when it is visible. _ShowInterface(false); From 402459960e49927432f8f7f9e6081b1f8d155d14 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 19 May 2010 20:07:20 +0000 Subject: [PATCH 280/349] Fix empty URL input bar when switching to a tab after it loaded in the background. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@503 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 3ff7e2d9f3..9888677abf 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -188,9 +188,9 @@ public: fURLInputContents = text; } - const char* URLInputContents() const + const BString& URLInputContents() const { - return fURLInputContents.String(); + return fURLInputContents; } void SetURLInputSelection(int32 selectionStart, int32 selectionEnd) @@ -946,7 +946,10 @@ BrowserWindow::SetCurrentWebView(BWebView* webView) if (userData != NULL) { fURLInputGroup->SetPageIcon(userData->PageIcon()); - fURLInputGroup->SetText(userData->URLInputContents()); + if (userData->URLInputContents().Length()) + fURLInputGroup->SetText(userData->URLInputContents()); + else + fURLInputGroup->SetText(webView->MainFrameURL()); if (userData->URLInputSelectionStart() >= 0) { fURLInputGroup->TextView()->Select( userData->URLInputSelectionStart(), From af7e6dd1a4d25e5c44ebf550c03c149243a5e87f Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 19 May 2010 22:23:51 +0000 Subject: [PATCH 281/349] Display tool tips for browser tabs with the page title. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@504 94f232f2-1747-11df-bad5-a5bfde151594 --- .../webpositive/tabview/TabContainerView.h | 1 + src/apps/webpositive/tabview/TabManager.cpp | 21 +++++++++++++++++++ src/apps/webpositive/tabview/TabManager.h | 1 + 3 files changed, 23 insertions(+) diff --git a/src/apps/webpositive/tabview/TabContainerView.h b/src/apps/webpositive/tabview/TabContainerView.h index 13815d1592..a5a7ee04fa 100644 --- a/src/apps/webpositive/tabview/TabContainerView.h +++ b/src/apps/webpositive/tabview/TabContainerView.h @@ -43,6 +43,7 @@ public: virtual void DoubleClickOutsideTabs() = 0; virtual void UpdateTabScrollability(bool canScrollLeft, bool canScrollRight) = 0; + virtual void SetToolTip(const BString& text) = 0; }; public: diff --git a/src/apps/webpositive/tabview/TabManager.cpp b/src/apps/webpositive/tabview/TabManager.cpp index bdde273b04..743b83916a 100644 --- a/src/apps/webpositive/tabview/TabManager.cpp +++ b/src/apps/webpositive/tabview/TabManager.cpp @@ -307,6 +307,17 @@ public: fTabContainerGroup->EnableScrollButtons(canScrollLeft, canScrollRight); } + virtual void SetToolTip(const BString& text) + { + if (fCurrentToolTip == text) + return; + fCurrentToolTip = text; + fManager->GetTabContainerView()->HideToolTip(); + fManager->GetTabContainerView()->SetToolTip( + reinterpret_cast(NULL)); + fManager->GetTabContainerView()->SetToolTip(fCurrentToolTip.String()); + } + void CloseTab(int32 index); void SetCloseButtonsAvailable(bool available) @@ -333,6 +344,7 @@ private: bool fCloseButtonsAvailable; BMessage* fDoubleClickOutsideTabsMessage; BMessenger fTarget; + BString fCurrentToolTip; }; @@ -502,6 +514,8 @@ WebTabView::MouseMoved(BPoint where, uint32 transit, } } + fController->SetToolTip(Label()); + TabView::MouseMoved(where, transit, dragMessage); } @@ -695,6 +709,13 @@ TabManager::TabGroup() const } +BView* +TabManager::GetTabContainerView() const +{ + return fTabContainerView; +} + + BView* TabManager::ContainerView() const { diff --git a/src/apps/webpositive/tabview/TabManager.h b/src/apps/webpositive/tabview/TabManager.h index 04f86062a2..6558a1620f 100644 --- a/src/apps/webpositive/tabview/TabManager.h +++ b/src/apps/webpositive/tabview/TabManager.h @@ -58,6 +58,7 @@ public: #endif BView* TabGroup() const; + BView* GetTabContainerView() const; BView* ContainerView() const; BView* ViewForTab(int32 tabIndex) const; From f94d5e280024f8c54675efb36373b9357156eb41 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 19 May 2010 22:41:36 +0000 Subject: [PATCH 282/349] Don't store the last window frame with the full-screen window size... git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@505 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 2 +- src/apps/webpositive/BrowserWindow.cpp | 12 +++++++++++- src/apps/webpositive/BrowserWindow.h | 2 ++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index b6f1cc349e..3e936e273f 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -253,7 +253,7 @@ BrowserApp::QuitRequested() if (!webWindow->Lock()) continue; if (webWindow->QuitRequested()) { - fLastWindowFrame = webWindow->Frame(); + fLastWindowFrame = webWindow->WindowFrame(); webWindow->Quit(); i--; } else { diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 9888677abf..b3e88a54de 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -846,7 +846,7 @@ BrowserWindow::QuitRequested() _ShutdownTab(0); BMessage message(WINDOW_CLOSED); - message.AddRect("window frame", Frame()); + message.AddRect("window frame", WindowFrame()); be_app->PostMessage(&message); return true; } @@ -1018,6 +1018,16 @@ BrowserWindow::CreateNewTab(const BString& _url, bool select, BWebView* webView) } +BRect +BrowserWindow::WindowFrame() const +{ + if (fIsFullscreen) + return fNonFullscreenWindowFrame; + else + return Frame(); +} + + // #pragma mark - Notification API diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 4fd972fcce..adbe3742a2 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -107,6 +107,8 @@ public: void CreateNewTab(const BString& url, bool select, BWebView* webView = 0); + BRect WindowFrame() const; + private: // WebPage notification API implementations virtual void NavigationRequested(const BString& url, From e979801bf732ee2bab87b51fcce9a861a0d43043 Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 19 May 2010 22:52:34 +0000 Subject: [PATCH 283/349] Introduced --fullscreen and -f command line options. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@506 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 39 ++++++++++++------- src/apps/webpositive/BrowserApp.h | 9 +++-- src/apps/webpositive/BrowserWindow.cpp | 54 +++++++++++++------------- src/apps/webpositive/BrowserWindow.h | 2 + 4 files changed, 61 insertions(+), 43 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 3e936e273f..5f8972a5f4 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -102,6 +102,11 @@ BrowserApp::ArgvReceived(int32 argc, char** argv) { BMessage message(B_REFS_RECEIVED); for (int i = 1; i < argc; i++) { + if (strcmp("-f", argv[i]) == 0 + || strcmp("--fullscreen", argv[i]) == 0) { + message.AddBool("fullscreen", true); + continue; + } const char* url = argv[i]; BEntry entry(argv[i], true); BPath path; @@ -163,16 +168,15 @@ BrowserApp::ReadyToRun() fInitialized = true; int32 pagesCreated = 0; + bool fullscreen = false; if (fLaunchRefsMessage) { - _RefsReceived(fLaunchRefsMessage, &pagesCreated); + _RefsReceived(fLaunchRefsMessage, &pagesCreated, &fullscreen); delete fLaunchRefsMessage; - fLaunchRefsMessage = 0; - } - if (pagesCreated == 0) { - BrowserWindow* window = new BrowserWindow(fLastWindowFrame, fSettings, - ""); - window->Show(); + fLaunchRefsMessage = NULL; } + if (pagesCreated == 0) + _CreateNewWindow("", fullscreen); + PostMessage(PRELOAD_BROWSING_HISTORY); } @@ -284,10 +288,15 @@ BrowserApp::QuitRequested() void -BrowserApp::_RefsReceived(BMessage* message, int32* _pagesCreated) +BrowserApp::_RefsReceived(BMessage* message, int32* _pagesCreated, + bool* _fullscreen) { int32 pagesCreated = 0; + bool fullscreen; + if (message->FindBool("fullscreen", &fullscreen) != B_OK) + fullscreen = false; + entry_ref ref; for (int32 i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) { BEntry entry(&ref, true); @@ -298,23 +307,25 @@ BrowserApp::_RefsReceived(BMessage* message, int32* _pagesCreated) continue; BString url; url << path.Path(); - _CreateNewPage(url); + _CreateNewPage(url, fullscreen); pagesCreated++; } BString url; for (int32 i = 0; message->FindString("url", i, &url) == B_OK; i++) { - _CreateNewPage(url); + _CreateNewPage(url, fullscreen); pagesCreated++; } if (_pagesCreated != NULL) *_pagesCreated = pagesCreated; + if (_fullscreen != NULL) + *_fullscreen = fullscreen; } void -BrowserApp::_CreateNewPage(const BString& url) +BrowserApp::_CreateNewPage(const BString& url, bool fullscreen) { uint32 workspace = 1 << current_workspace(); @@ -334,12 +345,12 @@ BrowserApp::_CreateNewPage(const BString& url) if (loadedInWindowOnCurrentWorkspace) return; } - _CreateNewWindow(url); + _CreateNewWindow(url, fullscreen); } void -BrowserApp::_CreateNewWindow(const BString& url) +BrowserApp::_CreateNewWindow(const BString& url, bool fullscreen) { // Offset the window frame unless this is the first window created in the // session. @@ -350,6 +361,8 @@ BrowserApp::_CreateNewWindow(const BString& url) BrowserWindow* window = new BrowserWindow(fLastWindowFrame, fSettings, url); + if (fullscreen) + window->ToggleFullscreen(); window->Show(); } diff --git a/src/apps/webpositive/BrowserApp.h b/src/apps/webpositive/BrowserApp.h index f83d379a63..1f48b9d947 100644 --- a/src/apps/webpositive/BrowserApp.h +++ b/src/apps/webpositive/BrowserApp.h @@ -54,9 +54,12 @@ public: private: void _RefsReceived(BMessage* message, - int32* pagesCreated = NULL); - void _CreateNewPage(const BString& url); - void _CreateNewWindow(const BString& url); + int32* pagesCreated = NULL, + bool* fullscreen = NULL); + void _CreateNewPage(const BString& url, + bool fullscreen = false); + void _CreateNewWindow(const BString& url, + bool fullscreen = false); void _CreateNewTab(BrowserWindow* window, const BString& url, bool select); void _ShowWindow(const BMessage* message, diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index b3e88a54de..b988105d4e 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -674,7 +674,7 @@ BrowserWindow::MessageReceived(BMessage* message) break; case TOGGLE_FULLSCREEN: - _ToggleFullscreen(); + ToggleFullscreen(); break; case TOGGLE_AUTO_HIDE_INTERFACE_IN_FULLSCREEN: @@ -863,7 +863,7 @@ BrowserWindow::MenusBeginning() void BrowserWindow::Zoom(BPoint origin, float width, float height) { - _ToggleFullscreen(); + ToggleFullscreen(); } @@ -1028,6 +1028,31 @@ BrowserWindow::WindowFrame() const } +void +BrowserWindow::ToggleFullscreen() +{ + if (fIsFullscreen) { + MoveTo(fNonFullscreenWindowFrame.LeftTop()); + ResizeTo(fNonFullscreenWindowFrame.Width(), + fNonFullscreenWindowFrame.Height()); + + SetFlags(Flags() & ~(B_NOT_RESIZABLE | B_NOT_MOVABLE)); + SetLook(B_DOCUMENT_WINDOW_LOOK); + + _ShowInterface(true); + } else { + fNonFullscreenWindowFrame = Frame(); + _ResizeToScreen(); + + SetFlags(Flags() | (B_NOT_RESIZABLE | B_NOT_MOVABLE)); + SetLook(B_TITLED_WINDOW_LOOK); + } + fIsFullscreen = !fIsFullscreen; + fFullscreenItem->SetMarked(fIsFullscreen); + fToggleFullscreenButton->SetVisible(fIsFullscreen); +} + + // #pragma mark - Notification API @@ -1848,31 +1873,6 @@ BrowserWindow::_ShowPage(BWebView* view) } -void -BrowserWindow::_ToggleFullscreen() -{ - if (fIsFullscreen) { - MoveTo(fNonFullscreenWindowFrame.LeftTop()); - ResizeTo(fNonFullscreenWindowFrame.Width(), - fNonFullscreenWindowFrame.Height()); - - SetFlags(Flags() & ~(B_NOT_RESIZABLE | B_NOT_MOVABLE)); - SetLook(B_DOCUMENT_WINDOW_LOOK); - - _ShowInterface(true); - } else { - fNonFullscreenWindowFrame = Frame(); - _ResizeToScreen(); - - SetFlags(Flags() | (B_NOT_RESIZABLE | B_NOT_MOVABLE)); - SetLook(B_TITLED_WINDOW_LOOK); - } - fIsFullscreen = !fIsFullscreen; - fFullscreenItem->SetMarked(fIsFullscreen); - fToggleFullscreenButton->SetVisible(fIsFullscreen); -} - - void BrowserWindow::_ResizeToScreen() { diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index adbe3742a2..16cb5d2b3d 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -109,6 +109,8 @@ public: BRect WindowFrame() const; + void ToggleFullscreen(); + private: // WebPage notification API implementations virtual void NavigationRequested(const BString& url, From 86007edfa7722de33470ad300ae256c59f319bae Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 19 May 2010 23:08:26 +0000 Subject: [PATCH 284/349] Use Cmd-J for hiding the downloads window. (Ticket #37) git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@507 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 00d57dc50f..fc6fd0c3ce 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -156,7 +156,7 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, BMenu* menu = new BMenu("Downloads"); menu->AddItem(new BMenuItem("Open downloads folder", new BMessage(OPEN_DOWNLOADS_FOLDER))); - menu->AddItem(new BMenuItem("Hide", new BMessage(B_QUIT_REQUESTED), 'H')); + menu->AddItem(new BMenuItem("Hide", new BMessage(B_QUIT_REQUESTED), 'J')); menuBar->AddItem(menu); fDownloadsScrollView = new DownloadContainerScrollView(downloadsGroupView); From 0953daf31f467e4938c1dcbc5708be73f71dd55e Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 20 May 2010 17:59:00 +0000 Subject: [PATCH 285/349] "Manage Bookmarks" shortcut is now Cmd-M. Closed ticket #38. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@508 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index b988105d4e..a2c8fb0ae1 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -135,7 +135,7 @@ public: if (CountItems() > 0) AddItem(new BSeparatorItem(), 0); AddItem(new BMenuItem("Manage bookmarks", - new BMessage(SHOW_BOOKMARKS)), 0); + new BMessage(SHOW_BOOKMARKS), 'M'), 0); AddItem(new BMenuItem("Bookmark this page", new BMessage(CREATE_BOOKMARK), 'B'), 0); DoLayout(); From 795b44ebe65e6bc045f517773d0683b50a3baac1 Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 20 May 2010 18:49:18 +0000 Subject: [PATCH 286/349] F11 -> Toggle fullscreen F5 -> Reload page. (Ticket #56) git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@509 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index a2c8fb0ae1..d5b037fe3d 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -506,6 +506,21 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) } else if (bytes[0] == B_RIGHT_ARROW && modifiers == B_COMMAND_KEY) { PostMessage(GO_FORWARD); return; + } else if (bytes[0] == B_FUNCTION_KEY) { + // Some function key Firefox compatibility + int32 key; + if (message->FindInt32("key", &key) == B_OK) { + switch (key) { + case B_F5_KEY: + PostMessage(RELOAD); + break; + case B_F11_KEY: + PostMessage(TOGGLE_FULLSCREEN); + break; + default: + break; + } + } } else if (target == fURLInputGroup->TextView()) { // Handle B_RETURN in the URL text control. This is the easiest // way to react *only* when the user presses the return key in the From 11365e77e8ba872f6f81353697d2101801d2cc76 Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 20 May 2010 19:31:56 +0000 Subject: [PATCH 287/349] Added Home button... by popular request. Will perhaps make it a setting. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@510 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 22 ++++++++++++++++------ src/apps/webpositive/BrowserWindow.h | 1 + src/apps/webpositive/WebPositive.rdef | 13 +++++++++++++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index d5b037fe3d..09d90210c7 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -83,6 +83,7 @@ enum { GO_BACK = 'goba', GO_FORWARD = 'gofo', STOP = 'stop', + HOME = 'home', GOTO_URL = 'goul', RELOAD = 'reld', CLEAR_HISTORY = 'clhs', @@ -359,6 +360,10 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fStopButton->SetIcon(204); fStopButton->TrimIcon(); + fHomeButton = new IconButton("Home", 0, NULL, new BMessage(HOME)); + fHomeButton->SetIcon(206); + fHomeButton->TrimIcon(); + // URL input group fURLInputGroup = new URLInputGroup(new BMessage(GOTO_URL)); @@ -402,12 +407,14 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, // Navigation group BView* navigationGroup = BGroupLayoutBuilder(B_VERTICAL) - .Add(BGridLayoutBuilder(kElementSpacing, kElementSpacing) - .Add(fBackButton, 0, 0) - .Add(fForwardButton, 1, 0) - .Add(fStopButton, 2, 0) - .Add(fURLInputGroup, 3, 0) - .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) + .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) + .Add(fBackButton) + .Add(fForwardButton) + .Add(fStopButton) + .Add(fHomeButton) + .Add(fURLInputGroup) + .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, + kInsetSpacing) ) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) ; @@ -580,6 +587,9 @@ BrowserWindow::MessageReceived(BMessage* message) case STOP: CurrentWebView()->StopLoading(); break; + case HOME: + CurrentWebView()->LoadURL(fStartPageURL); + break; case CLEAR_HISTORY: { BrowsingHistory* history = BrowsingHistory::DefaultInstance(); diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 16cb5d2b3d..6ef6f4d034 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -204,6 +204,7 @@ private: IconButton* fBackButton; IconButton* fForwardButton; IconButton* fStopButton; + IconButton* fHomeButton; URLInputGroup* fURLInputGroup; BStringView* fStatusText; BStatusBar* fLoadingProgressBar; diff --git a/src/apps/webpositive/WebPositive.rdef b/src/apps/webpositive/WebPositive.rdef index 5b89991cc9..c9561eebac 100644 --- a/src/apps/webpositive/WebPositive.rdef +++ b/src/apps/webpositive/WebPositive.rdef @@ -296,6 +296,19 @@ resource(204, "kActionStop") #'VICN' array { $"000A0503070809100117810004" }; +resource(206, "kActionGoStart") #'VICN' array { + $"6E63696605050002001602B53D77BAF2653D77A7B7CFFC460F874A2D7700F0FF" + $"D50200160236FB2637191CBC57873C40E14B0E7149D82700A2FFBB0200060239" + $"FB483A6DC2BDAC713D02DB4B384746086300EA0606FFD005050200060238B0C7" + $"397C47BD2A963C71B74A82C348B2B700FF4444FFF106060A0A06304942525044" + $"50383E32303D0A09303B3049324A32C0723643364C4252424036320A04503650" + $"44425242400A082D3E3535434645455439462C35312B3C0A062B3C2D3E353543" + $"46454535310A0445455439462C35310A0432C072324A364C36430A043A453A4A" + $"3E4C3EC2630A044645464A484848430A044C3F4C444E424E3D070A0001001001" + $"178400040A010101000A020102000A000406070809000A000103100117840004" + $"0A030105000A04010400" +}; + resource(205, "kActionGo") archive BBitmap { "_frame" = rect { 0.0, 0.0, 15.0, 15.0 }, "_cspace" = 8200, From 02a2ef19691fcce4fd29226eba6f315dc06296ba Mon Sep 17 00:00:00 2001 From: stippi Date: Thu, 20 May 2010 19:57:34 +0000 Subject: [PATCH 288/349] * Small refactoring for retrieving the URL for a new tab. * Load new files into the current tab, if the URL of that tab is either empty or the URL for new tabs, instead of always opening a new tab. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@511 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 5 ++- src/apps/webpositive/BrowserWindow.cpp | 61 +++++++++++++++++--------- src/apps/webpositive/BrowserWindow.h | 3 ++ 3 files changed, 48 insertions(+), 21 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 5f8972a5f4..4efe1858e2 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -336,7 +336,10 @@ BrowserApp::_CreateNewPage(const BString& url, bool fullscreen) continue; if (webWindow->Lock()) { if (webWindow->Workspaces() & workspace) { - webWindow->CreateNewTab(url, true); + if (webWindow->IsBlankTab()) + webWindow->CurrentWebView()->LoadURL(url); + else + webWindow->CreateNewTab(url, true); webWindow->Activate(); loadedInWindowOnCurrentWorkspace = true; } diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 09d90210c7..33c347aa15 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -474,7 +474,10 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, kSettingsKeyAutoHideInterfaceInFullscreenMode, fAutoHideInterfaceInFullscreenMode)); - AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(EDIT_HIDE_FIND_GROUP)); + AddShortcut('F', B_COMMAND_KEY | B_SHIFT_KEY, + new BMessage(EDIT_HIDE_FIND_GROUP)); + // TODO: Should be a different shortcut, H is usually for Find selection. + AddShortcut('H', B_COMMAND_KEY, new BMessage(HOME)); // Add shortcuts to select a particular tab for (int32 i = 1; i <= 9; i++) { @@ -993,6 +996,17 @@ BrowserWindow::SetCurrentWebView(BWebView* webView) } +bool +BrowserWindow::IsBlankTab() const +{ + if (CurrentWebView() == NULL) + return false; + BString requestedURL = CurrentWebView()->MainFrameRequestedURL(); + return requestedURL.Length() == 0 + || requestedURL == _NewTabURL(fTabManager->CountTabs() == 1); +} + + void BrowserWindow::CreateNewTab(const BString& _url, bool select, BWebView* webView) { @@ -1006,25 +1020,8 @@ BrowserWindow::CreateNewTab(const BString& _url, bool select, BWebView* webView) fTabManager->AddTab(webView, "New tab"); BString url(_url); - if (applyNewPagePolicy && url.Length() == 0) { - uint32 policy = isNewWindow ? fNewWindowPolicy : fNewTabPolicy; - // Implement new page policy - switch (policy) { - case OpenStartPage: - url = fStartPageURL; - break; - case OpenSearchPage: - url = fSearchPageURL; - break; - case CloneCurrentPage: - if (CurrentWebView() != NULL) - url = CurrentWebView()->MainFrameURL(); - break; - case OpenBlankPage: - default: - break; - } - } + if (applyNewPagePolicy && url.Length() == 0) + url = _NewTabURL(isNewWindow); if (url.Length() > 0) webView->LoadURL(url.String()); @@ -1980,3 +1977,27 @@ BrowserWindow::_ShowInterface(bool show) fLoadingProgressBar->Hide(); } + +BString +BrowserWindow::_NewTabURL(bool isNewWindow) const +{ + BString url; + uint32 policy = isNewWindow ? fNewWindowPolicy : fNewTabPolicy; + // Implement new page policy + switch (policy) { + case OpenStartPage: + url = fStartPageURL; + break; + case OpenSearchPage: + url = fSearchPageURL; + break; + case CloneCurrentPage: + if (CurrentWebView() != NULL) + url = CurrentWebView()->MainFrameURL(); + break; + case OpenBlankPage: + default: + break; + } + return url; +} diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 6ef6f4d034..9e85994e51 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -104,6 +104,7 @@ public: virtual void SetCurrentWebView(BWebView* view); + bool IsBlankTab() const; void CreateNewTab(const BString& url, bool select, BWebView* webView = 0); @@ -187,6 +188,8 @@ private: void _CheckAutoHideInterface(); void _ShowInterface(bool show); + BString _NewTabURL(bool isNewWindow) const; + private: BMenu* fHistoryMenu; int32 fHistoryMenuFixedItemCount; From fb03e2c5739385c47ec9fbdc7a2ffaab1d9ebc69 Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 21 May 2010 16:59:58 +0000 Subject: [PATCH 289/349] * When downloads are still in progress, warn the user when the app quits and allow to continue downloading. * If the Downloads window is the only window, minimize on close instead of hiding without any way to get the window back. * Added menu item "New browser window" to Downloads window. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@512 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 23 +++++++++++ src/apps/webpositive/DownloadWindow.cpp | 55 +++++++++++++++++++++++-- src/apps/webpositive/DownloadWindow.h | 4 ++ 3 files changed, 79 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 4efe1858e2..79b2d3418e 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -212,6 +212,7 @@ BrowserApp::MessageReceived(BMessage* message) } case WINDOW_OPENED: fWindowCount++; + fDownloadWindow->SetMinimizeOnClose(false); break; case WINDOW_CLOSED: fWindowCount--; @@ -250,6 +251,28 @@ BrowserApp::RefsReceived(BMessage* message) bool BrowserApp::QuitRequested() { + if (fDownloadWindow->DownloadsInProgress()) { + BAlert* alert = new BAlert("Downloads in progress", + "There are still downloads in progress, do you really want to " + "quit WebPositive now?", "Quit", "Continue downloads"); + int32 choice = alert->Go(); + if (choice == 1) { + if (fWindowCount == 0) { + if (fDownloadWindow->Lock()) { + fDownloadWindow->SetWorkspaces(1 << current_workspace()); + if (fDownloadWindow->IsHidden()) + fDownloadWindow->Show(); + else + fDownloadWindow->Activate(); + fDownloadWindow->SetMinimizeOnClose(true); + fDownloadWindow->Unlock(); + return false; + } + } else + return false; + } + } + for (int i = 0; BWindow* window = WindowAt(i); i++) { BrowserWindow* webWindow = dynamic_cast(window); if (!webWindow) diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index fc6fd0c3ce..bd2c7e84c4 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -46,6 +46,7 @@ #include #include "BrowserApp.h" +#include "BrowserWindow.h" #include "DownloadProgressView.h" #include "SettingsKeys.h" #include "SettingsMessage.h" @@ -135,7 +136,8 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, SettingsMessage* settings) : BWindow(frame, "Downloads", B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, - B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE) + B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE), + fMinimizeOnClose(false) { SetPulseRate(1000000); @@ -156,6 +158,13 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, BMenu* menu = new BMenu("Downloads"); menu->AddItem(new BMenuItem("Open downloads folder", new BMessage(OPEN_DOWNLOADS_FOLDER))); + BMessage* newWindowMessage = new BMessage(NEW_WINDOW); + newWindowMessage->AddString("url", ""); + BMenuItem* newWindowItem = new BMenuItem("New browser window", + newWindowMessage, 'N'); + menu->AddItem(newWindowItem); + newWindowItem->SetTarget(be_app); + menu->AddSeparatorItem(); menu->AddItem(new BMenuItem("Hide", new BMessage(B_QUIT_REQUESTED), 'J')); menuBar->AddItem(menu); @@ -305,12 +314,52 @@ DownloadWindow::MessageReceived(BMessage* message) bool DownloadWindow::QuitRequested() { - if (!IsHidden()) - Hide(); + if (fMinimizeOnClose) { + if (!IsMinimized()) + Minimize(true); + } else { + if (!IsHidden()) + Hide(); + } return false; } +bool +DownloadWindow::DownloadsInProgress() +{ + bool downloadsInProgress = false; + if (!Lock()) + return downloadsInProgress; + + for (int32 i = fDownloadViewsLayout->CountItems() - 1; + BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) { + DownloadProgressView* view = dynamic_cast( + item->View()); + if (!view) + continue; + if (view->Download() != NULL) { + downloadsInProgress = true; + break; + } + } + + Unlock(); + + return downloadsInProgress; +} + + +void +DownloadWindow::SetMinimizeOnClose(bool minimize) +{ + if (Lock()) { + fMinimizeOnClose = minimize; + Unlock(); + } +} + + // #pragma mark - private diff --git a/src/apps/webpositive/DownloadWindow.h b/src/apps/webpositive/DownloadWindow.h index e4e62bfecc..d76661ba4e 100644 --- a/src/apps/webpositive/DownloadWindow.h +++ b/src/apps/webpositive/DownloadWindow.h @@ -50,6 +50,9 @@ public: virtual void MessageReceived(BMessage* message); virtual bool QuitRequested(); + bool DownloadsInProgress(); + void SetMinimizeOnClose(bool minimize); + private: void _DownloadStarted(BWebDownload* download); void _DownloadFinished(BWebDownload* download); @@ -66,6 +69,7 @@ private: BButton* fRemoveFinishedButton; BButton* fRemoveMissingButton; BString fDownloadPath; + bool fMinimizeOnClose; }; #endif // DOWNLOAD_WINDOW_H From 8a48f074d8c7c3c3b2b5b51e23e4d85132dec77b Mon Sep 17 00:00:00 2001 From: stippi Date: Fri, 21 May 2010 20:45:23 +0000 Subject: [PATCH 290/349] Handle B_RETURN and B_ESCAPE when the Find text control has focus. Refactored the code to visibly invoke a BButton and use it to show the respective buttons go down in the Find group. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@513 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 40 ++++++++++++++++++++------ src/apps/webpositive/BrowserWindow.h | 4 +++ 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 33c347aa15..b0f8ce1d23 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -390,16 +390,21 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fFindTextControl = new BTextControl("find", "Find:", "", new BMessage(EDIT_FIND_NEXT)); fFindTextControl->SetModificationMessage(new BMessage(FIND_TEXT_CHANGED)); + fFindPreviousButton = new BButton("Previous", + new BMessage(EDIT_FIND_PREVIOUS)); + fFindNextButton = new BButton("Next", new BMessage(EDIT_FIND_NEXT)); + fFindCloseButton = new BButton("Close", + new BMessage(EDIT_HIDE_FIND_GROUP)); fFindCaseSensitiveCheckBox = new BCheckBox("Match case"); BView* findGroup = BGroupLayoutBuilder(B_VERTICAL) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) .Add(fFindTextControl) - .Add(new BButton("Previous", new BMessage(EDIT_FIND_PREVIOUS))) - .Add(new BButton("Next", new BMessage(EDIT_FIND_NEXT))) + .Add(fFindPreviousButton) + .Add(fFindNextButton) .Add(fFindCaseSensitiveCheckBox) .Add(BSpaceLayoutItem::CreateGlue()) - .Add(new BButton("Close", new BMessage(EDIT_HIDE_FIND_GROUP))) + .Add(fFindCloseButton) .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) ) @@ -538,11 +543,19 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) // when the text control just goes out of focus. if (bytes[0] == B_RETURN) { // Do it in such a way that the user sees the Go-button go down. - fURLInputGroup->GoButton()->SetValue(B_CONTROL_ON); - UpdateIfNeeded(); - fURLInputGroup->GoButton()->Invoke(); - snooze(1000); - fURLInputGroup->GoButton()->SetValue(B_CONTROL_OFF); + _InvokeButtonVisibly(fURLInputGroup->GoButton()); + return; + } + } else if (target == fFindTextControl->TextView()) { + // Handle B_RETURN when the find text control has focus. + if (bytes[0] == B_RETURN) { + if ((modifiers & B_SHIFT_KEY) != 0) + _InvokeButtonVisibly(fFindPreviousButton); + else + _InvokeButtonVisibly(fFindNextButton); + return; + } else if (bytes[0] == B_ESCAPE) { + _InvokeButtonVisibly(fFindCloseButton); return; } } @@ -1978,6 +1991,17 @@ BrowserWindow::_ShowInterface(bool show) } +void +BrowserWindow::_InvokeButtonVisibly(BButton* button) +{ + button->SetValue(B_CONTROL_ON); + UpdateIfNeeded(); + button->Invoke(); + snooze(1000); + button->SetValue(B_CONTROL_OFF); +} + + BString BrowserWindow::_NewTabURL(bool isNewWindow) const { diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 9e85994e51..4097bbcdac 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -187,6 +187,7 @@ private: void _SetAutoHideInterfaceInFullscreen(bool doIt); void _CheckAutoHideInterface(); void _ShowInterface(bool show); + void _InvokeButtonVisibly(BButton* button); BString _NewTabURL(bool isNewWindow) const; @@ -220,6 +221,9 @@ private: BLayoutItem* fToggleFullscreenButton; BTextControl* fFindTextControl; + BButton* fFindPreviousButton; + BButton* fFindNextButton; + BButton* fFindCloseButton; BCheckBox* fFindCaseSensitiveCheckBox; TabManager* fTabManager; From 3a3173e8cb42451fb9f99ea773b50085cfe5ba41 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 22 May 2010 13:50:48 +0000 Subject: [PATCH 291/349] Set a tool-tip for the area outside of any tabs. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@514 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/tabview/TabContainerView.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/apps/webpositive/tabview/TabContainerView.cpp b/src/apps/webpositive/tabview/TabContainerView.cpp index fc0f41b8bc..73457eaf5b 100644 --- a/src/apps/webpositive/tabview/TabContainerView.cpp +++ b/src/apps/webpositive/tabview/TabContainerView.cpp @@ -459,6 +459,11 @@ TabContainerView::_MouseMoved(BPoint where, uint32 _transit, fLastMouseEventTab = tab; if (fLastMouseEventTab) fLastMouseEventTab->MouseMoved(where, B_ENTERED_VIEW, dragMessage); + else { + SetToolTip(static_cast(NULL)); + HideToolTip(); + SetToolTip("Double-click or middle-click to open new tab."); + } } } From 807ee4b4772640407e98deeab3f6f98a7a0805d6 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 22 May 2010 13:51:29 +0000 Subject: [PATCH 292/349] Revert the default of the Auto-hide mouse pointer setting, by popular request. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@515 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 2 +- src/apps/webpositive/SettingsWindow.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index b0f8ce1d23..d058e4e049 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -236,7 +236,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fZoomTextOnly(true), fShowTabsIfSinglePageOpen(true), fAutoHideInterfaceInFullscreenMode(false), - fAutoHidePointer(true) + fAutoHidePointer(false) { // Begin listening to settings changes and read some current values. fAppSettings->AddListener(BMessenger(this)); diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 8cfece44f9..79afb38ccc 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -335,7 +335,7 @@ SettingsWindow::_CreateGeneralPage(float spacing) fAutoHidePointer = new BCheckBox("auto-hide pointer", B_TRANSLATE("Auto-hide mouse pointer."), new BMessage(MSG_AUTO_HIDE_POINTER_BEHAVIOR_CHANGED)); - fAutoHidePointer->SetValue(B_CONTROL_ON); + fAutoHidePointer->SetValue(B_CONTROL_OFF); BView* view = BGroupLayoutBuilder(B_VERTICAL, spacing / 2) .Add(BGridLayoutBuilder(spacing / 2, spacing / 2) @@ -538,7 +538,7 @@ SettingsWindow::_CanApplySettings() const canApply = canApply || ( (fAutoHidePointer->Value() == B_CONTROL_ON) - != fSettings->GetValue(kSettingsKeyAutoHidePointer, true)); + != fSettings->GetValue(kSettingsKeyAutoHidePointer, false)); canApply = canApply || (_MaxHistoryAge() != BrowsingHistory::DefaultInstance()->MaxHistoryItemAge()); @@ -671,7 +671,7 @@ SettingsWindow::_RevertSettings() fSettings->GetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode, false)); fAutoHidePointer->SetValue( - fSettings->GetValue(kSettingsKeyAutoHidePointer, true)); + fSettings->GetValue(kSettingsKeyAutoHidePointer, false)); BString text; text << BrowsingHistory::DefaultInstance()->MaxHistoryItemAge(); From 82117cd7eb59625d0dfb0524dec5b00f618a81c0 Mon Sep 17 00:00:00 2001 From: stippi Date: Sat, 22 May 2010 19:04:46 +0000 Subject: [PATCH 293/349] Added "View->Page source" feature. For local files, it will open the file in the preferred app for text/x-source-code. For remote pages, it will save a temporary file and open the editor with that. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@517 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 97 ++++++++++++++++++++++++-- src/apps/webpositive/BrowserWindow.h | 3 + 2 files changed, 96 insertions(+), 4 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index d058e4e049..9e527b4892 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -100,6 +100,8 @@ enum { TOGGLE_AUTO_HIDE_INTERFACE_IN_FULLSCREEN = 'tgah', CHECK_AUTO_HIDE_INTERFACE = 'cahi', + SHOW_PAGE_SOURCE = 'spgs', + EDIT_SHOW_FIND_GROUP = 'sfnd', EDIT_HIDE_FIND_GROUP = 'hfnd', EDIT_FIND_NEXT = 'fndn', @@ -315,9 +317,12 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, menu = new BMenu("View"); menu->AddItem(new BMenuItem("Reload", new BMessage(RELOAD), 'R')); menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Increase size", new BMessage(ZOOM_FACTOR_INCREASE), '+')); - menu->AddItem(new BMenuItem("Decrease size", new BMessage(ZOOM_FACTOR_DECREASE), '-')); - menu->AddItem(new BMenuItem("Reset size", new BMessage(ZOOM_FACTOR_RESET), '0')); + menu->AddItem(new BMenuItem("Increase size", + new BMessage(ZOOM_FACTOR_INCREASE), '+')); + menu->AddItem(new BMenuItem("Decrease size", + new BMessage(ZOOM_FACTOR_DECREASE), '-')); + menu->AddItem(new BMenuItem("Reset size", + new BMessage(ZOOM_FACTOR_RESET), '0')); fZoomTextOnlyMenuItem = new BMenuItem("Zoom text only", new BMessage(ZOOM_TEXT_ONLY)); fZoomTextOnlyMenuItem->SetMarked(fZoomTextOnly); @@ -327,6 +332,8 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fFullscreenItem = new BMenuItem("Fullscreen", new BMessage(TOGGLE_FULLSCREEN), B_RETURN); menu->AddItem(fFullscreenItem); + menu->AddItem(new BMenuItem("Page source", + new BMessage(SHOW_PAGE_SOURCE), 'U')); mainMenu->AddItem(menu); fHistoryMenu = new BMenu("History"); @@ -347,7 +354,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, mainMenu->AddItem(bookmarkMenu); } - // Back, Forward & Stop + // Back, Forward, Stop & Home buttons fBackButton = new IconButton("Back", 0, NULL, new BMessage(GO_BACK)); fBackButton->SetIcon(201); fBackButton->TrimIcon(); @@ -727,6 +734,13 @@ BrowserWindow::MessageReceived(BMessage* message) _CheckAutoHideInterface(); break; + case SHOW_PAGE_SOURCE: + CurrentWebView()->WebPage()->SendPageSource(); + break; + case B_PAGE_SOURCE_RESULT: + _HandlePageSourceResult(message); + break; + case EDIT_FIND_NEXT: CurrentWebView()->FindString(fFindTextControl->Text(), true, fFindCaseSensitiveCheckBox->Value()); @@ -2025,3 +2039,78 @@ BrowserWindow::_NewTabURL(bool isNewWindow) const } return url; } + + +void +BrowserWindow::_HandlePageSourceResult(const BMessage* message) +{ + // TODO: This should be done in an extra thread perhaps. Doing it in + // the application thread is not much better, since it actually draws + // the pages... + + BPath pathToPageSource; + + BString url; + status_t ret = message->FindString("url", &url); + if (ret == B_OK && url.FindFirst("file://") == 0) { + // Local file + url.Remove(0, strlen("file://")); + pathToPageSource.SetTo(url.String()); + } else { + // Something else, store it. + // TODO: What if it isn't HTML, but for example SVG? + BString source; + ret = message->FindString("source", &source); + + if (ret == B_OK) + ret = find_directory(B_COMMON_TEMP_DIRECTORY, &pathToPageSource); + + BString tmpFileName("PageSource_"); + tmpFileName << system_time() << ".html"; + if (ret == B_OK) + ret = pathToPageSource.Append(tmpFileName.String()); + + BFile pageSourceFile(pathToPageSource.Path(), + B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY); + if (ret == B_OK) + ret = pageSourceFile.InitCheck(); + + if (ret == B_OK) { + ssize_t written = pageSourceFile.Write(source.String(), + source.Length()); + if (written != source.Length()) + ret = (status_t)written; + } + + if (ret == B_OK) { + const char* type = "text/html"; + size_t size = strlen(type); + pageSourceFile.WriteAttr("BEOS:TYPE", B_STRING_TYPE, 0, type, size); + // If it fails we don't care. + } + } + + entry_ref ref; + if (ret == B_OK) + ret = get_ref_for_path(pathToPageSource.Path(), &ref); + + if (ret == B_OK) { + BMessage refsMessage(B_REFS_RECEIVED); + ret = refsMessage.AddRef("refs", &ref); + if (ret == B_OK) { + ret = be_roster->Launch("text/x-source-code", &refsMessage); + if (ret == B_ALREADY_RUNNING) + ret = B_OK; + } + } + + if (ret != B_OK) { + char buffer[1024]; + snprintf(buffer, sizeof(buffer), "Failed to show the " + "page source: %s\n", strerror(ret)); + BAlert* alert = new BAlert("Page source error", buffer, "OK"); + alert->Go(NULL); + } +} + + diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 4097bbcdac..67ac0f5311 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -191,6 +191,9 @@ private: BString _NewTabURL(bool isNewWindow) const; + void _HandlePageSourceResult( + const BMessage* message); + private: BMenu* fHistoryMenu; int32 fHistoryMenuFixedItemCount; From a933ccf28dc6f4be8996b43b90b1a6ae4d64bfa3 Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 23 May 2010 12:56:24 +0000 Subject: [PATCH 294/349] When a download starts, do not start node monitoring the path while it is still pointing to the containing folder. Fixes ticket #62. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@518 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadProgressView.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/apps/webpositive/DownloadProgressView.cpp b/src/apps/webpositive/DownloadProgressView.cpp index f0c4e5bb3b..ad02111a05 100644 --- a/src/apps/webpositive/DownloadProgressView.cpp +++ b/src/apps/webpositive/DownloadProgressView.cpp @@ -308,14 +308,18 @@ DownloadProgressView::SaveSettings(BMessage* archive) void DownloadProgressView::AttachedToWindow() { - if (fDownload) + if (fDownload) { fDownload->SetProgressListener(BMessenger(this)); + // Will start node monitor upon receiving the B_DOWNLOAD_STARTED + // message. + } else { + BEntry entry(fPath.Path()); + if (entry.Exists()) + _StartNodeMonitor(entry); + } + fTopButton->SetTarget(this); fBottomButton->SetTarget(this); - - BEntry entry(fPath.Path()); - if (entry.Exists()) - _StartNodeMonitor(entry); } From 4a09831444efe276c2186c9158951577e58472cb Mon Sep 17 00:00:00 2001 From: stippi Date: Sun, 23 May 2010 13:21:43 +0000 Subject: [PATCH 295/349] When the expected size of a download is unknown, at least set the progress bar to 100% when it finished. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@519 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadProgressView.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/apps/webpositive/DownloadProgressView.cpp b/src/apps/webpositive/DownloadProgressView.cpp index ad02111a05..f819651f72 100644 --- a/src/apps/webpositive/DownloadProgressView.cpp +++ b/src/apps/webpositive/DownloadProgressView.cpp @@ -372,7 +372,7 @@ DownloadProgressView::MessageReceived(BMessage* message) = fProcessStartTime = fLastSpeedReferenceTime = fEstimatedFinishReferenceTime = system_time(); break; - }; + } case B_DOWNLOAD_PROGRESS: { int64 currentSize; @@ -383,6 +383,12 @@ DownloadProgressView::MessageReceived(BMessage* message) } break; } + case B_DOWNLOAD_REMOVED: + // TODO: This is a bit asymetric. The removed notification + // arrives here, but it would be nicer if it arrived + // at the window... + Window()->PostMessage(message); + break; case OPEN_DOWNLOAD: { // TODO: In case of executable files, ask the user first! @@ -414,12 +420,6 @@ DownloadProgressView::MessageReceived(BMessage* message) // TOAST! return; } - case B_DOWNLOAD_REMOVED: - // TODO: This is a bit asymetric. The removed notification - // arrives here, but it would be nicer if it arrived - // at the window... - Window()->PostMessage(message); - break; case B_NODE_MONITOR: { int32 opCode; @@ -610,6 +610,10 @@ void DownloadProgressView::DownloadFinished() { fDownload = NULL; + if (fExpectedSize == -1) { + fStatusBar->SetTo(100.0); + fExpectedSize = fCurrentSize; + } fTopButton->SetEnabled(true); fBottomButton->SetLabel("Remove"); fBottomButton->SetMessage(new BMessage(REMOVE_DOWNLOAD)); From 591220f9b2c37416d9ec9ce244128967fa28296b Mon Sep 17 00:00:00 2001 From: anevilyak Date: Sun, 30 May 2010 20:46:40 +0000 Subject: [PATCH 296/349] When disabling auto-hide, if the interface was currently still hidden, it wouldn't be restored, Closes ticket #6098. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@521 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 9e527b4892..4b6f347769 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1950,6 +1950,7 @@ BrowserWindow::_SetAutoHideInterfaceInFullscreen(bool doIt) } else { delete fPulseRunner; fPulseRunner = NULL; + _ShowInterface(true); } } From ed0c70c14d54d2e70168fbdfda1168c25411214a Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 14 Jun 2010 15:19:36 +0000 Subject: [PATCH 297/349] * Small cleanups. * Make sure that the BWebView for which a notification is received still exists. This affected only the title changed notification, for which this was already checked, and the icon received notification, which could actually lead to a crash if the tab was closed before receiving the notification. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@522 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 17 +++++++++++------ src/apps/webpositive/tabview/TabManager.cpp | 7 +++++++ src/apps/webpositive/tabview/TabManager.h | 1 + 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 4b6f347769..5b11c79aca 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1245,12 +1245,12 @@ BrowserWindow::MainDocumentError(const BString& failingURL, void BrowserWindow::TitleChanged(const BString& title, BWebView* view) { - for (int32 i = 0; i < fTabManager->CountTabs(); i++) { - if (fTabManager->ViewForTab(i) == view) { - fTabManager->SetTabLabel(i, title); - break; - } - } + int32 tabIndex = fTabManager->TabForView(view); + if (tabIndex < 0) + return; + + fTabManager->SetTabLabel(tabIndex, title); + if (view != CurrentWebView()) return; @@ -1261,6 +1261,11 @@ BrowserWindow::TitleChanged(const BString& title, BWebView* view) void BrowserWindow::IconReceived(const BBitmap* icon, BWebView* view) { + // The view may already be gone, since this notification arrives + // asynchronously. + if (!fTabManager->HasView(view)) + return; + _SetPageIcon(view, icon); } diff --git a/src/apps/webpositive/tabview/TabManager.cpp b/src/apps/webpositive/tabview/TabManager.cpp index 743b83916a..4a26c33271 100644 --- a/src/apps/webpositive/tabview/TabManager.cpp +++ b/src/apps/webpositive/tabview/TabManager.cpp @@ -746,6 +746,13 @@ TabManager::TabForView(const BView* containedView) const } +bool +TabManager::HasView(const BView* containedView) const +{ + return TabForView(containedView) >= 0; +} + + void TabManager::SelectTab(int32 tabIndex) { diff --git a/src/apps/webpositive/tabview/TabManager.h b/src/apps/webpositive/tabview/TabManager.h index 6558a1620f..4ccc64d35e 100644 --- a/src/apps/webpositive/tabview/TabManager.h +++ b/src/apps/webpositive/tabview/TabManager.h @@ -63,6 +63,7 @@ public: BView* ViewForTab(int32 tabIndex) const; int32 TabForView(const BView* containedView) const; + bool HasView(const BView* containedView) const; void SelectTab(int32 tabIndex); void SelectTab(const BView* containedView); From d848a89394e95064164c94f55582b1179a8bf664 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 14 Jun 2010 15:43:35 +0000 Subject: [PATCH 298/349] Changed download short cut from J to D, as all the rest of the shortcuts make more sense and don't necessarily follow Firefox conventions. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@523 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 18 ++++++++++++------ src/apps/webpositive/DownloadWindow.cpp | 2 +- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 5b11c79aca..d3d985f165 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -280,18 +280,24 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, newItem = new BMenuItem("New tab", new BMessage(*newTabMessage), 'T'); menu->AddItem(newItem); newItem->SetTarget(be_app); - menu->AddItem(new BMenuItem("Open location", new BMessage(OPEN_LOCATION), 'L')); + menu->AddItem(new BMenuItem("Open location", new BMessage(OPEN_LOCATION), + 'L')); menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Close window", new BMessage(B_QUIT_REQUESTED), 'W', B_SHIFT_KEY)); + menu->AddItem(new BMenuItem("Close window", new BMessage(B_QUIT_REQUESTED), + 'W', B_SHIFT_KEY)); menu->AddItem(new BMenuItem("Close tab", new BMessage(CLOSE_TAB), 'W')); menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Downloads", new BMessage(SHOW_DOWNLOAD_WINDOW), 'J')); - menu->AddItem(new BMenuItem("Settings", new BMessage(SHOW_SETTINGS_WINDOW))); - BMenuItem* aboutItem = new BMenuItem("About", new BMessage(B_ABOUT_REQUESTED)); + menu->AddItem(new BMenuItem("Downloads", + new BMessage(SHOW_DOWNLOAD_WINDOW), 'D')); + menu->AddItem(new BMenuItem("Settings", + new BMessage(SHOW_SETTINGS_WINDOW))); + BMenuItem* aboutItem = new BMenuItem("About", + new BMessage(B_ABOUT_REQUESTED)); menu->AddItem(aboutItem); aboutItem->SetTarget(be_app); menu->AddSeparatorItem(); - BMenuItem* quitItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); + BMenuItem* quitItem = new BMenuItem("Quit", + new BMessage(B_QUIT_REQUESTED), 'Q'); menu->AddItem(quitItem); quitItem->SetTarget(be_app); mainMenu->AddItem(menu); diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index bd2c7e84c4..6329cf3c45 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -165,7 +165,7 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, menu->AddItem(newWindowItem); newWindowItem->SetTarget(be_app); menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem("Hide", new BMessage(B_QUIT_REQUESTED), 'J')); + menu->AddItem(new BMenuItem("Hide", new BMessage(B_QUIT_REQUESTED), 'D')); menuBar->AddItem(menu); fDownloadsScrollView = new DownloadContainerScrollView(downloadsGroupView); From 054e7e4344d6f6c5fb5bde6052a420ad5c1c4ae2 Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 14 Jun 2010 16:02:50 +0000 Subject: [PATCH 299/349] Make sure the interface is showing when the menus are used (i.e. by invoking Cmd-Esc shortcut). git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@524 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index d3d985f165..dede2493c0 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -918,6 +918,7 @@ BrowserWindow::MenusBeginning() { _UpdateHistoryMenu(); _UpdateClipboardItems(); + _ShowInterface(true); } From fdd4f3bbb8025e3ace4756b836969a516267515e Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 15 Jun 2010 21:24:07 +0000 Subject: [PATCH 300/349] Add the static items at Bookmark menu construction, so the shortcuts work even when the menu has never been opened yet. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@526 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index dede2493c0..cd02a496a9 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -127,6 +127,10 @@ public: : BNavMenu(title, B_REFS_RECEIVED, target) { + // Add these items here already, so the shortcuts work even when + // the menu has never been opened yet. + _AddStaticItems(); + SetNavDir(navDir); } @@ -137,11 +141,17 @@ public: BNavMenu::AttachedToWindow(); if (CountItems() > 0) AddItem(new BSeparatorItem(), 0); + _AddStaticItems(); + DoLayout(); + } + +private: + void _AddStaticItems() + { AddItem(new BMenuItem("Manage bookmarks", new BMessage(SHOW_BOOKMARKS), 'M'), 0); AddItem(new BMenuItem("Bookmark this page", new BMessage(CREATE_BOOKMARK), 'B'), 0); - DoLayout(); } }; From ef6778d11e46ede4e674d30de71501627f90ad1f Mon Sep 17 00:00:00 2001 From: anevilyak Date: Sun, 4 Jul 2010 03:24:04 +0000 Subject: [PATCH 301/349] Fix building Web+ against updated locale kit (currently requires manually placing liblocalestub.a from Haiku's build tree) git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@527 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 1 - src/apps/webpositive/BrowserApp.h | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 79b2d3418e..2afbab8045 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -71,7 +71,6 @@ BrowserApp::BrowserApp() fDownloadWindow(NULL), fSettingsWindow(NULL) { - be_locale->GetAppCatalog(&fAppCatalog); } diff --git a/src/apps/webpositive/BrowserApp.h b/src/apps/webpositive/BrowserApp.h index 1f48b9d947..05885583f6 100644 --- a/src/apps/webpositive/BrowserApp.h +++ b/src/apps/webpositive/BrowserApp.h @@ -77,8 +77,6 @@ private: DownloadWindow* fDownloadWindow; SettingsWindow* fSettingsWindow; - - BCatalog fAppCatalog; }; From aef38397d3d2704c80e471c92ce5d07dbf3624c2 Mon Sep 17 00:00:00 2001 From: anevilyak Date: Fri, 16 Jul 2010 01:13:07 +0000 Subject: [PATCH 302/349] Fix crash that occurred when hitting pgup/pgdn in the URL input without having the choice list visible. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@530 94f232f2-1747-11df-bad5-a5bfde151594 --- .../autocompletion/AutoCompleterDefaultImpl.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp index 1f7f27c3ea..9a9925d8ed 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp @@ -419,7 +419,14 @@ BDefaultChoiceView::ChoicesAreShown() int32 BDefaultChoiceView::CountVisibleChoices() const { - return min_c(fMaxVisibleChoices, fListView->CountItems()); + if (fListView) + { + return min_c(fMaxVisibleChoices, fListView->CountItems()); + } + else + { + return 0; + } } From 7f88e2461b704a8d950fda6ab8a063cd7b9ad927 Mon Sep 17 00:00:00 2001 From: anevilyak Date: Fri, 16 Jul 2010 01:18:56 +0000 Subject: [PATCH 303/349] When asked to programmatically open a new URL (i.e. by being launched from another app), give the resulting web view input focus. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@531 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 2afbab8045..2782892c3f 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -363,6 +363,7 @@ BrowserApp::_CreateNewPage(const BString& url, bool fullscreen) else webWindow->CreateNewTab(url, true); webWindow->Activate(); + webWindow->CurrentWebView()->MakeFocus(true); loadedInWindowOnCurrentWorkspace = true; } webWindow->Unlock(); From 0c938691153d71116baa8ddeaa6d40d9b4b4c9d9 Mon Sep 17 00:00:00 2001 From: anevilyak Date: Fri, 16 Jul 2010 03:04:21 +0000 Subject: [PATCH 304/349] Fix style violation. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@532 94f232f2-1747-11df-bad5-a5bfde151594 --- .../webpositive/autocompletion/AutoCompleterDefaultImpl.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp index 9a9925d8ed..5c4d742aaf 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp @@ -420,13 +420,9 @@ int32 BDefaultChoiceView::CountVisibleChoices() const { if (fListView) - { return min_c(fMaxVisibleChoices, fListView->CountItems()); - } else - { return 0; - } } From 01abe0e23c8f9bef0af1239c5ecf4d9352786226 Mon Sep 17 00:00:00 2001 From: anevilyak Date: Tue, 20 Jul 2010 19:02:13 +0000 Subject: [PATCH 305/349] Fix Web+ build for this morning's locale changes/cleanups. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@537 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/SettingsWindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 79afb38ccc..f0be0810c4 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include From e71c5717b1aa65043bbef09830a474257e05403b Mon Sep 17 00:00:00 2001 From: stippi Date: Mon, 26 Jul 2010 12:05:26 +0000 Subject: [PATCH 306/349] Account for the fact that the visible frame of a tab is one pixel larger at the bottom. Will fix Haiku ticket #6383 when a new package is made available. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@539 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/tabview/TabContainerView.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/tabview/TabContainerView.cpp b/src/apps/webpositive/tabview/TabContainerView.cpp index 73457eaf5b..483a692749 100644 --- a/src/apps/webpositive/tabview/TabContainerView.cpp +++ b/src/apps/webpositive/tabview/TabContainerView.cpp @@ -429,9 +429,14 @@ TabContainerView::_TabAt(const BPoint& where) const BGroupLayout* layout = GroupLayout(); int32 count = layout->CountItems() - 1; for (int32 i = 0; i < count; i++) { - TabLayoutItem* item = dynamic_cast( - layout->ItemAt(i)); - if (item && item->IsVisible() && item->Frame().Contains(where)) + TabLayoutItem* item = dynamic_cast(layout->ItemAt(i)); + if (item == NULL || !item->IsVisible()) + continue; + // Account for the fact that the tab frame does not contain the + // visible bottom border. + BRect frame = item->Frame(); + frame.bottom++; + if (frame.Contains(where)) return item->Parent(); } return NULL; From a4841f3a5de8c50f348a3a9212d3c152c8d8994b Mon Sep 17 00:00:00 2001 From: anevilyak Date: Sat, 31 Jul 2010 19:12:48 +0000 Subject: [PATCH 307/349] Apply patch by Matt Madia: Add the escape key as a shortcut to stop page loads. Closes ticket #6409. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@541 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index cd02a496a9..1bb698234a 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -544,6 +544,9 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) } else if (bytes[0] == B_RIGHT_ARROW && modifiers == B_COMMAND_KEY) { PostMessage(GO_FORWARD); return; + } else if (bytes[0] == B_ESCAPE) { + PostMessage(STOP); + return; } else if (bytes[0] == B_FUNCTION_KEY) { // Some function key Firefox compatibility int32 key; @@ -2084,27 +2087,27 @@ BrowserWindow::_HandlePageSourceResult(const BMessage* message) // TODO: What if it isn't HTML, but for example SVG? BString source; ret = message->FindString("source", &source); - + if (ret == B_OK) ret = find_directory(B_COMMON_TEMP_DIRECTORY, &pathToPageSource); - + BString tmpFileName("PageSource_"); tmpFileName << system_time() << ".html"; if (ret == B_OK) ret = pathToPageSource.Append(tmpFileName.String()); - + BFile pageSourceFile(pathToPageSource.Path(), B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY); if (ret == B_OK) ret = pageSourceFile.InitCheck(); - + if (ret == B_OK) { ssize_t written = pageSourceFile.Write(source.String(), source.Length()); if (written != source.Length()) ret = (status_t)written; } - + if (ret == B_OK) { const char* type = "text/html"; size_t size = strlen(type); From a071b4d0417fbb6971696d8bd5c54b1c5738c9ab Mon Sep 17 00:00:00 2001 From: stippi Date: Wed, 18 Aug 2010 14:53:43 +0000 Subject: [PATCH 308/349] Adapt to recent layout API changes. (Untested) git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@543 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 4 ++++ src/apps/webpositive/DownloadProgressView.cpp | 2 ++ src/apps/webpositive/SettingsWindow.cpp | 6 ++++++ 3 files changed, 12 insertions(+) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 1bb698234a..e74bcabc3b 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -431,6 +431,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) ) + .TopView() ; // Navigation group @@ -445,6 +446,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, kInsetSpacing) ) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) + .TopView() ; // Status bar group @@ -456,6 +458,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, .AddStrut(12 - kElementSpacing) .SetInsets(kInsetSpacing, 0, kInsetSpacing, 0) ) + .TopView() ; BitmapButton* toggleFullscreenButton = new BitmapButton(kWindowIconBits, @@ -466,6 +469,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, BView* menuBarGroup = BGroupLayoutBuilder(B_HORIZONTAL) .Add(mainMenu) .Add(toggleFullscreenButton, 0.0f) + .TopView() ; // Layout diff --git a/src/apps/webpositive/DownloadProgressView.cpp b/src/apps/webpositive/DownloadProgressView.cpp index f819651f72..7048e1d56a 100644 --- a/src/apps/webpositive/DownloadProgressView.cpp +++ b/src/apps/webpositive/DownloadProgressView.cpp @@ -266,12 +266,14 @@ DownloadProgressView::Init(BMessage* archive) BView* verticalGroup = BGroupLayoutBuilder(B_VERTICAL, 3) .Add(fStatusBar) .Add(fInfoView) + .TopView() ; verticalGroup->SetViewColor(ViewColor()); layout->AddView(verticalGroup); verticalGroup = BGroupLayoutBuilder(B_VERTICAL, 3) .Add(fTopButton) .Add(fBottomButton) + .TopView() ; verticalGroup->SetViewColor(ViewColor()); layout->AddView(verticalGroup); diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index f0be0810c4..743b03570a 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -365,6 +365,8 @@ SettingsWindow::_CreateGeneralPage(float spacing) .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing)) .SetInsets(spacing, spacing, spacing, spacing) + + .TopView() ; view->SetName(B_TRANSLATE("General")); return view; @@ -422,6 +424,8 @@ SettingsWindow::_CreateFontsPage(float spacing) .Add(fFixedSizesMenu->CreateMenuBarLayoutItem(), 1, 13) .SetInsets(spacing, spacing, spacing, spacing) + + .View() ; view->SetName(B_TRANSLATE("Fonts")); return view; @@ -464,6 +468,8 @@ SettingsWindow::_CreateProxyPage(float spacing) .Add(BSpaceLayoutItem::CreateGlue()) .SetInsets(spacing, spacing, spacing, spacing) + + .TopView() ; view->SetName(B_TRANSLATE("Proxy server")); return view; From 0e126349915b259d217eacfd502c66061058f400 Mon Sep 17 00:00:00 2001 From: anevilyak Date: Thu, 19 Aug 2010 00:51:51 +0000 Subject: [PATCH 309/349] Fix BrowserWindow to work with new layout changes. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@544 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 33 ++++++++++++-------------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index e74bcabc3b..59c30af523 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -62,6 +62,7 @@ #include #include #include +#include #include #include #include @@ -419,7 +420,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fFindCloseButton = new BButton("Close", new BMessage(EDIT_HIDE_FIND_GROUP)); fFindCaseSensitiveCheckBox = new BCheckBox("Match case"); - BView* findGroup = BGroupLayoutBuilder(B_VERTICAL) + BGroupLayout* findGroup = BLayoutBuilder::Group<>(B_VERTICAL) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) .Add(fFindTextControl) @@ -431,12 +432,11 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, kInsetSpacing) ) - .TopView() ; // Navigation group - BView* navigationGroup = BGroupLayoutBuilder(B_VERTICAL) - .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) + BGroupLayout* navigationGroup = BLayoutBuilder::Group<>(B_VERTICAL) + .Add(BLayoutBuilder::Group<>(B_HORIZONTAL, kElementSpacing) .Add(fBackButton) .Add(fForwardButton) .Add(fStopButton) @@ -446,19 +446,17 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, kInsetSpacing) ) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) - .TopView() ; // Status bar group - BView* statusGroup = BGroupLayoutBuilder(B_VERTICAL) + BGroupLayout* statusGroup = BLayoutBuilder::Group<>(B_VERTICAL) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) - .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) + .Add(BLayoutBuilder::Group<>(B_HORIZONTAL, kElementSpacing) .Add(fStatusText) .Add(fLoadingProgressBar, 0.2) .AddStrut(12 - kElementSpacing) .SetInsets(kInsetSpacing, 0, kInsetSpacing, 0) ) - .TopView() ; BitmapButton* toggleFullscreenButton = new BitmapButton(kWindowIconBits, @@ -466,14 +464,13 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, new BMessage(TOGGLE_FULLSCREEN)); toggleFullscreenButton->SetBackgroundMode(BitmapButton::MENUBAR_BACKGROUND); - BView* menuBarGroup = BGroupLayoutBuilder(B_HORIZONTAL) + BGroupLayout* menuBarGroup = BLayoutBuilder::Group<>(B_HORIZONTAL) .Add(mainMenu) .Add(toggleFullscreenButton, 0.0f) - .TopView() ; - + // Layout - AddChild(BGroupLayoutBuilder(B_VERTICAL) + AddChild(BLayoutBuilder::Group<>(B_VERTICAL) #if !INTEGRATE_MENU_INTO_TAB_BAR .Add(menuBarGroup) #endif @@ -489,12 +486,12 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, mainMenu->SetViewColor(B_TRANSPARENT_COLOR); fURLInputGroup->MakeFocus(true); - - fMenuGroup = layoutItemFor(menuBarGroup); - fTabGroup = layoutItemFor(fTabManager->TabGroup()); - fNavigationGroup = layoutItemFor(navigationGroup); - fFindGroup = layoutItemFor(findGroup); - fStatusGroup = layoutItemFor(statusGroup); + + fMenuGroup = menuBarGroup; + fTabGroup = fTabManager->TabGroup()->GetLayout(); + fNavigationGroup = navigationGroup; + fFindGroup = findGroup; + fStatusGroup = statusGroup; fToggleFullscreenButton = layoutItemFor(toggleFullscreenButton); fFindGroup->SetVisible(false); From 26bc1632000d90f95e6aaef5f468c735c5370ed6 Mon Sep 17 00:00:00 2001 From: anevilyak Date: Thu, 9 Dec 2010 21:50:56 +0000 Subject: [PATCH 310/349] Layout fixes that hadn't yet been committed. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@548 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/AuthenticationPanel.cpp | 4 ++-- src/apps/webpositive/BrowserWindow.cpp | 8 ++++---- src/apps/webpositive/DownloadWindow.cpp | 6 +++--- src/apps/webpositive/URLInputGroup.cpp | 2 +- src/apps/webpositive/tabview/TabContainerView.cpp | 2 +- src/apps/webpositive/tabview/TabManager.cpp | 4 ++-- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/apps/webpositive/AuthenticationPanel.cpp b/src/apps/webpositive/AuthenticationPanel.cpp index 8d81bbb311..7dcc55260f 100644 --- a/src/apps/webpositive/AuthenticationPanel.cpp +++ b/src/apps/webpositive/AuthenticationPanel.cpp @@ -136,9 +136,9 @@ bool AuthenticationPanel::getAuthentication(const BString& text, m_rememberCredentialsCheckBox->SetValue(previousRememberCredentials); // create layout - SetLayout(new BGroupLayout(B_VERTICAL)); + SetLayout(new BGroupLayout(B_VERTICAL, 0.0)); float spacing = be_control_look->DefaultItemSpacing(); - AddChild(BGroupLayoutBuilder(B_VERTICAL) + AddChild(BGroupLayoutBuilder(B_VERTICAL, 0.0) .Add(BGridLayoutBuilder(0, spacing) .Add(textView, 0, 0, 2) .Add(m_usernameTextControl->CreateLabelLayoutItem(), 0, 1) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 59c30af523..643c20ad26 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -420,7 +420,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fFindCloseButton = new BButton("Close", new BMessage(EDIT_HIDE_FIND_GROUP)); fFindCaseSensitiveCheckBox = new BCheckBox("Match case"); - BGroupLayout* findGroup = BLayoutBuilder::Group<>(B_VERTICAL) + BGroupLayout* findGroup = BLayoutBuilder::Group<>(B_VERTICAL, 0.0) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing) .Add(fFindTextControl) @@ -435,7 +435,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, ; // Navigation group - BGroupLayout* navigationGroup = BLayoutBuilder::Group<>(B_VERTICAL) + BGroupLayout* navigationGroup = BLayoutBuilder::Group<>(B_VERTICAL, 0.0) .Add(BLayoutBuilder::Group<>(B_HORIZONTAL, kElementSpacing) .Add(fBackButton) .Add(fForwardButton) @@ -449,7 +449,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, ; // Status bar group - BGroupLayout* statusGroup = BLayoutBuilder::Group<>(B_VERTICAL) + BGroupLayout* statusGroup = BLayoutBuilder::Group<>(B_VERTICAL, 0.0) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) .Add(BLayoutBuilder::Group<>(B_HORIZONTAL, kElementSpacing) .Add(fStatusText) @@ -470,7 +470,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, ; // Layout - AddChild(BLayoutBuilder::Group<>(B_VERTICAL) + AddChild(BLayoutBuilder::Group<>(B_VERTICAL, 0.0) #if !INTEGRATE_MENU_INTO_TAB_BAR .Add(menuBarGroup) #endif diff --git a/src/apps/webpositive/DownloadWindow.cpp b/src/apps/webpositive/DownloadWindow.cpp index 6329cf3c45..859722df47 100644 --- a/src/apps/webpositive/DownloadWindow.cpp +++ b/src/apps/webpositive/DownloadWindow.cpp @@ -66,7 +66,7 @@ class DownloadsContainerView : public BGroupView { public: DownloadsContainerView() : - BGroupView(B_VERTICAL) + BGroupView(B_VERTICAL, 0.0) { SetFlags(Flags() | B_PULSE_NEEDED); SetViewColor(245, 245, 245); @@ -149,7 +149,7 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, downloadPath.Path()); settings->SetValue(kSettingsKeyDownloadPath, fDownloadPath); - SetLayout(new BGroupLayout(B_VERTICAL)); + SetLayout(new BGroupLayout(B_VERTICAL, 0.0)); DownloadsContainerView* downloadsGroupView = new DownloadsContainerView(); fDownloadViewsLayout = downloadsGroupView->GroupLayout(); @@ -180,7 +180,7 @@ DownloadWindow::DownloadWindow(BRect frame, bool visible, const float spacing = be_control_look->DefaultItemSpacing(); - AddChild(BGroupLayoutBuilder(B_VERTICAL) + AddChild(BGroupLayoutBuilder(B_VERTICAL, 0.0) .Add(menuBar) .Add(fDownloadsScrollView) .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER)) diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index e5d5c9ecb3..f84f0e12bf 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -540,7 +540,7 @@ private: URLInputGroup::URLInputGroup(BMessage* goMessage) : - BGroupView(B_HORIZONTAL), + BGroupView(B_HORIZONTAL, 0.0), fWindowActive(false) { GroupLayout()->SetInsets(2, 2, 2, 2); diff --git a/src/apps/webpositive/tabview/TabContainerView.cpp b/src/apps/webpositive/tabview/TabContainerView.cpp index 483a692749..a95136a508 100644 --- a/src/apps/webpositive/tabview/TabContainerView.cpp +++ b/src/apps/webpositive/tabview/TabContainerView.cpp @@ -49,7 +49,7 @@ static const float kLeftTabInset = 4; TabContainerView::TabContainerView(Controller* controller) : - BGroupView(B_HORIZONTAL), + BGroupView(B_HORIZONTAL, 0.0), fLastMouseEventTab(NULL), fMouseDown(false), fClickCount(0), diff --git a/src/apps/webpositive/tabview/TabManager.cpp b/src/apps/webpositive/tabview/TabManager.cpp index 4a26c33271..7ab8066436 100644 --- a/src/apps/webpositive/tabview/TabManager.cpp +++ b/src/apps/webpositive/tabview/TabManager.cpp @@ -197,7 +197,7 @@ class TabContainerGroup : public BGroupView { public: TabContainerGroup(TabContainerView* tabContainerView) : - BGroupView(B_HORIZONTAL), + BGroupView(B_HORIZONTAL, 0.0), fTabContainerView(tabContainerView), fScrollLeftTabButton(NULL), fScrollRightTabButton(NULL) @@ -263,7 +263,7 @@ class TabButtonContainer : public BGroupView { public: TabButtonContainer() : - BGroupView(B_HORIZONTAL) + BGroupView(B_HORIZONTAL, 0.0) { SetFlags(Flags() | B_WILL_DRAW); SetViewColor(B_TRANSPARENT_COLOR); From 8c15e2338555542ec1f90471e3b39fab287cc7b3 Mon Sep 17 00:00:00 2001 From: leavengood Date: Sun, 12 Dec 2010 07:36:07 +0000 Subject: [PATCH 311/349] Set the tab label to the URL if no title is provided in the HTML. Fixes #6330. And so I'm back on Web+ development. Yay. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@549 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 4 ++++ src/apps/webpositive/tabview/TabManager.cpp | 9 +++++++++ src/apps/webpositive/tabview/TabManager.h | 1 + 3 files changed, 14 insertions(+) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 643c20ad26..9dc7430c68 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1246,6 +1246,10 @@ BrowserWindow::LoadFinished(const BString& url, BWebView* view) NavigationCapabilitiesChanged(fBackButton->IsEnabled(), fForwardButton->IsEnabled(), false, view); + + int32 tabIndex = fTabManager->TabForView(view); + if (tabIndex > 0 && strcmp("New tab", fTabManager->TabLabel(tabIndex)) == 0) + fTabManager->SetTabLabel(tabIndex, url); } diff --git a/src/apps/webpositive/tabview/TabManager.cpp b/src/apps/webpositive/tabview/TabManager.cpp index 7ab8066436..3f364b652c 100644 --- a/src/apps/webpositive/tabview/TabManager.cpp +++ b/src/apps/webpositive/tabview/TabManager.cpp @@ -831,6 +831,15 @@ TabManager::SetTabLabel(int32 tabIndex, const char* label) fTabContainerView->SetTabLabel(tabIndex, label); } +const BString& +TabManager::TabLabel(int32 tabIndex) +{ + TabView* tab = fTabContainerView->TabAt(tabIndex); + if (tab) + return tab->Label(); + else + return ""; +} void TabManager::SetTabIcon(const BView* containedView, const BBitmap* icon) diff --git a/src/apps/webpositive/tabview/TabManager.h b/src/apps/webpositive/tabview/TabManager.h index 4ccc64d35e..97cd65c898 100644 --- a/src/apps/webpositive/tabview/TabManager.h +++ b/src/apps/webpositive/tabview/TabManager.h @@ -76,6 +76,7 @@ public: int32 CountTabs() const; void SetTabLabel(int32 tabIndex, const char* label); + const BString& TabLabel(int32); void SetTabIcon(const BView* containedView, const BBitmap* icon); void SetCloseButtonsAvailable(bool available); From f0db6a3bb1b6908454fc8dd2e02867f65b885926 Mon Sep 17 00:00:00 2001 From: leavengood Date: Sun, 12 Dec 2010 07:59:57 +0000 Subject: [PATCH 312/349] Don't try to load a blank URL for a new page. Fixes #6430. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@550 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 2782892c3f..653516f526 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -358,9 +358,10 @@ BrowserApp::_CreateNewPage(const BString& url, bool fullscreen) continue; if (webWindow->Lock()) { if (webWindow->Workspaces() & workspace) { - if (webWindow->IsBlankTab()) - webWindow->CurrentWebView()->LoadURL(url); - else + if (webWindow->IsBlankTab()) { + if (url.Length() != 0) + webWindow->CurrentWebView()->LoadURL(url); + } else webWindow->CreateNewTab(url, true); webWindow->Activate(); webWindow->CurrentWebView()->MakeFocus(true); From 8ee88f9b6d32b6e6d03ac76feefda8d7f7bd8809 Mon Sep 17 00:00:00 2001 From: leavengood Date: Sun, 12 Dec 2010 22:11:56 +0000 Subject: [PATCH 313/349] Show the status bar and therefore the progress bar even in fullscreen mode when a page is loading. Fixes #6086. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@551 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 22 ++++++++++++++++++++-- src/apps/webpositive/BrowserWindow.h | 1 + 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 9dc7430c68..7d7d56a0b8 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1211,9 +1211,9 @@ BrowserWindow::LoadProgress(float progress, BWebView* view) return; if (progress < 100 && fLoadingProgressBar->IsHidden()) - fLoadingProgressBar->Show(); + _ShowProgressBar(true); else if (progress == 100 && !fLoadingProgressBar->IsHidden()) - fLoadingProgressBar->Hide(); + _ShowProgressBar(false); fLoadingProgressBar->SetTo(progress); } @@ -2036,6 +2036,24 @@ BrowserWindow::_ShowInterface(bool show) } +void +BrowserWindow::_ShowProgressBar(bool show) +{ + if (show) { + if (!fStatusGroup->IsVisible() && (fVisibleInterfaceElements & INTERFACE_ELEMENT_STATUS) != 0) + fStatusGroup->SetVisible(true); + fLoadingProgressBar->Show(); + } else { + if (!fInterfaceVisible) + fStatusGroup->SetVisible(false); + // TODO: This is also used in _ShowInterface. Without it the status bar + // doesn't always hide again. It may be an Interface Kit bug. + while (!fLoadingProgressBar->IsHidden()) + fLoadingProgressBar->Hide(); + } +} + + void BrowserWindow::_InvokeButtonVisibly(BButton* button) { diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 67ac0f5311..e9f5fe3a6f 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -187,6 +187,7 @@ private: void _SetAutoHideInterfaceInFullscreen(bool doIt); void _CheckAutoHideInterface(); void _ShowInterface(bool show); + void _ShowProgressBar(bool); void _InvokeButtonVisibly(BButton* button); BString _NewTabURL(bool isNewWindow) const; From 290dc1146486029fd8c6de58dbdf327e0b8ee35f Mon Sep 17 00:00:00 2001 From: leavengood Date: Mon, 27 Dec 2010 17:08:35 +0000 Subject: [PATCH 314/349] Make the default location for the download window the lower right corner of screen, like NetPositive. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@554 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 653516f526..b9f905fb70 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -152,8 +152,15 @@ BrowserApp::ReadyToRun() #endif fLastWindowFrame = fSettings->GetValue("window frame", fLastWindowFrame); + // Put download window in lower right of screen. 375 is about the minimum + // width with the default layout. + BRect defaultDownloadWindowFrame(0, 0, 375, 275); + BRect screenFrame = BScreen().Frame(); + // The extra 5 pixels is for the decorator frame + defaultDownloadWindowFrame.OffsetTo(screenFrame.Width() - defaultDownloadWindowFrame.Width() - 5, + screenFrame.Height() - defaultDownloadWindowFrame.Height() - 5); BRect downloadWindowFrame = fSettings->GetValue("downloads window frame", - BRect(100, 100, 300, 250)); + defaultDownloadWindowFrame); BRect settingsWindowFrame = fSettings->GetValue("settings window frame", BRect()); bool showDownloads = fSettings->GetValue("show downloads", false); From 8d1fc88170fd654a9ae84a6a41669221a5457abc Mon Sep 17 00:00:00 2001 From: leavengood Date: Mon, 27 Dec 2010 22:12:55 +0000 Subject: [PATCH 315/349] As indicated by Axel the border width for positioning the download window was hard-coded. This fixes that and refactors the code a bit. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@555 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserApp.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index b9f905fb70..1504638ae7 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -152,13 +152,7 @@ BrowserApp::ReadyToRun() #endif fLastWindowFrame = fSettings->GetValue("window frame", fLastWindowFrame); - // Put download window in lower right of screen. 375 is about the minimum - // width with the default layout. - BRect defaultDownloadWindowFrame(0, 0, 375, 275); - BRect screenFrame = BScreen().Frame(); - // The extra 5 pixels is for the decorator frame - defaultDownloadWindowFrame.OffsetTo(screenFrame.Width() - defaultDownloadWindowFrame.Width() - 5, - screenFrame.Height() - defaultDownloadWindowFrame.Height() - 5); + BRect defaultDownloadWindowFrame(-10, -10, 365, 265); BRect downloadWindowFrame = fSettings->GetValue("downloads window frame", defaultDownloadWindowFrame); BRect settingsWindowFrame = fSettings->GetValue("settings window frame", @@ -167,6 +161,17 @@ BrowserApp::ReadyToRun() fDownloadWindow = new DownloadWindow(downloadWindowFrame, showDownloads, fSettings); + if (downloadWindowFrame == defaultDownloadWindowFrame) { + // Initially put download window in lower right of screen. + BRect screenFrame = BScreen().Frame(); + BMessage decoratorSettings; + fDownloadWindow->GetDecoratorSettings(&decoratorSettings); + float borderWidth = 0; + if (decoratorSettings.FindFloat("border width", &borderWidth) != B_OK) + borderWidth = 5; + fDownloadWindow->MoveTo(screenFrame.Width() - fDownloadWindow->Frame().Width() - borderWidth, + screenFrame.Height() - fDownloadWindow->Frame().Height() - borderWidth); + } fSettingsWindow = new SettingsWindow(settingsWindowFrame, fSettings); BWebPage::SetDownloadListener(BMessenger(fDownloadWindow)); From 530dea0f1619582b0246b5c7e1daad06e783b7ff Mon Sep 17 00:00:00 2001 From: leavengood Date: Mon, 27 Dec 2010 23:05:48 +0000 Subject: [PATCH 316/349] Let the controller handle setting the default tool tip for the tab bar so it knows the state changed. A good example of where using a controller-based design can't be done halfway. It took me way too long to debug this (that mostly being my fault.) Fixes #6382. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@556 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/tabview/TabContainerView.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/apps/webpositive/tabview/TabContainerView.cpp b/src/apps/webpositive/tabview/TabContainerView.cpp index a95136a508..d5269fd699 100644 --- a/src/apps/webpositive/tabview/TabContainerView.cpp +++ b/src/apps/webpositive/tabview/TabContainerView.cpp @@ -464,11 +464,8 @@ TabContainerView::_MouseMoved(BPoint where, uint32 _transit, fLastMouseEventTab = tab; if (fLastMouseEventTab) fLastMouseEventTab->MouseMoved(where, B_ENTERED_VIEW, dragMessage); - else { - SetToolTip(static_cast(NULL)); - HideToolTip(); - SetToolTip("Double-click or middle-click to open new tab."); - } + else + fController->SetToolTip("Double-click or middle-click to open new tab."); } } From 1526be737a797d99f96f8f85500deca19950047b Mon Sep 17 00:00:00 2001 From: leavengood Date: Tue, 28 Dec 2010 03:02:37 +0000 Subject: [PATCH 317/349] Add a stupidly simple "search Google from the URL bar" feature, a la Chrome. It still needs a lot but this doesn't seem to break anything and it already is making my browsing more productive. The hard-coding of Google will be fixed when some proper search engine provider handling is added. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@557 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 15 ++++++++++++++- src/apps/webpositive/BrowserWindow.h | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 7d7d56a0b8..e2db73b96d 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -618,7 +618,10 @@ BrowserWindow::MessageReceived(BMessage* message) if (message->FindString("url", &url) != B_OK) url = fURLInputGroup->Text(); _SetPageIcon(CurrentWebView(), NULL); - CurrentWebView()->LoadURL(url.String()); + BString newUrl = _SmartURLHandler(url); + if (newUrl != url) + fURLInputGroup->TextView()->SetText(newUrl); + CurrentWebView()->LoadURL(newUrl.String()); break; } case GO_BACK: @@ -2090,6 +2093,16 @@ BrowserWindow::_NewTabURL(bool isNewWindow) const } +BString +BrowserWindow::_SmartURLHandler(const BString& url) const +{ + BString result = url; + if (url.FindFirst(".") == B_ERROR || url.FindFirst(" ") != B_ERROR) + result.Prepend("http://www.google.com/#q="); + return result; +} + + void BrowserWindow::_HandlePageSourceResult(const BMessage* message) { diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index e9f5fe3a6f..fcae9d5f7b 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -191,6 +191,7 @@ private: void _InvokeButtonVisibly(BButton* button); BString _NewTabURL(bool isNewWindow) const; + BString _SmartURLHandler(const BString& url) const; void _HandlePageSourceResult( const BMessage* message); From c5efa2c0b94fafdec516818fb4ceb40a36fdc379 Mon Sep 17 00:00:00 2001 From: leavengood Date: Tue, 28 Dec 2010 05:03:13 +0000 Subject: [PATCH 318/349] Use the more conventional Google search URL, not the "Instant" one. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@558 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index e2db73b96d..54a5be2885 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -2098,7 +2098,7 @@ BrowserWindow::_SmartURLHandler(const BString& url) const { BString result = url; if (url.FindFirst(".") == B_ERROR || url.FindFirst(" ") != B_ERROR) - result.Prepend("http://www.google.com/#q="); + result.Prepend("http://www.google.com/search?q="); return result; } From ac09a4729657d4947422933153cf31a6ae9e27b0 Mon Sep 17 00:00:00 2001 From: leavengood Date: Tue, 28 Dec 2010 05:07:06 +0000 Subject: [PATCH 319/349] Make the max tab width always 300px instead of being proportional to the label text. I think a consistent tab size is more important. Also made the minimum a little smaller (60px.) git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@559 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/tabview/TabView.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/tabview/TabView.cpp b/src/apps/webpositive/tabview/TabView.cpp index bc5e2a6703..3bb78ec185 100644 --- a/src/apps/webpositive/tabview/TabView.cpp +++ b/src/apps/webpositive/tabview/TabView.cpp @@ -67,7 +67,7 @@ BSize TabView::MinSize() { BSize size(MaxSize()); - size.width = 100.0f; + size.width = 60.0f; return size; } @@ -83,8 +83,7 @@ BSize TabView::MaxSize() { float extra = be_control_look->DefaultLabelSpacing(); - float labelWidth = fContainerView->StringWidth(fLabel.String()) + 2 * extra; - labelWidth = min_c(300.0f, labelWidth); + float labelWidth = 300.0f; return BSize(labelWidth, _LabelHeight() + extra); } From 675a92e06038f86359f0ac69f24ba1d9886796dc Mon Sep 17 00:00:00 2001 From: leavengood Date: Tue, 28 Dec 2010 06:05:25 +0000 Subject: [PATCH 320/349] Implement http://webpositive.haiku-os.org/ticket/61 so that holding the command key and using the scroll wheel will zoom in and out. Also made it so that the scroll wheel only works when the mouse is over the view. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@560 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 36 +++++++++++++++++++++----- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 54a5be2885..f51f1f97c9 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -533,16 +533,16 @@ void BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) { const char* bytes; - uint32 modifiers; + uint32 modifierKeys; if ((message->what == B_KEY_DOWN || message->what == B_UNMAPPED_KEY_DOWN) && message->FindString("bytes", &bytes) == B_OK - && message->FindInt32("modifiers", (int32*)&modifiers) == B_OK) { + && message->FindInt32("modifiers", (int32*)&modifierKeys) == B_OK) { - modifiers = modifiers & 0x000000ff; - if (bytes[0] == B_LEFT_ARROW && modifiers == B_COMMAND_KEY) { + modifierKeys = modifierKeys & 0x000000ff; + if (bytes[0] == B_LEFT_ARROW && modifierKeys == B_COMMAND_KEY) { PostMessage(GO_BACK); return; - } else if (bytes[0] == B_RIGHT_ARROW && modifiers == B_COMMAND_KEY) { + } else if (bytes[0] == B_RIGHT_ARROW && modifierKeys == B_COMMAND_KEY) { PostMessage(GO_FORWARD); return; } else if (bytes[0] == B_ESCAPE) { @@ -576,7 +576,7 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) } else if (target == fFindTextControl->TextView()) { // Handle B_RETURN when the find text control has focus. if (bytes[0] == B_RETURN) { - if ((modifiers & B_SHIFT_KEY) != 0) + if ((modifierKeys & B_SHIFT_KEY) != 0) _InvokeButtonVisibly(fFindPreviousButton); else _InvokeButtonVisibly(fFindNextButton); @@ -594,6 +594,30 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) fLastMouseMovedTime = system_time(); _CheckAutoHideInterface(); } + if (message->what == B_MOUSE_WHEEL_CHANGED) { + BPoint where; + uint32 buttons; + CurrentWebView()->GetMouse(&where, &buttons, false); + // Only do this when the mouse is over the web view + if (CurrentWebView()->Bounds().Contains(where)) { + // Zoom and unzoom text on Command + mouse wheel. + // This could of course (and maybe should be) implemented in the WebView, but there + // would need to be a way for the WebView to know the setting of the + // fZoomTextOnly member here. Plus other clients of the API may not want + // this feature. + if ((modifiers() & B_COMMAND_KEY) != 0) { + float dy; + if (message->FindFloat("be:wheel_delta_y", &dy) == B_OK) { + if (dy < 0) + CurrentWebView()->IncreaseZoomFactor(fZoomTextOnly); + else + CurrentWebView()->DecreaseZoomFactor(fZoomTextOnly); + return; + } + } + } else // Also don't scroll up and down if the mouse is not over the web view + return; + } BWebWindow::DispatchMessage(message, target); } From 36badc2d94f226f8c72178e62b8de8fef33ceba2 Mon Sep 17 00:00:00 2001 From: leavengood Date: Wed, 29 Dec 2010 21:00:13 +0000 Subject: [PATCH 321/349] Add a scrollview (with associated resizing trickery to cut-off the sides of the scrollbar) to the auto-complete list. This now also makes the scrollwheel work but selection by mouse still needs implementing. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@561 94f232f2-1747-11df-bad5-a5bfde151594 --- .../autocompletion/AutoCompleterDefaultImpl.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp index 5c4d742aaf..4bfd556175 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp @@ -10,6 +10,7 @@ #include #include +#include #include @@ -324,7 +325,7 @@ BDefaultChoiceView::BDefaultChoiceView() : fWindow(NULL), fListView(NULL), - fMaxVisibleChoices(5) + fMaxVisibleChoices(8) { } @@ -373,10 +374,12 @@ BDefaultChoiceView::ShowChoices(BAutoCompleter::CompletionStyle* completer) ); } + BScrollView *scrollView = new BScrollView("", fListView, B_FOLLOW_NONE, 0, false, true, B_NO_BORDER); + fWindow = new BWindow(BRect(0, 0, 100, 100), "", B_BORDERED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_NOT_MOVABLE | B_WILL_ACCEPT_FIRST_CLICK | B_AVOID_FOCUS | B_ASYNCHRONOUS_CONTROLS); - fWindow->AddChild(fListView); + fWindow->AddChild(scrollView); int32 visibleCount = min_c(count, fMaxVisibleChoices); float listHeight = fListView->ItemFrame(visibleCount - 1).bottom + 1; @@ -390,8 +393,13 @@ BDefaultChoiceView::ShowChoices(BAutoCompleter::CompletionStyle* completer) else listRect.OffsetTo(pvRect.left, pvRect.top - listHeight); - fListView->MoveTo(0, 0); - fListView->ResizeTo(listRect.Width(), listRect.Height()); + // Moving here to cut off the scrollbar top + scrollView->MoveTo(0, -1); + // Adding the 1 and 2 to cut-off the scroll-bar top, right and bottom + scrollView->ResizeTo(listRect.Width() + 1, listRect.Height() + 2); + // Move here to compensate for the above + fListView->MoveTo(0, 1); + fListView->ResizeTo(listRect.Width() - B_V_SCROLL_BAR_WIDTH, listRect.Height()); fWindow->MoveTo(listRect.left, listRect.top); fWindow->ResizeTo(listRect.Width(), listRect.Height()); fWindow->Show(); From 927bc248a345908efb52355296f9fb32eeb89325 Mon Sep 17 00:00:00 2001 From: leavengood Date: Wed, 29 Dec 2010 22:08:08 +0000 Subject: [PATCH 322/349] Only use the scrollview if it is needed (to avoid the problem of a useless disabled scrollbar.) git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@562 94f232f2-1747-11df-bad5-a5bfde151594 --- .../AutoCompleterDefaultImpl.cpp | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp index 4bfd556175..0808239ef3 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp @@ -374,12 +374,18 @@ BDefaultChoiceView::ShowChoices(BAutoCompleter::CompletionStyle* completer) ); } - BScrollView *scrollView = new BScrollView("", fListView, B_FOLLOW_NONE, 0, false, true, B_NO_BORDER); + BScrollView *scrollView = NULL; + if (count > fMaxVisibleChoices) { + scrollView = new BScrollView("", fListView, B_FOLLOW_NONE, 0, false, true, B_NO_BORDER); + } fWindow = new BWindow(BRect(0, 0, 100, 100), "", B_BORDERED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_NOT_MOVABLE | B_WILL_ACCEPT_FIRST_CLICK | B_AVOID_FOCUS | B_ASYNCHRONOUS_CONTROLS); - fWindow->AddChild(scrollView); + if (scrollView != NULL) + fWindow->AddChild(scrollView); + else + fWindow->AddChild(fListView); int32 visibleCount = min_c(count, fMaxVisibleChoices); float listHeight = fListView->ItemFrame(visibleCount - 1).bottom + 1; @@ -393,13 +399,18 @@ BDefaultChoiceView::ShowChoices(BAutoCompleter::CompletionStyle* completer) else listRect.OffsetTo(pvRect.left, pvRect.top - listHeight); - // Moving here to cut off the scrollbar top - scrollView->MoveTo(0, -1); - // Adding the 1 and 2 to cut-off the scroll-bar top, right and bottom - scrollView->ResizeTo(listRect.Width() + 1, listRect.Height() + 2); - // Move here to compensate for the above - fListView->MoveTo(0, 1); - fListView->ResizeTo(listRect.Width() - B_V_SCROLL_BAR_WIDTH, listRect.Height()); + if (scrollView != NULL) { + // Moving here to cut off the scrollbar top + scrollView->MoveTo(0, -1); + // Adding the 1 and 2 to cut-off the scroll-bar top, right and bottom + scrollView->ResizeTo(listRect.Width() + 1, listRect.Height() + 2); + // Move here to compensate for the above + fListView->MoveTo(0, 1); + fListView->ResizeTo(listRect.Width() - B_V_SCROLL_BAR_WIDTH, listRect.Height()); + } else { + fListView->MoveTo(0, 0); + fListView->ResizeTo(listRect.Width(), listRect.Height()); + } fWindow->MoveTo(listRect.left, listRect.top); fWindow->ResizeTo(listRect.Width(), listRect.Height()); fWindow->Show(); From a9112961b9f0b3fc1566eb58bc6fcc48c5fc94a5 Mon Sep 17 00:00:00 2001 From: leavengood Date: Wed, 29 Dec 2010 22:51:13 +0000 Subject: [PATCH 323/349] Restore the original URL text when the escape key is pressed. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@563 94f232f2-1747-11df-bad5-a5bfde151594 --- .../autocompletion/TextViewCompleter.cpp | 16 ++++++++++++++-- .../autocompletion/TextViewCompleter.h | 2 ++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp index 66e95e9ae6..4e76f7255a 100644 --- a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp +++ b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp @@ -73,7 +73,8 @@ TextViewCompleter::TextViewCompleter(BTextView* textView, ChoiceModel* model, new BDefaultChoiceView(), patternSelector), BMessageFilter(B_KEY_DOWN), fTextView(textView), - fModificationsReported(false) + fModificationsReported(false), + fOriginalTextSaved(false) { fTextView->AddFilter(this); } @@ -102,6 +103,11 @@ TextViewCompleter::TextModified(bool updateChoices) filter_result TextViewCompleter::Filter(BMessage* message, BHandler** target) { + if (!fOriginalTextSaved) { + fOriginalText = fTextView->Text(); + fOriginalTextSaved = true; + } + const char* bytes; int32 modifiers; if (!target || message->FindString("bytes", &bytes) != B_OK @@ -140,7 +146,13 @@ TextViewCompleter::Filter(BMessage* message, BHandler** target) } case B_ESCAPE: - CancelChoice(); + if (fOriginalText != fTextView->Text()) { + fModificationsReported = false; + fTextView->SetText(fOriginalText.String()); + fTextView->SelectAll(); + fModificationsReported = true; + CancelChoice(); + } return B_SKIP_MESSAGE; case B_RETURN: if (IsChoiceSelected()) { diff --git a/src/apps/webpositive/autocompletion/TextViewCompleter.h b/src/apps/webpositive/autocompletion/TextViewCompleter.h index 1a2955f6d7..aeda86a7f0 100644 --- a/src/apps/webpositive/autocompletion/TextViewCompleter.h +++ b/src/apps/webpositive/autocompletion/TextViewCompleter.h @@ -43,6 +43,8 @@ private: private: BTextView* fTextView; bool fModificationsReported; + BString fOriginalText; + bool fOriginalTextSaved; }; #endif // TEXT_CONTROL_COMPLETER_H From a65490807d3c889418680b9c51d419ba78199736 Mon Sep 17 00:00:00 2001 From: leavengood Date: Thu, 30 Dec 2010 01:31:41 +0000 Subject: [PATCH 324/349] Mostly revert r563 and fix it properly. The ESC key should be dispatched to the text view from the filter as well as from the browser window. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@564 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 10 +++++++--- .../autocompletion/TextViewCompleter.cpp | 18 +++--------------- .../autocompletion/TextViewCompleter.h | 2 -- 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index f51f1f97c9..fd2b2f49da 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2007 Andrea Anzani - * Copyright (C) 2007 Ryan Leavengood + * Copyright (C) 2007, 2010 Ryan Leavengood * Copyright (C) 2009 Maxime Simon * Copyright (C) 2010 Stephan Aßmus * Copyright (C) 2010 Michael Lotz @@ -546,8 +546,12 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) PostMessage(GO_FORWARD); return; } else if (bytes[0] == B_ESCAPE) { - PostMessage(STOP); - return; + // Let the URL input handle escape when it is the target + if (target != fURLInputGroup->TextView()) { + // Otherwise do a stop + PostMessage(STOP); + return; + } } else if (bytes[0] == B_FUNCTION_KEY) { // Some function key Firefox compatibility int32 key; diff --git a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp index 4e76f7255a..cdde7ffc66 100644 --- a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp +++ b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp @@ -73,8 +73,7 @@ TextViewCompleter::TextViewCompleter(BTextView* textView, ChoiceModel* model, new BDefaultChoiceView(), patternSelector), BMessageFilter(B_KEY_DOWN), fTextView(textView), - fModificationsReported(false), - fOriginalTextSaved(false) + fModificationsReported(false) { fTextView->AddFilter(this); } @@ -103,11 +102,6 @@ TextViewCompleter::TextModified(bool updateChoices) filter_result TextViewCompleter::Filter(BMessage* message, BHandler** target) { - if (!fOriginalTextSaved) { - fOriginalText = fTextView->Text(); - fOriginalTextSaved = true; - } - const char* bytes; int32 modifiers; if (!target || message->FindString("bytes", &bytes) != B_OK @@ -146,14 +140,8 @@ TextViewCompleter::Filter(BMessage* message, BHandler** target) } case B_ESCAPE: - if (fOriginalText != fTextView->Text()) { - fModificationsReported = false; - fTextView->SetText(fOriginalText.String()); - fTextView->SelectAll(); - fModificationsReported = true; - CancelChoice(); - } - return B_SKIP_MESSAGE; + CancelChoice(); + return B_DISPATCH_MESSAGE; case B_RETURN: if (IsChoiceSelected()) { ApplyChoice(); diff --git a/src/apps/webpositive/autocompletion/TextViewCompleter.h b/src/apps/webpositive/autocompletion/TextViewCompleter.h index aeda86a7f0..1a2955f6d7 100644 --- a/src/apps/webpositive/autocompletion/TextViewCompleter.h +++ b/src/apps/webpositive/autocompletion/TextViewCompleter.h @@ -43,8 +43,6 @@ private: private: BTextView* fTextView; bool fModificationsReported; - BString fOriginalText; - bool fOriginalTextSaved; }; #endif // TEXT_CONTROL_COMPLETER_H From 0afc39c5b1ee8f3d28ea45b0113206fc110697e7 Mon Sep 17 00:00:00 2001 From: leavengood Date: Thu, 30 Dec 2010 02:13:38 +0000 Subject: [PATCH 325/349] Ticket #69. Update the icon from tweaks made by Meanwhile. Thanks! git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@565 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/WebPositive.rdef | 389 +++++++++++++------------- 1 file changed, 193 insertions(+), 196 deletions(-) diff --git a/src/apps/webpositive/WebPositive.rdef b/src/apps/webpositive/WebPositive.rdef index c9561eebac..9b475b34d1 100644 --- a/src/apps/webpositive/WebPositive.rdef +++ b/src/apps/webpositive/WebPositive.rdef @@ -49,202 +49,199 @@ resource vector_icon { $"37A9FFB9B9B904017E03FF360003FFFF0003FF9C0003FF000002010202BB36AE" $"BA1760B80FFF392B574ACCFB48652300000001FFFF0000013205400500030052" $"7502001002F8006BFF003E04006C050003900000020310020000006E00650400" - $"6B05000359463503C3A414039D816035000000000204BFC2B55BBBC5B55BC3BF" - $"B55BC6FABC93C6FAB896C6FAC090BFC2C3CBC3BFC3CBBBC5C3CBB88ABC93B88A" - $"C090B88AB896026EC5DCB8B6C713BAA0C4CAB706C110B579C307B5D5C0A2B565" - $"BFC2B55BC032B55BBDBCB55BBA69B7BABBC5B63AB8F9B94FB89DBD9CB84FBB7E" - $"B8C7BE9AB924BF77B8E0BEE7B9DEC11FBCE0C332BB38C279BEC5C405C2D8C31A" - $"C0FBC3FCC2C6C2C1C22FC2B7C27AC2BEC22FC2B7C227C2B7C227C2B7C227C2B7" - $"C241C2BDC241C2BDC206C2B0C199C2DBC1D0C2CBC159C2EEC0D4C2DDC115C2E5" - $"C051C2CEBF43C313BFB0C2B4BF3DC313BF36C313BF36C313BF36C313BF20C313" - $"BF20C313BF20C313BDEDC313BE23C313BDB9C2EDBD57C2DFBD87C2E3BD54C2DC" - $"BD3EC2C3BD3EC2C3BD31C2B4BD13C2A5BD26C2ABBD13C2A5BCA4C27EBCA4C27E" - $"BCA4C27EBC31C254BC31C254BC27C251BC12C24FBC1DC250BC10C24BBC0FC242" - $"BC11C246BC0FC242BBF5C219BBF5C219BBD3C1DEBB68C195BBAEC1A4BB71C16E" - $"BB58C129BB63C14EBB4BC101BB4BC0ADBB48C0D7BB4BC0ADBB4EC087BB4EC087" - $"BB52C054BB4DBFEEBB55C021BB9EBF93BBA9BEBFBBB0BF36BBA9BEBFBBA7BE93" - $"BBA7BE93BBA7BE53BBBCBE2FBBA8BE4BBBBCBE2FBBC7BE21BBC7BE21BC00BDD5" - $"BBE3BCFCBC5BBD3DBBE3BCFCBAB7BC58BAB7BC58BAB7BC58BA8BBC44BA90BC46" - $"BA8BBC44BA8BBC42BA8BBC42BA89BBEABA23BB79BA6ABBADBA23BB79BA12BB6B" - $"BA12BB6BBA12BB6BB9F8BB49B9F8BB49B9F8BB49B9AEBAF0B9AEBAF0B97EBAC3" - $"B928BAB1B950BAB5B924BAA9B91BBA9AB920BAA1B984BA6EB9DEB997B9B5B9F9" - $"B9F6B95DBA36B8F0BA0BB91FBA5EB8C4BA78B85EBA83B89EBACCB83DBB61B7E7" - $"BB18B813BB61B7E7BB6BB7E1BB6BB7E1BB6BB7E1BBFEB787BBFEB787BC65B74A" - $"BCB6B684BC94B6F6BCF5B68ABD58B665BD2DB67BBDA8B695BE6DB651BE29B697" - $"BE6FB650BE88B64FBE7CB64FBE62B6A0BEE1B72FBE88B70EBEE4B733BEE9B73E" - $"BEE5B73ABED8B744BEC6B74ABEC6B74ABEC6B74ABE75B7A5BE75B7A5BE63B7DD" - $"BE90B849BE74B817BE91B84CBE92B852BE92B852BE94B85CBE9DB87ABE97B86B" - $"BE94B884BE8CB88DBE8CB88DBE3AB8F0BD92B98FBDB7B906BD92B98FBD8DB9A1" - $"BD8DB9A1BD64B9D8BD7EBA55BD59BA19BD7BBA5CBD77BA63BD77BA63BD56BAA0" - $"BD4DBB2CBD39BAE6BD60BB70BDCCBBCEBD98BBA2BDFFBBFABE73BC3FBE33BC27" - $"BEBEBC5CBF5EBC42BF12BC56BF5EBC42BFAC37BFAC37BFD0BC1EC01CBC0FBFF5" - $"BC0BC046BC14C083BC4EC066BC35C04DBCD9C0F4BDDAC0B6BD63C0F4BDDAC107" - $"BDF9C102BDF2C0BABE84C127BF91C0B2BF1DC127BF91C133BF9DC133BF9DC131" - $"C00FC1C5C0F9C135C0D6C259C11CC348C059C2EEC0C9C348C059C36BC02FC36B" - $"C02FC36BC02FC388C019C388C019C3A8C003C3DBBFC5C3C9BFE8C3EEBFA0C409" - $"BF52C3F0BF73C409BF52C409BF53C409BF53C40DBF9AC495BFC1C450BFCEC4EB" - $"BFB3C542BF10C51FBF56C542BF10C551BEF2C551BEF2C551BEF2C555BEEBC555" - $"BEEBC57FBEA3C568BDFCC59EBE47C53ABDBBC4A3BDDFC4E1BDAAC4A3BDCAC4A3" - $"BDB5C4A3BDB5C4A3BDB5C4A5BD31C4A5BD31C4A8BD1EC4E8BCDFC4D2BCF5C4E8" - $"BCDFC4FEBCC9C4FEBCC9C4FEBCC9C516BCB3C516BCB3C545BC8BC582BC20C571" - $"BC5EC58CBC05C588BBBCC586BBD9C588BBBCC587BBA8C587BBA8C587BBA8C588" - $"BB9DC588BB9DC58DBB614EBAFAC584BB24C58ABADAC5C2BA5DC5B0BAA2C5C4BA" - $"62C5CBBA70C5CBBA70C5D9BA8EC60FBAD4C5EDBAB3C60ABB1FC648BBAAC627BB" - $"67C669BBEBC66FBC7BC670BC33C66FBC7BC672BCC4C672BCC4C674BCEAC66EBD" - $"37C678BD11C664BD5AC649BD9CC652BD79C633BDECC62CBE92C62DBE3FC621BE" - $"D5C67FBF2CC648BF16C750BD0F0006BC12B6E4BC12B6E4BC32B6B0BC55B638BC" - $"47B674BB81B6ABBA2BB802BAC4B747BA88B7E3BB30B77EBADDB7B0BB59B765BB" - $"AAB733BB82B74DBBCBB71DBC12B6E4BBFCB707BC12B6E4001DBACDBFD1BACDBF" - $"D1BAEBBFAABB29BF5CBB13BF89BB43BF24BB34BE93BB34BED0BB34BE4DBB60BD" - $"EABB34BE25BB80BDBEBBABBD60BBA1BD98BB48BD2ABA81BCBEBAE5BCF3BA67BC" - $"B1BA20BC83BA2DBCA0BA0FBC5BBA0DBC02BA1FBC28B9FEBBE5B9BABBB6B9D0BB" - $"D0B99BBB91B95FBB44B983BB66B93DBB24B8F0BB2DB91CBB16B8C0BB48B8BEBA" - $"DFB8C3BAFFB8B1BB14B89FBB7EB8A7BB49B8C9BB7EB8C5BBB2B8C3BB8AB8C6BB" - $"DBB8C9BC2EB8C7BC05B8D0BC40B8BABC49B8CBBC49B8B4BC4BB8AABC4EB8AFBC" - $"4DB8A0BC57B893BC4BB898BC56B882BC4AB88FBD10B88EBD00B893BD49B8E1BD" - $"E7B88DBE03B90DBE04B923BE75B906BE4BB946BEA8B985BF00B973BEC1B997BF" - $"3EB9A3BFC1B998BF81B9B0C011BA17C05FB9DBC02EBA25C0B3BA75C127BA3DC0" - $"E7BA8FC144BAC0C17FBAA9C160BAD8C19FBAFCC17CBAE4C19DBADDC13ABAD7C0" - $"A6BAD3C0EFBADBC061BACDBFD1BAEAC013BACDBFD10009BD5EB5D7BD5EB5D7BD" - $"81B5EEBDB1B60EBD84B605BDD0B613BE19B601BE01B61ABE55B5C3BEF6B5C4BE" - $"B0B5EFBF2DB5A2BFA3B55EBF5BB55EBFCEB55DC00CB58CBFE9B578C03CB5A7C0" - $"90B566C064B575BF3AB541BCA7B60EBDDDB57ABCECB623BD5EB5D7BD29B601BD" - $"5EB5D70005BF35B6EABF35B6EABF55B6ECBF9AB6F5BF7BB702BFCEB6E0BF87B6" - $"7DBF9CB693BF78B66DBF3CB664BF2FB623BF45B690BF35B6EABF6BB6CCBF35B6" - $"EA0004BA07B87FBA07B87FBA0CB868B9EFB850B9FEB85FB982B8E4B8F0BA35B9" - $"2CB988B97E31BA07B87FB974B8F0BA07B87F0066C6F7BC24C6F7BC24C6DCBB0A" - $"C6002FC68BB9F2C5B9B87CC4FFB79CC563B805C4CEB768C463B709C49AB737C4" - $"52B6FBC428B6EFC440B6E2C412B6FAC407B6C1C401B6D1C316B60FC0D0B56FC1" - $"F9B59AC0FBB58BC15FB59CC131B589C170B5A2C179B5C9C19FB5BDC12DB5E2C0" - $"8AB5C9C0D7B5C4C05AB5CDC03FB60EC043B5DDC03DB629C040B676C036B65DC0" - $"4BB694C0B6B65FC0A8B66FC0CDB643C0F1B61AC0B1B608C108B64BC0D0B6B1C1" - $"3AB6D6C0B5B6A7C066B689C083B67CC064B68AC05DB6AFC05FB6ABC053B6C0C0" - $"31B6D0C044B6CBBFE6B6E5BF94B741BFB0B6EFBF87B769BF5DB791BF88B781BF" - $"3BB79DBEF7B7B2BF17B7A4BECCB7C7BEFAB81CBEEAB7FFBF06B830BF19B86CBF" - $"03B860BF59B891BFBEB7E0BFA3B802BFE1B7B3C038B7ADC008B7BDC04FB7A6C0" - $"84B777C06CB76EC0D3B795C0F8B83EC0EBB7F4C110B83FC135B810C100B802C1" - $"0DB7E5C0ECB77043B7ABC125B795C15FB7FDC14DB7BDC170B83DC1C2B820C18E" - $"B860C1CFB813C1FDB7D5C1E2B7BDC214B7EAC1F1B838C215B82FC206B84BC23A" - $"B83DC222B843C25AB834C28BB842C26CB836C2AFB850C2FAB857C2D5B854C320" - $"B859C347B898C335B87BC377B8E7C24AB8C5C259B8C6C228B8C3C1E2B8D0C202" - $"B8C2C1C9B8DAC199B8F0C1B62FC179B8E5C13FB8B6C15BB8C8C118B89CC0C5B8" - $"72C0EFB885C07FB853BFE3B84FC02FB83FBFBFB856BF7FB87CBF9CB866BF5CB8" - $"97BF11B8A4BF35B87FBEDCB8DCBE6EB942BEB6B91FBE51B950BE19B976BE2EB9" - $"5CBE04B990BDF6B9D1BE04B9B4BDE9B9EEBDE2BA1DBDCAB9FCBDF8BA3CBDEFBA" - $"76BDFEBA53BDD9BAA9BDC9BB27BD9FBAEFBDF235BE71BBBCBE3ABB94BEAFBBE9" - $"BF41BBD2BEFBBBE5BF83BBC1C009BB9CBFC5BBA1C05FBB96C0DDBC03C0A1BBCD" - $"C104BC26C0F5BC67C114BC34C0D3BC9FC103BD00C0E8BCC8C11FBD37C159BDA3" - $"C13CBD6DC166BDBAC182BDE8C177BDD0C18EBE04C16DBE2DC17BBE15C152BE5E" - $"C13FBECFC13FBE97C13FBF0EC185BF4CC15DBF24C1AABF71C1A4BFE3C1A8BFB3" - $"C1A0C025C1DBC087C1B3C053C216C08AC289C06CC253C086C2CBC04DC319BFDE" - $"C2E8C00FC347BFB0C386BF66C378BFABC396BF13C3FEBEBFC3C2BEF2C435BE90" - $"C430BE0CC42EBE4DC432BDC0C433BD22C429BD6DC43CBCDEC4ABBC78C47EBCA7" - $"C4CDBC56C512BC03C505BC34C519BBE7C513BBA8C51336C513BB93C51135C51A" - $"BB71C4F8BB29C47EBB2CC48ABB5DC476BB0EC48BBB01C477BB14C4A1BAEDC478" - $"BACDC48BBAD8C442BAADC3F1BA66C418BA9AC3CCBA36C391B9CBC3AEBA00C389" - $"B9BEC36CB93BC342B92EC39AB94AC3E2B9A3C3C4B981C419B9DFC46DBA6AC44A" - $"BA20C46EBA73C496BA8AC48FBA85C4AFBA9CC4EABAA8C4CABAABC533BAA2C55A" - $"BA20C555BA61C562B9C7C4E8B9AFC51DB9DAC4CAB997C49EB958C4B6B975C48F" - $"B946C474B90EC466B92AC493B8F9C4BDB91DC49FB90BC4E0B932C52CB951C505" - $"B944C555B95EC5B4B96CC592B952C5C9B97CC5E7B9B8C5D9B9A2C5FEB9DCC627" - $"BA26C614BA00C645BA61C694BA9FC64DBA89C667BAE8C6B6BB83C693BB3FC6DF" - $"BBD4C6E3BC7CC6E4BC23C6E2BCCEC6D0BD79C6F5BD2CC6A7BDCCC69FBE9AC69F" - $"BE3EC6A1BE95C6A5BE88C6A3BE8DC6A2BE8FC6A1BEC0C696BEBEC6B2BEC4C6D6" - $"BE02C6D2BE15C6F6BD65C6F7BC24C700BCC4C6F7BC240008C301B7D8C301B7D8" - $"C2E6B7DCC2D4B7A4C2E8B7AEC2B1B792C269B7B8C288B7A7C204B7EFC236B743" - $"C221B77BC239B73AC285B744C27AB746C2A7B740C2F3B74FC2D8B731C30CB76B" - $"C33CB7A1C31FB787C360B7C2C301B7D8C31CB7D4C301B7D80004BB53C203BB53" - $"C203BB45C20DBB26C221BB38C21DBB55C249BBBAC291BB87C26EBB92C265BB53" - $"C203BB84C227BB53C2030005C4F4BE2EC4F4BE2EC4D3BE57C48CBEA4C4A6BE76" - $"C46EBEDAC47DBF53C47DBF18C4B6BF38C4EDBEB9C4D0BEECC502BE93C4F4BE2E" - $"C531BE48C4F4BE2E0009C213C327C213C327C17FC390BFF7C345C09DC332BFD0" - $"C349BF8EC36ABFACC350BF67C38CBF20C386BF56C386BEAFC386BDCDC386BE3E" - $"C386BEC1C3CBC0C0C3BABFC4C3DDC137C3AAC221C367C1AFC38EC22AC364C262" - $"C32BC280C337C249C322C213C327C22AC331C213C32702024E284E2C542E4C32" - $"4C30482E020250304C3252344C364E344C340202C951B81858305C3254365432" - $"4E300202583456365836563C5A3854380204BCD6C1F1BACDC370BEA5C09BC4A7" - $"BFA6C361BE3CC67FC1B1C065C5ADC23AC445BE91C715B827C85DB962C9B9B682" - $"C68C0204C3CFC072C309BF46C522C2743DC65FC0DEC4E4BC10C7F7B880C76BB8" - $"DAC831B842C6E2BC70C2E3B880C5CDBE43C189061EAEE6BAEAAAAF9A0EB9E5C6" - $"DFB9CC50B985C673BA12C5CDBAE4C593BA9EC0BFBC89BE0E36B8E6B993B8DA2E" - $"B874B92DB971B7B0BCD6BA52BCEFB87ABE3BB7AEBD62B7AEBF13B7AEBF862EBF" - $"93BA78C0D2BB91C49BBB6AC51ABC10C51ABBB6C51ABC5AC49BBCB6C21DBCC3BF" - $"A0BDCEBFCCC18BC1FDC323BF00C13E46C33BC197C43B46C3DCC12BC484C02CC4" - $"94C012C3EFC092C36FBE21C2BDBF40BC50C14BBBF74EBB8451BBE8C66FBA9EC6" - $"B90611AAAAA8BA02BBF0B9ECBB4ABAB8BCC9BB9DBCE2BE4EBB71C019BC7CC0A5" - $"BE08BF73BE6144BFA0BF6DBDDBC06CBD0245BCAFC1CABC30BF40BAABBE0EBB04" - $"BF0DBB04BD83BB04BD15BAB8BCAFBA38060BBAAA2A31C653BA0CC6C5BB84C646" - $"BB2BC69FBBB6C614BBB0C5A0BBDDC309BC1DC164BCAFC0CBBB71BFE6BAD8C0CB" - $"BACBC395BAE4C5C6060AAAAB0ABE47C125BF99C131BF80454448C1FDC395C21D" - $"C362C1C4C3F1C11EC448C052C494C02CC3EFC105C389BE67470605EA02BB37BA" - $"C5BBD7BA12B9ACB887B8E0B8ADB90BB86AB887B939B920B96C0A05C16BBB91C4" - $"74BB91C4DABC36C4A7BCC3C16BBCE906078A2EBD4F2EBDB5B814BEA7BF402EBF" - $"4DBA45BE0EBB04BEA7BB2BBD8ABAE3BD29BA520607AA3A39B8EDBE012F3CB99F" - $"3EB993BEDAB920BF99B946BE34B77BBFF6B7C339B74804032EBCE932BDCEBB2B" - $"BD34BB13BECDBB51BF4DBA380208CA68BA5FCB41BD02CA3AB9D0CA0FB6BCCAF4" - $"B7AEC947B5E955B58A55B58A55B58AC844B841C8FFB76C53B953C718B814C6E6" - $"B8FBC74BB728C5A02FC601B84FC2703DC646BCB6C5ADBC1DC712BD82C89DBEE7" - $"C79E40C89DBEE7060ABFFB0FC6F2C098C626BFCCC6F2BFCC5A345C3758315A2E" - $"5A305A2C582A562E582C54305230C692B854C692B920C692B7DAC53ABAAB4FB9" - $"ACC501BB1EC46EBBF7C4AEBB9DC3FBBCB6C56DBE0EC38FBE4EC64DBDF00207C8" - $"70BE74C870BE74C7A4BDA8C78BBB44C80BBB28C71835C633BBB7C6D5BBF0C5DB" - $"BB98C501BB44C50ABB7AC4F2BAEEC3F5BC43C43FBBD2C4B4BC83C6FF38C63336" - $"C7CB3AC83DBE9AC5B3BF8DC909BD020202C6392F4DB9F9C66CBAC54DBBE34FBB" - $"17C46EBAEB0202C969B7CEC967B916CAFFB9E2543654324E3002025834563658" - $"36C877BD8FC969BB84C7ABBBF70604EAC2BD4448C111C32FC07FC362C17EC33C" - $"C0E5C37CC1E40205C5ADB861C65F31C52CB75E50204E224E20C3E2BA5FC37CB9" - $"50C455BB91C606BD02C494BCB6C723BE0DCB1BBDA8CB97BDE4C79EBBF702044E" - $"B44BC4D4284EB5174BB9B9C408B8BAC43EBAD855BD4F4BBBD057BD4FC745BB77" - $"C818BC3C51BAC502034E28C4A1B847C53AB61650BA52C593B8A0C691BBAFC4E1" - $"BAAB59BD8FC4E1B7A104032EB77BC613B63CC969B50AC7ABB778CB36BCA9C99C" - $"04032EB966B906B953B7D4B8D3B86DB9C7B749BAB82C0406BE0BB689BE67B5FD" - $"C04CB608BF7FB5F1C11CB689C1D7B65BC1A2B73BC2A3B85448B77BC33CB801C3" - $"1EB70849B609C32304032EBDA8B887BEB4B76EBE11B775BFEC2BC059B8AD0403" - $"2E28BE01B3FFC0D8B4253FB3D3C288B5BDC2FC0406FE0BC79EBB2BC8F6BBAAC8" - $"41BB48C9ECBC2FCB27BDDBCB06BD15CB41BE74CA4FC07FCA99BFCBCA0FC118C9" - $"CFC27DCA0FC1E4C998C30058C3890A04C6FFBB11C857BC50C8BDBCC3C88ABD4F" - $"040CAAFABABC70C74BC092C699C303C5CDC3DBC54DC441C4CEC44EC382C1EAC3" - $"03C237C34DC1D5C2EEC05FC402C14AC3E0BF76C423BD88C461BD48C4FABE47C5" - $"14BE2E4DBE98C58CBDBBC5870608BAAABFECC1FD4448C1FDC395C21DC362C1C4" - $"C3F1C11EC448C052C494C02CC3EFC105C389BED4C2BD0A04C369BC83C6D838C6" - $"66BD1CC35CBD350A03B46542B4BE41B4BE420605AF03B6AFC969B63DC9F2B72F" - $"C8D0BE4155B821CA8EC11CC6FAC42EC5C6C560C53ABE67C91DC1E8C7EAB86DCB" - $"270604EEBFCCBB51C1FDBBD0C13EBC43C29FBB6FC18BBAAB43BB1EC146BAF2C0" - $"9ABB4B0A0430303050505050302C0A0001021240BAB100000000000040B755C6" - $"CCDBBE997901178300040A0101020240BAB100000000000040B755C6CCDBBE99" - $"790A0201030240BAB100000000000040B755C6CCDBBE99790A030A0506070809" - $"0A0C0D040B0240BAB100000000000040B755C6CCDBBE99790A11011312408447" - $"3AE65BBB0539406A8F40BD7AC6ED3001178400040A00012712401CCA00000000" - $"00004031D6BEA7B4C5651401178100040A150112024046733A7FB6BABB054015" - $"08437714C3BB840A3B012E0A401CC92E6813AE6813401CC9C0B293C4BE831DFF" - $"0A11011412402E52374883B74883402E5243A84DC5C35901178200040A160115" - $"02402E52374883B74883402E5243A84DC5C3590A17011602402E52374883B748" - $"83402E5243A84DC5C3590A18011702402E52374883B74883402E5243A84DC5C3" - $"590A17011802402E52374883B74883402E5243A84DC5C3590A1801190240268F" - $"36C1F1B73CD33FA9DD442903C369B00A1B011A02402E52374883B74883402E52" - $"43A84DC5C3590A2C011B02402E52374883B74883402E5243A84DC5C3590A1101" - $"1C12402E52374883B74883402E5243A84DC5C35901178100040A20011D124018" - $"A13C2DD3BC6F843F776243040C3B35B701178400040A28011D024018A13C481B" - $"BC6F843FA13143AD0CC180CE0A27011E024018A13C3669BC6F843F850B43AD0C" - $"BDA6830A2603212022023F94B53C057BBC14913F373546DE4E423FFC0A2B0122" - $"02401CCA000000000000401CCAC64FB846E7CF0A2B01230241774E3E9634BD97" - $"FB40685AC6A141CA33220A0001291240075E0000000000004029CCC0DC88C59D" - $"5C01178100040A2E0124123E3A7739EBE1BA96D53D1E7BC874E948577D011784" - $"00040A360124023DE4F539818BBA43313CC9E6C7EFC848861D0A350125023DE4" - $"F539818BBA43313CC9E6C7EFC848861D0A340126023DE4F539D28CBA43313D0A" - $"55C7EFC8485E9A0A000128123FEA4E3675EFB6F2733F44E3440366C2D2660117" - $"8200040A00012A12402E52374883B74883402E5241C554C5CE0401178100040A" - $"00012B12401CCA000000000000401CCAC0623FC4B46E01178100040A00012C12" - $"403196000000000000401CCAC3AEA8C4B46E01178100040A3A012D02401CCA00" - $"0000000000401CCAC0E971C4B46E0A3C012F0A401CCA000000000000401CCAC0" - $"E971C4B46E1DFF0A3B01300A3FEC520000000000003C6A0B41051D473FEE1DFF" - $"0A3E01310240FA05000000000000417C4D3E5061C9E26E0A3F013212401CCA00" - $"0000000000401CCAC0E971C42D3C01178200040A4001330A401CCA0000000000" - $"00401CCAC0E971C4B46E1DFF0A42013402360000000000000000360000489000" - $"4AE8000A420134023600000000000000003600004870004AE8000A4301340236" - $"00000000000000003600004850004AF8000A4301340236000000000000000036" - $"00004870004AF8000A430134023600000000000000003600004890004AF8000A" - $"44013402360000000000000000360000485000466000" + $"6B05000359463503C3A414039D816035000000000204BFC1B55A36B55AC3BEB5" + $"5AC6FABC92C6FAB895C6FAC08FBFC1C3CBC3BEC3CB36C3CBB889BC92B889C08F" + $"B889B895066EFFFFF30FFFFEFFFFBFBFFEFFFEFFFEFFFFFFFFBFFFEFDFFBFBFF" + $"FF0FC5DBB8B5C713BA9FC4CAB706C10FB579C307B5D4C0A226BFC1B55AC031B5" + $"5ABDBCB55ABA69B7BA36B63AB8F9B94EB89CBD9BB84EBB7EB8C7BE9AB924BF76" + $"B8E0BEE7B9DEC11FBCDFC332BB37C278BEC4C405C2D7C31AC0FAC3FCC2C5C2C0" + $"C22EC2B7C279C2BDC22EC2B7C226C240C2BDC240C2BDC206C2AFC199C2DAC1D0" + $"C2CB44C2EEC0D4C2DCC114C2E5C051C2CEBF42C312BFB0C2B4BF3DC312BF35BF" + $"1FBDECC312BE23C312BDB8C2EDBD57C2DEBD86C2E2BD53C2DBBD3EC2C2BD3EC2" + $"C2BD31C2B4BD12C2A4BD26C2AABD12C2A4BCA4C27EBC31C254BC31C254BC27C2" + $"51BC11C24FBC1DC250BC10C24BBC0FC241BC10C245BC0FC241BBF5C219BBF5C2" + $"19BBD2C1DDBB68C194BBADC1A4BB70C16EBB58C128BB62C14EBB4BC101BB4BC0" + $"ACBB47C0D7BB4BC0ACBB4EC087BB4EC087BB51C054BB4DBFEEBB54C021BB9DBF" + $"92BBA9BEBFBBAFBF35BBA9BEBFBBA7BE92BBA7BE92BBA7BE52BBBBBE2FBBA8BE" + $"4BBBBBBE2FBBC6BE20BBC6BE20BC00BDD4BBE2BCFBBC5BBD3DBBE2BCFBBAB7BC" + $"58BA8ABC43BA90BC45BA8ABC43BA8ABC42BA8ABC42BA88BBEABA22BB78BA6ABB" + $"ACBA22BB78BA12BB6AB9F8BB48B9ADBAEFB9ADBAEFB97DBAC3B927BAB0B94FBA" + $"B5B924BAA9B91ABA9AB920BAA0B984BA6DB9DEB996B9B5B9F9B9F6B95DBA36B8" + $"EFBA0AB91FBA5EB8C4BA78B85EBA83B89EBACCB83CBB60B7E7BB18B813BB60B7" + $"E7BB6AB7E1BBFEB787BBFEB787BC65B749BCB6B683BC93B6F5BCF5B689BD58B6" + $"64BD2CB67BBDA8B695BE6CB6503C29BE6FB64FBE88B64FBE7CB64FBE62B6A0BE" + $"E1B72FBE88B70EBEE4B733BEE8B73DBEE5B73ABED8B743BEC5B749BE74B7A5BE" + $"74B7A5BE63B7DCBE8FB848BE74B816BE90B84CBE91B852BE91B852BE93B85BBE" + $"9CB87ABE97B86BBE93B883BE8CB88DBE8CB88DBE39B8EFBD91B98FBDB6B906BD" + $"91B98FBD8DB9A0BD8DB9A0BD64B9D7BD7EBA54BD59BA19BD7ABA5CBD76BA62BD" + $"76BA62BD56BA9FBD4DBB2BBD38BAE6BD5FBB6FBDCCBBCEBD98BBA1BDFFBBF9BE" + $"73BC3FBE33BC27BEBEBC5CBF5DBC42BF11BC55BF5DBC42BFAB37BFAB37BFD0BC" + $"1DC01CBC0FBFF4BC0BC045BC13C083BC4EC066BC35C04DBCD9C0F3BDDAC0B6BD" + $"63C0F3BDDAC107BDF8C102BDF2C0BABE83C126BF90C0B1BF1CC126BF90C133BF" + $"9CC133BF9CC130C00EC1C4C0F8C135C0D6C258C11CC347C059C2EEC0C8C347C0" + $"59C36BC02EC388C018C388C018C3A7C003C3DABFC4C3C9BFE8C3EEBF9FC408BF" + $"51C3EFBF73C408BF51C408BF52C408BF52C40CBF99C49540C450BFCEC4EBBFB3" + $"C541BF0FC51FBF56C541BF0FC551BEF24EBEEA4EBEEAC57FBEA3C568BDFCC59E" + $"BE46C53ABDBAC4A2BDDEC4E0BDA9C4A2BDCABDB5C4A4BD31C4A4BD31C4A7BD1D" + $"C4E8BCDEC4D2BCF5C4E8BCDEC4FEBCC8C516BCB3C516BCB3C544BC8BC582BC1F" + $"C570BC5DC58BBC04C587BBBBC586BBD9C587BBBBC587BBA8C587BB9DC587BB9D" + $"C58CBB604EBAF9C584BB23C589BADAC5C1BA5DC5B0BAA1C5C3BA61C5CBBA6FC5" + $"CBBA6FC5D8BA8EC60EBAD3C5EDBAB3C609BB1EC648BBAAC626BB67C669BBEAC6" + $"6EBC7AC66FBC33C66EBC7AC671BCC3C671BCC3C673BCE9C66DBD36C677BD10C6" + $"64BD5AC649BD9BC652BD78C633BDEBC62BBE91C62DBE3F50BED5C67FBF2BC648" + $"BF16C750BD0F0006BC11B6E3BC11B6E3BC32B6AFBC54B637BC46B674BB81B6AA" + $"BA2BB801BAC4B747BA87B7E2BB2FB77DBADDB7AFBB59B764BBAAB733BB82B74D" + $"BBCBB71CBC11B6E3BBFBB707BC11B6E3001DBACDBFD1BACDBFD1BAEBBFA9BB29" + $"BF5BBB12BF89BB43BF24BB34BE92BB34BECFBB34BE4DBB5FBDE9BB34BE25BB80" + $"BDBEBBAABD5FBBA0BD98BB47BD29BA81BCBEBAE5BCF3BA67BCB1BA1FBC8332BC" + $"9FBA0FBC5BBA0DBC02BA1FBC28B9FDBBE5B9B9BBB6B9D0BBD0B99BBB91B95FBB" + $"44B983BB66B93DBB23B8EFBB2CB91BBB15B8C0BB47B8BEBADEB8C2BAFFB8B1BB" + $"13B89FBB7EB8A7BB48B8C8BB7EB8C5BBB2B8C2BB89B8C6BBDBB8C8BC2DB8C7BC" + $"04B8CFBC40B8BABC48B8CBBC48B8B3BC4BB8A9BC4EB8AEBC4DB8A0BC57B893BC" + $"4BB898BC55B881BC4AB88EBD0FB88DBD00B893BD49B8E0BDE7B88DBE02B90DBE" + $"03B922BE74B906BE4BB946BEA7B985BF00B972BEC1B996BF3EB9A240B997BF80" + $"B9AFC010BA16C05EB9DBC02DBA24C0B3BA75C126BA3CC0E7BA8FC143BAC0C17F" + $"BAA9C15FBAD7C19FBAFBC17BBAE3C19DBADDC13ABAD6C0A5BAD2C0EFBADBC060" + $"BACDBFD1BAEAC012BACDBFD10009BD5DB5D6BD5DB5D6BD81B5EDBDB1B60DBD83" + $"B605BDCFB613BE19B600BE01B619BE55B5C3BEF5B5C3BEB0B5EFBF2CB5A1BFA3" + $"B55D3FB55DBFCEB55DC00CB58CBFE9B577C03CB5A6C08FB566C063B574BF39B5" + $"40BCA7B60DBDDCB57ABCEBB623BD5DB5D6BD29B600BD5DB5D60005BF34B6E9BF" + $"34B6E9BF55B6EBBF99B6F5BF7BB702BFCEB6E0BF87B67CBF9BB693BF77B66DBF" + $"3CB663BF2FB623BF44B68FBF34B6E9BF6AB6CBBF34B6E90004BA06B87FBA06B8" + $"7FBA0BB867B9EEB84FB9FDB85FB982B8E4B8EFBA35B92CB987B97D31BA06B87F" + $"B974B8EFBA06B87F0066C6F6BC24C6F6BC24C6DBBB09C6002FC68AB9F1C5B9B8" + $"7BC4FFB79BC563B805C4CEB768C463B708C49AB736C452B6FBC427B6EFC43FB6" + $"E2C411B6FAC407B6C1C401B6D0C315B60FC0D0B56EC1F8B59AC0FAB58AC15EB5" + $"9CC130B589C170B5A1C178B5C9C19FB5BDC12CB5E2C08AB5C9C0D7B5C3C059B5" + $"CDC03FB60DC042B5DDC03DB629C03FB676C036B65CC04AB694C0B6B65EC0A7B6" + $"6FC0CDB643C0F1B619C0B0B607C108B64AC0D0B6B0C13AB6D5C0B5B6A7C066B6" + $"89C083B67CC063B689C05CB6AFC05EB6AAC053B6C0C030B6CFC043B6CABFE5B6" + $"E4BF94B741BFB0B6EFBF87B768BF5CB790BF88B781BF3BB79CBEF6B7B2BF17B7" + $"A3BECCB7C7BEF9B81BBEE9B7FFBF05B82FBF19B86CBF02B860BF59B891BFBEB7" + $"E0BFA3B801BFE0B7B3C038B7ADC008B7BCC04FB7A6C084B776C06CB76EC0D3B7" + $"95C0F7B83EC0EBB7F4C10FB83FC135B80FC100B801C10CB7E5C0ECB76F43B7AA" + $"C125B795C15EB7FCC14DB7BCC170B83CC1C1B820C18DB860C1CFB813C1FCB7D4" + $"C1E1B7BCC213B7E9C1F1B838C2142DC206B84BC23AB83CC222B842C259B83447" + $"B841C26CB835C2AEB84FC2F9B856C2D5B854C320B859C346B898C335B87AC376" + $"B8E6C249B8C5C258B8C6C227B8C2C1E1B8CFC202B8C1C1C8B8DAC199B8EFC1B6" + $"2FC178B8E5C13EB8B5C15AB8C7C117B89BC0C4B872C0EFB885C07EB853BFE2B8" + $"4EC02EB83FBFBFB855BF7FB87BBF9BB866BF5BB896BF10B8A4BF34B87FBEDBB8" + $"DBBE6DB941BEB5B91FBE50B94FBE19B976BE2DB95BBE03B990BDF5B9D1BE03B9" + $"B4BDE8B9EDBDE2BA1DBDCAB9FBBDF7BA3BBDEFBA76BDFEBA52BDD9BAA9BDC9BB" + $"27BD9EBAEEBDF235BE71BBBBBE39BB93BEAFBBE9BF40BBD1BEFBBBE5BF82BBC1" + $"C009BB9CBFC4BBA0C05EBB95C0DCBC03C0A1BBCDC104BC26C0F4BC67C113BC34" + $"C0D3BC9EC103BD00C0E8BCC7C11FBD3644BDA3C13CBD6CC166BDB9C182BDE8C1" + $"76BDCFC18DBE03C16DBE2CC17ABE15C152BE5DC13EBECEC13EBE97C13EBF0DC1" + $"85BF4CC15CBF24C1A9BF71C1A4BFE2C1A7BFB3C1A0C025C1DAC087C1B3C053C2" + $"15C08AC289C06CC253C086C2CBC04DC319BFDDC2E8C00EC346BFB0C386BF66C3" + $"77BFAAC396BF12C3FEBEBFC3C1BEF2C435BE8FC430BE0CC42DBE4DC432BDC0C4" + $"33BD21C428BD6CC43BBCDDC4AABC77C47EBCA7C4CDBC55C511BC03C505BC34C5" + $"19BBE7C512BBA8C51236C512BB92C51035C51ABB70C4F7BB29C47EBB2BC489BB" + $"5DC475BB0EC48ABB01C476BB13C4A1BAECC477BACDC48ABAD7C441BAACC3F0BA" + $"66C418BA9AC3CCBA36C390B9CAC3ADBA00C389B9BDC36CB93AC341B92DC39AB9" + $"4AC3E1B9A2C3C3B981C419B9DFC46DBA6AC44ABA1FC46EBA73C496BA89C48EBA" + $"85C4AFBA9CC4EABAA8C4CABAABC533BAA1C559BA1F4EBA60C56231C4E8B9AEC5" + $"1DB9DAC4CAB996C49EB958C4B6B975C48EB946C473B90DC466B92AC492B8F9C4" + $"BCB91CC49FB90BC4DFB932C52BB951C505B9444EB95EC5B4B96CC591B952C5C9" + $"B97BC5E7B9B8C5D8B9A1C5FEB9DCC626BA26C614BA00C644BA60C694BA9EC64D" + $"BA88C667BAE8C6B6BB83C693BB3FC6DEBBD3C6E3BC7BC6E4BC22C6E2BCCEC6D0" + $"BD78C6F4BD2BC6A6BDCCC69FBE9AC69FBE3EC6A0BE95C6A4BE88C6A2BE8DC6A1" + $"3DC6A0BEC0C696BEBEC6B2BEC3C6D5BE01C6D2BE15C6F5BD65C6F6BC24C700BC" + $"C3C6F6BC240008C301B7D8C301B7D8C2E6B7DBC2D4B7A3C2E8B7AEC2B1B792C2" + $"69B7B7C288B7A7C204B7EEC236B742C221B77BC239B73AC285B743C279B746C2" + $"A6B740C2F2B74EC2D7B730C30BB76AC33CB7A1C31FB787C35FB7C1C301B7D8C3" + $"1CB7D4C301B7D80004BB52C203BB52C203BB44C20CBB26C221BB37C21DBB54C2" + $"48BBB9C290BB86C26EBB91C265BB52C203BB84C226BB52C2030005C4F3BE2DC4" + $"F3BE2DC4D3BE57C48BBEA4C4A5BE75C46EBEDAC47DBF52C47DBF18C4B6BF37C4" + $"EDBEB8C4D0BEEBC502BE92C4F3BE2DC531BE48C4F3BE2D0009C212C326C212C3" + $"26C17FC38FBFF6C344C09DC332BFD0C348BF8DC36ABFABC350BF66C38BBF1FC3" + $"86BF56C386BEAFC386BDCDC386BE3EC386BEC1C3CBC0BFC3BABFC3C3DCC137C3" + $"A9C221C367C1AEC38DC229C364C261C32AC280C337C248C322C212C326C229C3" + $"31C212C32602024E284E2C542E4C324C30482E020250304C3252344C364E344C" + $"34020258B81858305C32543654324E300202583456365836563C5A3854380204" + $"BCD5C1F1BACDC36FBEA5C09BC4A6BFA6C360BE3CC67FC1B0C064C5ACC23AC444" + $"BE90C715B827C85CB961C9B8B682C68B0204C3CFC072C309BF45C521C2733DC6" + $"5EC0DDC4E4BC10C7F6B880C76BB8DAC831B841C6E2BC6FC2E2B880C5CDBE42C1" + $"890622AEAAE6BAEAAAAF9A0EB9E4C6DEB9CB50B985C672BA12C5CDBAABC593BA" + $"C54DBAB8C4BBBAEBC3C8BAABC37CBA85C0CBBC88BE0E36B8E6B993B8DA2EB874" + $"B92DB970B7AFBCD5BA52BCEEB87ABE3AB7AEBD61B7AEBF12B7AEBF852EBF92BA" + $"78C0D2BB91C49BBB6AC51ABC10C51ABBB6C51ABC5AC49BBCB6C21DBCC3BF9FBD" + $"CEBFCBC18BC1FCC323BF00C13E46C33BC196C43B46C3DBC12AC484C02BC493C0" + $"11C3EFC091C36FBE20C2BDBF40BC50C14ABBF74EBB8451BBE8C66EBA9EC6B906" + $"11AAAAA8BA02BBEFB9ECBB49BAB8BCC8BB9DBCE1BE4EBB70C018BC7BC0A5BE07" + $"BF73BE6044BF9FBF6CBDDBC06CBD0245BCAEC1C9BC2FBF40BAABBE0EBB04BF0D" + $"BB04BD82BB04BD14BAB8BCAEBA38060BBAAA2A31C653BA0BC6C4BB84C645BB2B" + $"C69FBBB6C614BBAFC5A0BBDDC309BC1DC163BCAEC0CABB70BFE5BAD7C0CABADE" + $"C36FBAE3C5C5060AAAAB0ABE46C125BF99C130BF80454448C1FCC394C21DC361" + $"C1C3C3F0C11EC447C052C493C02BC3EFC105C389BE67470605EA02BB37BAC5BB" + $"D6BA12B9ACB887B8E0B8ADB90BB869B887B939B920B96C0A05C16BBB91C473BB" + $"91C4D9BC36C4A6BCC3C16BBCE906078A2EBD4F2EBDB5B814BEA7BF402EBF4DBA" + $"45BE0EBB04BEA7BB2BBD8ABAE2BD29BA520607AA3A39B8EDBE012F3CB99F3EB9" + $"93BEDAB920BF99B946BE34B77BBFF5B7C239B74804032EBCE932BDCEBB2BBD34" + $"BB12BECDBB51BF4DBA380208CA68BA5FCB40BD02CA39B9D0CA0EB6BCCAF3B7AE" + $"C947B5E955B58A55B58A55B58AC843B841C8FFB76C53B953C718B814C6E62FC7" + $"4BB728C5A02FC601B84EC2703DC645BCB6C5ACBC1DC711BD82C89DBEE7C79E40" + $"C89DBEE7060ABFFB0FC6F1C097C625BFCBC6F1BFCB5A345C3758315A2E5A305A" + $"2C582A562E582C54305230C691B854C691B920C691B7DAC53ABAAB4FB9ACC501" + $"BB1EC46EBBF7C4ADBB9DC3FABCB6C56DBE0EC38EBE4EC64DBDF00207C86FBE74" + $"C86FBE74C7A3BDA8C78ABB44C80ABB28C71835C633BBB7C6D4BBEFC5DABB98C5" + $"01BB44C509BB79C4F1BAEDC3F4BC43C43EBBD1C4B4BC83C6FF38C63336C7CB3A" + $"C83CBE9AC5B3BF8DC908BD020202C6392F4DB9F9C66CBAC54DBBE24FBB16C46E" + $"BAEB0202C969B7CEC967B915CAFFB9E1543654324E300202583456365836C876" + $"BD8FC969BB84C7AABBF70604EAC2BD4448C110C32EC07EC361C17DC33CC0E4C3" + $"7BC1E30205C5ACB861C65E31C52BB75D50204E224E20C3E1BA5FC37BB94FC455" + $"BB91C606BD02C493BCB6C722BE0DCB1BBDA8CB97BDE4C79EBBF702044EB44BC4" + $"D4284EB5174BB9B9C408B8BAC43DBAD755BD4F4BBBD057BD4FC744BB77C818BC" + $"3B51BAC502034E28C4A1B847C53AB61650BA52C592B8A0C690BBAEC4E0BAAB59" + $"BD8FC4E0B7A104032EB77BC612B63CC969B50AC7AAB777CB35BCA9C99C04032E" + $"B965B906B953B7D4B8D3B86D31B748BAB82C0406BE0BB689BE67B5FDC04BB607" + $"BF7FB5F0C11CB689C1D7B65BC1A2B73BC2A3B85448B77BC33CB801C31EB70849" + $"B609C32304032EBDA8B887BEB4B76EBE10B775BFEC2BC059B8AD04032E28BE01" + $"B3FFC0D8B4253FB3D2C288B5BDC2FB0406FE0BC79EBB2BC8F5BBAAC840BB47C9" + $"EBBC2ECB26BDDBCB05BD14CB40BE74CA4FC07ECA99BFCACA0EC117C9CFC27CCA" + $"0EC1E3C998C30058C3890A04C6FFBB11C856BC50C8BCBCC3C889BD4F040CAAFA" + $"BABC6FC74BC091C699C303C5CDC3DAC54DC440C4CEC44EC382C1EAC303C237C3" + $"4DC1D5C2EEC05EC402C149C3DFBF754BBD87C460BD47C4F9BE46C513BE2D4DBE" + $"98C58BBDBAC5870608BAAABFECC1FC4448C1FCC394C21DC361C1C3C3F0C11EC4" + $"47C052C493C02BC3EFC105C389BED3C2BD0A04C369BC83C6D738C666BD1CC35B" + $"BD350A03B46542B4BE41B4BE420605AF03B6AFC969B63CC9F1B72FC8D0BE4155" + $"B821CA8DC11CC6FAC42DC5C5C55FC53ABE67C91DC1E8C7EAB86DCB260604EEBF" + $"CBBB51C1FCBBD0C13EBC43C29FBB6EC18BBAAB43BB1EC145BAF2C09ABB4B0A04" + $"30303050505050302C0A0001021240BAB100000000000040B755C6CCDBBE9979" + $"01178300040A0101020240BAB100000000000040B755C6CCDBBE99790A020103" + $"0240BAB100000000000040B755C6CCDBBE99790A030A05060708090A0C0D040B" + $"0240BAB100000000000040B755C6CCDBBE99790A110113124084473AE65BBB05" + $"39406A8F40BD7AC6ED3001178400040A00012712401CCA0000000000004031D6" + $"BEA7B4C5651401178100040A150112024046733A7FB6BABB05401508437714C3" + $"BB840A3B012E0A401CC92E6813AE6813401CC9C0B293C4BE831DFF0A11011412" + $"402E52374883B74883402E5243A84DC5C35901178200040A16011502402E5237" + $"4883B74883402E5243A84DC5C3590A17011602402E52374883B74883402E5243" + $"A84DC5C3590A18011702402E52374883B74883402E5243A84DC5C3590A170118" + $"02402E52374883B74883402E5243A84DC5C3590A1801190240268F36C1F1B73C" + $"D33FA9DD442903C369B00A1B011A02402E52374883B74883402E5243A84DC5C3" + $"590A2C011B02402E52374883B74883402E5243A84DC5C3590A11011C12402E52" + $"374883B74883402E5243A84DC5C35901178100040A20011D124018A13C2DD3BC" + $"6F843F776243040C3B35B701178400040A28011D024018A13C481BBC6F843FA1" + $"3143AD0CC180CE0A27011E024018A13C3669BC6F843F850B43AD0CBDA6830A26" + $"03212022023F94B53C057BBC14913F373546DE4E423FFC0A2B012202401CCA00" + $"0000000000401CCAC64FB846E7CF0A2B01230241774E3E9634BD97FB40685AC6" + $"A141CA33220A0001291240075E0000000000004029CCC0DC88C59D5C01178100" + $"040A2E0124123E3A7739EBE1BA96D53D1E7BC874E948577D01178400040A3601" + $"24023DE4F539818BBA43313CC9E6C7EFC848861D0A350125023DE4F539818BBA" + $"43313CC9E6C7EFC848861D0A340126023DE4F539D28CBA43313D0A55C7EFC848" + $"5E9A0A000128123FEA4E3675EFB6F2733F44E3440366C2D26601178200040A00" + $"012A12402E52374883B74883402E5241C554C5CE0401178100040A00012B1240" + $"1CCA000000000000401CCAC0623FC4B46E01178100040A00012C124031960000" + $"00000000401CCAC3AEA8C4B46E01178100040A3A012D02401CCA000000000000" + $"401CCAC0E971C4B46E0A3C012F0A401CCA000000000000401CCAC0E971C4B46E" + $"1DFF0A3B01300A3FEC520000000000003C6A0B41051D473FEE1DFF0A3E013102" + $"40FA05000000000000417C4D3E5061C9E26E0A3F013212401CCA000000000000" + $"401CCAC0E971C42D3C01178200040A4001330A401CCA000000000000401CCAC0" + $"E971C4B46E1DFF0A420134023600000000000000003600004890004AE8000A42" + $"0134023600000000000000003600004870004AE8000A43013402360000000000" + $"0000003600004850004AF8000A43013402360000000000000000360000487000" + $"4AF8000A430134023600000000000000003600004890004AF8000A4401340236" + $"0000000000000000360000485000466000" }; resource(201, "kActionBack") #'VICN' array { From 1220bcc0af8ede85c24be8c80157861313fb0f6e Mon Sep 17 00:00:00 2001 From: leavengood Date: Thu, 30 Dec 2010 06:34:45 +0000 Subject: [PATCH 326/349] Add a setting to show or hide the Home button. I find it pretty useless myself. While I was able to add this fairly easily by cutting and pasting, it was still quite a bit of work. Seems like there should be a less-verbose way of doing this. But it did work the first time I tested, so I can't complain too much. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@566 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 8 ++++++++ src/apps/webpositive/SettingsKeys.cpp | 1 + src/apps/webpositive/SettingsKeys.h | 1 + src/apps/webpositive/SettingsWindow.cpp | 15 +++++++++++++++ src/apps/webpositive/SettingsWindow.h | 1 + 5 files changed, 26 insertions(+) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index fd2b2f49da..5a4de8c5d7 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -387,6 +387,8 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, fHomeButton = new IconButton("Home", 0, NULL, new BMessage(HOME)); fHomeButton->SetIcon(206); fHomeButton->TrimIcon(); + if (!fAppSettings->GetValue(kSettingsKeyShowHomeButton, true)) + fHomeButton->Hide(); // URL input group fURLInputGroup = new URLInputGroup(new BMessage(GOTO_URL)); @@ -929,6 +931,12 @@ BrowserWindow::MessageReceived(BMessage* message) } else if (name == kSettingsKeyAutoHideInterfaceInFullscreenMode && message->FindBool("value", &flag) == B_OK) { _SetAutoHideInterfaceInFullscreen(flag); + } else if (name == kSettingsKeyShowHomeButton + && message->FindBool("value", &flag) == B_OK) { + if (flag) + fHomeButton->Show(); + else + fHomeButton->Hide(); } break; } diff --git a/src/apps/webpositive/SettingsKeys.cpp b/src/apps/webpositive/SettingsKeys.cpp index 5bd2f32cb9..10208c8aff 100644 --- a/src/apps/webpositive/SettingsKeys.cpp +++ b/src/apps/webpositive/SettingsKeys.cpp @@ -33,6 +33,7 @@ const char* kSettingsKeyShowTabsIfSinglePageOpen const char* kSettingsKeyAutoHideInterfaceInFullscreenMode = "auto hide interface in full screen mode"; const char* kSettingsKeyAutoHidePointer = "auto hide pointer"; +const char* kSettingsKeyShowHomeButton = "show home button"; const char* kSettingsKeyNewWindowPolicy = "new window policy"; const char* kSettingsKeyNewTabPolicy = "new tab policy"; diff --git a/src/apps/webpositive/SettingsKeys.h b/src/apps/webpositive/SettingsKeys.h index 8f2b96de35..1a95bbfe89 100644 --- a/src/apps/webpositive/SettingsKeys.h +++ b/src/apps/webpositive/SettingsKeys.h @@ -34,6 +34,7 @@ extern const char* kSettingsKeyDownloadPath; extern const char* kSettingsKeyShowTabsIfSinglePageOpen; extern const char* kSettingsKeyAutoHideInterfaceInFullscreenMode; extern const char* kSettingsKeyAutoHidePointer; +extern const char* kSettingsKeyShowHomeButton; extern const char* kSettingsKeyNewWindowPolicy; extern const char* kSettingsKeyNewTabPolicy; diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 743b03570a..8b17a19f88 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -73,6 +73,7 @@ enum { MSG_TAB_DISPLAY_BEHAVIOR_CHANGED = 'tdbc', MSG_AUTO_HIDE_INTERFACE_BEHAVIOR_CHANGED = 'ahic', MSG_AUTO_HIDE_POINTER_BEHAVIOR_CHANGED = 'ahpc', + MSG_SHOW_HOME_BUTTON_CHANGED = 'shbc', MSG_STANDARD_FONT_CHANGED = 'stfc', MSG_SERIF_FONT_CHANGED = 'sefc', @@ -203,6 +204,7 @@ SettingsWindow::MessageReceived(BMessage* message) case MSG_TAB_DISPLAY_BEHAVIOR_CHANGED: case MSG_AUTO_HIDE_INTERFACE_BEHAVIOR_CHANGED: case MSG_AUTO_HIDE_POINTER_BEHAVIOR_CHANGED: + case MSG_SHOW_HOME_BUTTON_CHANGED: case MSG_STANDARD_FONT_CHANGED: case MSG_SERIF_FONT_CHANGED: case MSG_SANS_SERIF_FONT_CHANGED: @@ -338,6 +340,11 @@ SettingsWindow::_CreateGeneralPage(float spacing) new BMessage(MSG_AUTO_HIDE_POINTER_BEHAVIOR_CHANGED)); fAutoHidePointer->SetValue(B_CONTROL_OFF); + fShowHomeButton = new BCheckBox("show home button", + B_TRANSLATE("Show Home Button"), + new BMessage(MSG_SHOW_HOME_BUTTON_CHANGED)); + fShowHomeButton->SetValue(B_CONTROL_ON); + BView* view = BGroupLayoutBuilder(B_VERTICAL, spacing / 2) .Add(BGridLayoutBuilder(spacing / 2, spacing / 2) .Add(fStartPageControl->CreateLabelLayoutItem(), 0, 0) @@ -361,6 +368,7 @@ SettingsWindow::_CreateGeneralPage(float spacing) .Add(fShowTabsIfOnlyOnePage) .Add(fAutoHideInterfaceInFullscreenMode) .Add(fAutoHidePointer) + .Add(fShowHomeButton) .Add(fDaysInHistoryMenuControl) .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing)) @@ -547,6 +555,9 @@ SettingsWindow::_CanApplySettings() const (fAutoHidePointer->Value() == B_CONTROL_ON) != fSettings->GetValue(kSettingsKeyAutoHidePointer, false)); + canApply = canApply || ((fShowHomeButton->Value() == B_CONTROL_ON) + != fSettings->GetValue(kSettingsKeyShowHomeButton, true)); + canApply = canApply || (_MaxHistoryAge() != BrowsingHistory::DefaultInstance()->MaxHistoryItemAge()); @@ -612,6 +623,8 @@ SettingsWindow::_ApplySettings() fAutoHideInterfaceInFullscreenMode->Value() == B_CONTROL_ON); fSettings->SetValue(kSettingsKeyAutoHidePointer, fAutoHidePointer->Value() == B_CONTROL_ON); + fSettings->SetValue(kSettingsKeyShowHomeButton, + fShowHomeButton->Value() == B_CONTROL_ON); // New page policies fSettings->SetValue(kSettingsKeyNewWindowPolicy, _NewWindowPolicy()); @@ -679,6 +692,8 @@ SettingsWindow::_RevertSettings() false)); fAutoHidePointer->SetValue( fSettings->GetValue(kSettingsKeyAutoHidePointer, false)); + fShowHomeButton->SetValue( + fSettings->GetValue(kSettingsKeyShowHomeButton, true)); BString text; text << BrowsingHistory::DefaultInstance()->MaxHistoryItemAge(); diff --git a/src/apps/webpositive/SettingsWindow.h b/src/apps/webpositive/SettingsWindow.h index 9648860bff..251d84405a 100644 --- a/src/apps/webpositive/SettingsWindow.h +++ b/src/apps/webpositive/SettingsWindow.h @@ -98,6 +98,7 @@ private: BCheckBox* fShowTabsIfOnlyOnePage; BCheckBox* fAutoHideInterfaceInFullscreenMode; BCheckBox* fAutoHidePointer; + BCheckBox* fShowHomeButton; FontSelectionView* fStandardFontView; FontSelectionView* fSerifFontView; From 1af1ea854634d4b2c84bf0bc170a63b58a6269b5 Mon Sep 17 00:00:00 2001 From: leavengood Date: Wed, 5 Jan 2011 06:18:01 +0000 Subject: [PATCH 327/349] Implement #35: Add a tab menu. Still needs icons but this works for now. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@569 94f232f2-1747-11df-bad5-a5bfde151594 --- .../webpositive/tabview/TabContainerView.cpp | 4 + src/apps/webpositive/tabview/TabManager.cpp | 79 ++++++++++++++++++- 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/tabview/TabContainerView.cpp b/src/apps/webpositive/tabview/TabContainerView.cpp index d5269fd699..52217fa9c7 100644 --- a/src/apps/webpositive/tabview/TabContainerView.cpp +++ b/src/apps/webpositive/tabview/TabContainerView.cpp @@ -330,6 +330,10 @@ TabContainerView::SelectTab(TabView* tab) if (fSelectedTab != NULL) index = GroupLayout()->IndexOfItem(tab->LayoutItem()); + if (!tab->LayoutItem()->IsVisible()) { + SetFirstVisibleTabIndex(index); + } + fController->TabSelected(index); } } diff --git a/src/apps/webpositive/tabview/TabManager.cpp b/src/apps/webpositive/tabview/TabManager.cpp index 3f364b652c..dc3fbb0251 100644 --- a/src/apps/webpositive/tabview/TabManager.cpp +++ b/src/apps/webpositive/tabview/TabManager.cpp @@ -38,6 +38,9 @@ #include #include #include +#include +#include +#include #include #include @@ -184,12 +187,34 @@ public: be_control_look->DrawArrowShape(this, frame, updateRect, base, BControlLook::B_DOWN_ARROW, 0, B_DARKEN_4_TINT); } + + virtual void MouseDown(BPoint point) + { + if (!IsEnabled()) + return; + + // Invoke must be called before setting B_CONTROL_ON + // for the button to stay "down" + Invoke(); + SetValue(B_CONTROL_ON); + } + + virtual void MouseUp(BPoint point) + { + // Do nothing + } + + void MenuClosed() + { + SetValue(B_CONTROL_OFF); + } }; enum { MSG_SCROLL_TABS_LEFT = 'stlt', - MSG_SCROLL_TABS_RIGHT = 'strt' + MSG_SCROLL_TABS_RIGHT = 'strt', + MSG_OPEN_TAB_MENU = 'otmn' }; @@ -200,7 +225,8 @@ public: BGroupView(B_HORIZONTAL, 0.0), fTabContainerView(tabContainerView), fScrollLeftTabButton(NULL), - fScrollRightTabButton(NULL) + fScrollRightTabButton(NULL), + fTabMenuButton(NULL) { } @@ -210,6 +236,8 @@ public: fScrollLeftTabButton->SetTarget(this); if (fScrollRightTabButton != NULL) fScrollRightTabButton->SetTarget(this); + if (fTabMenuButton != NULL) + fTabMenuButton->SetTarget(this); } virtual void MessageReceived(BMessage* message) @@ -223,6 +251,43 @@ public: fTabContainerView->SetFirstVisibleTabIndex( fTabContainerView->FirstVisibleTabIndex() + 1); break; + case MSG_OPEN_TAB_MENU: + { + BPopUpMenu* tabMenu = new BPopUpMenu("tab menu", true, false); + int tabCount = fTabContainerView->GetLayout()->CountItems(); + for (int i = 0; i < tabCount; i++) { + TabView* tab = fTabContainerView->TabAt(i); + if (tab) { + BMenuItem* item = new BMenuItem(tab->Label(), NULL); + tabMenu->AddItem(item); + if (tab->IsFront()) + item->SetMarked(true); + } + } + + // Force layout to get the final menu size + tabMenu->InvalidateLayout(); + BRect buttonFrame = fTabMenuButton->Frame(); + BRect menuFrame = tabMenu->Frame(); + BPoint openPoint = ConvertToScreen(buttonFrame.LeftBottom()); + // Open with the right side of the menu aligned with the right + // side of the button and a little below. + openPoint.x -= menuFrame.Width() - buttonFrame.Width(); + openPoint.y += 2; + + BMenuItem *selected = tabMenu->Go(openPoint, false, false, + ConvertToScreen(buttonFrame)); + if (selected) { + selected->SetMarked(true); + int32 index = tabMenu->IndexOf(selected); + if (index != B_ERROR) + fTabContainerView->SelectTab(index); + } + fTabMenuButton->MenuClosed(); + delete tabMenu; + + break; + } default: BGroupView::MessageReceived(message); break; @@ -241,6 +306,12 @@ public: GroupLayout()->AddView(button, 0.0f); } + void AddTabMenuButton(TabMenuTabButton* button) + { + fTabMenuButton = button; + GroupLayout()->AddView(button, 0.0f); + } + void EnableScrollButtons(bool canScrollLeft, bool canScrollRight) { fScrollLeftTabButton->SetEnabled(canScrollLeft); @@ -256,6 +327,7 @@ private: TabContainerView* fTabContainerView; TabButton* fScrollLeftTabButton; TabButton* fScrollRightTabButton; + TabMenuTabButton* fTabMenuButton; }; @@ -669,7 +741,8 @@ TabManager::TabManager(const BMessenger& target, BMessage* newTabMessage) NewTabButton* newTabButton = new NewTabButton(newTabMessage); newTabButton->SetTarget(be_app); fTabContainerGroup->GroupLayout()->AddView(newTabButton, 0.0f); -// fTabContainerGroup->GroupLayout()->AddView(new TabMenuTabButton(NULL), 0.0f); + fTabContainerGroup->AddTabMenuButton(new TabMenuTabButton( + new BMessage(MSG_OPEN_TAB_MENU))); } From 255cade7a020c9a71e4fd48579eb4d3f53d8e842 Mon Sep 17 00:00:00 2001 From: leavengood Date: Fri, 7 Jan 2011 21:07:08 +0000 Subject: [PATCH 328/349] Use the loader page in the settings directory which handles the case when no welcome page is installed (such as nightlies.) To do: not hard-coding the settings directory. Fixes Haiku bug #6869. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@572 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/SettingsKeys.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/webpositive/SettingsKeys.cpp b/src/apps/webpositive/SettingsKeys.cpp index 10208c8aff..b72166cd3a 100644 --- a/src/apps/webpositive/SettingsKeys.cpp +++ b/src/apps/webpositive/SettingsKeys.cpp @@ -43,7 +43,7 @@ const char* kSettingsKeySearchPageURL = "search page url"; const char* kDefaultDownloadPath = "/boot/home/Desktop/"; const char* kDefaultStartPageURL - = "file:///boot/system/documentation/welcome/welcome_en.html"; + = "file:///boot/home/config/settings/WebPositive/LoaderPages/Welcome"; const char* kDefaultSearchPageURL = "http://www.google.com"; const char* kSettingsKeyUseProxy = "use http proxy"; From 552778e90ca6fb2df4728cb2fe4d5279039980c3 Mon Sep 17 00:00:00 2001 From: leavengood Date: Fri, 7 Jan 2011 21:42:19 +0000 Subject: [PATCH 329/349] Align the tabs menu by using AttachedToWindow. Somewhat of a hack and I swear InvalidateLayout worked before, but it does not seem to now. Also use a const for an empty BString instead of returning a local for the tab label. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@573 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/tabview/TabManager.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/tabview/TabManager.cpp b/src/apps/webpositive/tabview/TabManager.cpp index dc3fbb0251..f25b67769d 100644 --- a/src/apps/webpositive/tabview/TabManager.cpp +++ b/src/apps/webpositive/tabview/TabManager.cpp @@ -48,6 +48,9 @@ #include "TabView.h" +const static BString kEmptyString; + + // #pragma mark - Helper classes @@ -265,8 +268,9 @@ public: } } - // Force layout to get the final menu size - tabMenu->InvalidateLayout(); + // Force layout to get the final menu size. InvalidateLayout() + // did not seem to work here. + tabMenu->AttachedToWindow(); BRect buttonFrame = fTabMenuButton->Frame(); BRect menuFrame = tabMenu->Frame(); BPoint openPoint = ConvertToScreen(buttonFrame.LeftBottom()); @@ -911,7 +915,7 @@ TabManager::TabLabel(int32 tabIndex) if (tab) return tab->Label(); else - return ""; + return kEmptyString; } void From 1ef6069fe4a9b07fd312bda1b70b796b09b4f762 Mon Sep 17 00:00:00 2001 From: phoudoin Date: Wed, 2 Mar 2011 18:15:57 +0000 Subject: [PATCH 330/349] Fix why escape wasn't closing the find panel as expected (#75). Fix fullscreen icon layout spacing issue (#76). git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@576 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 5a4de8c5d7..23e7973ee1 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -466,11 +466,11 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, new BMessage(TOGGLE_FULLSCREEN)); toggleFullscreenButton->SetBackgroundMode(BitmapButton::MENUBAR_BACKGROUND); - BGroupLayout* menuBarGroup = BLayoutBuilder::Group<>(B_HORIZONTAL) + BGroupLayout* menuBarGroup = BLayoutBuilder::Group<>(B_HORIZONTAL, 0.0) .Add(mainMenu) .Add(toggleFullscreenButton, 0.0f) ; - + // Layout AddChild(BLayoutBuilder::Group<>(B_VERTICAL, 0.0) #if !INTEGRATE_MENU_INTO_TAB_BAR @@ -488,7 +488,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings, mainMenu->SetViewColor(B_TRANSPARENT_COLOR); fURLInputGroup->MakeFocus(true); - + fMenuGroup = menuBarGroup; fTabGroup = fTabManager->TabGroup()->GetLayout(); fNavigationGroup = navigationGroup; @@ -547,13 +547,6 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) } else if (bytes[0] == B_RIGHT_ARROW && modifierKeys == B_COMMAND_KEY) { PostMessage(GO_FORWARD); return; - } else if (bytes[0] == B_ESCAPE) { - // Let the URL input handle escape when it is the target - if (target != fURLInputGroup->TextView()) { - // Otherwise do a stop - PostMessage(STOP); - return; - } } else if (bytes[0] == B_FUNCTION_KEY) { // Some function key Firefox compatibility int32 key; @@ -591,6 +584,10 @@ BrowserWindow::DispatchMessage(BMessage* message, BHandler* target) _InvokeButtonVisibly(fFindCloseButton); return; } + } else if (bytes[0] == B_ESCAPE) { + // Default escape key behavior: + PostMessage(STOP); + return; } } if (message->what == B_MOUSE_MOVED || message->what == B_MOUSE_DOWN From 56b050f337f5cebf1fdd1a87047a0146c9c5a1a2 Mon Sep 17 00:00:00 2001 From: phoudoin Date: Thu, 10 Mar 2011 18:00:40 +0000 Subject: [PATCH 331/349] * Don't trust anymore provided MIME type (if any): use instead the registrar's type guessing feature, which we can (and should) trust way more. * Notify back the download objet when it's file location has changed. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@577 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/DownloadProgressView.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/apps/webpositive/DownloadProgressView.cpp b/src/apps/webpositive/DownloadProgressView.cpp index 7048e1d56a..7031e429c3 100644 --- a/src/apps/webpositive/DownloadProgressView.cpp +++ b/src/apps/webpositive/DownloadProgressView.cpp @@ -451,6 +451,7 @@ DownloadProgressView::MessageReceived(BMessage* message) BEntry entry(&ref); if (entry.GetPath(&fPath) != B_OK) break; + // Find out if the directory is the Trash for this // volume char trashPath[B_PATH_NAME_LENGTH]; @@ -474,6 +475,10 @@ DownloadProgressView::MessageReceived(BMessage* message) } } + // Inform download of the new path + if (fDownload) + fDownload->HasMovedTo(fPath); + float value = fStatusBar->CurrentValue(); fStatusBar->Reset(name); fStatusBar->SetTo(value); From c17922668baabee266ee2df0c10ecb2297355d6f Mon Sep 17 00:00:00 2001 From: leavengood Date: Wed, 1 Jun 2011 20:06:11 +0000 Subject: [PATCH 332/349] Don't do the "smart URL handling" (also known as dumb URL handling) for file:// URLs. Fixes #7596. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@579 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 23e7973ee1..c0ed3abed9 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -2130,8 +2130,12 @@ BString BrowserWindow::_SmartURLHandler(const BString& url) const { BString result = url; - if (url.FindFirst(".") == B_ERROR || url.FindFirst(" ") != B_ERROR) - result.Prepend("http://www.google.com/search?q="); + + // Only process if the URL is not for a local file + if (url.FindFirst("file://") == B_ERROR) { + if (url.FindFirst(".") == B_ERROR || url.FindFirst(" ") != B_ERROR) + result.Prepend("http://www.google.com/search?q="); + } return result; } From ae5b937ac2472a0d84c63a4ed5173cc2fae7ca13 Mon Sep 17 00:00:00 2001 From: leavengood Date: Wed, 1 Jun 2011 21:43:31 +0000 Subject: [PATCH 333/349] Make the check for URLs more generic before doing a search. Thanks for the suggestion mmlr. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@580 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/BrowserWindow.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index c0ed3abed9..c0d5ce63ef 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -2131,8 +2131,9 @@ BrowserWindow::_SmartURLHandler(const BString& url) const { BString result = url; - // Only process if the URL is not for a local file - if (url.FindFirst("file://") == B_ERROR) { + // Only process if this doesn't look like a full URL (http:// or + // file://, etc.) + if (url.FindFirst("://") == B_ERROR) { if (url.FindFirst(".") == B_ERROR || url.FindFirst(" ") != B_ERROR) result.Prepend("http://www.google.com/search?q="); } From 6c086bdf6a4b39ff2300cb52ab6eff83d89c19af Mon Sep 17 00:00:00 2001 From: anevilyak Date: Sat, 31 Mar 2012 02:19:48 +0000 Subject: [PATCH 334/349] Don't try to filter any of these keys if modifiers are pressed. Fixes Web+ eating things like the workspace switching shortcuts if the URL input group happened to have focus. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@585 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/autocompletion/TextViewCompleter.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp index cdde7ffc66..bed5ef0dd5 100644 --- a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp +++ b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp @@ -104,8 +104,9 @@ TextViewCompleter::Filter(BMessage* message, BHandler** target) { const char* bytes; int32 modifiers; - if (!target || message->FindString("bytes", &bytes) != B_OK - || message->FindInt32("modifiers", &modifiers) != B_OK) { + if ((!target || message->FindString("bytes", &bytes) != B_OK + || message->FindInt32("modifiers", &modifiers) != B_OK) + || modifiers != 0) { return B_DISPATCH_MESSAGE; } From b4bab54a16381816e0f534b3d073a043aa74e13a Mon Sep 17 00:00:00 2001 From: anevilyak Date: Sat, 31 Mar 2012 18:17:01 +0000 Subject: [PATCH 335/349] Be more specific about how we check the modifiers mask. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@586 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/autocompletion/TextViewCompleter.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp index bed5ef0dd5..48f7bcb4da 100644 --- a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp +++ b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp @@ -106,7 +106,8 @@ TextViewCompleter::Filter(BMessage* message, BHandler** target) int32 modifiers; if ((!target || message->FindString("bytes", &bytes) != B_OK || message->FindInt32("modifiers", &modifiers) != B_OK) - || modifiers != 0) { + || (modifiers & (B_CONTROL_KEY | B_COMMAND_KEY | B_OPTION_KEY + | B_SHIFT_KEY)) != 0) { return B_DISPATCH_MESSAGE; } From a79446f47116535b146eaa022c4b6de4e01bb3ad Mon Sep 17 00:00:00 2001 From: aldeck Date: Tue, 1 May 2012 21:34:23 +0000 Subject: [PATCH 336/349] * B_TRANSLATE_CONTEXT is now B_TRANSLATION_CONTEXT as per the recent change in Haiku, cf. hrev44041 git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@587 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/SettingsWindow.cpp | 4 ++-- src/apps/webpositive/support/FontSelectionView.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 8b17a19f88..5a5ee41873 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -56,8 +56,8 @@ #include "WebSettings.h" -#undef B_TRANSLATE_CONTEXT -#define B_TRANSLATE_CONTEXT "Settings Window" +#undef B_TRANSLATION_CONTEXT +#define B_TRANSLATION_CONTEXT "Settings Window" enum { MSG_APPLY = 'aply', diff --git a/src/apps/webpositive/support/FontSelectionView.cpp b/src/apps/webpositive/support/FontSelectionView.cpp index 81ce76bcb0..d0df01baa1 100644 --- a/src/apps/webpositive/support/FontSelectionView.cpp +++ b/src/apps/webpositive/support/FontSelectionView.cpp @@ -26,8 +26,8 @@ #include -#undef B_TRANSLATE_CONTEXT -#define B_TRANSLATE_CONTEXT "Font Selection view" +#undef B_TRANSLATION_CONTEXT +#define B_TRANSLATION_CONTEXT "Font Selection view" static const float kMinSize = 8.0; From 1ef59aee8ebaf0870fd60e4e66a60c116d2fb5a0 Mon Sep 17 00:00:00 2001 From: Alexandre Deckner Date: Tue, 3 Jul 2012 21:12:20 +0200 Subject: [PATCH 337/349] Add Jamfile for WebPositive --- src/apps/Jamfile | 1 + src/apps/webpositive/Jamfile | 65 ++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 src/apps/webpositive/Jamfile diff --git a/src/apps/Jamfile b/src/apps/Jamfile index 0d7b2f7519..13783d4521 100644 --- a/src/apps/Jamfile +++ b/src/apps/Jamfile @@ -60,4 +60,5 @@ HaikuSubInclude text_search ; HaikuSubInclude tracker ; HaikuSubInclude tv ; HaikuSubInclude webwatch ; +HaikuSubInclude webpositive ; HaikuSubInclude workspaces ; diff --git a/src/apps/webpositive/Jamfile b/src/apps/webpositive/Jamfile new file mode 100644 index 0000000000..60febdd8d9 --- /dev/null +++ b/src/apps/webpositive/Jamfile @@ -0,0 +1,65 @@ +SubDir HAIKU_TOP src apps webpositive ; + +UseLibraryHeaders webkit ; + +SubDirC++Flags $(defines) -Wno-error=sequence-point ; +SubDirCcFlags $(defines) -Wno-error=sequence-point ; + +# source directories +local sourceDirs = + autocompletion + support + tabview +; + +local sourceDir ; +for sourceDir in $(sourceDirs) { + SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src apps webpositive $(sourceDir) ] ; +} + +# SVN revision +#local svnRevisionFile = [ FGristFiles svn_revision ] ; +#MakeLocate $(svnRevisionFile) : $(LOCATE_TARGET) ; +#CreateSVNRevisionFile $(svnRevisionFile) ; + +Application WebPositive : + # autocompletion + AutoCompleter.cpp + AutoCompleterDefaultImpl.cpp + TextViewCompleter.cpp + + # support + BaseURL.cpp + BitmapButton.cpp + DateTime.cpp + FontSelectionView.cpp + IconButton.cpp + SettingsMessage.cpp + StringForSize.cpp + + # tabview + TabContainerView.cpp + TabManager.cpp + TabView.cpp + + AuthenticationPanel.cpp + BrowserApp.cpp + BrowserWindow.cpp + BrowsingHistory.cpp + CredentialsStorage.cpp + DownloadProgressView.cpp + DownloadWindow.cpp + SettingsKeys.cpp + SettingsWindow.cpp + svn_revision.cpp + URLInputGroup.cpp + : + # webkit libs + javascriptcore webcore webkit wtf + # dependencies + curl icuuc icudata png sqlite3 xml2 z + # haiku + be bsd localestub network stdc++ tracker translation + : + WebPositive.rdef +; From 2ee4319d112fb910c9c90b7b0baec5e3828f0da0 Mon Sep 17 00:00:00 2001 From: Alexandre Deckner Date: Tue, 3 Jul 2012 21:26:13 +0200 Subject: [PATCH 338/349] Remove unneeded includes --- src/apps/webpositive/BrowserApp.cpp | 1 - src/apps/webpositive/BrowserWindow.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/src/apps/webpositive/BrowserApp.cpp b/src/apps/webpositive/BrowserApp.cpp index 1504638ae7..71e2177e42 100644 --- a/src/apps/webpositive/BrowserApp.cpp +++ b/src/apps/webpositive/BrowserApp.cpp @@ -26,7 +26,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" #include "BrowserApp.h" #include "BrowserWindow.h" diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index c0d5ce63ef..4987ea7f40 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -30,7 +30,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" #include "BrowserWindow.h" #include "AuthenticationPanel.h" From 7f21f81f4f3f268e34011a6f3a9f94022da93f65 Mon Sep 17 00:00:00 2001 From: Alexandre Deckner Date: Tue, 3 Jul 2012 21:31:18 +0200 Subject: [PATCH 339/349] Apply old patch by AnevilYak, fix BMenuField border drawing --- src/apps/webpositive/SettingsWindow.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 5a5ee41873..66639f24b0 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -396,13 +396,13 @@ SettingsWindow::_CreateFontsPage(float spacing) fStandardSizesMenu = new BMenuField("standard font size", B_TRANSLATE("Default standard font size:"), new BPopUpMenu("sizes"), - NULL); + B_WILL_DRAW); _BuildSizesMenu(fStandardSizesMenu->Menu(), MSG_STANDARD_FONT_SIZE_SELECTED); fFixedSizesMenu = new BMenuField("fixed font size", B_TRANSLATE("Default fixed font size:"), new BPopUpMenu("sizes"), - NULL); + B_WILL_DRAW); _BuildSizesMenu(fFixedSizesMenu->Menu(), MSG_FIXED_FONT_SIZE_SELECTED); BView* view = BGridLayoutBuilder(spacing / 2, spacing / 2) @@ -435,6 +435,7 @@ SettingsWindow::_CreateFontsPage(float spacing) .View() ; + view->SetName(B_TRANSLATE("Fonts")); return view; } @@ -469,7 +470,7 @@ SettingsWindow::_CreateProxyPage(float spacing) .Add(BGridLayoutBuilder(spacing / 2, spacing / 2) .Add(fProxyAddressControl->CreateLabelLayoutItem(), 0, 0) .Add(fProxyAddressControl->CreateTextViewLayoutItem(), 1, 0) - + .Add(fProxyPortControl->CreateLabelLayoutItem(), 0, 1) .Add(fProxyPortControl->CreateTextViewLayoutItem(), 1, 1) ) From 08cada49a6f90a03657efa9fc3cba9110c9993fc Mon Sep 17 00:00:00 2001 From: Alexandre Deckner Date: Tue, 3 Jul 2012 21:43:53 +0200 Subject: [PATCH 340/349] Apply old patch by AnevilYak, fix BMenuField border drawing Should have been part of the previous commit, sorry --- .../webpositive/support/FontSelectionView.cpp | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/apps/webpositive/support/FontSelectionView.cpp b/src/apps/webpositive/support/FontSelectionView.cpp index d0df01baa1..be1adcbd5f 100644 --- a/src/apps/webpositive/support/FontSelectionView.cpp +++ b/src/apps/webpositive/support/FontSelectionView.cpp @@ -6,7 +6,7 @@ * Mark Hogben * DarkWyrm * Axel Dörfler, axeld@pinc-software.de - * Philippe Saint-Pierre, stpere@gmail.com + * Philippe Saint-Pierre, stpere@gmail.com * Stephan Aßmus */ @@ -59,14 +59,14 @@ FontSelectionView::FontSelectionView(const char* name, const char* label, fFontsMenu = new BPopUpMenu("font menu"); // font menu - fFontsMenuField = new BMenuField("fonts", label, fFontsMenu, NULL); + fFontsMenuField = new BMenuField("fonts", label, fFontsMenu, B_WILL_DRAW); fFontsMenuField->SetFont(be_bold_font); // styles menu, if desired if (separateStyles) { fStylesMenu = new BPopUpMenu("styles menu"); - fStylesMenuField = new BMenuField("styles", B_TRANSLATE("Style:"), - fStylesMenu, NULL); + fStylesMenuField = new BMenuField("styles", B_TRANSLATE("Style:"), + fStylesMenu, B_WILL_DRAW); } else { fStylesMenu = NULL; fStylesMenuField = NULL; @@ -74,17 +74,17 @@ FontSelectionView::FontSelectionView(const char* name, const char* label, // size menu fSizesMenuField = new BMenuField("size", B_TRANSLATE("Size:"), fSizesMenu, - NULL); + B_WILL_DRAW); fSizesMenuField->SetAlignment(B_ALIGN_RIGHT); // preview fPreviewText = new BStringView("preview text", B_TRANSLATE_COMMENT("The quick brown fox jumps over the lazy dog.", "Don't translate this literally ! Use a phrase showing all " - "chars from A to Z.")); + "chars from A to Z.")); fPreviewText->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, - B_SIZE_UNLIMITED)); + B_SIZE_UNLIMITED)); fPreviewText->SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 1.65)); fPreviewText->SetAlignment(B_ALIGN_RIGHT); @@ -351,35 +351,35 @@ FontSelectionView::UpdateFontsMenu() // #pragma mark - private -BLayoutItem* +BLayoutItem* FontSelectionView::CreateSizesLabelLayoutItem() { return fSizesMenuField->CreateLabelLayoutItem(); } -BLayoutItem* +BLayoutItem* FontSelectionView::CreateSizesMenuBarLayoutItem() { return fSizesMenuField->CreateMenuBarLayoutItem(); } -BLayoutItem* +BLayoutItem* FontSelectionView::CreateFontsLabelLayoutItem() { return fFontsMenuField->CreateLabelLayoutItem(); } -BLayoutItem* +BLayoutItem* FontSelectionView::CreateFontsMenuBarLayoutItem() { return fFontsMenuField->CreateMenuBarLayoutItem(); } -BLayoutItem* +BLayoutItem* FontSelectionView::CreateStylesLabelLayoutItem() { if (fStylesMenuField) @@ -388,7 +388,7 @@ FontSelectionView::CreateStylesLabelLayoutItem() } -BLayoutItem* +BLayoutItem* FontSelectionView::CreateStylesMenuBarLayoutItem() { if (fStylesMenuField) @@ -484,7 +484,7 @@ FontSelectionView::_BuildSizesMenu() BMessage* message = new BMessage(kMsgSetSize); message->AddInt32("size", size); - message->AddString("name", Name()); + message->AddString("name", Name()); BMenuItem* item = new BMenuItem(label, message); if (size == fCurrentFont.Size()) From 79adea96897d45291ef5f98c07edac01007866fb Mon Sep 17 00:00:00 2001 From: Alexandre Deckner Date: Tue, 3 Jul 2012 21:45:58 +0200 Subject: [PATCH 341/349] Fix src/apps/Jamfile alphabetical order Thanks augiedoggie --- src/apps/Jamfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/Jamfile b/src/apps/Jamfile index 13783d4521..cd66b3e6c1 100644 --- a/src/apps/Jamfile +++ b/src/apps/Jamfile @@ -59,6 +59,6 @@ HaikuSubInclude terminal ; HaikuSubInclude text_search ; HaikuSubInclude tracker ; HaikuSubInclude tv ; -HaikuSubInclude webwatch ; HaikuSubInclude webpositive ; +HaikuSubInclude webwatch ; HaikuSubInclude workspaces ; From c4ba387bf8a43bca900c26e8af454a3df40b74c2 Mon Sep 17 00:00:00 2001 From: Alexandre Deckner Date: Wed, 4 Jul 2012 00:58:25 +0200 Subject: [PATCH 342/349] Adapt WebPositive build to make use of a webkit optional build package --- build/jam/OptionalBuildFeatures | 35 +++++++++++++++++++++++++++++++++ src/apps/webpositive/Jamfile | 26 +++++++++++++++--------- 2 files changed, 52 insertions(+), 9 deletions(-) diff --git a/build/jam/OptionalBuildFeatures b/build/jam/OptionalBuildFeatures index 8cdc51972b..509e87f5d7 100644 --- a/build/jam/OptionalBuildFeatures +++ b/build/jam/OptionalBuildFeatures @@ -419,3 +419,38 @@ if $(HAIKU_BUILD_FEATURE_TAGLIB) { } } + +# WebKit +local webkitBaseURL = http://dude.uzzl.net/haiku ; +if $(TARGET_ARCH) = x86 { + if $(HAIKU_GCC_VERSION[1]) >= 4 { + HAIKU_WEBKIT_FILE = webkit-0.1.1-x86-gcc4-2012-07-03.zip ; + } else { + Echo "WebKit support not available on gcc $(HAIKU_GCC_VERSION[1])" ; + } + + local zipFile = [ DownloadFile $(HAIKU_WEBKIT_FILE) + : $(webkitBaseURL)/$(HAIKU_WEBKIT_FILE) ] ; + + HAIKU_WEBKIT_DIR = [ FDirName $(HAIKU_OPTIONAL_BUILD_PACKAGES_DIR) + $(HAIKU_WEBKIT_FILE:B) ] ; + + echo $(HAIKU_WEBKIT_DIR) ; + + HAIKU_WEBKIT_HEADERS_DEPENDENCY = [ ExtractArchive $(HAIKU_WEBKIT_DIR) + : include/ : $(zipFile) : extracted-webkit ] ; + + HAIKU_WEBKIT_LIBS = [ ExtractArchive $(HAIKU_WEBKIT_DIR) + : + lib/libwtf.so + lib/libjavascriptcore.so + lib/libwebcore.so + lib/libwebkit.so + : $(zipFile) + : extracted-webkit + ] ; + + HAIKU_WEBKIT_HEADERS = [ FDirName $(HAIKU_WEBKIT_DIR) include ] ; +} else { + Echo "WebKit support not available on $(TARGET_ARCH)" ; +} diff --git a/src/apps/webpositive/Jamfile b/src/apps/webpositive/Jamfile index 60febdd8d9..c1cb3b00a1 100644 --- a/src/apps/webpositive/Jamfile +++ b/src/apps/webpositive/Jamfile @@ -1,6 +1,6 @@ SubDir HAIKU_TOP src apps webpositive ; -UseLibraryHeaders webkit ; +SubDirSysHdrs $(HAIKU_WEBKIT_HEADERS) ; SubDirC++Flags $(defines) -Wno-error=sequence-point ; SubDirCcFlags $(defines) -Wno-error=sequence-point ; @@ -17,12 +17,7 @@ for sourceDir in $(sourceDirs) { SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src apps webpositive $(sourceDir) ] ; } -# SVN revision -#local svnRevisionFile = [ FGristFiles svn_revision ] ; -#MakeLocate $(svnRevisionFile) : $(LOCATE_TARGET) ; -#CreateSVNRevisionFile $(svnRevisionFile) ; - -Application WebPositive : +local sources = # autocompletion AutoCompleter.cpp AutoCompleterDefaultImpl.cpp @@ -53,9 +48,22 @@ Application WebPositive : SettingsWindow.cpp svn_revision.cpp URLInputGroup.cpp +; + + +Includes [ FGristFiles $(sources) ] : $(HAIKU_WEBKIT_HEADERS_DEPENDENCY) ; + # Dependency needed to trigger downloading/unzipping the package before + # compiling the files. + +# SVN revision +#local svnRevisionFile = [ FGristFiles svn_revision ] ; +#MakeLocate $(svnRevisionFile) : $(LOCATE_TARGET) ; +#CreateSVNRevisionFile $(svnRevisionFile) ; + +Application WebPositive : + $(sources) : - # webkit libs - javascriptcore webcore webkit wtf + $(HAIKU_WEBKIT_LIBS) # dependencies curl icuuc icudata png sqlite3 xml2 z # haiku From 36aac7c55f78fdd6aae2dff8759150dd6d34dea6 Mon Sep 17 00:00:00 2001 From: Alexandre Deckner Date: Wed, 4 Jul 2012 01:15:26 +0200 Subject: [PATCH 343/349] Fix typo --- build/jam/FileRules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/jam/FileRules b/build/jam/FileRules index 2a5b896000..86fbe8b2c6 100644 --- a/build/jam/FileRules +++ b/build/jam/FileRules @@ -199,7 +199,7 @@ rule ExtractArchive directory : entries : archiveFile : grist # and combo. # # - The directory into which to extract the archive file. The - # directory is created is by this rule and it is the target + # directory is created by this rule and it is the target # that the extract action is associated with. # - The entries of the archive file one is interested in. The # rule always extracts the complete archive file, from the From 40c493ce343abb484c96f84e3ce7ca867b153bf6 Mon Sep 17 00:00:00 2001 From: Alexandre Deckner Date: Wed, 4 Jul 2012 01:18:37 +0200 Subject: [PATCH 344/349] Hardcode kSVNRevision = 0 until i adapt version tracking --- src/apps/webpositive/svn_revision.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/webpositive/svn_revision.cpp b/src/apps/webpositive/svn_revision.cpp index 489c64cdd4..9e415b5262 100644 --- a/src/apps/webpositive/svn_revision.cpp +++ b/src/apps/webpositive/svn_revision.cpp @@ -5,6 +5,6 @@ #include "svn_revision.h" -const int32 kSVNRevision = - #include "svn_revision" +const int32 kSVNRevision = 0; +// #include "svn_revision" ; From 69914905f5fb21097ba8856a119d821f9b6e0693 Mon Sep 17 00:00:00 2001 From: Alexandre Deckner Date: Wed, 4 Jul 2012 01:21:57 +0200 Subject: [PATCH 345/349] Remove left-over echo --- build/jam/OptionalBuildFeatures | 2 -- 1 file changed, 2 deletions(-) diff --git a/build/jam/OptionalBuildFeatures b/build/jam/OptionalBuildFeatures index 509e87f5d7..1650242892 100644 --- a/build/jam/OptionalBuildFeatures +++ b/build/jam/OptionalBuildFeatures @@ -435,8 +435,6 @@ if $(TARGET_ARCH) = x86 { HAIKU_WEBKIT_DIR = [ FDirName $(HAIKU_OPTIONAL_BUILD_PACKAGES_DIR) $(HAIKU_WEBKIT_FILE:B) ] ; - echo $(HAIKU_WEBKIT_DIR) ; - HAIKU_WEBKIT_HEADERS_DEPENDENCY = [ ExtractArchive $(HAIKU_WEBKIT_DIR) : include/ : $(zipFile) : extracted-webkit ] ; From 8ae2b062a6a39fdbcb41fc6c2f75d30460b5f336 Mon Sep 17 00:00:00 2001 From: Alexandre Deckner Date: Wed, 4 Jul 2012 01:49:32 +0200 Subject: [PATCH 346/349] Fix control flow, stop if gcc < 4. Change package URL --- build/jam/OptionalBuildFeatures | 42 ++++++++++++++++----------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/build/jam/OptionalBuildFeatures b/build/jam/OptionalBuildFeatures index 1650242892..c29c74feed 100644 --- a/build/jam/OptionalBuildFeatures +++ b/build/jam/OptionalBuildFeatures @@ -421,34 +421,34 @@ if $(HAIKU_BUILD_FEATURE_TAGLIB) { # WebKit -local webkitBaseURL = http://dude.uzzl.net/haiku ; +local webkitBaseURL = http://haiku-files.org/files/optional-packages ; if $(TARGET_ARCH) = x86 { - if $(HAIKU_GCC_VERSION[1]) >= 4 { - HAIKU_WEBKIT_FILE = webkit-0.1.1-x86-gcc4-2012-07-03.zip ; - } else { + if $(HAIKU_GCC_VERSION[1]) < 4 { Echo "WebKit support not available on gcc $(HAIKU_GCC_VERSION[1])" ; - } + } else { + HAIKU_WEBKIT_FILE = webkit-0.1.1-x86-gcc4-2012-07-03.zip ; - local zipFile = [ DownloadFile $(HAIKU_WEBKIT_FILE) - : $(webkitBaseURL)/$(HAIKU_WEBKIT_FILE) ] ; + local zipFile = [ DownloadFile $(HAIKU_WEBKIT_FILE) + : $(webkitBaseURL)/$(HAIKU_WEBKIT_FILE) ] ; - HAIKU_WEBKIT_DIR = [ FDirName $(HAIKU_OPTIONAL_BUILD_PACKAGES_DIR) - $(HAIKU_WEBKIT_FILE:B) ] ; + HAIKU_WEBKIT_DIR = [ FDirName $(HAIKU_OPTIONAL_BUILD_PACKAGES_DIR) + $(HAIKU_WEBKIT_FILE:B) ] ; - HAIKU_WEBKIT_HEADERS_DEPENDENCY = [ ExtractArchive $(HAIKU_WEBKIT_DIR) - : include/ : $(zipFile) : extracted-webkit ] ; + HAIKU_WEBKIT_HEADERS_DEPENDENCY = [ ExtractArchive $(HAIKU_WEBKIT_DIR) + : include/ : $(zipFile) : extracted-webkit ] ; - HAIKU_WEBKIT_LIBS = [ ExtractArchive $(HAIKU_WEBKIT_DIR) - : - lib/libwtf.so - lib/libjavascriptcore.so - lib/libwebcore.so - lib/libwebkit.so - : $(zipFile) - : extracted-webkit - ] ; + HAIKU_WEBKIT_LIBS = [ ExtractArchive $(HAIKU_WEBKIT_DIR) + : + lib/libwtf.so + lib/libjavascriptcore.so + lib/libwebcore.so + lib/libwebkit.so + : $(zipFile) + : extracted-webkit + ] ; - HAIKU_WEBKIT_HEADERS = [ FDirName $(HAIKU_WEBKIT_DIR) include ] ; + HAIKU_WEBKIT_HEADERS = [ FDirName $(HAIKU_WEBKIT_DIR) include ] ; + } } else { Echo "WebKit support not available on $(TARGET_ARCH)" ; } From d061a7009519756006ab8b2430d17883765b43af Mon Sep 17 00:00:00 2001 From: Alexandre Deckner Date: Wed, 4 Jul 2012 02:57:38 +0200 Subject: [PATCH 347/349] Fix WebPositive jamfile, cross building works --- src/apps/webpositive/Jamfile | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/apps/webpositive/Jamfile b/src/apps/webpositive/Jamfile index c1cb3b00a1..c13bb56bf9 100644 --- a/src/apps/webpositive/Jamfile +++ b/src/apps/webpositive/Jamfile @@ -64,10 +64,8 @@ Application WebPositive : $(sources) : $(HAIKU_WEBKIT_LIBS) - # dependencies - curl icuuc icudata png sqlite3 xml2 z - # haiku - be bsd localestub network stdc++ tracker translation + $(TARGET_LIBSTDC++) $(HAIKU_LOCALE_LIBS) + be network tracker translation : WebPositive.rdef ; From 851c719d021e7f867be9f6dd97da23ce881b86ff Mon Sep 17 00:00:00 2001 From: Humdinger Date: Wed, 4 Jul 2012 08:42:38 +0200 Subject: [PATCH 348/349] Small text changes in alert when renaming/moving special folders. Since the button was renamed from "Do it!" to the specific action, an additional explanation in case of special user folders isn't needed any more. Split text into paragraphs for better readability. --- src/kits/tracker/FSUtils.cpp | 23 ++++++++++------------- src/kits/tracker/OpenWithWindow.cpp | 4 ++-- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/kits/tracker/FSUtils.cpp b/src/kits/tracker/FSUtils.cpp index ac2c1580e7..fb4e9d2fd0 100644 --- a/src/kits/tracker/FSUtils.cpp +++ b/src/kits/tracker/FSUtils.cpp @@ -634,20 +634,20 @@ ConfirmChangeIfWellKnownDirectory(const BEntry *entry, if (DirectoryMatchesOrContains(entry, B_SYSTEM_DIRECTORY)) { warning.SetTo( B_TRANSLATE("If you %ifYouDoAction the system folder or its " - "contents, you won't be able to boot %osName! Are you sure you " - "want to do this? To %toDoAction the system folder or its " + "contents, you won't be able to boot %osName!\n\nAre you sure you " + "want to do this?\n\nTo %toDoAction the system folder or its " "contents anyway, hold down the Shift key and click " "\"%toConfirmAction\".")); } else if (DirectoryMatches(entry, B_COMMON_DIRECTORY)) { warning.SetTo( B_TRANSLATE("If you %ifYouDoAction the common folder, %osName " - "may not behave properly! Are you sure you want to do this? " + "may not behave properly!\n\nAre you sure you want to do this?\n\n" "To %toDoAction the common folder anyway, hold down the " "Shift key and click \"%toConfirmAction\".")); } else if (DirectoryMatches(entry, B_USER_DIRECTORY)) { warning .SetTo( B_TRANSLATE("If you %ifYouDoAction the home folder, %osName " - "may not behave properly! Are you sure you want to do this? " + "may not behave properly!\n\nAre you sure you want to do this?\n\n" "To %toDoAction the home folder anyway, hold down the " "Shift key and click \"%toConfirmAction\".")); } else if (DirectoryMatchesOrContains(entry, B_USER_CONFIG_DIRECTORY) @@ -659,24 +659,21 @@ ConfirmChangeIfWellKnownDirectory(const BEntry *entry, B_COMMON_SETTINGS_DIRECTORY)) { warning.SetTo( B_TRANSLATE("If you %ifYouDoAction the mime settings, " - "%osName may not behave properly! Are you sure you want to " - "do this? To %toDoAction the mime settings anyway, click " - "\"%toConfirmAction\".")); + "%osName may not behave properly!\n\nAre you sure you want to " + "do this?")); requireOverride = false; } else if (DirectoryMatches(entry, B_USER_CONFIG_DIRECTORY)) { warning.SetTo( B_TRANSLATE("If you %ifYouDoAction the config folder, %osName " - "may not behave properly! Are you sure you want to do this? " - "To %toDoAction the config folder anyway, click " - "\"%toConfirmAction\".")); + "may not behave properly!\n\nAre you sure you want to do " + "this?")); requireOverride = false; } else if (DirectoryMatches(entry, B_USER_SETTINGS_DIRECTORY) || DirectoryMatches(entry, B_COMMON_SETTINGS_DIRECTORY)) { warning.SetTo( B_TRANSLATE("If you %ifYouDoAction the settings folder, " - "%osName may not behave properly! Are you sure you want to " - "do this? To %toDoAction the settings folder anyway, click " - "\"%toConfirmAction\".")); + "%osName may not behave properly!\n\nAre you sure you want to " + "do this?")); requireOverride = false; } } diff --git a/src/kits/tracker/OpenWithWindow.cpp b/src/kits/tracker/OpenWithWindow.cpp index 464a1eeb47..9b9b8ac478 100644 --- a/src/kits/tracker/OpenWithWindow.cpp +++ b/src/kits/tracker/OpenWithWindow.cpp @@ -681,8 +681,8 @@ OpenWithPoseView::OpenSelection(BPose *pose, int32 *) if (!fIterator->GenericFilesOnly()) { BString warning(B_TRANSLATE( "The application \"%appname\" does not support the type of " - "document you are about to open. Are you sure you want to " - "proceed? If you know that the application supports the " + "document you are about to open.\nAre you sure you want to " + "proceed?\n\nIf you know that the application supports the " "document type, you should contact the publisher of the " "application and ask them to update their application to list " "the type of your document as supported.")); From eb971526498ad040cc8eb4b03ad439afb20d8f35 Mon Sep 17 00:00:00 2001 From: Matt Madia Date: Wed, 4 Jul 2012 20:37:22 -0400 Subject: [PATCH 349/349] Updated CARootCertificates. --- build/jam/OptionalPackages | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/jam/OptionalPackages b/build/jam/OptionalPackages index c1639dfb28..926469fda5 100644 --- a/build/jam/OptionalPackages +++ b/build/jam/OptionalPackages @@ -359,8 +359,8 @@ if [ IsOptionalHaikuImagePackageAdded Bzip ] { # CARootCertificates if [ IsOptionalHaikuImagePackageAdded CARootCertificates ] { - InstallOptionalHaikuImagePackage cert-2012-05-02.zip - : $(baseURL)/cert-2012-05-02.zip + InstallOptionalHaikuImagePackage cert-2012-07-04.zip + : $(baseURL)/cert-2012-07-04.zip : common data ssl ; }

    Px}iy!MU}$5 zk=Eacftz@rPf)kafihthhXH{WBex)hek9nEXqX|)f5gI0VJ<8Z<|5=4QCC_n%*E&~ zq3$;HZ;ue>zmm~gM#}z;;j%d3eK}Ds$M9VO5WE`)e2LtyK;u9z>(2MOfC3SmAp6DWT;4K~pKl`+DsB+^F^c%(*{ zD`R1qFdvPFQejr5Lz^%;I5k(LLX$8bC)mg9g}EBJC(v6%2G-(eZL2V!juhrINy4l~ z@7YFSKDR}f&(9EM4K1$OF3cASV5czGl>op0GHdgNS%-l-oYfJ)i#T`*<1e)f^W{0f z=lWPcvA#~2>$8OU3dUZ+*=qutg}IRcIqWhy+%h-g{6ENSNrt_`d;>dgVV@%=^X+0` zzJts=_8n2nw^VZJwCnC~Oh)F8|cbA`Dr4iNqb!H-bjExtluA?hV5H zrbd{1b_ny^Mq#!P#CIjoEX?n5#zBYqBg#MR73R+<{=8P0t&vawb;8`21k0dRn7`x+ zvyJb+VS~RZnf?sn5W9uLSSB213~Uh&SD|o(MG8kabptYl$1$)#IM{bPB6bMJAPNUn z0ZIoYL91{a%;(5_SOMFGV{j~F!CK*niW80@VNfX?(K*5~6dS|QAK?J(#->1p`2V)< zIKHXs3gGymo-5DyvRP*xaRw+QU@R?0tr9e7(IN#?sZd${taEJZwxU(ptg|0im!cIa z1gKI;U{NX*i5RtNU8?J}V$p1i+HIY5(#^V6=v-Bt{YcTO`|fcwa?_$S2$<1|QPI34j*8AK0b^c4x9IFOqCW6j z5S=q5TG$}!4~bqx+`Kl?`K-CPQ}mL0(I8_B$a`6-XmLXHa!d4z3UC1>E);`YC1Dnp zjEnNaK^OT!!bNqU>qP`#=@wng+~OY5(pFJ!IO>uX(WM=tS8*N^tN~4jMn%hrEhBkZ z4VW*Z@v;%os~NwVaceej=NX7lH}Yc z(#k>6>uB~nMWR)#`EI4?^~8TKBf6?W^!vG@KX9Q<^oP}=)ul*_{-{&*$Bg}?9tre| z)(8sN|C%b%)ts#Mp&S%lO_3XN!TAl1Xv3K3jU>FW4#aRLL~D!Ci~-S`ykPF8wCK$q zw20oq{4Ejmi>@gEk3X#y{aFsiL~m_j|LeL%Z{y_W1m3P_LJw%7-j512pcP5sv-40X zdIt^OF(UelA<>3x6oa)5y`py#bLT3=L36+KVhv6lpD@Z(F9_3Vm?Gg2YCsbwUK3%O z3KJNf5N&iL2og3j-^hF;^Nq|mGQXDjwal+&el7EB6UgAG=v^KZqZTnRe%BCKcQ@<8 zceC*BN;H7P{IJlwxvC}?XsoFUjYwiZ^d83V@gW4R=$<%wFe42HmXvzz^I4st*P%?)S+0nIdUuM0GAFAMK&L=rT>PcGd+!VMu%XhR${ zuwhhmBMoe1d?Vu<8Q(|)8z)2~#7D>zp@B#S&5Unu zMmJcn#e;H0(1AhG77IbtAdWuK`&fTp0JY$P?j!F0Y=l6*`!g8Agy_~V9d9MU)=D&h z1zQQ&O2Jka{HOvAwkAP?4>10K4LZ~VEe|sq!kN|;u2;4*9o_ZuPB>IR4<%l3H zy4M8??5za__OdR)xyTEx53wlW0Lz0(R_tJ>y ze&$}bP$AmOdTu)D0h&2Lo>yq@72;p@fP!h_(lyA4{;mML|JUEOb1*9U`y$k%Tl5bE z{-GQMWPsY=6J#Up%Nr z5@VuomV)>H`eqDt{U(bKa#aUe#M>=BNaBM-q60Yyp$S~=z_93Fvk?Rd|JsUPkdzxt z`W6km#qps6kmnHj4>5m;CI@+D2CL91`Zq%f9LUSlD^%5i0F`j4u@Kh5q-x3 zG4GJ*AI$xu5*+{2k2unx=r9F`heh9I{$29C+Xm(i7lEVVb&fAvj0aaI3V$n zCXna|ogJaz5t1C45FN=u0ZLGXI*@pz9o^{1sOY~G9uy&jYBZn~N%Ue6W1{c5;6;%A zf3JdrS~MY!PGm5Q3DJM&pa3PPLLDM#M>qO0Dmtq0pa>yUqXDf*q8Ec06Mf$WFM{m< z`vkvVg<7!S1D?_khA|=fVGa_aM+0ChK4R`85`ILI{}iJceWD+`!Q98C=ocL$C-0DT zEF$^|Yd>ihJ*Hs(7-PqdijK35^Mywr@(Q>kN06*^wV6B zexlbuUHDVYMWBX7F&K)lw zLF16jm5mzVV}?P3uaoFh3S~EnIc=4gZ}`QW?iQ27;+$eIoT!ot??l?M;!7wJooSB0Hl%NWAh@c(a=*Os- zZz((|LI~ApK&zOuX#Okl^Z%Zf|avo*B}O-N!u z%rpVdBikwZ6vun|cZcxLQjR2_OZ?nNtcHE)WDk!9tD;Syvbb=W~gl+a>1Q26Tw=)4ZQX{C#51W9~eT z&(A@a&MvSJ5mUrt5fc{{fTk`S6~kXH%|*;zL?iQh#RNj&cs|AE4~n^%*o()+T*CP! z!(zBWX@V3DX2dM;p$7G6MhppbA&mj{pMRNT7L1Fz)Pfs61W<}f)Sw>Ch#`S4q%nXI zjElLrP>M>_pdQVLA%QNW!3P4F%SJdD7gKD(4Ict1MI~xbk7mS>Ko`;&zzD|0 zEVST;4*`^-5;dqtGh#@f3u*BCKeKQI<6&<7&u(3P%gwpx&%MB(dh5{SPv)QaB(6W5VU3<1mZ#+z+ijm|e~S+oNJ+1KmUPOq za=`Y;U9w-++f(gn_H=p7&b4RQdG<`(YtOQ0%PaQTw$DDt&bQ~-1$Lo5S6+}8?Q?Cv zeV%>3eSuwMUua)s&y#LDV9&QNwlA@R_5%A-`!c)OUT9x#UtyQni|i}y=z@If_AEIT z?aa6Gq67KX@+^r&^XFKzQ_JUAb(3l(=4@~_IuS`Yo1D$g7N^Cz&$-{(>a@xZ=K($i z_d{o!6Ln(Fc4vq4D<>{{oClqUoSkyN)8;(v>~eNH?am(O5ofQHa2|E`Igd%)Nji@^ zPdHCH9nMqE)6O$ar}M1yYbO=;7g}!H>2(e`uQ;#D-sti|YpzSSIBz>c&O6d74@8>_ zt^AXnW6rp9JoQ4M<1urFK+V zxo4*K-)1d5Idyu2HJFw9@|V_PE46aHbu25oX@k|CTDZ~Ll$AQX$=W?BwS9~ASk& zjeZtF2_a@&1ky1fVQA`zM}w~sLVKXrBQd^TLe|{jf8ah7a5iyZ`j8{r&n+W__a`Lz zNaB!TeFA>XTSQ3eRYLUI^daF9n=d{T2pM@B?`MoH$}4$2e1n0IZ1iWkHg-m-&ugzA z3M6Do8}wH=p=6?^=uZB_(}a{P#S5z^=1ngl68@2?c!_8y7S5iKb>Z?o+)A0njZe@doIFa7a+ z?JA<=_Ym?)ddal$B^zGh+7jibkHIo6-eLSBXD)_qVdWR=O+L>`_C${cpRgLjktD)% zhY01~;XVa+hC2h?I-f4IXbBZ{qKiw2fjkR33$2sHNvZRsCS^|b@fivys6#=e7E`o;2)|_0RKpR1^89< zRp8$m|4pdzE919>GhQ=Z1OA=yJHi{Un>2))v?eX#OgfV%a4(Y=;Z5EqZ{R-QmnU!X zHUC7Y`KI|k;myA~IuYvV?C4B*M;FJo)&BeBMwWfRKeDgg&6Znt%ZkPcp6X#g##lGfoVAmvZvY0OxpkS-*a#FJ#J-r#NhOA%mbd}v!vs7+|Zq#I}1O07PU zo6y)`J8A7A1xBzMbmzoea+kTQ+%@hy?gsZgcayuv{leYn{^ogJ zp>(lkOF`9dN#i*FNAWwWK|R8k3C~xSND!EGlZ2UXn{ShFb1fLwk+I6UN*&|MT6xQ@ z0%TT(%1n$QU94-IhFQZk$EddYuEw7#sggh?sK3?U)Yr0+@q=?^SGrHe_siD_>`MNW z>!HPHBiC?qZ5MxH=^F4n6GZ_6sOo@^r9$xgC|93V$PQ7l=5tH5DF(C+f}7Q1rC*p+<9 zyW=`tt~oE)tYb7Z@&hM!j^pYX> z(vbwBrVA#^6D7=#Bc5Cna&fJauipt~+`udZiJj0P({pd*ch!Q)l}09tc^J72w!>Xq zDlR1+;xcg=!IA|Ht(FSx%1m*VI9r?}&aED39!-ObnJD;0vS@fQQ5=PCMx!$qbg-Pb z$>U))iN)1d9s5wMK&yvyA|=)Z?FMT3T7Cvz{tXltStE4Q!ng>o3m419bIII5Oe&ij z!%gCfxl(Qpw~$-Lt>HFso4Fm_E^aS(h&yV%;MT2rp-ULGu5aT_&sx{J#90rt@s~s8;!k>l@k- zNEgE|hWn(C;djFW5^tzC)RP3m6T?%IXq;`FNBSEV8`qFj<2vIel4;y*+)Q$fZy0xx zJmWs&elp&8z<8KUbZqO`mJ~8Z!|?gY=0}ZD4bjjV6(h-hC1Xe$8s&oxN@5~yh!@BU zAstCH=>g%LQ$UdXKxwK~>*nUg_m>6|Dy)!J;uR%11?n%6U#SD_0IChv2)7`bZ_RQ` z?_6)R8aEo>G5^NK=dLPUo{tY(#hi5WRkv1C3$yt-(bBoqwQiN%K=nQK19iQ+LBna3 z8okC*a(M-}5Yf3e9Gz&G$G;1^)G@CU$G`lo= zHHS1uH6Lg`(R{A?N^{YA$kW~Wk*AhH^+%o=RPtiO(+{i$Z%@@ZhI2y*sSfep!6(xr zw!ye>ZXvh3!Hg`OBVTK6CxK_l*AUxm;APCn(z7;jiB7b^fpG82Z-rN%Zfl|f{ZG?v z>qWmVYPz3wOfT66Th;!r54s{ZvJdu|Ou|ul;6ZZz7P)OZhLbrm{=0lV%&z1QcIB8o zqSPk8TL;BH;on3PtS15jEKH+%lREtC3p4sB^y~@#^`knfBMGvmCDK835J{p#=}^+2 z=FvQoObclt89-;y86<_yrE^Itt*4Jk8YgmEGKkZ2MPvk@z$cLR_!K^c9OqZ?E6Dr& zR(>n_fWOE8LOv7}fXd?C$| z7L%`~Wzs5gRaz@q$qiZcZ^^2ETiK){EMy8f;u(w9pR5MaDHW9II+O?atN{?Qh&`JWNwf6{f>9 z!*tekmQFT(Y5J1po2gk%3(UWnf2U=R3P*{~bTl{`=xny;I69}gjT85xwXry!F@+K8 zq$OIeudqT`D{K_D3Kc@7uwOVV91~6mr-ie^IpMN!UAQUS6@C*Q2~R{KDnu=OOdG^u z{$hyO5f-_J*hfqf)5M`-mY6F}fN`4!o45dWbCtMW+$3%ncZz$&1L6_!xOh@LBYr7f z5U+}s@5S5VJ@J89FE%JRg;JqcI4ax}K8ip^s3JnqMG>orS0pP2Dl!z=iZO~wieg2n zVvb^=Vwqx%VuNC{VuxavVz1(m;;7;S#V3l-6<;YXDy}JhRMaZ&EB;VCR@fv#QcDKO zS@MwDO6{aDDN5=l#YqWLiZoctv`9J9I4NH$k!DEqq{Y$-h<&59RjQCGrTx-j>6mmv zIxU@*&PkW0>(Wi>uJoJqNP40qN`+FZG%4FCy_EjS5M@VYw6ce?k1|P_rW~rwQsycr zC<~R-l(UozluMPXly-^E zPNh`oRgNk*m5(Y=6{?C*by3Bt;#JA2fvOBuwrY%OlB!r$s+yx(s9L64quQX_tlFX4 zrP`}Hq&lklK=q00bJbU>i>hm?A62!g`>H=wk5x9cpjN95YG<{Fx~;mMIt;OGH+7sk zL7k!=Y*A;bbJXM1`RWq&4D~$qVg$Qu)f?4Yq2`t9{ZQ>=>J#eI>a$Sb%j)auo9esj z-_(!PPc%fM&}cO#O&g7u#$OYn>8Od;^w9LtBx%w#Lp52NT+IYcp=O$9mS%xwsb-aC zy=IeUyJn|mkLG~ph~~KFq~?s~OO54%=Bnm<&27y+%>zxnra{YTm0G>lQR}Al(FSTm zwGrAb+E{J8Hd#ARo1x9tj?qri7HdnjbF>S!%d~5>8?>9XJG8sBd$otON3|blKhb`! z{YraLdrkYJwpM#z`-k?i)}|A5YMnvntn<*d)wR=w>7sPqbaA=_U5cY_ur5=VqZ_Bo z*OlmI=;rAb>sDAFw0E+c)t%E_)?L@#)ZNwnrhBA&q9=NVUaL3h+vvUYf%;H=guaVD zRv)iV)(_NY=(F|X^!fS{{S5s){bKzJ{aXD-{Z@U2zEZzme^`G^e?os+e^!4^e_4NB ze^Y-~|C|1i{)q!|P&jBEOb%@vyd3-;LL53eL_73w=;M%NaY%C*>X7A->oCEg&|#Xx zEQbXSOC44@tasStu-##&!ybnN4o4i0JDhYl&@rGo>KtqNh+c3s3$xv)4HOw(AHmoqLHEc9&HB=ZX4f_p; z4aW>845tm2FAWzAR}J4AZX50y9>CK#7&)WTs5d$q-HblQKx3#e!q~+aYm7H08wVOQ zjM>I9#!1FvW2teDaiMXUagA{UB7hynU9eS$j7N#`^AMq1%A6>);)j83=l(&iBSm(vWs(C8+ zfDx*X#YnWnPjWN+5HjujzvSVv-Di%npX?|TWJj4u+tGG#k-cdjxX2{hAI@3+JOfNKABvB zHyuoF@I(2bXkV;1jnL;Mb6-EjpX&&?9bd0cCSWU+X8w4vI zFH{LtbRryAHJv29E4)kdg&LuT7BEjw3*qT!(qj1dC3Gh9@pO^&vSg*pq;jd8zRWy5 zU8^)I+gRv2=IUuVbML7k+4QzC$CyJcKg-U) zR(AgPWaochcK(mCoOW;uV})@SCmG)|9_F+x1mK)m2*3ri5P%C|ApqCj{HytQt}_b( zxGs)rM>W^YQRk@Vy0dVA>*;86bmC&=pr8)|V2zxCA>41=f3Pk8%Q~-zrxV*d2g`fs zaCz?>&GydK2YPg+w4wTLPpii7i3)pHHK*o?J3Nd)Jk$!c0=QDGB%a2Z#+gK0y`%rX zY2-`Fmq=UXa^-SdS1MQH`j_%A;wQiAujbV}36Nj)SHn}20OQxjbJiUL=4zgxg@7kY z<4mi6N+4%EVogbj2sM6*SQF7Z5sXKS#|SYVH=ZD(@ucxIQ5(+~&k|&e5PgC!?t*o1 z%E%4}iVLRr(Bo4k<`vO1)5?mc(F>&$iYLlKwYB-Mu`3{J;2YRG^gz=y~+g!QUG zzasV|YN8Qs7GW{wC$rH(X z`MOEIZlAamTCMs6s9-@bF4e+z;gOgk?n0nARIy3% zy%Z=FqZNjhHZ_-9?LDh$L8`jdmou!UNj$<3EFI#Ezs5Di_!X}G0ScluUXbh0vwFOZdOW4j z2_DPT8L2BwP)>#`F;O*)h%@nES!Ll*;}u*V8ZYDei}4b!OwR-(vd;_)BfRhnc56)K z7|$7jg7G2-7!Hh*48ZgHZ>(uqLE|Iwv@OeqVq5YiFiAeD~vkkZx6O6t zd*+*t&gNgtcg*+Acdge(23p_)edUeu-{epFH}i&$8b>WU(t+!#pC+C8R!om2Dd*^@Lv!rF~_AJFkxxV%eIEYU)e%bQx#irWbGEbPm zpUH(C6Cm@+cok@^$c{vk`eJrWB2yInXE+C*GAtA&thpkE2nrvp=%uKX$WlC6z}3OA z|H=Kur}IPjOg@VrgNSVbzlvYOzhNCZYKm&U=S!X+d4A#b)cWNpU+-}~Q+?L@Z1;KB z=RKeEK39CM`~2jq^6l?Cz&FkJCEt}+b&iML@2UrV<@D-0Gt?5+ zCM+NwpRU#)Vk@~&!M)vIbi)sU*;RTHb0RIROgrK;(7*ZNPN zDxSJn_vD0Izs)I>$=K$3+KX7zM*Df@`;_{u_o?tX=5x;Hvd?!Qg7|7=A_jtpHKS!B z+WO}Pkid$-lOW>I=-yptgM_vq;bdieWlH71%Au8GDpyr*tWs9FSGBF`Sd~zfR+UjT zu4-Y`%BuBMPktvLfjl)o^|XfOwzsToTHds*>7}OJrktjXra^y6^=Ilotv^-&N&U(C z=AFHpaKU#mJzPkQ!{h|7U^#|(r*YACF_tEzcuRZ+s;njy%9$tQU>ESmIFFZW^ z@Qa6^Km6$7`wtI4T>5bFL$3#q?@hT^e6R3c!M*%@Irp;fjl4JXUax!I?}_(lT~l3S z-P5|iEp?CU{;I35`%m4Ub$`@7toyz0x4Qdvztr8U`?>B`-Oaim>TcA1R(GoIWZegK zJL+Dm+g`V|ZcE*!y7hId>Q>Y(t6N$ZTi30wOI>)KU!CV&+udL8-n)DE?!mj$@7%a^ z?anuM-n~J^%K+o40R%ck`Q5ee!MjPx2q<*XQ5QKcD}v z{1N%X@`vQ7=l9P~%`W zRpCE1Q&9Hb57zjx?^^$MZ`yd-Z+BnWd|_< z*aY0t4+yAsI*1$A_hc+z{X?Axe=DZ{Xfegs8xB?=}EXsB%H+1Hfcexc5#1K$lc~A%AbM%6m9& z`lE#MFi;`&?mf~DDsaUcR5MWFY`}XoU_Nk&#d{&(2=M7Bj{-oHY7fdYfNy};pu7zD z4)~`iZvcJ={x6h&03KOz1D1Q&18l&-au7;;qQ$OvR#2M+y1)tOX8YebxiE z1D}Sn0`M+y^yP!Sna_K`UqyKia2|L$N)X|51^5<}AjStutKNpv!UhE3oSpb$U|%Q= zPTOJk0pN%lv+*5Z2lXA4X?9TGMG4ONzJxY)C|BA+1OEGhI6osH8qCBGBJgv?R}?!@ zdH^tpb{9&2Ks(4^yBA1%KqwwS3H`uIzcS$Opqyg|Em-UamNU>|rhd!qpaskQHrhc8 zR{LQ_eh1J7T=4q}@HOx+QQoqHmeu`i2Q8lYVFSc2LfM0<3NBMw|c9tgGV9;Pt8Z5zLjYg>kXnC*4`Tc$N4vtnS0nWg|(JFTUCSe4Js@j6eDooD^wp4Wl^a9T6 zFksaH;OkJL<0{P5h|a2@6IE>BZ79b9z<%RvC>H`C9^)G*R|3`o-;HuT;1%HeP=cFP zO~BtKUKw7)+HY6J#K!eJGOw5QAwy%E5pF;MIg)#xCn}ci{N6;mTFOPx9Af^Z|B953IoP z@y`Q{@!$aPDJb6oV5OKB5DR_qF>b!b%^H;F0Y3oWM(CpsfH2^DQR4dv05N0WN1bIL z=C=tFxc~#|51_>Mq23Yr36#z<5HtF&ZzBUSe}WQUApnT^6iN?(7Zl8V8i)@7EHZzF z5?@CFi1}YA5x><#Kg?gE1VI2|MpB_3GpmmT4ub1JP<9fY6HFtSWI3b<fG5VH7QEYHEV+3&m0a)Qs5#$$aaD`l4s`wXN!>NjcBz zZ?~#1meQWp-?R!_o^a-$H*9rwL#H8ZFaiw_R!XeXcJg4g){gA)&F7CfcbS$@`SH)z zT={M8Zp+);`|{iN$Fu2FhxpDudTVkHvSA>0D)?D_u z_Jzl68urJxt?Re3zN+_ZGf~E!xpFTB=%uaP3w(mio!0eiBKG>)7uqu}*z0dL*Oy}A z-^=~--t_77*?A;@k?by4g<#*wh@NRcohA^P{T^K~X zn{2gJ#GiK+ulOMTUO`22^{Fm z*^9fMtTXnWV3pDP(DF|8_I)WxqtsdN?GNM3zf`-uU5wjX)>Q}CQ|p5Rpz@a0?I0f3 zT9XgTm4^;uz&lpMA-TJDhdy9b)E<(lNO%XuFV@O;WHPje<@b6V4s(POY8n5Uu3$4^ zkO~b!=y$>4s0d6uhfc)V~w&G z6Q>Hb;DZDl)LzoOtt-pdRhIHS*W+G(_>;^`}X#6 z&)Ppm``Z7}{?QBVpZEVr?%z7~oG&9~<2k6$ALOzu)&U^JNAVD|f&YN|{84@V+)=O` zT6RI!vL&*X!CVTHWF<_qPuhC@LJ4b?_RU&Ir26}B6nN=pYwg7-NAoT59GwC3(6_k0 znYCe;WYH&F0yl11XIzTn%=fMP+1*|1bynQBYA?%oJy>zyT4=x9Zom7|e%D~X3%w$@ z%x1-X>l*p4`hzRSWV&T-yi>jQ+tqx)K#27ovsjQG?46w^{z0=;5qzLN-Wq!&p7CYr zjj%E1zi<%A+F@Ao-t5vfK;iiJ)#}HO z#b7Fx+kEL?o!d1`Kp258ZJotnQlLmONZi(j)2t4kv3@4DZ`y>f&3M+YetU1t;7Aj!#xxZvZvRg)2OdfFz_GHbOp4h+%1FdU@sicpvANcybWG3DR=}cU^v7gc9IGp_@9MIa{Yd}9)W=H8Pj0C zM((bzCO4BV;9zTNe$1lRU7<-eCrar$o+gy1&7$5kvAlQ|_2L}8%h%4L&M0dtXVEgQ zlgT$i6apmwpunI&>B+!qx^x1*;X}mcVq5cBeb%S@MM_iVmeOS|*;6I9YpO|_OS3sQ zM<4sRI0I(BF%kB(016Z6=v#AQJ{@dil$h4h3;|Os&$rSvRFof=%bVrujTE|mv%Fh# znZFUVGlO-fruw6o&6+`4jp6m-3KJ_WG<%bR+6(9&Dm|y+vkLo_Go0 zn?h||Vj`)FUywxoR0uz5Bu|65opTC*ud}UqW#Op3bmq?oW4R<7_-QZf2b|Wl`fGuJh+MtB~9H2OU`RbQk1qSQ{j!a<_3Sb}Sv;nN13YMf9~#%C~t8&Vl;H z$n(?4l<*#w9nQ*LWtkZ-jqB&6II4=G-5MLtM@BO;_|+{_@##u~XprrS?K|67Y*Ofa z0SxJH5F0p#Psza_SwgW~FZ9b1S!(oZZ+^IU!&|+aKzwG#^0ECKr5bf-+nL6ObCGX~ zmu#yK+O}ApkHOey7Z4ku8>sgZ|0Kb<(Tfs>Fh@#}5wQXj3#7tk63hE|aiWtcb>fVf z#lf`N>*=*_H6E!kue`SXrE!iXUE<<1n~VAy@Nt&&})?|u4U(EWfS+!?i*K9o{>0U_JysPS-bDZIst_g4q}EXLSisFln~da+y?K4V^pl^ z!#j94JUoa7n8ph_J-a&r(g{Zr@Xj`ST4p4)usHGS1V_wIq#@>({*b- zZD__zLp?1aS@Sm!J}){O2irz^>ca<&8r(NRA8{cvqpz68)VQIH-(|hAF*$kT4Qtdv z+m(Vhi@SE4e(>I&!pJsr-Y#nRX-`QX5BJ^$1F4^DFFV2Q5g;rC=bUAYx0A=T9TMcB z|GsVYOxLlT%|g7zt>Cq<=Px*%@9X54UvXgpP408F_fOtGHQI))9N*hr>Q*{>|L5&v zxZxY>b`Br)+WFGbb33x}h4JcxeTvub*f_o4Uw_~;ap(&Z*Cq_w1~-v>ERBrtl6Azc zEwE6uea*1`2MgvMp6uzSJBkk-V@uy&HqH|7oP88R^z79)$$DecfCyP13-`}%{L|hk zKMkFV=#+_{(wldRIl?W{Q{o(`$TUfXd`%Br}#Wyou*%Z7%JJ@D(w zg?Gl=qDCKlX<&+FPj=kwg3LJoykEefcOjmi?c(wEGc&u+I1|ZR?A(Ic5ZcxZNjj82 z?{L1Sd+yPZ%;LShY<#@4TMfNs7Y-NL_@`Yw`{p1R!|`d;S>X~obw_$qf+vL9NBhU{ zk!C&kz{7_KVg3z=I}Zs_B)>Z6H5&8!OPBW)eRksgF^MBP>2!hao4=x#ICIyO+_F^z zCsiiWaNElEnR!KVVTm#Ayj|3GZBB1Ghaa>2Njl@xae{Rh8R6^_%m32~VZ7E(D~tjHKD)WFuY;yWYjG~9yg~J+O8wm&x(}VyJ!DAm z#&(0+PkT5mt|ZN$7JK!G@E5gx($n@1OY27+5tAcF5;M_`}=B4JKtw_~weQWNoo z&*Pu`MQE8Oz=f}$@nX}RsUJ_X6`8dkite{2v>`|o0U z0B597LJyEyq&!D_o`(#~5c*1@a%q(9tc{+FVnKqcXIbX(lZ z)ik!^y6x9brUja6G^V5_JI|OpZSLq-Cq{RkU>((c z(vThw#$F?5fXFc*@@sGavXu=G9A#@)>=(nizV0N&&KQxoY)rhP1hLvaZ?b(Ixy165 zk9f%*5JeX6o#oRNp~Pj{f%@Gmm34&TeH7C29 zh1zPUUrTr+$zfUyX@bJ;tYM1W9H;Gohh-rQRJI}ed0^8}W{>|CHJuUau*QS1G+ZPa z!?>+O->ssTH(Et71z9sZ4lP+QLxZKS} zy_NU~q<80{SJRZNA$|r(K>o9K=2Avh2S-w#W;~Hc)bwCg4eXx zGH#ar^YE2zDCMM#c*%lP0Sl|_=J6+JI`Y!NwAn+kXx8qan6HWyKCn$5(*I!oylTV{ z-Zkzlu$6sO_R-p(TD;Udn_GMor+aeEKAAySp1Z~0SZc}q+sk29(9ofM zf`bw)qhliacMj0G^qIV+c*3sfJqIjC*!f?}?4LU#IhK9;^lE3e8`AWekuhTFm_E*I zm9c%$4cn#X`=Ew07Q|+O17E_5c9H{^=XTW6vd(;CBE$G*UNB$E(`R-S5)i6nb9(>d zW^=lD!g%ZWt{Ugp-);QG`wO>ru1d);>g9JY?8;|WG%15w(Kfa=FteRhPIGK^yPXw^ zh>8EptXd8lBYGtV|Cdpv6J>ily>xEiuw)!F$N{D|^g{xBi!S9$a;j=drJN|>;Kq%l687n~KG>kXdO{N#m=`GBU_GG&0#ul((! z!`7FiwsjdWZ-{Nn?Bg>+!prtvo$FEKG4q2Nq2V+3eLKg!Mp(;tFWfTb)2ouuy5_1DFrn=jiQT>}0Zw2x~#1!4?XNp3PJZ3BZC_1NC}#bB>% z!Dd&s1onLc&-PZ7+f%Z`KZ5V!-Ei9NsM|iTeT9)U=IQ*SMShNs6L)-Vd&5oDbH<6~ zIbGZ}u`}LZF^XPE?`f+&xOMA6Zanp;K545zDJ}hYRVtUYeNlEq#K=WEUdoG($z#h- zPPB;+uX&M4?JnjplXdVz!5}-6@s`4KT|a2g()-AIpm=9p;~W zV*BpK%blI28l{8xz`1FQ3pQnWY26-Nc{^p+hqD{Ehb89p@YHELj^I>!x6}oL7Y|-n zlFTi&eX(Xh>e|oe1qEeTmXC@OxZ03`C5c-$*ai)F`6_-L=Np+2;p5Qw!?2aPk&T{0 z)aYfPypjK%L;lXB;1+>QO1|c8TnGqfdxJ=3nP}k&kAIae7B6kKeN3?x!aGZZ|8O%D zML5ryVXJ1EgZD-W5BXFn0KZ>ndSPKv1JphyQqR-RI}h*OPFbXhAHOuEM`lldsaP93 z_9gL@=-)M|UEJI;y%a(Ku*A7J-O>4J;Q<$+n1IgvHpxjube=2R<;N<1WxHlGI&PM& z9BfBAGNaC%8k8_l&wVn+DR0FdOLo_Z1N?N#&_2VX{rh(I;b!ZcU3D&j?nYj6@Q-QR z+ftY=JeYlAaeUi^;*^eqWBttS6C)kkm{ex308>zpkT$#`Y%C5JG5B80>=d$<;0SUy z(6POd3p}}{&cZ|L_tqRVL7TFs+lu#uT&9WvY!_g$Zv$E)Dwg~~%*?{JNZv1owFu<- zA)l0`mGsh@XH?DBi|vv+$4wa#tDjO?<~g9SS4n11hvKSJRbB%Q6_zZ%Jin~htV2_| zU5#mjrY8Ax%3d;~D29 zVdZksX)b+zrNZHTL2tc}Cq`4}8gFm{|~`;?HFvrk9DaQxZ)Y4+FW|7>}}74t92N8MC4?n{lb(w2teLlNOydpj)VyQpbgj z0-oGG)XP?1!Pqry+qX-We7kMfr+XW}PTM{=HK6yfya^rCEZgR#2F7LNvIPVd!X*8S z*&^o?Oq-|c%Ux_Nq6SQ`n@8iBHS{-yBWBa^Bigqp5lgiCHZvR?!YpJBl6dY;nau7T z(4dAR&-G^pw}Y{}VSa_BS$i6@89P{qVhXs?UXIm#TVev1KtM1iFK1}Yvshb1E~PnI zi{*GVH5vUg<|ihJ;!_v9%ac`9L49;3R{^>6Y_1+#Sp~j4DSC>>wePePb|Nh0v$y53V zR5AlIi5^n6u`+V(OVvnR?QLKiPT0t9j$!DCyB-YQ=c^immIkQ|kvY zVy6CU>qz_}J*A?B{TSSYp`UAfbNa_w;Ad3Y+5cV@&S47Vr3=fDZD;<|8`6o!9TqHI zaNgb--3!YE>xDG~As+k5!#11hE1^INITs+yTX7l#GM_GQ?pqrwX34PVAP_mjIDNMeR`|b0^Kqh9!cKG-p)N3E!W1zmc}_ zCD_zEt3y&}j?D<|SGJYe2`u9T5QI${vlH+%F)Wqe zZ1k9c__)gt%W_70PN}s0Q8@{g;lL_p7%WfUwtX@>XE!(Z?|Lp{;+Wr=+l)h|0;g^W z5^&^%*>-8V$sa@Kq4*6y7_X<2vk6R=-2=Fe>9Wv~vZw*iU@&mg!hl{ZUI^0je7=uc zl-sf?J|lK}#?{QuT$JqSWXfD*smkj3C5WN#IQSaJ*>1nr*t9>Zq|dCqlXGj{escge?n8ooW8J#;^6c)? zp_eajH2O7E^qW4UL(HhT@fn?GmQ4zbC|kZ2)XQet3rn0G&PcwN|F+YD7Yy7#%=Geh zyP<~vFwzZ!W$xrc7Zxh~@i74SW{!!J70*S2(}60=CWEm`P7=cz#XQf{M@NP6_`#!| z|Iq85zT5U4&vgkh`-XIgn?1dt6JKzkw4>vsN-xg=ql#m*=OsDmOk)S=G)~cjBYI68 z*-L9ux^zgMl+Y`%XGb6Y=-%AjbNVTS4?RN$OzN4k>XVs`2M>fMM|=04wk>N3^<3T9 zm|2$K898!Z|4Hpf4DBD|(|h^S1&kXOI2ds-WDBp=tT=2)!Ik)vFO`jXwolmN5W*{-tbtcyOBrYRA+`*Nk${x}AKy(qF}@ZBIs z9B8^Q9|glNN2?MGuvj<&y|l+)k`JYl!GUw~XnZ#?#!shE_AgkzYWb8@tk=}me~?b$7~D7VT#rFfZi3P&GBMbtmtWhYCDZeg!j!zI zhekSwC4_fdzIOe}`H`GYd_js=uY}alfTX^$ZXM&>=|$ejRMTVe^5yfVg=yU!br3}v z;-&v%{MTYT{x9*L?T@O-|Cay|MkbR*fLzlRh;NTD&jO>;58~8I%$~Qf3W-aW;T4)i zXwT((3Cz044>-P3H)y&nCQ)c(mL=P^OMpS48I$hb-rGoV;u`Gbpwef}wY15ZttrMbg1eBm<&~B5i%0c$b#be3ZQs?W&-(tZ@hR#4 z;e!Vxr4EfqUzQu)t$4>?x2V)e-#+n4DMLa-(u2A!Sh^~y-{d45Dl(%2ix~@LWJip4 z57Zp@*|R*DmwiSYcQSGIs95bZ#D8AN?-z}*EF0`@a)?gJ>qa&1wvH}1$cfhLRN=$< z@1nBiBs5MJa`)#=NSJ?M;*iyIr*^Ga8dWrV)xiFX@>tRYiYI@=BIH8xGG#)TAK36; z%Q^B{U>DeWIak^~wy8I#u zcNTaAw8|vdV_sR^{Ms^~%hV8d5qmi*^x)38H+C~r85X%MzE$OwaBvC>-ksZwSz)Qn zzRpD%)tz&eOdr+P#3I8brP+P<*!FB2J$jpH*gGzdMSV-IZp+|OSajN>) z?6UZSy7>ckCzqXB*44?dQ}57W%$h-KGM5c&tI_qJx_RV|)P-NI?9!MLSu#VX&ErNH z{qtVUT|N4(B_p`LOD~rXhVR)se9JfUMr91&JgpD!);_(sZ&FEWkS!%)jkPS|Wb;}?{Pk`Q{B3+0yJXN|<{ z93UwIgA!^7D@C%>S( zz40YLQxo;Dx$^^>ZWw|@$0l#G#tcMoo_4X^aohji%PsZXfau~Ss<=HET!S!G1;P`b@Fp3Brb zb?#l<&-UoOL922HMT9!(=(ff^I;Ut8ZKwO?d00!C4(kLoAqz0bx|YtmX*KJeI5G^_Y-goR#?tE%HNK} z_zEKq@2lF^_{5bT&7W@w=g+T$xDl2J%;od!NA+wwBm$!CCsfY#>ddMFK4qMxsvuxQ zl`Y$q?)>|8ZhzxYE;q3843~R#%Q}ohNfi{wEO#Pz!I@9*IW6QqeP)A>;`yI=&OUU* z7j9sj9~g;LBKN0jQd)-Zl&WHvab16K6>`^Y`>=62H`{VJXq~-ZVJ6z+Oxtp z!daM^zh{bH_U^`gRj29B$2+;4#+}^kGaDMhh1>_=GNDw!68}gjklEaFy3V#W$g0Fd zBgCQ#d~(7L{W#-9M{V4g^;2^DIXbGH5_)zY;aZrMJ-s9E+S&HIE$~QZ%Xl2JA1U2A zvR%88J4>g&HovFWI*KwyXSwCB zU2$NkzC{OEGt@W2i`NVGgG8RGBsJ6M$*+wF=e@d(S#V^s?W`+}&RRLLi?0|_nq@mH zr2*JrMkAvYrKf$MA`Dt2hd2^_~O=HOhE;z$4yHd#Q zw&=rEbb7-Hdhg5zdC-;Uqe>`|zut<(fqSeF>7$`I6lI+t>4krcLCD^4)O?Ebu_yvF z(sB|y(ERKIo8(Fd4{Dn_eCOmI{YB-$s#ipJm4lks1`4^F*U}QkMSCe5e{0;imYzHH ze#OYI^e#3N-D&9W9vS2uMxS4Id{sscWyL>VR3U*4W(l;R>@zx`T97^ z2g_!P{eurXlcV{x27ivSb7xzvEv&jTZLmE^OyLHnIqDJ$h1@65r*rt6DTsEYFWU-i z{pm+#+cW*yabM@AKEmth7&~PIGd#X+5@Q0`AvrbiCnNTEa_Tr>;wvA|x2^S}t|Jbn zE!tMh$HT1No^kl#3QKbE8dx`v3Zn;ZX-iEEQ zoOi3<^`Ef$c8En6)hD2rdrHq))4XHp>PK&KIZq!8>T_>A=-*Gb*|6~t9rqu`wkpVV z9y(=bk~m_;7hUY2o1GE9*gGwt3-4aZv3+vKw$PP!zjPxcaOb}_w$pd+8xZT3+GF-K zZz0!qz45N?`r4DfeRuqOOY<-?7`||tKu6B6~qd~YEZ zIO=TnDw3I5c+1DO!KeQgr8XWNy?xc;yM1(lK`|k{{Jq}NHN4}xmcP*W1uq(%qhhjR z;5w4$XQqaQI~iGoEYmGNa}3l0--c1@w&&e zKVx!2@Vd^UUVcN?^lx#DvkslK!}?~QTgED5A`xM+6&3*p8mX7)lDE26xrZin2?=oZ zGW+T_#s>8*%H8acxq4M$;qYMt{Hww&gGT4hT(bLpShI)J!PhUY^QeBa+uIr@?(5f6 zVf(j3yS|e*eEQ_I%7)u-t{mPIOa%4jrpLl77}yIp&#WCU=dzinLz>4Ax`8vg1^HF^ zI;BH+PSW>d0<9}L#=Ca$i|gqzcDpO*yKrZJ6-@i6om_76*zw&08vlLyoMD}Q+M8VD zy1uK9$e~;ntl}bU+XF@X)CVy`ds-yd;{dCYdK zj&yfiRye!R#e2!JZ#!nujQGM{2_|Fbj$aH}k&@!%Jf-~Oi_}$EYw~!f{Kt#bot7TG zMCTh-V&$?=AKL>@VO!ki987 z`o3iV#p`lMc7lGOg>pS+qj*iOmuD$9;css@6Qp>()c`-XZg20OwM73v%Iz(TEu$rT z;Lj=;PmwU|XrGzlbgO}HHFq?;d0-IQ+z~j~(!SNew_CS=Vc^?xd-Nk_O6h70j0!ez zO+z5Jg-f?H__6RMYbNvMUMogE<}LE;Z2mo3&HpifuBBTE2h3owELibz`R!oNm#UcB zxRiT_a0d3XcUgC$Lb#qW8vBi1cbX7{2z5+%6!!XN-Lcm*-Lcn0clO|Ai-Y~;XSzca zQ=W57AwAO_yDl_~78!xAGN~=P)2wR>Rclp1KhIP_0g796?Ky`P>i@6qFc04>l3}d~ z(%419W+Us)GZC^`wX|=pr^&@E?kQM9EvifUQm?EFum zW6WiLf&rGINq{G8o};(;N6QLV__McA?+#w+P|u`_mIejZ*|YYoco<-5{eqn-%`XHz zd!bJ&sRp)^lAlaa^K67&&)c^eAgFcw=Kj$V1O>_MWvSYioNRIwA#}a`0ES0lA3)|1 z=J9-hd#wg&-@5$^1GJa>nT&qq{vBnh+WUu8=W^S50aCpX&h<@~nX2#=9>}jS=0!86 zGNu`%mU>x}eZ?P8FV7kE*PfA@D%Z=TDtybwb>xa@pYjVGxtUTQ)(4!&z)sv$?|A!- zXpyC@Mbdq;tSa{Uo8>=t;)*PZ_C~yavy&kBo4L({!yz5nL+$N;0g1uuw2tp-SJp1~5-udolm zXvYBHlzjlPsMP>Tt=qpafh4&-lBIJ0K?=ENgMz6B;>yw7YOVq*aW<0sCS7JKM68fs zVa%KToO!56N*_bBIj6{?mnHbDJtK9tTrUd~DsexG8$@%@%hrCbotRAPH)ZjkpF z`^|r;guVV|xi*>`WEpR7^#4(boPVgqa|z_w8T1d8$o+>(Fe_naC@5nLW$jxrG|$rd zg%>!QXMf=zDlw+Dh+j|%%*rmY7gS-P5kn^j`0-2T5*Vti{6zn~J})c;V439Z|| zFo6kj`{ybl_uQ-!^qERri{bXsIpxc`aNVUj&C>h43)j_qUbFPZwAg+zMPAVM`kUoG zT{&M1f(Rz>R?>@PG%IFN=-o3L|24SY5%qzJS*$%)(L46Jp#G}de$ER%fyGkz$rjqn z6ruf|=j~fbZ*Gf?mtSb+E}CNf%zgF(Bd8@bn8(Pndn}nCrcNLQ?J=un_1MvBfcdT4 zH}`LEKVNRoY`pNW)c`F7b!wgg8^BJGJ=~Jpw;Et!vy+nBzc7J?@&J>Y`wvpcJwKCP z1h<_F6@REX(T&qk`fB;v?%X=*)qmL+Uv3ZXCGT>^Y4bhtM$`Wz?mGahD7OB0X7Apc z1W0arq2-b$y(jbzB2_?&^j;JJ0Z{>26fF3Zt``tNLsLK>SO^x1V)>q;AcEzIK2cD? z_EbQH+|Bl~p$O_KH2Ea2I+`Wq7BVk={Xv@=3UT5O3(|w%@bFaJ(gK_$p zf+EyFcuzwm)x>|Sk+lOFpe=@);C4U82VjI2bFKxWUlp}!NAD)&DgXZVbexANmIa$@ zI?xd{x0fQXfPdxR3?%g#yS(7%9t;0l4S502037TvN#Pw^O?jWQ;6J6a-yHbyI{r$I zZ@R1JIg7kctJV%eUPW|x+8khkWq|EEL$F>5Ly$_it7m~_fE`wRoxTu2EUd%01uO$R z6Er}G1kjW|fYoBpTJdcHJnJ9YiM~x<^VjN32Y6l+diKxnOncWnB>qrt;DO{-*t8uF zBm(}G|2rV5ZwVy1mYEs!vrMZ4`nb=cb21MM2N*sk*P{lX${!Z|*Ys({;sRT^bKRUH z;NyH*$mJexnTD?$^Okqe=OIvG`qzyP%2CSzhXg|WCN(`X5Ed#u5#kUFYHpfRG;q>#|oU$26Zbu*) zk3jNVSL&gj&x95H2d|~O&9i|!y3^h2e?*JxGb2*4HwF>t|IM;sGtkdMa_}>QViD6kBG_7gl`X*bEc)6vqd{z)_T98Q?#9hsOEL1jTUhDZ)=-I!yC+%4Cy!b=8mrsg`FyVAQa|9eQycZ5$eiulV zC3w8WkN&G~BKo0oHwJfOC%|XU{|P<;pKHPY)iQG);`p2+*t1Fy-(s2HtTX2!-7-Lh z=6*9fd}SHnyv`7lhB3q(8>|2yQVGX)_p=Oe!HO^F>-acF20ouTODzNZu1l~B1274g zFA9dBDKUVu)H1*yR(zWPI7$OPn>mbro|{v)%$&#QGsvl5?~QL5xk=H*-n1zpasE1e zu{0s==1bG+zI22qUjO5dzI2NxN&jQ>_4LM?CF~DRvL4-LVWecnnJ1aSm6D=r{b&v$ z)%~6N(~X|$de86r(-oeY`X37i(6udn;t$LD$*!P)o?2q=pxO|QD};dJG{IA=sQ(SL zu3YmPz5jOZXQ&9|`k0+$d1~u}tRGC@^wiV;m^_4j(6WKvL*Ltj@+r%R4RxDg)8)<* zBeFfN*X?OoH1kHfjCh*q#G;1LC7yi!k2S;S!=4uUAN7XQwJ5Q~EU*^K-(68Xp%*;P z!mhQWEC=B{3Uy)-kVm_L&xUn(w!<-3hhpoJ=k5{)-^cO0+Tk70A)R-)*51J2yhC?8 zoc=@E#P&uyqeF@okD#{_^?J_sDAzwYdut>qT4BM^BjBU0a8NbiV+=S(i&9RT@UaxG z4KddMezOICTo4}hgav;>T98oG6P6AWiyj(9w-8p2k~?dQG4w{y4f-EzaPz=3NdKdF z3_ax;s{e6%EFCy*xcGyGCLB57FW2>WH0Z@iIPL)8W{ z`8~J!NY{73b2B9hc%>IPe6*((ha=({aBiwGc6iCx(M3>Fo_nk^+KONDbxa1wA1B~V zJUXG0uPa^8J4^^AROx!&VWI&qS~rnyj3M_GwYrraPMnUu}j8toljZFIbL!aKg&c<*?h>-pis_YZ$^IR1ZsQKN@wO%F z)gGk_hvP5=-qu*VUmO(C6@q_2$Nx%Rg33=I zbge&S4J}ZUb^I@o4HA=nJ1tqq{{r7MVQ`&3=H-&8p{ODxLi|N(pUHo9Pa5Fe`CPjw ztMi`;R|H3n~?B_tT4>#@^hhHvW|LbPhA{ z()E;=J3G&rYGm}sC%AY`CfASLTG#u(SWnxr(q@lxXMvvdag5qcTRC1of4j%&W;O9L z9u+eT<|hw$yx?5K*vry#Z4co5CAFv_fH&b1{YgZ0VE9cutSFnn|5LhOd)35eb`tZkg@sy17Ihl7{jK^v1EFuPc!*qzlm-0aAJz{O>00XI8;B{-@XxD#2@@PF|SFJ$g{#(%t!qJGoYe%B^C1lm!CbN9mnhhFQEE`FoCX&bJcq5cJ% zgqz;Pd2Y?{N{%uc=~`UQ@rL=o03J%#$r{H)Z{Qtcwjsc7^T znoBYgizTr$WJTtD?zf=xF5E`N{wKClRDKLd&=<6eb`*RIwg>!2S$mRf>7VKT&gh>c zKe~-|*MiNidhTzG=0wfkXdCU8f$aZlgS@M|`&XkqN%Aje{ZYXDOS9c&X(#@Jyq!wN zjduBxr?%Oj`v1$vFOg0f?I^o=!Dvq`@n=3opFo8}|LafDW=su591jsh8RUK&cw!|e z_IsZeYOt&nTn(Z<;P1fNp@x^t{-d}WczcrUpTYZULHa0H#`GZiYyKymrjybyX!nz! z*`^J*<1s_#hU)G)^ z+xjyr@piD6xr6oB^mxJg-^ke${WbsfJ7@{ksE#RrZ7Sr{$5)PT$GxH0C~~7OR$VWgj^bcUOxB0Y~^$DsfH^lmNoINRR7ULV#Dg z2`T*V|C3f#50;D-W7T6ygf)@)Ar?lzS29|_r!x4ph!&fL(zz_icev7n@Uu;sBv$yx zg6Ha?@Dm*Vu8+ez1qr#j@`eM~hIDX^Y0qCr7q{@EE^t*2*Mi(7G~*C3qJQf?!&+~;fw{t_pI<2#qi9MUUw(U0CTy$ z4oVM&3_MBr-dyXzkWu+aS6j?;7PZxr*6BPzZJs9u&s=TwENa`z;lkVM(OV3)d75$F z47JrGmvvfDn`gA(+rJdUk%Rv2_@N5t^2qfF(iBc*9`=J#g0T`7GTm}-6HbL@OR_ES z1mOS9DI*`Wz|l)~arnC>*IVF_N*0_PC>g6-8sPo%6v3jc0~nGsgl0n-l2h~nM4h1#0Y4hDTUV<Q8UEQVKdSn zFh+kW^u#6xR+R!K*o|TEvuUC5F9bhXq41A5{M{NMaMukSeqfNK+6Qn=W)Gjnx|7+ie@u>x3z|E&qJJPF;Uvm!NTGY#%~d(ErriBj{@_H01sNc zEx|U2x3Td30&hF)kKN1TP#yfJZp5LsWT=kG(u*ye`se;~72+AoXy*RvjDexL5 zyn$PV1ZIbtW93-Bj&czX`7$KiK@Q9em! zypYG?151J9_yFSqUquJ5YQ2M)WP*?t&i5~@LkK#_0>dtL#srB)z!(7dTVi$)p2bIFMaKZl1T0E0Rrlcdqd1(IfJF%ghYmnzG>5~) zdX(5jJ27~V=rOzjCeTB~F18}0g9t0k1Y&XBMUy#v9LHxSSf-nx4~LKUpW8>fk_rAs z`)S9<&++vX*5}w0;G$dH1>Rgag>6pQx1AVV|Lg=idpPSa+)o=K+#K6a^V0PYAa(}i zCD-fpB!qWI@AfAgphMX{Y}x@@lT7h1J%INzpYy+uzv7GdP_H4h{vVh8bH8=~?^S*7 zuXB*r9k@&ShOsFNPdVXwU4B_$Nk0MZ!DghI&TKK-G_>VLf7e>HbY_&v6u^ICA}5}f zKP8JfJKGOp{LlR74${2F&y@fVBbb>RUJ7JeiRVlBB+%iFkqmvrshst9dX0-b^EFzx z?dSLi02}RWNrK=57202Sr3pR;i55P+9QZiv|MzR0kBrx89&&T27kmicuMXAsz|3C!k4X53Ub489F5@K1Q4fH(H$;a=x#(%S3x zAAFt0Gef=(<)8IyuVcOW+@Em>4BqM=%6>fOUv~)hIwkCdy8w6T_Il?Kx7S7XW0$|y z8}w#!sc7jN^m!$(8sU4w7#InI%C6D!^X#E*Of?FKHNenL^%_CjvOyM63+hG!8>Z(eWDK+1Et&Jk0Z~ z32P773J!b0277?R_L;CI5H7%;ebFr@Ol^(MOF80;CJ?r#v*k%ZMC8&3X0Y81=6Tr) zBQ-hRCKHC~=t|`DUa`XH19TCDLk!gERmG#W7wJ9qKoAi|2V#w(W9TXjyxD}czyZ&3 zIR|*J7cKpS-sw?mVF+C0W*;bK6-w}d2fU$;2dMny=fL#s)999e2l^2;SzAQTeX02t z?6~`ZWcdbqcVG#4o#`M%I96QZHbi+L&{<2;odw0yoj$S?Z2Wp+G#&D(+*86>hnVr(mL&@Ci25%!}jgkFHcVYvt+q@o>P(gli2*^wz9MV63LvHBnEe;B~G+I4I7%gd5ox7N_IUMzZ1!#(%y zcWl4>JG+Dn?j}Ogm%$yDd-fR5m*PoE#?w6Zjv1aXrsA**A4gzsP^O@`54gu)S%Svbr@b=-QwMReB+XuQY;WJHn z(!A2}-1~tiKI0VpT+?l?RDVnrIhi!@XI7DGqN?53JfIEHKjVZ4m+qasAEF7uUT8b} z%#&zGWN~Q6akpq^QO2R2eMaiNAYZCEz>PWssRlv}LXw4m(as3G6C_~vAEx(b42pI; zgGM`}&)Yfu&Or$cgk>fILY;*Hqa6$=f0_*716M^0W93SUx&)b1b5uM>Kp^-eL{=?H zrU~q=L-;d$0G=tKo*v$DRhsAaJaF5$+KJ{(_kVNSsi})z>|LqSt+#7Ov~%s+lcz}I zJKj;oo)|S!dt3ViUmAFO=8-N}oIJD#m<(~>% zisAEqwTjkdquxOdb{W!s;PwMvCxI))D*tp{1TGGLcw6tHUvuQID@SMPbbUo%G?8(8 zp>olJwz6NT{R&~}j~ibuV`ELxdLu)RMgLdilZ^dJW_wY)&hj?5I*{a&We{s1-J;#= z^;8~M@|1>z6n&>k@42pVVNGT*0|!5WgHmwFfH4;~dueAJ%UZ+4`f+7{j0k zI&@1K!IFo;4$=BbH`h(x+)9N^U6lv==l77ib{r@lBH65`{JJ)nkAf!w{AU1vyBRX; zEN$eSfk*x$+Q}EZ{csWODc6r71O1H#%Bk0}=9jntUj$x8$Jg*(`);lhKER>CKFs3G z5p;X1pZLF?$Sm*l(W$%h$1*B{zX>}S#Y z1Le4D$hM*{?vmA5bs)X1_!5KD+vrTzm)=&ghxa{BH1|ka?9Ht_Fm8{)DA~g>aEX&W zgg#!<$vslp%UYy3LBsV~D2*VF>ob8P#aVHRPCg{JCD8*(iHkyiYl>>2daRPSN|K6m zaa9gW8WLlqKdz;&su)SYa{>R@>q&|)TD(f$ixQ<%d7*;%W(66nFlKTRuASgBIcze@ zG`UecSuDrw*wcMz%O-j0$+1dQ+z78nla#3JyYV#g)f+nIw@>uu#&r)oqJ2m&t$|~s zn68#V3p`5%-6T&8NaZ$fhGGs_W?1d*#DwOJ;%PpodyS2-XUU}t*>?v5S{IWr(#-l) zxmhau+Asg&ZjyvuJ@mH?iE{&17$zx+|IGr-gLqrmos`V~W=AEHTzBH{1iyQud`!hR zda=}ytmfXtgv6#)Mi$&>*Yc+xS$?kH%s}xu*-yTrjffohO}j7fQ}K^Xj17Te(g$M5 zY>A4`+OTVvXUWA`kdU=$NwgSkjAk+;nZ-ypCw*ovE?WM|JrY1nild%AbP>SEtg#b7$B3W=@Jep2sl_`>C&$e;5JoS5ESlgz7bDrD&ldxjLu8D)!a-#k~ zvF!2O=l|wOxn|2|xx==N@BDp1!P&0kw++jtuVuDfrF9N`M=O(}Q5{|6m9FE+^RzOG z9CTmPhVwg0OTw7<`P&uB=>=P-kMrF3$Le*1Chpp>>=gTOG-K*K=s&~-%8G9aR<;Gs zM~kW951d2WE&iqGTy@(m(^&Z#t72@hRO1my_o~Ds~tJ(^&v?L}L*G1F#B#*l;Y0e5YHm9Svji0{d z59p#9cwK*L8B{T79qU6DX%e5QO!x6kG1s5dr069VZ%68kYbiw&HsL9Vx)i9gR89L` zE~Z1_@l~Z-fUwF+sVS^#L_>m!jVzJ}4&;vcB+C=mM(hq9S z&MV$06|LSZzgUBeDe7@ZE+S+~5q(o0MU$}y@?^2O?mB~T^qBh^ucyjX|D3nwhUzT( z5g0^M$xpcN_Xcmmymj$VQSuYe*8!GW1u*=Vu=EK z?J6UwGr$H2Ctz<6BcS&Oyc7mRf1{oEM}3Z!l3V#oc~dGXO2+Lowd5xES@$%+lkt7; z`V!^?VarVlTg!5Dn&s=uTCU=ie3?=_|8Ju8cQ|b(7AFt(Jelxh+UdIH&3g1`*8Dme z)njtcp7^D>FZq=8CD)UWwc6S)ZMT+pCs{?Rk?JU4t4`Ox)=q1;oXBjjnH=3*-!~~E zYoWG!VOEA5Xx*>hoc;q^;YaIM0|tDGkI}^ie$oD+J%qVinatMS&^nWSqz!3H4r(0& zIW3yL_+rx*-RtEoefXNX@L@$-TfT5AU$je?t^oVHOiWB%EOlq*a9C8TqONQeDCNn%w;n&qPWl)`^)-YmD4n^=sM zqf3(~q{*Y5#s{s1-+K0(+#}ptq>qDfS`FwwM;L|~NPEt1onb*^EX}K1R4?6inW|4K z|3R=uph4H3j<}0~gDHC(k?TK%ioQ0)1t9jG-T$lTp_SummB( zAwIU!51*yWC+m^mXwNMm`|j5EPoU31w7s8vviUo0A6)t*85lo_3}31xEhD#Sn^zVs zt?t4F?~)Sbr1A;BupS>xJkcaCniND6mLDhs0{4>YV=$lY8ABFmUyUWz>0GUVK2JX( z#ew$Pp{b;;He@Qcd~K&{hv;i-0=TmJbGB<}qrNQE@d!lkHbR_yogU(N=nH|f$l`=A z;FF8i40LT%JkOSVuDqoj^>-WQ>aHeaQg1?Lf*19RYvm%W$ccS()7rGUwQI|sb!x2k z#oa5*_s02F*QnF8W!GCXuFC-_`WBzQf23!#g%@sV@KU!{x1- zFVHSbnKGFsakuZ*&F=Vy^UEvP+=zdKJo|V;@#^|9+8-o3W{dX|a_#Aa$F=KQOeNRO zoTyi<{1U2t%SO$^>C@P9TN<55^+3VD##^pU-r4ryj-tpII-@=gq?ShEZHrw zlP^rIyj;>Gzj-aUyz(aa_vAW_<4Ee>blQbE`PwO&caB*LM}K_0?&xIPLT&$eT=s31 zHnA<~`o|Ylw4eVkqv2#s_9?Xk@2>c8^khwm}u5@Mb zAr(wRLTuISaR<_J(=q{#X`7>33`$sd)h&ra;*+LKk*Rk4vj=DP87iXFoy@KeOrQPW z`{PMBZ8s)1q@7Ug5@wxuS2J>b(-tc~{BUKfW((y1gOJQ3+V|gTuXe2mYnf4O0XK7( z9=Pp`*VN1q@Rn}gof{JZRbbZc%&dKR#M4UL9?w7op=*Lch(%Ypswqn{^4hWj?Z?mD zN4gl{XuKYB8-~W*X=Iqm(Ca^kMc<;S6J5W>=%F6_NrzCMRa%HIbPn%rHF0d^GgWd-A-PB+q%+Y`AIm zR?MKxb$sank61G{=)_}L&HTh@YFUs9qUi>zP({0*FAKd%UG0Q+Lf%MQ2i^>v)z0f? ztNaw1PI_oK!@$!7w#yaV;!zDLNW})B0G3Gh;Vj!i+Jm~{&3*X9(&;C^o?ar6vD)TK z(@t||Iz8=@wwa7|{W&*4#%qrk&(%)P*S?<@2s|ssqx}Q(Nb-CPCQDOG;*{r<9NhA& z!Vl1s{ol=WRq4dOaGQ*e+h!@xX}@Sw@xNcl9Voq7_tVF;4d-5a?c72p$U@R%zSfZ( zn6K?2J><^=P&WpZk_Ioe@_JHR-~0F*+Ixj9;&Kv8AcHLR zmZFqbT(_X&Vs)u0ERdYU^RBiiVX3mjOG0j`!uEuO&&B(0LBfvvE>8(w8B0Qw461orTRc0GO{0jWtMdbPL+3|>gtFoETY(0 zBNomX<8sK~7&$qe1bI(Ky3Lq(#ah_C{G~+{^+d~D%bzD&x@tK{qfD}}ug$lKroCqS zQy$8tGvs691qD=0Q&hr+pt00mQU}6?p=*A&mEy~kSh}B*3X==4*TeTE`s}ho4O>OpuP5g2VOU75NHey7L zjB#|+i0akSV`EdQRma~|(<;ZMRjaO@uqmTdvzt~|J*LgY9;r3HzA#K;?%=2itFGAe zF!V+%=qIXha>G%m*HKH&|HuLvN zNTPA8K_&VTC_7+HWUj{+Z^;X%t3;YdljKS)1L51A1{GX+w?Y3F8zLb z^QKQekvDBVUF4nZs(p{IC&9B@uRE?MKXf>+{VI=eCwTMXdg<_9MME#T`nc631)pZ- zM<)2Z=jXJVD+Z^=fYHxcM*(wp@a73Tdz-YCRwEw@7`rgW@EI%=-`WQHoEH6@_fuo7 zjh2p9BppYtqa?Xn00#`R-^GAB%)(%>jegGYEwn=0R8ulXBx!4qfV9m%u(eIWt87d| zW#K^La2%DZEI5ck$Pu|juEQh}CSt!ECbISSFzr~|>?*gnsm>}7A~7iq0)})3@v<~v z#WDJa3I!Z?_l!A>O#;IdHgyStj4=b3*;1Iq7%bSvoSLb-Y#jPIw}074c9VqTTA7E2 z90#@H81y)<>cF8D*`l(D376dmS8AYbF>U2KYH<1)YUQf)Fx6SxEH(^lE6sJX2BW3*(VbA`ODne@w~Z4McEXY23Wm$a)z^P9HzVz& z&tt=xB4j+M3E^YhCsa>ppfRKkRk@{8seQ_DUPmUi87i$-vYvS_iPdI^si@5e&tR-= z7N01q9|q(;5Qbxmglg#na{?j~+L^O3P%4h0MF)-87*e$vM%*`oh;=ZdEp$0`#ybyHs|sjto~Y zTpBLoe{k?nj!Wxg?_+4q(Z0HQ?TlL@p{i%87M1XPz{-@6z|tv#KBcKXlu68gBkJ*_ zklP0mIXX+wrYtuM$Fci}Gfs#mRC7IdB4`Pf5i%Ckk`p~UgA7;C|DBLSIMo>~djQcV z=r`rk)${*yr3>}qatVvYhtoA|?$pQJ|Dmy58qC5Z>Y0WWOJzw2C7K<*aZkWFdGN)KcaaW=KbX} z8Jq=W;HvCA2X-#~^HYxbe4>8SUd3tEbriaYu=yv!U*a4CvUG&Hu8v6-)(f zR*`|rqTyhFxei-=L{`jx53Uau6?&N8SlcX47S?9z$4w1}44mNlZ;ACrW7tY4r03cQ z!?7^H2N7DeGa1f^e*R}i78(%9+#$mTvlA*C$M7pKA5KT?{|xUpys~V97DoyvXq!zo zzj4In`JaP>I3fq9sljMz0|*TYlNkA)qbXGLoX+ADrrqr}Et614vgwR#&@(j1&i~4l zG>9CIYY+_8pp!6mpV2kQ_J7U;ggIeeFm-lRrKw3vj3`w&!7$GMB0)B$ozW?hK88@` z;EMAfV}J-dK@*M+7@>x&eS_z}4xNPwL|`()blIwh0AVV(`$z~KWB=#q9Ol|!AJh^l zInz#qhSD=M8;Z;K|8@?84jGDU-IN$63-x?^AE80POmJzp-~{8ponuF2GcFjop$=&w z9ENLW*r1Q~zpPGZ<0>}1xGY>_fGg=k)!;*+D;_9R_0CKR69^NBCa;+P)-~Kvt3k+6 zuanevp9v>iI$dM>@jh(+JDb25z))vd%-9(ZI&fKi1byuPL)BPTr_g~S>+3uVc;8_D zXP@KtfederOwEP>k(klk{~6wUC7lf>4HHE&pwUMkk3IjjPcef5C#N$y3!I>xD=@Hb zcG&+)7(iAGhh^tK;c?zz&d{V2j^WgX0Gb*BArsjF*S;1+#+VRT;PU+6I#)wEv?7P* z{Gk#XjF#WWaA=}Nph^?DOk6Q|WVnWjtj~YTwX5Avu0+*kFva%&h8peaE2ER8Pf!x! zn2|6kOe|sv&;Ok~)nLj#wVb84`-~B!oN?`RVSmGJhV)L%7y}s6m4zEJfH}RL`{?Jt z#sCIVMFzU^zA&-n{I^^OG)!UqGzN6in4txMWB5|IY06mtjg_(V&ephL3}|RBLMF@2 z|I5{ip@l0PnA6qI{|re>TML{$*|IMvmq|k#f=LTK)pERIcS4>OMM&5XpzJ>OwL;)V zIRAs136r2y0V3)Xdj4lf5>aP8at0l=EanUcHB2FXiu}J^HHS{4$Oke6Duqdw|3xy5 zu4F)gTgreT@c3VTE@yNyenv8& zVTLmMl(zqmsB;MmB%#lagEObhf%U$o{l#=Jy!Fb62(ttoE|P(DQwGofjCpwloz2{# zB7ODwZ%AAr?#<+)!VFl?|0+U6Xe(&0E2Yt@oHJcS#?q!{(Sz40?W0reRZ4PM6%*7$ zd8O#f#>z`E>iz65)B<^<bl(HBs|~!<9V1b$sbOIc4B; zIKyX^H{LVh*Wx;}i7&rF4;%RIDms1O7p1jTUW%&8imq`kw4XTEVtf}X7g$dSc+r2m zDsQH$wB!ulkd%~P@C}q4Nh7ZdmAsCp@0p4#Ur(ew7>Q) zqU^e6#P_Rzo7F41t+wd5)%)d6Nez4LeMvjtB&kvFm-doM-+rf@_;&F^^3g+YO}<0h ztPNa9ADA&>`Pf3Dy`p_Bej}u7(e4q-y)sGg7mQKz@nTLR&Ffl#x;dx?CFvX`fP~WsNR_M%CYvT{+J;>E@iV|2Jv9dN5VVZhYU(hk7+=AX{EG2!-U*KPOa^=MwG-5yv_ zvud|`?P{jgAKm5Vx{cpDjcS$nhQVdci$Xvr*f$K=M~rH5rcsQFz4(Q1kk`Z;C-ROl zH5O;}9Xq2=voozH&d6}pD1M{5E3@k5ZzkNhf6^lDWj@kx?bo?hY+rYIdX-V{O}nmW z${1xEQIk?p5+xtSK=2c0UaP&T;PrLvi)!d_{ItRGdKSm876QlL9FF&YZTJR#JAN)3 z4@-#3yV*JzgzN+7CIOBPoGlx^F+f#wVE#o!eE?{!INySw%P4>j@5RcfhD(elTL-}@ zUjMZb$`d4@IkedD#Q@NQ4L>&tnhO!&sG>4e8!82_7D9PRkSIi@OtQQrE)xb0)e!JQ z1`wt+=!Y^27TKemP|0$W&`>5J`@lf~LNzDo=&Cj~ZO~_IsfKNY%^(>D=5kv!Vc0&@ zS8^HaAp%(Glx6}8eO32%jv6)#44Z{Y5S$&MDiyX5*QhX!6)qSRpAi!lb&xnzf;=`0 zxKBWNI=&zzR2}Z^Vqoq8HhiJ!R5i>?g|}N&Bt9_8Sak3SV>*T62N^{_2f++{l}$gZ z&8#Y7-fP&{=wM7&!!%aO1isKjsOEB+S3v+P9OJ4O03^^5t~voPjUg)`F|ZiG%BWSa zaQX}%S9z^oEjoxuXYC;1VgM^#3@jK8XGqWq6(DFDv=q6fC}-U9k8mSRKnb{CP&q0$ z{?VdK)0IPR6)(ZDl98x)RDic=cPqzPWrC&!nF&7ePey@6nYO4-YWLATu10D%*WRo~ zzHOfQ?5b-zZlZac$eV@QLuba_qFvU8f(+<%1D%^(qaEmYXt$~)wz2kW28m74eyvJ& z=cq}GXI5*xmdsyEGS+C{ZRmaDtJ+==8BgAo2Vjjy^+rNdJ+vUf=gB0M>vvt>J!ceM znxm!5?`hhx2Bh(En)#U+c)T=79)K^)mD0zD!dyelKKn$UqPOQLTPq{Sc@A%e4#pZ> ziPiTZvPcz>Ib`MdP~b;o6?KX6X%u{1@aVWR>gH4r$!no%_mIcF8r8K@-UIiaI-PYQ z{iFIX*4vT3Q)w7Dvhx1CTK$_{xAoS3_vg3&{MK9FSgsWl*K#&EEt!NmUhTkeyo&cw zC6PpVSZN`a%@j1rM>$IKyLd*bm50*3S)Qx{`R-U>!Qw>+vSNMtix(X%j!ED7IsX`5 z(cl)|2HL5j=}T+npH4rMzBQdT?AvK_x7p;|cdzd>iTw;LT<-dTeE{#KNBR!e{?J}k z$BfqwFJH=P9nq5CQFx_0G?Bx;&4rKd3F%#Rc~wx9mqO(uu*b{AuoMbqr(`3qs!LFN zece~1yH?KAem!+&%AP6L3~1Dc`~KR ztU!aVJI-8l&K%yK59%<5r>l8#7R~a^ShR55=cyS&#%(1{D&b?LGmhx0d{_HAJ*`@YcyDG^ zo$Fe;_ube!m2PGFo$|=_T)%~Z4MJ&83 zD}2>7giN~ap25Dz=xso1?3uANtH##Pcc$-zAD&77M(Y;KKE=4`V0M*SE$&%#;3?*W ztFKpwlPJ<<%=qn>li-ER=_`hIb;sq?MZ%k#uDX1RW(B7x+jp?f7O}4~>gm7ks$i~g zET5x!Ef#9K_C%dXKT+ijpQqZdU!88V=QP-I)xSx1LY}R^yeFA)J*Mi( zue4{CG<}|4gf?2@8)NYy(^MB71#SuZK$!S&5_U!+VDO!he3$UBtSU(6A$MTMB@T~i><*QaL*WMJG;_ftt%?5wz z+K?@p;F`%|A1||Oqd`y;2_LEHAI0xUFx6pb1La3_WsF=te*AI_I<9O@AYh^NnOy^B zzzWesadgHGQfKQ;OarY4wG%i5WFz13t@od*{^iV!^r|E4RcpVgMT;CcVR6rvPmCOOF`Y&gYfl8`u5H|C z{pc|#B#FIYkB@L3P@2F&SwX(0gpI%oDI;!@f(vBUsomeL9k{mOg0}S3Zso*f6g0VX zLQ5tcm8eU9Fb5}62knfjE@mCpd8|O_yXwpPlXLOTv`ZebxX0qg+vY^Yj2?L3!5Y)I z9NJo|+v_*qyDExq4*ab3CskK1dmuR$NPko&*Q5R zhj|WgKb=fpa%Fox@h_OLMx+@%$zd-Vuo6^Wq-Qy7kKg^S(yCqjUZYJa1dUPjzo7Aa z$?CuwPPZRuEaI>i3|Pq}(AdghFZvg78v9HdbAaEQx9v6XrKy0`Ca-e3Ba4xjKqBNs zv^R&n;J^5;lHV@=b(03_e$!T*#y*oq2f$J}{@xOU267v6UV4Dh_1|<@$twEuUghPe z#K)vz5Ubx>6b@-@qGEOUCeq&fG%CZCpo?+oXVABFYOE zUX?;+Jn2NYAb908SNTf+;7vZzqXn4yY|uS zJ-hCn-ZgKx{7+`_^|00e(94u0RQVvWvIkagC#wbUpLTKqR<2l=Yc5GXp}Fde9eaIT z!z~RGMlYP#R{P-uxm!5eQ#gcF zzBp*zw4u-f8x%%Se#W34{E>z6aLS;Z*t28Xj^caLU7yJx6gO1m50+s9y$r-(fSAZ@ zk}%Fl0~wryS|@(;IfyP5o`C6XU+ z`p4`J_2QOgv>&nJxvqg5=xD|OD&8n-Ko^!Jj8?3R6K$t7pjkeWNSCVjzcsC;QnS@9 zt4`h@xHX+Fo48?0k87%u?7qt<25xnY?l|R=m`4G6#KkyZITFPsE5ct zRYQYGk$2whR--VxhIq|z3*PYz_H(=#idA09)K0zc5C`<}d|_A-#-%nvU4L)nb} z*kGzU0jNXfi!U!h#XfDxI8;{LwC$!U(Q%DNcGqqgm$Pa~qt59qYISH^ee7fD^yj+^ zuZyB11BG;Sk8u-P9Wobz5w1xHYyaqskpfPVN9kbW!vQi)yc&% z{xReNt-oER^#dP*Da=0brtDE3O~_T+V>9Dce6d0JG867mP~5`A-)F*e6(7EZgjQOu z7<$p^1^eYGzG4(SGBD7-O?$=lqly5QtKe`91Eyj;)^VG5o9jml9GfH^jt&+$>K|}8 zoJ>B?;dy+3Y9-j8fKK0%i}VnOi-D_YaC5*hD_pZUoPGKQ991i6#~aY>g3o~=I2jnK zhUJ%afG+7y9wX|qnv<-D_N+cQ{+7p}Emx^GO|-0LeTWN%?GCtZ2CW8y)^tH@8!4pQ zIjx4$8~n@$#0sS+1ZP;s(1=crbV;t`a3w*c=lEark zkZrCRfWuS_&c3?AGy*~Pa%S@dTvLy+1`-2q#lVOhO!7&B+qc2cAG|}$bsT=9E(Hdd z&lzf^5AeP*fNKzy@Xoalz@QaK>dE z&YY3CRnuZtk~6X757!C~?;!Al4ABS92An zQZzt=Y~XE7GTuQ*R#V!J2Esng=Q@RegCZvcD}AgB@w=d%n^kaU`2}g`;xXJUkKKDn z`>k45o7#0NH{6mLTc>{OCY|cmxMM5g(o{++SIufur%sgyTQlQWOUK4_$z$3CIwUr^ zdBCUwl3B*Ys@(EQx4v3=Y=bPCNaq_Gex-J->|L{A#sYQdCwFho z&iQ0VUdH?)?Tewa$Ug>;|M2D}F$u5iqzkmHnXNnB_=r3>am>7!OrM5URQ zys&MH$xE3!hvH+Fe<;5pHIkHQk{V6uLxK0@j>7}p$%*Q6lpLi7ZV%kfm}M1u@!3-4 zm{b{cPbH+C*e;>a6!o}WzJhi%0c__rA+G*p#2s^!qr124k4FlpX1{W1bSF>ja(v0| zj=6tM(8j8JpE(#c?l_q{eCLW7Fo0Pp?^b^08646!#gik8f5ektNMh*iEwpwm$Y(9J z_UykXX!efs>ut{s&<+jZ|52Y~QW!+oIfO}sj9O|XAlE7W$n1(fE)1N@_cjv2cPZdI z$SB}ZF|=CdzPI*e22Qgd%83^)uX^DHRN3O@g7aaX!*Cv6irYt2te!qu@yR}tFQ;k6 z#ox(M1GIVr$ctLN8wkEMbE&S}m7LVFU(m9kayN@D)<3#0$K-A6hEmT1SCa39mvYOsFB2YuSIq;O$b}!uNGn{$#0s8uVN_lRYG$z zzt&0`HTk}fD38n}?MR!(t+a>fjT4XW`O|&r4dr-}c0kpB&~~j9c6P@>g_U?{h-MCy z2-PDX6q3=jd7*Z>@Oa>`_5`K`GNqB1>bmv?o}{BLcSc~r$)NllVn8Kc=r+FrsTE6W zkS6U|RWO#Gv(E#xqfPKku0=-O@r&*noKX+|{qM?&9lEH~3a7PgHlTam6-Q2PxlaCe z)%@<==dZe}d-q-+w9biTAI*u)X>;`akvs1^f`K5htSM*VV90Tzh=&C)q>s5UnuAJVQ3<1l0$kp{L`9t|IsDd337)<_Kk4$(hBjvuNIOGtbiQZun?9& z--9s4A!xvZKM(=45_1Y%hx%!A-!43+P3`A;aOWeJA9g*ncBf&s?HGsQrn0;h)6vy? zc=12*6jv#nqnuk<{I9@!Q1fsQ_F~?i;;O~;L(y9{ZBYQ1rfA=-A^14aoWNz0wx&eV z>dv7*(oJKTO~wXB1cr>I;{)r*f;m~b56n%3X%n%1z#`?#D!?f%!aX)(9u+4*P@*SM z#cnO&~uy7#F9TDh9&(j49HHmz!Rc8SPxr_|+{30(>UV_@Hvxn+Zer~N; zlF}sGoylb3BIRdtS(r$AD;-qx#>W@e9J-!l{I30HYm0eJ^6S?c(DHZU(|=b7+8{3GVgd<{$+mQV&r56ZGI*_-a!ko5ekAlDRY4QZS3Ic!4gzRF|&6*ccr96-8YI zd$^@ozMIDOnMiu*QdS0Hj{I5p75%3+aLD8~NkgWzX8DiuT!%~lR&oQM@GyitPhWHr z+zHSNp3EEB6yy`R6cKsUSAl*afl_iW{Tuys$8L#^NM*tKIB>H{#C-%F>?z?P0!1DVcJn>vhS}7;lT`g8! zo}ln1Ya^Hm7<4UZi?&LlP42As8=<$g7X1XiD1T3oew+P3(`e)4p&vU$TMNdIDBX3U zl0NW4uc(&KOGdjETJUm%MeyYywjJ-J13fN~YoTCT%jAry!NH*kve0DW3I=B+8B4@q zk`K-#)G`GLK6;nroHX>9MgeGodK0kGF?F= z(~8Ill1x*DhBZr<8tP=m(fc_`ZL}HEPr|VS6sG&6b#UR&VsKyxsX0kIlOcF~0C>HQ zY15<_)b5%dRd5@E2o>scz>wOBpfQ+%BS`C*x-cxR1f{i3a4xhY=KCbMI=Jf=|2g6L4z;Ep8iD(4z8XxijW7JW#|{88H*fKr~ozkVc>PhBEb`89Vd|XO&xA-NW!y8=^6- z41(s+f~1|vkT?+O;JO}lCRLGsnJVY17SYVGDd&?u5i+>Iv8mjVNjn}>xs4v|F9Hxc zKOvSIrXofPtmvpVRf3>pO$0#}1$1eG!Wa$)Z1@)!#Su?6nj%&?x1dmBX(~4~XV4bR zgfoeD$ZsJSBDYQDVla~=*OyMxhG$|h|Ik-aM?9`$HPcj%uw^)x#=yENSvTTj8qPdg z3{93UwS|((I&e-*l6GnI;S45(;=`HbQu6@Bq&8S79nTmu82{Kn)b8bCP<>Uj%WY#) zNLoIgF{lO8EmT=Fd9%_cktTVIwiYSx6Pn~Hn)8yfjD3Fi1*uzf4W%{Q!~@0SgMIk0 zU%cySRV}U*brTsy4;5#-E?mZ`6ELi}fD`~T5C3xTC5acJZc_hPEzeQAG3*zB3rQj642EUD_Uu5#v>FtV9+4m`P*{}vN_Z_j`)Z|*3DXHFA{Fc%&B_%%g zQX69kdMGr$Pr-EaTRb8cEIYQ5lKw!Hj!U{CbVb4phS6 z?878(D^s3hnaQc%xVYH#B$% zKZJce)<{he+=t5QERz~4l=cH8jgO0qOHb~YoW=xAPtyK-<${vvI0)T?+X}yQPtQn* zBT;tYA-ftbJbcmcwPcA&KNuf37{!ht2sd3&M*bm#T*+oorVu82b`V$GcI3!{0(<(S zt0~<7ln0q@JHq`e<|ZfO0QC8|6X?xaayTM+KO8Ua&pw7r$cMQTz%QT~?iXs+)WBK& zcf&_4%@zAd6V#wt`4|KH3b`iMbiD!KWr0NcR>~IDsvr* z`<+40%nY5tscZ&I9GVw&ZU&?b*nqGnm}Y;0XkHp+AL|9CHKw`0#7tL1rg|-h+5def z7J`Mclhfj232a8wJ0&6FkvN1r7ALAyLBI$H1@=4iz4W{}ANs3CM2O?zA_dVf@UsY) zsrcP!6~U6lN(RZsOh}+K7*&lx8~B0;RRfQOStqpOugz(rhA&jfcz9Ty-?0m7S%eU- zd#eiRB7}gX&M7H~6>)5-f_AjVhIElERdv}SDFs)nWITH}R;$qA{SWtbrG^JAx){q+ zQs?9pX3De_SR*b@K40eCaO5l}A_rH4YZK$O6Yj_NkowqSi&a^nPAuBWUvQl?tMp|K zYYod0tiq0>YEK#-!yK!WrP*<1#$2|oPxVS!pRPy;=A?}v6H!amOsHZiu#!ihELGQ5 zgzJ0w@*ciE-6Gv8-6q{xst*O{0fHS8wyUu0M>LaVPxt~Kt6rs4z){ttLHHUUk{+n> z$bHT9!SG#xBFqnh>ywdO-6AcP9*`cAa64S2N8BB)4s105Td=N{0U}5n!n|EYh;=l~ zU$RTtsf5*5s=4Wiz*tvetH|<;7}d-#l6ihHNV*v@=@A@mJuW?2ngw%$VK^9TDwcMr zmK>vEc}JK@VNutJ@Vvu06;c1LT*PW*)5b3t35c1VsQ=si#7Ixf3_->Hu)286-ITrH zCXzfpJ;k1e&swp%hUSyjyu~GT!X}UJSJ}>$Z?ps7;WuOuv1!SjS!%~OevcTr4C%o3 z*+{6a;~Q78_ZGQTa2w9IwZ-Sn<;3 zxT+#L)o@CkoYkiy{R(j)%MLb$@BhW=$2guLgeod5pA5#gFl9R_mF<5cn?H_Ptw4@t zSF~FC4?Z;PD!?bVP!Pdr?ml(3lGN$UbcUXG2^R| z)EQ?!%cZU1MziE^D!&SCyb;Vy6lOP$EevNlIOB$oAb|_Br+tZ1t!EbQ5R;0d*1s{a z(>_s!HT5IhQWrvtsm;T>ki@)Vxt=tFFEmm3 z+Yg?sE};gahI87&PpSUCLn@UWT$OW5RZcuGvn9EIShiShvZ!9w(=48F*~13+FULd; zal&7xq_{@C099^kS%32oDNnq$f&Jf91bgn>uIL;}>f%pOwrbSC8VD&+3rtGk{ zDP5~r|7|-S<#}vGLr>Dmd(da>jmpurld9Fgj}<88P5tI5#Js^_Y-(kXs%y+*2r8+MBSKl!lPI*N|Hm`rumhsd^C7aD8P~X)gcBZI zO(37Mi&^YEhgn{n`Xq&+kt1PPaRIfnaR6%B;==&q&eoNl=9F=m!{WU)V-|M|@>QuP zwj8$^XEc_%$mf@JnRQgnUpRVWnsuvX-?l5B8m7j-pl!=BJNI#H+0?MRd-N7_-Mt!i zfZBsuvi&%IE*^QR4rlV*al=wy0kv#2LhTWjTSc<4vh%M{qdT57m$L^6F_hR+i+Q16 zSahBkD#sL4!;To|c>WxEf6?ir-(taX56e{R<;YT=Vza3eJmCy|Ca_FGrW|IiNH;3j z{}>7M)i!NJmQ`^|U4czZMa>;%ZPf^v&gQP@)+S;XP)!dpkIS9%A6}zAQ3tn%L>62n({WkP{p~>)j#+SZi3466}5~-Gt5~`U$Lx}ru`~* z9Io;USfQJvh~38=y=?E1!ZPK-`eBvI7J;qUY8|Vv3zh3ZW$lzyL>+d8zJl&s?%3ry z7CZlPd``v}1IO#k4!bDJCaO$t3wJiv%;f$T-o~BHwzpDCd4u4pdteoFt7dydqw>15_($}_i?5c0I9Cuo3@Psw&g7Dwvlh#K%s_~A&|8^H$Sb#qN-jQrJZJDQ-M$VHf(jBO3ec$cxHa54leN$>&M!(v-(g-%C ze8$55b_WPv#BkcCvTaJa9uQpj!*IinAk_cubPsb2l|8!o|G0g{?M?kyBhDda+kNFP zzPI2QKh%o9y5}76Ll5+gS09aS?g#c=3V(a`uWv#{D2O251d~M(Zp7~O%5RK?F6QO! zQcByTsHN{xBHaIm??@upkeI&4c2D|iUsrESd<8pVhtm_|#nN)pI%oHjP$|^@M9J7E z2e--JSzOS#J#e*Lu&kZ3(?_Plso-;Bx@H?Pp1Jn}8MTJHPB71@)QzFV~JJ(%NLZV%gb zi(;c*OKK%uFHMx@ODjXR>J~S*Y&fjmZ{40aUkGN|X}JH3m)R}vqKh4lxKJrB7I4!1 zu*uxR2i_33L2b8%d=4<}ht5fQQ3`fog!PwrW7EhVJ_f~m>FG(La0Aj(p93uLp{={< z9kR72zXo3k=9f!ZjAQSlXQbwedy&E0rMDQD@XZ^ijyG)sKe5ZH{2r=_=%oq4-;HM5 zV=l4bZz=VYCP{ZmtE8t(+wxy6Yla0gCu6cD*V&rooCQ?W#vvxgh2aX=IHDthh%9fJ za(09MMayIUS~riz;Xz-+_|gHfW?{;OX5kUMH7>T2miZ@ aA|&%+B-_7%^`NlNvR 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 delta 80453 zcmagH30&00|35zSK9}8P*xlcI+1OrdR3vV$sMMMOz1QkiqJkm8a@6=p%y)_Ro z^GZvsOwF`Uhnbbyr5$D}cBvJa!t#I4ycb-m@9&?FdC$D({hE25^Lo8z-fy-AYa;I7 z46+eQ2=T^6BFR}F@q3r%XA(p+Prj>)(J zkdj@PZ^GEpCv6jN7T-NXNU0eEmOWWGrIe`nM@l#2-uUE%8Dn4B`+0ZV?;-NA>*K~0 zj=r1Sd^3^HEywe;ap*8c`Td1^%t0c@O)Q&kI5>DY?r#y&`@QjFCYL<+OxZo6G(AK} zlj;eRMinNv8UF=Q68GTwxrv3g>7~9y#2TW^EW-q$C502mbgQWug!?swbojG$(v-5Y zqYo|-18!8;BqqWlywCvM&*3Ke;K|{&F+41LZ)pgXAEzgXM6v zBjgCQBjrN0N6I779wm=PdyG5*?TPXfw9DifXwOt15~|kdC=qpn9`opf^g%?>2kT?d zZmy5B;U-=`6*trL)6jleKOgM{`lUqFFVinW&vN}r^sLgqfc9$rOK9)azl`=i{TZ~+ z>d&J6t_8ManQH;OWw~WJ+Rs~_C!%GAWj)#(EW6QPZYf8*!tw^%Z(2S?`<&$*i4`p$ zSw6zedCPeW_}IFRP^-iGA`z`StRJBLq4h(w&spytX(~P|JbnzeO2N`-t=13FYQwLn zA#P)yR+}UOOD5DSj^E4XD?UwqX8QaZUJYHKzfFNwXQkP1%U!%jLUd#0C*^VSc=U7O z*)x@4*%N?Ekc;GE4z0&XGoen{Jg(vFN{$l{Os)|lv5-g-N0LbzX-_(n9;6=`L~=<1 z8A~RR$z(d2Ll)TYDbayWsrD-jw>X>NYI26)>f?mAo!-tS_AE8pzFmzvvQ1qo*n{*& z`(yh4VN88tTqiLQje{gwH&{22BA#uctkI9yY-Adrb2GncLRin+OfCYE zvHIbPEh{Y!k`#;;wwc6Owqc#c^A(nY35;+hUb0!X$X3}~_K};&zRaP>5%zwTR`xlj z9!9#FW`XYYFoYO;f;ruGkK89tDp5T(Q(qcL!)bGxNLvBsV}eCZcL>S2dh+YD>?#aq zS29d&hU*yKGnx0KupT;_wdp2)4dzcvcsr7}Kjqg&v?b;_%i1>bDVV3iLJo9^G=Ol`qd7EG9&zymK>`F2@af{efI+u^y%iFe> z@K}K0BIP(jj{yBs5C@vc^W=FXP<~E+jsyY7 zhJTHQ%G2bh<>~T_BmFERXza7h#KaPAVxrtl9)@X#V=_N^0VZIqh|C+x6OLTA zcBVpItv$e}JEis&&HLNLVBs4Kjs|DB;*5S9w7gmuDZVTZ6s zI3T<#ydj)IL_T-qP?J{F9_klmf81}W{bN7He$&rlmzqX()5EoQfKa-U;UvKPk@-An zWxinkgru22H-AoATLxK%kT#a#mM2LEOR;4t>0y~^nL`FyKev8PhBDP4)Sb6)ZR+2w zE5ZXMeIO$l#Y&ozV9ZU03yP2Zo2CJ*`yFzL{6f8G3%jp>3>|0B@XwC@+)`qhWSMQ< ziNRF(0#|NQwbz-xj3xSNT=x(o9d6HW()P$L|G9$wLSW31Zv#hCd*9%uN1h7aBp%5P zH&J^@M4J6j#1{Kgk$(2=k+n3#zBMY!Rz<2vC-OV~btVt+uM730o}?=sLw2&5( zEINTsAl;#uX`~081?Sb1R@3{Wmmmv9(pNAE6Uh@|mY79e6Z?pL$Wd{zxR_Lm8^w*} zn0QE9xM=uhh3A%E)M)xS?3m`|Ed5~ulX^J!9NK4ZQ}srj<`@h_;A zDUmj@47KD^e@mX_N!pC5lEyGq(o}1_wF7N!eZu+#?QI=m9YXt9ms{7;zSf=AU37@` zP3v(w)Oyx>mJVY|r+G(wy@h|Q5AUrO=-&G}F$$4VFR8yYSjv+|O5>ywsZ5$F&6O5P z%ca%QdTFb)OWG?Pl8#EprPI=T(s}8k^p*6TbVK@Cx+mS2oU$bA;n;nV8HUTv16f64~tp3IF3VDsZQMPTD%jJFYVfmPRLOvsZAYYI#%U9%U z@-6vS`49PlLKHR>fb9jT5}OVl!TraD($2wksM*Q;CAUFu%-ka|=-uAWxkQ_rgx)vwg= z)Eny0>OJ+o>eNX(z0R!j)dlLpbmZjx=dY`u8(ejE=QNI8?7tWmFlMHp3%+I zE!M5jtbC33b^COOb;ookbZ2xQ=q~6k>#pdo>2B$M)%~G+;6XeT52J_Gqp3%* zN2EubN3utnM|+RX9z8tzc?|N%^(gQd>oLJ&vd46fIUWlV0%+pG2K^;`A3kY*o(Eg#pP*1xAeufM4OO8=eyhW=;$ zJ^g*X(;yl22D8D}5NHTDG&dv~S{d3JG7VXVK868?97Dcgw4vBgYM5qt#xT#Y*s#K2 zTVvR0*ls8{>@yrT95b9SoH2Z0xL~+!xMH|wxMld&@Q2}nkr)-D(P%X`H3l0ajd8|g zW16wOv9qy&(`57X@eJ?`^^EpR@J#V+?U~`()w7ppf6u|5d7dLZ z$9a}`mU+(foa?#JbA{&`&yAkjJvW=6S;NjORJePd&fz{KoUT=WWkBp4FZ; zCc&gLnM^*W08^+b+LT~QF|{^jn7W#JnfjXsoAOK}P2)@@rZUq^(_GU+({ht-wQ0R+ zt7(^Muj!EKsOh-rwCO$5dDBJHSElbwH%vd9?wRhJoL-Wb-plOe>lNq~?$z8Y(W{kL zTdz#7EU!LZ1H5v)^1ViT6?>I>P4jxjYo6C)uN7Wvyf%7m_bT_==XKcYnAZufGhQEf zUGVzC>l?4@UbnsOdENJNnkBQ|Y|b&apD@gloV-CO!B8s9O;p?NwNR-*yST?dMLHG zXx;8eS!plWfenDj;jA5I3)5p)E};bCJa9ZScOTv|kn$uNYFQZk&D(dlF)4(eMLdv9K9I^6i})K&7k`&1Z7WHV2knXI6hX74I4Pb!E+tB~$LK&QQ_7^nq%KkynkV&@`qJT2 zj)Y7_8YT^+BUlKd1=2EU8664lZKtE83aNsQk&Z}5=ve7B={5SKTA&uvafokIX)z+( zvvdlJY;?A|OnrgQQ`f3%=@J&-=u#Hn=rR`H=n59!Z1e>d;OJ@=;OKf5;OGVx;OIsc z;OJ%+;OI6M;OKT1;OK4yxG(5SmKaL{eaDh$Nu=*vk}b*f151jfHT}@i&eD#4YUyC< zKtJOV?;?+QU+{?c6_0o~c*MKMBVLEUSjZFfEaV9W7V-om_T{?-Ul#HNf9px>Nuinb zwDlb!kcB@X*!n-~2SNx7f)Y+D-3x1~vZTbjnUrAKabXhZGIjD{m|9hVp) ze)ssDP>+Wm4@onRT8~;1=uziUN1Exe5g|d?=58X=k;}b4qN($A^GLXEfo=h=3v~-| zy{EfJBKXiqj~b5}62*r`>IpV|QI=;d^X!-V%rg8Ah+2<2J+*GK=k<*itY6v}^i4^y z-evg|Qhv$$rS&Qy)^Dvp5ZU^pwTkGiKUsexUOdy%3qGP?zt(qHi_<0JCxz1Ulb$S` zNWYpqwPZ5AQ8u>ZNqVnrTwxJ)^0Nj~SBDuzqS}l5rBa>!RJOnUqim!7oqnOzb9HtT zRm5VGiFtLlzpQ{v3x`P04)DzFH?VIg$r_N2Ypy*%+b_w37lgW z^CDLJs_dRN@4~_fWu%N>XY%XZQKKf7l7;-boL|@Q>*moDik>9p{JM`{507I#$N2RG znuX*Hj?E^J5BT*0zh0ig=D)(P*Z393ZIF`}zk1qu1@h3vIK^>_t7byM=^?-8X9Zx5 zL3!{i-=q^AZyWekKf=5km_-5q(@g*-Gl3$dh}t>ac1JN&ec)ws&BjM2U@MinIHS7-|DJ& zXcOtnUG*7PeT_?u>hEiChB&R?km#xlT=hCv&E|vrslhdo;ehMGQCEEe>M#+Benr2= z2I?w$B^pY@Xe5oo6DzhOq4>wt)S1hM%1BvxOFML6hm!(M5&Us&hQmpLA4Ljs8i&Jd zIJdXk zFackJQ)0Jin(#ZUQrEQFy@>lqJ@w<*4D}TI0A6ZzuZ;l&POR)J2FKf9c_P%_a!6Bq zr@_tbmcdQE{V-UwO|Bsz_OrJi+|3*3bN}dXivA?~JA-|_{r~mM-~Kbkum$dmEnNz}Yo&UqfquL+e08>mYC0 zv`JpaO%TpT>W9A4&^p}EI>KAbdKl-gvO65(2y&=p1Fkrn1)r~R7;VnY{Mjb{Ou#A3 ze;yUt{&80HDkk>DREp;txKi;fYg^c=rIf9gUXYibw1#^(5+ChE$g%+H=t;6I^LgFJ zG7m7>mS=J8W0{L&Hy!$5R`{TBhKMQIGR>9Ap8N9EodZOlJf!t=TjF z+ChPl>b0XNc78A2wJgE)H_KvNt1MWV(gQxvQddiqs-*ieTi}myECk{q=%HjV>u3H= zL;jronV~Ub;_x_}y>|dAPPIOkwe`(eKVT)iL=bTf(vG+B8iG$F>7jodsI%uU<9Txe zmx1;&w5>QrV>6lXT7uo>=vUcwxgp-AfWW&FTot3MZ7;};wU5e;)gwW9Q}DJPx9+g7 z%MI^ug%+%D!WDR?};v-L&m7JE%@v<>M{7(WyEoBU4yW{HvYl=W>4_k?=-lDmQdr&A-uMaVyY z)-lJZc|FD45|dM*LU@_`I>pS8x!>XfZ_>;Jid68rUGsZ_Ez z%}bAI53=x|*LFydwGvPx3M=i2q#(x9x#(2MT>G@VFdAfEmp94dxuBCl?+0%R{@ZRE z9u^c6Iy&^J&=sL;LSGC0B=qypE1}mAlFY=OPs@IYN;L}XF)=ICSg>BBq9 zlMw^OF*9Oz#G;5b5t|~; zNBj`+V`O+_K@^GJZg=K)qEFc~Mg#>#S0qlW2LSGS;UeqDZDUfrO&?7!sdGu7`@zg>N*`b71y>dNY))vr~*T79_smFh#) z2dej1@2lQhz2}b`e_Xly#of>EUcP(j?!~*G-Tmb5g}d+F{ombp@4j{S^}C1e&bvGJ zZs48j+Y@h3xLtg^==QkVdADes5D ztA47wU3IJKX4Q{X*QxNQ zRV7sus-mmHt3s>%sti@~tsA#KyY=aYFp1Jw<%^5eR-<)=H>dms7Q*M^toOBcK zUT+rN9CfqT&2Be4-E4QW%}x2nh%+~4-57f#=fGPn@#i1E{qe;gH~+Z)$KvZF zuIFDLe(jxWZ(KY4PFV5P;xCIoFTPa#Vez5jy~VAITNNi3#}!8whZo%|`lZMg@P_YP z-!k7xz9qgBeJA*i_kPp+Wy@tkk5~$)Q~UNz4=7BkCn6OHnYVj5odVJ1EEw<#$p3hZ2r* z0p&JIB+4C>KTta24XvxlT?w(7o<+wzJm`jcfmY=1sDa3YmsoNS)Ih|F+za*dT9JFB z#v5ak1O0tamGfD>9U!cxJfkae1Yl1nN6rMZJuA6Us@nKSvF<1iggFytP}A83QKkZKes+Fua@LP;oe?ePQZI24FkZ$J&Hg+7HgR1peY zhOR)nAL>;oYtSx2y&dH>w4tKV3n-tUy#O_c2n8PfLew@;6M6+Vi%~Q5(dO! z*drqD!||i^M0+i2NPrdnMbtpZiXLhT8;F9*^_V;iL_}B!G3Zc3>=FLhpkU63Kom@D zT#h;tr8)F(T#ZINN&+4@P)|XbiZ%=+0!xY&<7U(lGb_d|s26F)2pva&TULzQP;Wvx zfHpXfIFIr%+OML9^jI+-Mg5~zjFtF$B^>&Xgq0eP;idouVl%!$NEEn_22$f0)R-(9 z&rOAd#84CoZ4ecspg=;VIjD^&P!n@xF|jC+kO{=az%E!Zy^T5>1xwI$8uehUnBIl{ zV{%aP@!)@`84_?~0`)QLQLq%fVAV0NpqxNE0QFfE7?l^q7xSG~@Wlm*xq7g#+q@T90Bty9??}6dO9t-O!ki0{xl0qXzO==+xX3H6~=m{5a|d zC=byF7r;m2K$v+DYH%M1-I|A>PST2b9BQa5ZaexR)i|gn4w5xLj~dG}4s)3|LjUoY zC_Vr;5O;hC3Jk*x-NeJ7;xW1TE#ycAD3j1WiTWv&r_ufx^$ZjsF~jH*n`*@jgH8-b zfey`AP$z1|{2d{EPoY36=I;q9?~2kL`nQCk(FX;3vS3hoe-vQA1tjSQ(ZKLMmYK6~1U^qHcx)hAi2rqfx-A1@l!TqjW?&7j>2m zm)^K3M%@nuz?M?fb5WoY%Vg9`P?n=T4K>7H0S+uP38{u1u!66E2)fBb=-GmC54}MgeYXuudALL8QZsIyQQ5w8&9#H3CywBJM>iV}hL zhd2U*{_1Mc{+Q6ukg|RTYqne@^b)o=m)hV!FCH~^6_RyD#U4po+>9`qyG9GPwC36|un9J?Z&LQ;kFHoQ_>+&PUiM^>!#AiLD$rw_km+^Ve zi=>o{*YCr38^wk%$YQe5u#QZ@%ayC-N%FK|reTR;kvPb(6Q@+qh#klt@&tB=B4q5yp}cCe|} zOJs&eEe=U7N4_g5jP>d#`PGg#N0V7FD^(w5@4wzJHcI$`-H|f(42Ot8bw4OK+Q)Kd;_eT+#XL>^BW#-uorCb z6|4^X^bHSem?Vx(LRw;yC43UN2R2Eg{)rf^^>1p_->;$H@u**D#^*`k^K2Au)z2@S zcI#iy`{Oxc;Z2nx&<1RB8}O;h5NQ1ld*G&pHtPmy4xg`Q-4AjhpD#tjBc1!t{`HOe z85#|KQ=@(+9j$*uqke{7>vynzawKfCCl#z4?a5mp;q}rij&nR{3Fj=d=Co|G7qG_; z*W)sl26IxeqL^rptlDxz5um5(yP69)v9)!Zbc#;3D(o~3>KIh_gLqXjo1=wI zGYNXJym)_KprRZV;4s%_yKZ-4fOWGpl2d|V@=e7DRKp+R@j83|-QNk;t@f1i#BiX1 zt}z)jsiBa9G!&y5iXJ#+n^)ddz?|=ubGq)8w_;@UIXdb{%gduktj5S*>IuQ-T@o9rhJ^3KRZ`AmdHEu2@YiBPX8FwZ?^BzsxP!kcLANd?X53B@q2JGs6f(1 zbw5ZMYFjuIWCfslkA3b1nBaZ_kJ9isv*Gc6`yuxDrACh*jeg1g-37dN*=^T-0vr_t zaT1gC298kWF35ya29Am&{XaPh;lc(#<2E>-3y>)t@6P~+zyz?(_WqxhGN{v^t$^&0 z47jN9C6s%qRf2WBe1T5W=9X7!GLw(eX=a5~Fr0M=Git0$mTz1F-|OwSFTpBbw1-~C z-4=U)R=sGStKA*a?!MFR%%AgTnXKAkFV*h0Yj+p;-Rdvcqa(>*9HYzv{@Zpp9}&J< zCPpz|z#Xixi7GThBU-$pnCk^1Y$6-%hp%>Jg1dhe64^%)o&kqdDa9*4K>7o?ME2P; zzwu>ev6Gg$9{ccV*keW5G>)4E;Vw?s4%2HcsN%@tZ{7@uMPyC)P8C(f&$k^_Bf?{% z(+eMzKL`l$56Dkw)^TU+Hc@lsH4i4NIWq2VIhGPfNjUwhMM%w9&Dxxg$+2X-(!;C@ z8*9$E`cBDR>$bo$Rbf-jNqj!NF@jnpYh7LKTIV9?Y787~b~FJVZiBRH9!q+yP4 zl4(Z^(f}q$tc$r)fmtzMtW0c4Cn)fp!e88&G~Wr)i%1Y)OpeM|)9D#}J?5yK*_A$H zVNtM@LuvtxLB6CxI?RLVVi=5L<6yd#4QM-rmf*9X^=yDu5f5-FVWNXs@m=%kae7dcb-{sIb0z6A)!7zHoA4XT1F_o?qX_VvqbQ(gV9luVe!GiUo z!!&~;zFw@1o*r-00 z=eLlS&8j>%i{=RdR>%#^Zp9mF7Mr`n+m45`i?&{_>^z4KurMmtt)zn`u;uvGPWz$5 zk+Fu=4#$c$6h`fEoN(2@t^wV+FIlVgZ(Xaw{pz|8UPs~49F95b*z@g<1H5)PzF9}t zpue)rK~1L0xN`cOV4H{dGGD$#kkLgcs=|z~8BG;oim55-Y0NAYH8sW8i$)_g+&p-;VB4byYf+FlwI6dyryJDw-P_KWoF6;?a#4ow zT>HGSO)4lm32_8r1vD}_EQ7}P9yFg@n@bEoQMs}c1e2BJk_-&+ zV7>6=OU`BWZB6XS!1EyD_t&Ixt@KCbxOVLizA|ED z>|9`DTj#Z}%iibl0V!-%)=YI#ZyUCQOQ|@a<)We%EgsLb zTR{0d*Qy9+I|Ujc3YsB$v$dHV2A||cX)LW@qbXRsvYeR#$<^JTSlp`lj03OHimb}4 z%twpHdD=N=-IMM8n==Oj*JTr5ac*&5fswADiQheQgsyg$)T?cFkG0=%AEN0G_8~D( z*@P`s@t^Jra-8wxeft9kMis{89fc*d8@(24>Yc(?Oo;GL|6ytLw;TVmHTlwmuj)y|C`v-%y4RouJyTI|ci1jB9tN6HMR9CFieJct zDQSsKryqSLdS>BUhkFd{nC1LwcO{i=m7S%6+RvRoW(*n9dy#OcHvQ7?Q*C#61PDyRVff=!B6Jnx5uujfs|5Ki?ta z{CVdM=k@0nbjY}zw}`J9n6WLkr_{Q^a$X{m@mjN_rNWqVYm>?eENkjk|}FHkHG?RxewXgjssMbM&LXl=R)yevog{t1lKWTa^;nYtje9^P6jaa@12r z7s6w@$4{LfK4HnSyWL{4ttKk|IV2}As5N}$kRV%NdSGTmO39xapZ=|}&pdf9JPPr6 z^r@j#eD`rl*S>`iJ$!h*>%>NflK1O$@)FIXh1Ew(SF~a>G9aSW`;!RKwpH_Dg>lMJ z#40#9=eTjLYzs0qKW=3nt#PrFrI$QR_u!uUX*DdcPq-Y$lGxX>ni7E+tjvt5c+bL0yvjV~UrEgF{! zzp!3gt}h~GIq389(St4H#zU30G;8$QHTYnMNdTc#$p=9=Im8nDuk`7WOO23?&w=m8 z$&(G)(_d~Wj2vBS;O^)j=~KN8F{Ict6s(*(Y-niss8I+1yfvk)dPl#$ef#aG=-YQ&r%q)< zTP7#RZE7}1ZlO7~{A{#YySH*7xe9Ky*d7V3HU zRIGw5#`!;|G_IR@Xy*JLDIUl;)TVF|S8FGZ%5&CSL?(kI>hjvLyZVoyHF+J!C8TDh zL_HA*Q82{gAeobjorPHHie4Ns!d@iAf;bnI9+fVuvZN|BIJjfSeYS%IFvv-r6bp8E)5D_G~gX z1d;s{r+MUkZjJI>o<9OFC4-8~WI4atPF!J9Cpqk1I_>r6Q z6?~h%v8BcTmH!3)eSCJ4T%#eHr+~p_v#(s)yMjvpl>u&f=XAnbpP$HNIiPKC*&I!O z|9@$?TcY%Tr{S)A=s(kNx2z|R?ML|;BjP_!MsUaoBEEn-U4~@?>kZR_mUlXmaBV3! zPI@B5XR}{Ce!pZ~YUt5svF+N^;Uf#;@+xm&lhP1_SS(vbV_#XXMKZzjQThOMAV81R zV#~p4w1U5iVg&q`6}#=o>aF-bG90%(7_68ZaYG`?O_=Gr-chw+r(pCy-II;)up*eI zk&!Ze!_1gBYn0Vt1&Hs#Tm84QI`?F_^13d1*wRTYQ~mt6tfqH0|K>cuW5h_aPg?qU zmnRd4{L6LO`t}Vp2F8sF4;?yeE^~4DFTlmoFOypiE$f8;m|KHnko(DnP>nD6;9ix5 z7@l46JWx$l#S?BRAC*~paevYv>xE$Ybwk>xWr9<#9pvI4hB>pj{zc^H5LYfbR$}SJ zvy1@SPi;%ggaL=i1DY#2k3eDvC)$vCQRe+&Cw{)#f}u-?1vu;%zaBloKftl<%GK0p zdiqfc+{2lXUD-bf`#Ef%Y}Sa_p2C!83Wl02U3)w;t8l27xoa={sh)1_l+x0ftJcme z9oUd{vc0S;9t&4!r;I_vJ9MVBYlmTjGrBN?;>TOuo^S?(EJueU@4Luybi|vzji4e^ zGt(vfA`>7;wuNYRp@q(vbnxKk?XrZ_6jc~KY+TR6CO#=CzjrmHCZ`1ZTM~l4i#^-7 zUug6?M{U8_apNOLjc(VbaA)UU!BJ0)S$iQ;SW|o7(5ma4l8g@2N*81ZnNcr{N)73x zkDoZ<=$ECXO`9fN=oaCl7ZMVN6ufNvym0dS+H$BBe-ol`CZhPV38ie<`a@I}0lSO0uUSbR#lOFsc)q%EH1t5NtKnsCEq2F=e;Qo$vCd*F~B#wC7F zP2P!yVTtckljV;Fb?rK@c)}nXuQ&ntQ-?dk+sarh$1Z=eNh72m#T+%A1r={hXblVX zvxbFxrz)u_F%Xfeys{!Hem!kMQxw(t{k5bezC$J|%In7lMoD)+8%RTIoO`Km=GNr` zJ%V#v{B=5rY!4z8%$E#*5~haM_^m%CWClogg;vgy>lo0=y6ehWslfi=?-sFMg9-|# zZnecstC$wpyLfKiu%JohQ-k`9x8>!cb*4PHS5D5viCsEhw)cM!ZL6!sp_aEai-(R- ziw`%}$67^%W2GP|W2;3?6RK&TS4?@d@yNpCLH&i@!L_-)DyUa^@CIp?^WCf=*RFI- z{qV#tXWBvMU`2lbsu9TJnD=YU>&X)e1sOvq#M>$+I#i)4e(8)6%x=?MCh`k>7ilzw zr&Hxrgek1G^Y0V1)zz-SyLZ#{VCQ?i%Ev9aQaPlxIgy44N&WY9pK|lV?3Zw*&z{{| zlMS@OfU`S_*YwY$I*Lj-KPwUKQ1E| zV@?C6mU?jRY8OcbV2zS8c;N1e5Am_b-Jc$bMRtu8?P8k~9KLjlSTQlKKY zO*?(X`5ZNap|(M_XBS^y+$Jl?^Lf2BGFtHgGc|wrWShLA=x8<i`CY zgr6t+!cE)Mz_{4bg(HRsZ4$~uYF?#Y6(M~O7a!=_rTH{r>$dFd5hHfhEI$aN8Z-Lo z>9=b6VVJ-t-;c?|wIe}zCzd8_#>&>PRZLYQAiVmM6PX1pwzP%w2P4wcnM@+~!GbGn z!QFC(mK@ukI6v5)mig4?Rn3R`Ht9Ku3X4}ZG0*AJB|=Ez^7*hPM$zwu2%X2B_Yc09 z`y&3Be%v#&`b|5y>ZzyjI+3dn3A7H<^W>Q<-_Jl@+JUSn$Xt`m!|KqHgzV>-@R*!f*B`#k{cmdm7Zcyw9m%@#xILeV}0cl#6tcvy1cK#(1X0 zZ(pvUuR`Vwu}joI%;Fqkj4SihBAq5`Nt{;RAnDgD=&X;2!mNke*^0nY zdl3k{cqD2#*VVR0qLzBFmoL$(5<)?xH_t+tpXGsAI6h!auMuHP!kbId%~sD{Esb8D z-CDO;5YjDPk##B5HZI6{bF{aA;0yK-zZpCvDR#B(tavnc${UdRx}F2_;)VG2%?I~s z5p|HpMmF2J*Lk$#lJe(QQu^W!s{82x4jL$#k7djJ0mR>M2%iSVv6FxSvTf7+cXq!W z7#BBb;afqayPfyS$MqeWQ@p=hH~NN6%6+(hTmNjv@!!?L;ISz!r%z{5ITME=K6rzy zu(vXrB*Ys);>ps^#%_ScVr*NqvspL`Er`Wa?OdG2GWLdw?>DLOAD+QR@8>6tPAx1C zuJI1->Ha_@MrKoL|>o+SA}zcI<4Q z78F$4{jvVZCeNn?Y@wBalMi$WGR~0(jsCFR%;NCiT!9 z0r$Y%58(HPxK!rDK2}32!T2o*X8W%5Y2;XG={Q+POONCSFnAZ@=NpAR5nqqk)-o!@ zYX!T5Y)lgeyL655j4K-u{K~{NRQ^8Xz1KRm?t5@hM(yWw<2?i85+*`#hLC0%1wv@; zcl(%%W?k=j@9n*_3il=+Y%?V``JET`zE<69M_;J1-Qg^DmIcD(R1gNT+-(BOKZ){$ znZGhr6&o{L-zGj-to5|df4Y2{%UHTgf*?ow=>sx5%)S_WDbmMJQgjJAY4h%&1`86( zYYVvnQHQs0sNeC@JswzF)33RAy5Kj;GrsV#X_kthkG7uZ6*%RTcazW^-NFKMvxNO~Z3%%x z^GEHx_;P0E)zx6MelnD!7>>J&qPcz$NalOVN+NwL zh!N1tV2Gtpg&RznMQK(gsPo(7LWT|2>!QZ=^!90a)Di|#k}^6a(f!TacN?{H;F#tq zGY`_XiS0I(mQ2O#QzrVA@SJC*k;MM+?=agVM+H17B|mbxufm5LRC^68jHMJK|SIm|9a)Y<%w~ zLgGBTZ^lFbdCPGwb_4XfgqPwChM=O+5O#upv;Mu3bJJR9SoON5SF_C~P523&(%XDV zuP@2kIq}Jt$1K}8hAtc0qUDqAr#ny5fHC>(uR*%Nr&WO%7N?ME@@xS4m`%$zwS??G z4f4vN?LwTPEJPd+Dye`kc$AF^TitUprrIL7fDC5T?28Mw^5Bh`OK947<)tF+aOG3* z$B&lSo8?a1X`V*?dqqh}_pk4$_sQDiI60gK4&s1``!CIXxyRi4Wz1HQEBuS$rMpA= z9qxaiYuDImyQc=m$Cgga&qwqN?wgyFyWiHWTXPpdQw#IykHW0_WJe3k1v_gOxmJ*C zv5!C+^eDsnkFf8`u>KkL8cak+;o!*qjw@~pcB*-z&^23(^FZhucd_oVevSIWwv;S$KpV!YU2?S zX|=uCsY?~X-G=6{gfPi@?N|xY=_FxWv)Yj%6(Qm{mN`Bs7!ko@s8TTE!8++oeM;!O z?>vsI+WE)2Lx;pzEoJ0a2nbSTU!M4IsSZGgNPIz{L5V~D+JdCP2g%4-Vj69u)6=jj zMRq#CjtwKk2rNssd*mkuqLu(f(a zo9dXmI;;HeRG*H$n{_vM#|1x}G@$Lsu+Wyxn+ldD-QNu989;@dEedS~yX{XEP@z@! z8s|%Di;)w4a(-2m>nxFAt<}ul(v!8wa>=)Jb9!SKJR3~O}g?QON>di-uxS- zJiGaVeiXCZk{)c{3N_M+`@ z$|lEv59m(Sx(Xlp$W}+q2XuFcA5#+zbT$)v*IhNo$kw_LvfLakTW?fjgthY2hjbXV zb%O)Ln>YN8C}Ah#ii#rz6Ml6FFJsfv#Z>PM{4T=g^3cS$vrfI^e9&fcRBU;RU~V7G&9=!A>=l3? zPYvL?(!+#nW}A29bmszpI`dqQIPb^T`qy;u$IpJv$X^`Od*#fY#YGdGEmy7tkF@S9 ztb(1GjJ@?_lf~0?=Bb)sd+!|~(g;egd0V2U&+(uCZudBEL*x-Z=euWUt&l%?btIds zsCYvA+HdGU=YIThBQ%aYSIU)a1xzn&ivfC6ap}tyFW0{2FYfUdKdDI)KjFBcMJ6RL zAQu@g_)3H&!i_olxngp;@L0tpvv=eSXIcRL-?{Gb-onz_Y3|H0M%Y{|Wx-sS$>yE< z%bv3pxaAZHIPt)r`V(&u!;UN1EAjRIg17&ZMd6bwCMEV`B&|DLyGWQpJ$q}Dal-IE zFsz;=#*9nMtM@R1raP~`TyfS#5|?dFl2pLOi-k(bIvD>jAP&V1JUn|7!ajO%7qTj_ zZ&Glkf!~+P_YG*d(S9ny>=!%!Y5%7W4oowTb*5JjP4mGU+}pD%Q}f^ZY1pRLMJt!( zzK~s5`_c?L$PC)`{RRDCL5 zw|Ga*aHjjy_s&7Pa5WJw6Zvd{%g~reVH*(`ljg1)A61Ydy!~nR#ceH`L}tA0e8r#I z|LBv@B;8s4)e74-Do%Snw&%(P{ca$v{{})ps`w*Z0V5=hbfj!=i@hIVo6pGsbfi~A z?SL_R`UtPIYvSDEowSdd?9@E$tkA{T$GLB&^VS6CJ?Qz7&FI)+Tq;)ySc$@ZfiHz_ zTp_l2@8a4rT05Al=^Lh%&nDFFSV?a){xFZm9e#DB0Ir|7a*TA>B;f)x5w=eK(!@}R zt=Osf(}DfX&5{Rx@Oi?9igg{PJ$EMaMXA7fVi2ZXK`#thpFGHU*zPpbJMV3$I@{d2 z90>_UB7IrY4LekPZx1!?VJBZM0)!oS#ts$Ttb%1b>0$II3rzkw{{>7j#kKGI(^U;7 z&skyf3uGf~>?r22@`E6zCGH6D7uwoOxOD1L8$N)-KHJZiK7Q0+nEYEoC$IL-D>uI% z@>ml(VePvutqHw8xzy7qbs$#4s=|$ZhB{w$)~y_}F0ahl^);#+^?J%c=ZI+o<|p8* z{<=$b+2UV7ibWd*gT`A7_HLB_L!Kz6(lXm0Lz7y?SF}pb%6q?b%bB^sOM03P%Hszme&ds;uyZcNL9tB{%cA0PLVMN$xPhyhMAe{ zH*r$NnBM+97mn(w%V5?U-(bCW{JW*tR(437*1RPh&GZfg%+Uxy5CsG-5kW%CZ-Rcd zhlr<*@!_XYhTfde$JEk!`i8UIpZcErKEW$};JK1`u|wDKO^e2k>g6F7tQxbU`vB)1 z=XWbAf9lt9M#gZ4o1wNfZ>i~@Ex&C*Y~q}8$Isqany5<0R5(_@UQ{$8vRQdZ+?$&L zSRm|misspuHXXkE6-0p{%sq>@F&?YNn?()&x)ad^q;EZYz5BGNW(Xqh4*IO-Ie#G+ zeu9OFO^2Pfzt03Y+pd6tzyPJ)n81%6z2F^s8p)u1)5MtPwxS3sa~s0SkEXVu0TaCA z+LY8*`3oLLi?UOLY7=X>?m50^Y64B#H!<|_mRT#ya^}yS(9U@+vG$nMN@Ef}U#tWU zbAz|Exy7V5F7NH~GS&t&Mi|mmBR`M9$ik6*u~!J71+PCvetOB;B&^%n^5OReHcu>X zm9f&fCymD2-zwXfQ=YdK$&?LT-xXgONOjH+COo9hkK)s}U9{1f+F!0X5#ngwLFgWS znH|E0VO2xbqKWb_hyAOzVqjQ@_e=`!IsMM4=vQ~<`geHpiJ;Lh`3o5zVettwPOqyy zd->GL!g8SCRu97mY1uJfybv`&l%RNNtezOW~4vn7czh0m&v(waJLDWSyszq$?p$b+^0_y-`44p zBl$9Is&wye4a^zp=yRDiliRihgO%eh)7ch}ky6gX{@`Jxx* zNggHmfkJj)QhD!ZdQzklDi7bGPb-y{`}hMJN9igwd$7T$+eXk9ce&K_6 z5K(zr{sQW#W&QG(6uTV^UWMP(e2Mpe$@^<1Y(CJx1IQ-h^-qlaHG>2j7>A>eW$1qi z{n0X~RBi;XW;e`##ik+92H-)A28xNU)FV)~@rg8ou2L9|#*MOt_j4}gS~>U;yc>dV z+~KwP86@WahQr&KSVpMX5DPk(OqEEItZ}BCaYOvQYoa0e>W(1>p{|J_!FqT%#Mj*6 z8zH{N;W3Y#qh{-Y7#$38<>=a?y3%rV%jiU9t%tq^HW~24PY|IHl zhnAk&;0CiH$|R1JYe|tC%tkW<2+J`iLGZI_k5zZ2V_1XI6%eS&Ql9)smWs|DUXvxW zKeM9f>fx0q+|YYyvS+k6)|HJh;ZoKUZV2@51KgFxa*Tf~S24LOS7Sgk1_g5Yf569b z>uH1lF%1JWYhcpX1nY1dZy~%$!yWmF!Uz?60>0YMBnpM;{BJSvM-(gAg5~PD#MP$t zJJ8SmIF70F5?34Vhy3%BghE?$m)gG7Ry&SY7BTXbP>Lgt`qj%n*z#oZR6-d%mgI^C zwnF54^{ZD2XQMzpf}-Myex^r2LNB1$C58|;F-O?k2WVn&4TxwM(AiCqk#2g4-~_q2 zk#;?TcS8{64)2;DkRS*-3kb690HxY;(k!t#UBw^3sVEu(E+O#o2*GVP1hMY$jSwJw z0YOpy{MIu}atfax@p+c8S(M~&9c^0*U9!1Ql@RF;AHsx}#)Qg*h9RzgZoFagx9E>_ z^&^b|3Px&Q-p@%@LLBE>3KMCjqiu@tw3^9a5g3l82v3D{)^21Q*R~O7IR=lb9jFe`WJI} zP7ws!u=3YF+A2!EG0X(>3 zHV61IZW`<24zJDcg73oNZ5V+68vzSdnn`qXall?FEY=V(+JOL)(h$fK-4JBC!#83e zi^Jo$Tms?`aet} z?;j@dNCTQT_@_za|HCAhm(TV$3fxuP$Rxm(rm;pQ zQRoh@&F?aaLJt2glNjZ$;zlL`NofcgnZ#&!_(lwj=J1b9g3s(S3EE&1o!ba6)9H?1 z+X(H{=`QUhw-wri%yemQWWDc~`|t&=^*bDk+X`W}+5ggBDx+DMMqzgiKK^4!JsJJc z$}|R#RrHF+3;Ms{@Y5T`1ePboaClA;;P*U&chlaCdLPdRxTFhEte+VT0~kT|>un|@ zON&^XAZAV=1@Pd?Wgc7I5X^Ficg?TC&*JdR$4htJ5X^Q3ot7>R7y^wTNJ>K>-E~7S z#~r>A19Lchk!$`Kh0oley%hXfdxHFJWpsPNfS;Rpq;wEgs`d}H#rIwZ;kl5tOw!hE z^3}Tbz#9O1ewLdc=4<^9$Ak=FiEX_GBpEmmypuXloZTR;7w8L|h^^=kVEydpY?%7w z&GpQvN#e!^`1LMZXUsn*ZUizuKbD~8Y9K5%N%m`i-;nG+01qH725ME54IBZRXaT2M zBh*p3tE2ENrR9$3PQoa)T%+Exs*^B0gh~0o_|^Iy4r6CwxDD}z0oC&hdgi&&zpI{K z^ar3HO zq+@AUVW4_ale6P`SD|mn+uDshh&z(w&}jyDBwD}2(Z8F}*M>O7G$V#LWCoABEvvU& zcn@H36Ydz^V(?g8>*@s|-*y$-!@|9}BsZi{lH8T13(HEXi=?Jzu(V=Rf}i z4+sNkd z@UW)$G&<2g(+&QP+sawa;WID$3mk1lQaU+;b7c zxM2h_!v-mU2UnV5E04P&_}v{|o8JZhJBQ~hXN4PrKV2Lg0s_VXvqg;{NJ>K>uW&<9 z?GE3FfocxVRt}p#M&UENt(;B5e&p0~*+PmS*Hz|c3#s^j0XbIpM`+S^*4rF4{e|JG zm!=^{!Q;Yi)#|!24iJWh)Uq4Z+vVM+08ULBfVMA=-`G0m-394632p+QE|AWv2%%0I{&NxEe_wMaepQT`11kX8b4tDd_Y#?eqouslWmP$ zgbuF!IbV2++WK*_hf6r91bIkhJY?nzRjohYy&tpI_m8OW2R5C2y`jGV|Jyu15BkTu z!52R2*KK!$AJz2HM7r&614dW=Q6TK5YJZo=w~rKtsspr}b)#UngIo_rj}pFDp-Zm* zKBI*vY`NNv49A26hdd;y{qeULW}JhkN2n1h-V@SPnjVI~|D)Gqj>fze^ja6;K<%8P z!o1+x0a337Nq>I#-7e?6+7`lv{TFvJZulJB=+I(_#Lj%~IAN1;K>n7^jSmL!$pAj? zpp~IxgqDI$GlvYO15K{FpSU^XNw+YE!sM&<8(!o6`D$CoOsDDmm=+6g?uJ5lD#tGZ>bV22g$-+5r8-A;! zFCn#~IXy^r1s`D^eg3Va083K!f^z@6cJ$OK${`Z|m7f;b6qi1x0& ze(3v>!@aBZ;T(X$?GxtV1twfZq~n)`!kDHQ1pliI!iz$S@V-!nzV{u)i-c`-i$lLy z=v`U6Sdiq7m_XP}cgtRQ^#P|w)v%5NzO}&z*-*7Nonm%gG>2Jeym>^w0*mvKd30a# z&%C@7d3nxmd3p5B%C0Mf5S5+t(bSfXachO)0$y93Su2E!zDUX+qf_vuR}>dUXZWDD zYCp$=^}IL9MKzvbeoTM zAS5iVYx8$>13kT+K79Td^f%-EpbK@=&`;`-qPj={XuF|^!IS}uXmpK z5BR;LvH`x3!RuTD_ByU_6!6PGTOETp2^oZ86 zR@x5;Nn`l$OC{FB<5!CK?@KxIw+PSCKONV%2)*TxaORhY&UymhO< ze?99DPE>OJcx55~(H`!i@S8yIIey(LWUyb#TF0#bas_@)y!M+l#Lr5Wie;CLtt?aTb%&s+Cc$O2h#R-d zu$!(Mw-~l_e(&%1InQ>^+Ey;F_jAtk{rvxazt8tM&spbr&T^}9xAb2S_xr1w_0>39 z`p-+NqxHW5)8lCAKQHcM97ov!W;GjZkc0U*Y}Uk`;_lTPV1rode~orEQKkmF?1fTe z@Dxgo(p@rC6{7xStz)$Al1qXkTA&M5c9*ENrdgkhQvA_1<}|H;Df-;^sGIN(e%3gd zp_ufnF|ZqpEnXQA^I7K+2ILCwea{*bR0ogIQ8^vsC5E4kJ*mA+v%GvMygxi^jPAsZ zem>w%QbhF*f6hqvM87B#YzuCD_67AR3wQL3VzK`|Jays#GeA2bCh17R*jL?n@Lp0Vj;bV9(SoS{aPwU-=PuF^kj?$YWbo-~oiL&nW=9|6NFy)CXeDd62{U33>#*`b0(i6Q&SQkIsOw8HW zwUcr(b(x#QZ2!X~@-&Iei#VHh28+SjEJ%$)(C1!TE&7{V^qngrW;W}q2POpdo$;>v zX8)C9I{weF0<4O-yxHKT76V7J>)U37m%MfBjR~IUmxK36BLPR2>!)V<%ZyiXbHeJd zvl8Aa_S*?K93lE!#ljH%hnn?$VvntF{^lOo?B6Hm`B&KqZwg6x3y(($R>(d0jx-x= z@$T7Rlyav!?`_W;sj8=&*JbB4*I&`I*6~fE$iJK(RfpvRx~Hvme{<-%uY20k-z>ap zWR$-1Zr#(Cex=x^^I&~(Ua5Q9(y!F|)}0+459!1$gO^$o;&xW5r!9k*yi+TTYkU9T zzhC}GT`O5Pd^GkLOmsT|!JQvBN!*Z!ig%%|$6C)eiHCGO)_SRCj$x4mF+i>;O3PhK!ySM5){XtnQr(P~fJs9vA+-nY?MuJn3tGEVDC z>Q@K8bF6XAiAs#z;C+3Q(X01Y=W@`Q<2mM3WtRAwsH8}r_Xj1e`Ms z!9QOJD%jQ>vWbz~yca3)&QT%O)`3XuBx2vC#9sxvYHKdYu;xz|&X4%{X(F*-P~w^* z4p%cVc#>lEah`xUiP&FmHu}gN-rsoXy)E!3%Sp0w63G<&T&)_BJH3Nn!pR1m0v`x; zjENlcWxD*Yyt9?qce2VbRQ$0{p~kyhi7O|z5H!QDzpP{I@cy90+jv@1&_3w=T0MX}y{Eh!Qed)R71aS$ zfggnxn9PG^EExs5pA8l`5A)y%CL1@{1-es%1+IEo7x)Sd%&VX8JY-@5c9ty^OZz~miJ{Gh~@e{L;)%8Ktjr4q37A z>B^M&OWl1wuV0CI7D%|*F;$Bzy@R(Q-f>ZDalD?w+q|=tcxTU0@uSSFlY^Bl-)8g~ zW-T&j8%#M0XI$KGhNXSBQ5VchP0IgRlhXSork)LwPda3Fg*LsDK3i^imJDU9cD*cO0BiW-KuweO6 z|E`p363w3K3>WcxSUU$su-!f)uh#l4?M?0I`$O8xRgVPya0N|V52sM&h{A$`NY$>o zrggit+5=CcKTmi2dZErHu1G`ax6y8W%Af6@rcaYek?W1lTHm4luTbqC-S@V@sRbhu zSSQZ)>V^UYaOw72X`f)}^VB-k?$&|dA)%-A$gEc%Bxz^HP(UQ@)~R*9?5^9Xjdpb} zQGG@-dj`B?UN>B_r+4t{9C@q-LGfS}2Js|q7VDj@#J!uv`mEP1KFPaWiTgB*|E!W} z7RPyCN35O}gYz6}P)iA&!M(IquBYhsM^$G8+i%wGd;^3&ou^kW^vw+29t(X_GR1ni#5=kg*;M`Fxm5d$pg`*&Uav0tiO-cM ziCsdwbr7$Y_v-e`bh|2C9l)ya^L4xaD9i`fX>M<@9nbh-8MZn$cp$Gg#_Dzs&S2p@ z?pZrhr#lR0YJn=;I%};rdg%69x?L4+9p~!}zM(|_3UANt#(4e-&8+Rlx$=4Ms_n+f z-Ji9O22PCgRR8fE&wJaAAsqVt?M71X;IU!qkBV}e<4t29!|URcVbodm6W0i8pvRTCqL(V(KItx?-@ml`eTUWWJLs#gyr=JE z8UMsPVJ88u_ui*op7-wDN%wwkbuVZ7JA>W(^G@Bpr~Q?e_1=sAYRr}Y^}X^}<0WTO zcd0+?cVgvWOiV|P`I7o8Q>X3*y&RRO+WCICySM0FW6;2!LFJxWnV$!kd$h9Ep46$Q zHga|9={xYQagM{y!5Zc26z@y^kbf`H%W{cpK9`5M_SJl3%yW4Hp9Ow2hL}@{HYxB> z@Y`dSP@}UsjwdDDVYda|rERj(<2ETly+Ap(XX&F;CbWwBLbLjQeZ5KDU zeM#H7rbh+Nwi^YjoH0i$PPW?uucA0wCpe|K?XR?*uG=oL+th;|%qhnE_~TC(!9wnk zY33B^rHx^?+r$p^B57ld@B|yL4qPX9nAgzA0ugNMOxrx&#^Mlc8_aj|*QoF5-4)Gk zV`y8U+ct-_E!AzWHn*KcaZTzwd1Fm;+X?4jyj&~3nZ z`u6C{FZ=k7Q@>%mZuH$~y!lhp+432Ge`C-WP2YL8F22^BVcgO5ka26%y*D?-8lN@| zH0oK5_~VTJ1`S`Fd!+ttUte=XuM_2nUg{T9?xZo&og`~#`1_yYxankn{5Y?(qF4Vl z&TTjNrmb+T>$%Eh_BUJ`Hu&$FbK$)EuD|gAnpVi~uefmTz1LjmyQ9vy%jtdjfKlAf z@b_{~5R+X|`Zp1Lz3=YVAN(V?_4mnpeEoc`DBq&*jS~~Qyw2UItS53Lb?W~_w0SD` z_KxSp6MQg7r;CFR=HM>?t_rQpk;q}uTCN`4Vaac8Q_goumRvo1sSW$vk-yuLjHfw3 zb})fnwn8VmFvNi^R}S83anNi(CFIE>mOMN`Tdw?Tx%NM4|?+Rp@k)8Zs1pEiF036(g~63mwCueP^*fT z%?Ok_Uv%aoLtoo<@|}J4MU zJ`$DGd6cone{Yn#^Qb_%pK~|1`Qly20PcQ_EKqLi@QRL14C)k$cX?v@Ct7EB(0+ID zFVbQ5$m|%lKl~VLVkK8S1bfREyX} zzqKD|V&A2dm9cn68>1)xVaer}TE4~iXtp`1lN{x(o?-SnPl>nb0={f|1;g#aiD5to zc&q6(j+XdFOC}+}ik?YBz2*ZdSI&t%0rDc8~PCW*d!BiJeECxYg1K zY*iZkLm>4Bls$p5+-|i}NyLek569nI`)JW|{N2*w!C4`3eEE->qh#bL8E_c%Ux9D) zW9B)|Bv$jrME<$OPL+wgo%8W>M;{_t?TNI1%9qzWeK9M|O4H-&s(vpfyA2<4lDf-n zj~IP-o}|ID-)Y=1Kc$;oV#rRF^74L;l%(mtHmX+~H&R z-SmlBO^1GVqeh0L2>>AKG zE&uGMCVytLV`J|2d5%uLTb?$5be$EwOZV?OE)@nl?x0HRa$6nK5AusMSM)ntt}gtp zb==PWU%gM1nIC#wJ;Vv*)^Au;_h^1stA1~Z;|IJN}2aKNbTO&o9{<;3H z{;7V>;!>NL4rF>7j1f(!+GGyXuzbercLHYG~5|SKO!3 zD_3p2X4;e5skf<-CzK?6Z(C=cdiL;ynd@@LeLrHvw^_OCW+oUhebbBmN1E!5&a%^$ z=Q`x897$iPq6ahFB>sBtm=!Q+)2iDh8(7D zv^LDhS(khBa}D%GD!JBu+R_#B9>35>s!FxnP>%J@ei1R?m%V)4;%_RxBjtRR%0H{{ zJ+r~wdWy{QO?%t)Ntx~I`Zx1RqX!ow?tbcUbA00$&Zk@hqTF3B@h*PX9O9W_@L^Vo z0zdGNGitPm>pn+})rR_$v?X?-jqOZzmg_RBm8`k7Rl8+_Ha2rw$&^iEms#qgOHjza z`H0cM++9ej%>=Y&D@UP;&GFv#p834{YMi>e%=4wZZ$5s3{>Mp4T?u5|7v)y3&MvI$ zD|xMT?ukxREm2A?4bH?}`6%S<9F)JW{=r00PP>+e+P5WF_O^d5_b8V-Kzk0tKAaPI2j;`T23b)|ez_Tt&`5BUGjU+@2y|F#F@NLeM*{Wbnf z|4!qi*CveaCR1f{xAd8Vu5!5Ya-7bl@2)bPc~`nzhUb7BA$|Vy{BQf;@lTRlrC?FOB`K`M0_wZ(QICzOp8%u{yrwdveBbCa_e?R>^yg zk$vnNWbgl*|Kn~WuaI{im41iWM|PGj|LW*id8ywoZ*QGG#}Wnbs9(E+lhwZf3hjK^ zFWQ;VJ;_LNk+u3s_3-||*Q1h_S5538=gQl9oImZ`_l#)~H{a!U{@)!{6%6-BkRMJsBJ_lx}>e7eW~;S+bLpmlZY;Lit5$V!96v*U&s2Z?s$?!P)9GxO$fTVyQ$j} znvY!P|Mt3Tuf0wtTz@U!Q+#NA{P+{n`?%!xVB`Ip?~< zY%EwH)0;jiD_irud0^ezZr93L%l$Er$Xor-<$ql-e6RO&oaCO!Z2p2nk*_}_C(0f} z-E^%9GD+<_e)M-T_Di|6{(+{RImW-(^Efk#uaiw_Mv6b6wvBJiHPefINoP1_q+G0) zFTJc8ciYRBd0ueY(#u(^cC}ixrEj%g?5myWSm$&v3l#AnmruQS&2eOTM7$9d9UmRV zU!P7(OdWof+3k{nr;Hmj_qo%2uZcTe9T=ZwypJ7(M|11~xK)iZx69{@Pn?uEA?NaLW6yqg+?n&@Ph4}R%eCgj_<3iJdpK=ex65-TARj-+lBe7d z-*v73CGK}|xBo}(W#n17{OYThU+uf?Pmb4Io)RW@ycjHoaq~9*94f6T-HXq+Vbi*= zJ+<}xcdNS=sVT`VuDkW^mZ)wmXB`tGu-CWuV^h{~C1&IL`lI zMf$M2{_o7QS9m^XdhX(xa^{u$hMl91n6xt&%E-LDYmFFvbWE5Ketg)+h|#sIuKTLb zKV1>E*IzZLlfOYmM4AtFSI1RU(VoBiPs)F8_02c0evXClY5&dc%bC<&xf9ng{tXOY zwzGsJ>bc!(xQBx%QM!_t-0FWl!TDgXXL$1**E79Wq?+#>4O)}?I;cBc^5IM!0uMjT zAuuqd)3T*oPm-IwAAR!poPM|GsN>+>ckSaqUZIYJ2=`)t)rekKkCNjXFNr-P&m;R^ zcP%G^0fU@Nm&MJGc{nfc5snq7Qy(mY`s{hi>pruw%NkiW_kqOgtV1R;LLW1C+DA>@ zcaARd1pjmA&g(Nq&T2es#1M6mt$O;Fa- zfBkr|`Y5Z44`062t&P+TiHF-gVIAwb+pLlAscv1Nd#h#ShmS~2V$_|#ct0w6MKi^*zBkNZ^-Q-_cYks^c zMoophx#eXy-@ImZa7Dd`K~rb2V#q4H_Ql8>HzSxXMfS<>ouS z?-V?}s1MwBV(Q>h6Efrk)34>U;=g2_?pf=^@>KIVg)cL#ehMBoOQB8`x9p|M(?;s4nG@#luqaQZJia-;-zDe^{nzJIH6PScL2 zZx~}w@VM5Oe^#cal4(+R)_OUjJ0Ipp^fI|D>+Uu~T+5s0{px>CUL6oOepm9%ynwvY zzwXz0-w@*KujL1K$R3Mi+@JBB=YPuoXMf!y|Mz$BSmX+84ERee|Cu5`aH4aww|b$Y zcVdsBk#gv;e(ogaX8(`=eE$DYF65RoXMFaQe^r5cQ*dDW_9t$4#6&FeZ4BCt7#BH5g=96*xz1K~Yofj^Qk01WZ zrFs9HH99xqc1pJ|FN;r3>zI3|!oI zkoDK}69?&!`iK2LnOC@?qmoV>9Bd!_@;lCpT%PDxWLKxYPLW-WFN`=xC%!GA&GPcsLZLJe@hQ_q(j9=>v(jRwFI#p zwW%C1PgfOLL!{o@LlkDOlMI!GcX_y-r|m9pQBqaf4(#e|=N+o$W=r?Co`~X&r{`C)&0S_8vW!cDEeckvbt+hge&>_8hT$uq~bN zq4l&>*p{;G&C`{}=ua@A zvXD8^ksSf`95_lRY$f!xA6PqJCLiS>B!PBy!skrbWDN7?@z1x9eR~lJ?Fn0^J|l*n z+1l0#nLlAcT4LCK?1W5D@EqQ@L;E-;_%R(GkM7ZPiXT^okA3Tk?M%aF?@>0^kl3qS z+r`*DND?jf>hquKp71d}9!GX!ZR^_p>|O~A8jPvtNZ9e;k+SWubr-hhSoLaqhhvD1 z_4%)5g0x<-I_}CgyELS_;31e4JVWZ&kl=itWc_am-a6ysOUCZC<4MNuk!BlD@URNc zDm*Dpz6YRBqiPf5fJpiRfu_BDD_Gj&Yl|))?zm@tD2pj0ujv-MwvfQTU`eUdQ2|sM_`K z30eE??rc}N`BdGqP#up=cmXXFSjA!eKd$5SsM&w)BwHqH2f7~heGcPfS9DxP%{I1U zdxqQlZ4G019Q*8PUH|Ecay-U%cmFQ|+q6~3e@EF`NwtjG{}Q+(A8m}kdAd3yTAzy5 z`O^|nxdH`LbY+3K-&6VO50(m6Vj;P-#w z%2p3p%6dW`BcYCU?0Ln|9qq@u{6e?|<5ut;bnG zOYa>c5dK;pWy-eY``whO!hLZ+S*(ZwLMk4J6IWy*0Hbu+MFEC=Z5g0AuHw4 z4qILQwC>r~3F_6B-*MD}`*~-UbY$s_C(I2r1##4X)4L`)}1lr2h4ruALx%Rg^ zpKROkLK*)*k^rBI3821eIeMLM9iS~8ds5p4_&vwrs9CuU-SBh4@g-&zZ0YLH|Dnff z>kLDcTc6olS8OMGY#Vz*OV4q1WwUaJx>oSx(`}gpVdwvjyDxm6bgXL!IHrxd{}T;fB)OoOtq7;DzVr1wyO@GGac)O`(^y?akHy$D;Yb0U0p}I ztpYS3-fi0izyGxZ*h>FPpg(TQ5QlvKdz=f4Jui;0o2{hUx9Q;gZ=V_4Hx6Al>~6Pv z?s(=6Hpl$@f6QKK-R;L2So;lr|7Ta)-npRdSs!v;aLgp_q^#Zv@#hJ-mzg32G08^=f_oKV~<# zK8%h(kX=waNvh9($8#9{k${$NI{{n8YySM#-eL4d0{;&_Ji)(w+N)W|Gr08_+QZUO zlC6)ba2vh;AN#YMZDhY5Pe6MZI<#r;`v16$18N~@{kP+mBd5c_LEGl>w+;t;w*E0E z*08ipxZ?>N9LkpO|Lo)P4;VLpcKBaxgU7#J@&A;4^M{N7If2mc|Na*zR&TWo*B|vU zvhAuGm&9_4>keV1mnJCkS+>WjnjpJDAvU;X0z-RAa*{A=cBeY3{cZR@+b1pTA$ zTRPFXE#lO>?JWF1XssnYQy>wo#a6p7C)>HBmv4QZ^KMf{dC$mq4);BLgL5@EN!`t_ z%ZKy3YF@Ei>92C~dqjHYqhLF)VeRh++dpX4&c61;530lTZU5o=i7Fnel1H0`8Q6}( z11Cn)j)6`qOy3Sr+ZQ!R*sS^7xWyG zFnuck{m?2fJ=dy$TBk>KwcVxU8saD^nu=O=sj4g~TGvG2);)xNs{qze+WuQ7N{Z^Q z1Fb7dj7HF*qwv5j1+?xt%TKVYn|s>!uhR0^V`GgOl@VCi9nur_*tec5i7NG01%&!( zZwNyCdxEoFs~&X}B&wkyK~q{KnO7z8<8j zxzWy#+=L^s+fBZc7CGN?Ij5+*Gx@f~*GgY)v9rJQttfH6645;}PQ{xIvV9(70!)+hv$P%emk9PkH~zlLxLHl=P41{qKJxSJ$tN z>$B$6KKo>iKi!xbzk2QW()j#er^(x!e(SOA>8Cb7?f+OMs-8`vAMNdChucH(V_&!9 zwddD8-?+H9Yi|WbQ_NpA3GuG0v^uonaVT81OF!QXsa^yfbZe09T|>(-FqAR z_B=DFN5bgsO$oit_`{P1^-S~s^7-;-qz6oS7cuFX=v{LUw&jM$Oz|jPpy0E6_9+3xhp{mQQ z?#-miZbCoUJiMcQxiz4dJLvv@SR$9gt8 z`Psgj8r9>`Pws6!9o@Vn#BJyU($yH~1oa({oDSjUC-~gugj<#LcuW55l}C(08;n6s zA8lYsQB@f&?K=zLZ2YyN5GzF_+= z+RtEJfGTX0)voTOh^HZ{-J@o``3=uENphZ~ZvKQI#Wrw^vjWGe*0Zd@s)vl{f&t#w z`l&k6CrNaxrGJCc9~Mlsp4%0rTKZyS;8Y|dv_45V42MT|(KX5-Ef|2VHV*^?EDAi0 zWTZBT$I%)qfbLSdQnxb%rq9w3OwkF^e|mE1g-I1A8gx6;j-h;!z(XuQgMfh|i5+pQ zFMWtJlr?w^_q@wCT<-4nvK&2pM3Pz*hvx4edu#tbYfc%meZuw{|8FC2>OXKz@{r1L zIb~OuJ93(S>-xZ+r#AclyX`dpNMmZZC3{$!W!D!59x%oU-^2>%_0oH}&zb4Dn4Xys zI6WZ?nv?hg!IevulC+c5!BvI+c*`FeIymVDHLV`wf`J>9w5lBCM2t(L zTxtMp#SZld9;Rp6+x0ewwo(e|$)v98K0PX6@P0dL#DmqCOzY;M3F&gXkL;?O^{hhF zdFu=dAL1V$u`oRXw@AOJjv=@y3p3Ml6I;6pk8w?w&AaJaHVS(tml7A zzAn}At(=AjwR)lrJ*&c_lT;qtNHUm!M;~Ot4wCVqiprr3PN0xZZ@+45@T@~D{-`e3 zJrwk5SAP*dr=`Q%n7z$iZqE;T!Eza%WGg)#oLR5CT*im>q!l!LYPvmEMy(W8uvUs~ z=-I*Sd2U$*Lx;?tmTE%}a9y;+QxKx49ob#YEVjnlQndA&yU{+jL-d21&Bdr$9uiz1 z7nG)s2i0#5eDZ}!y9P|{5RB9OP%2f}sU)oYlcrm(OYf@Uh&|Gzkp1x04m|{CshX&SNj^0t#SWCIx<#s=X zX@(59D%zuteM>>VhK@~3mp2D*(`EB`>n_(lV*3oMyA8cW`#xo1Ikur_JG2MDee}Fg zNy?V>A}n;sx?&BrJ=HzhA!hA3RAb%BaZocXNu3^j7wr0=MLRx;W+!p6C;V^-?{Za* za-}Dn)%9%#4~DZQV_4ncNw(6%BVQO;9od1RokAPcsKq;M^0IHOeMV{9T^^$CR_S=c z6q}Ff;8~$Lv{E%n!;@5r>m$KRB3QSj*+KANKL+(Y);YedV>>ArK<9Z>@L*8flmm`KoND?JtT*m`!*5KR~L9&2~*gsAQ{fN_UenI$CxaGON37Sxc`e*~4Mot#z919*%e@ zD#>`oJl}}ICo-Ng;Epw-pYomVcHb@KVP8dryRV@x-MG1`bjzo830=%rusWEn zbg}RA6Wr<2`}0cYC!?eH2Hx@Wrx%9zex8lI&5=M)e%9QUB2$fhy6tnjje|)T|I%%L z_jY>9IdXLL7q(11hmR|bL-^PmC~D%%B>Yas$3433GrKMD8$Q$5+ihGHC0i^}h(% zKKS-b9u`ZLU+=sUXTN?@pfzdt*wf$LdgY1fN5rYzj-UT_R%JbCzk1WUxQ83jKl$c& zaev)OZud@&b>AqT@YTe+7r4C{@$OiUYm`{*954E~W{91zh4+gc&xt-f7keo0Q(UKN znbJAgVbJ!2hMy53-~H}j`@iguG>2yV_&^D>H|%#8w0;PO4Po%2Qu(KhZ&09 z3>w}L_ZT8@rgNbvGq<9Mf;l$uf(pWZz`0b6qwPAUA?|U5a*Bg<%o1^d-ro?I=eSl( zb=)s{I`72S4J3VvxW&7%ulsV({bIahPT&Xg?7-h06GXA&DKTFDEXEs~toM%R#S`q$ zbBqQ8hW#HH(#`u<<=FaTo-IMGN$P2vHQSJfW#zF3DBY$Q<&!qI9 zz4?RP_ecKh6zm>hw{ft$!P_{*{gU%Ph>v*Vd${AhDLvd#Y7^l-nBp$*W(;+o?7f^P zclfrP>5g^y_6&2ME)xTv8(;DL?pJ~LU_E>atKlEC_u;h)c6k#$A?KrFqT^}t6n}r^yZy%dVHG^iXSrD4{t@nTq&Mko_jcbQ zHZJ$0fo~a=6mNBgJHcC<;dc1yGTe2J0j>pNWjMxTYTq$eJnbB3!T!^}L*w0-%l_Aj zWzJZU>AF@N2r|RjRjhQMEuMDQil-w+iWROqz4IozhxSp%6XbB7X0l4*Iz{BOe+?w~ zYA3ocjr0zj>>lFFne48U-l>hyj^Fz zZ|%J}uumjJEYaKh)Hbrwe@G;B65f*8?t$_r@6Oro0TGdnfsaIDC*k{fwmZ#;iTpi~ zDTbg~$TpzfBN{u$9cL=dePSfL*W|h%AqoEY6E;wfG(_zDJAi(c*g$CtMp8FVW&9TD(MymmpqZ zi|^Iqd$sspExs3Voh`mki|^Co`?UBz#F=^S!B*`LP|=_B+>ODCo}r?+X4^4+&t!}B}73dQewcz#E6$_=(8pd|q<2_PxACDK$9whXB>sramU?l%oR zhH@koH_mro;Q6l@5ttkKUvYNeFKkB!_OU%D;A5Mv+n-Te)+DtZ$@X`V5a`18Y;ghG zbSBL2VzF+yM{k$t?Y(+?pWZI@e}v96N>h$x+awb4-z3gbTaQT9J0k+8(sZ`JfvpPD zB+~tVVSApIULGjq{S5tnR-lac59s$rdi%KEKB2c>y)D+;Cj)Pz`Hc4ShPK+Sx4X3T zJ++md82yr{!po6LwcFjQrQ2e*0bOfA*Ba2Z26U|fp=u2XRck<~S_4AW8sMq&AF)-n z22`z`q^gxIwX&sDwv@`2QrV951m^NWt!$~4?d7_KT6sS!P{@{A*-|T8YGq5UY^jwk zwX&sFw$#e@4Q;huZ>g0QYV9N?rLv_|wv^gQQmTh0RcrK9Vz@|*eoDsa?J0U2ueYb^ z?dNK%){W?=ItjL)MgJJs8~r)kP0@d6yE=Lw+mh%nbo)Q_c0b!q(f?$-I{GX9{%hU- zjoyB%TF#38j+fQZ^=c>jUs~|J-X3II68&$stD}ElyD9oVs$Gb!x4Peo@bEXerR+Q~ z3+jY;uuzDHSQH=PGUK5#A(q9#QXwABgsD&phlE(p`{l?Vi2{5)LVF?a3(;MH?uud| z9%cX0T&NY|v3Qsd^+FWo0TWHT z0P6XEwk%nQvQi<|@VbV^H8@_&`?U*Umk{gHpd2tR9{}u^XTt&@a5;g?8--Y(0r=S< z0Q(Ko0e>5?-LM<*`+R4J1AIJ>{P_i3c0Rup%AgwRg{W{qEa0SqiYgXC1?&>yFUbB9 z5BacBh!;8o&R!sy7YOtMiM)vIi&bz~h>h59TnMGG8ybYzL;{;qAPdy^Z^GH8eL#kr z39uOlo0A~}aIiTK7C|A@L!%HcML_~&LJlkg5_qXjh%ExJ--7Ly`LG0vp&F3C90A#| zl<|LgBX9OH8)@8{03@^(XIo1FPg@D*BOxCSeHkzdaOm3&`{A$4|sPe`gQl|F_OU{4EQXKoQglu^Z>R3t+zx?@k9^-^1X&V!-%) zg1t|GT4c2ZtR-MA`yUYSgLp`Tg+hFo0#!nMGyo{(qgg;N?a2}1V*v{p|Bnv~@yP>t?eFM>Tn{1f|s zmJ9I}?O$Q@RW{@RKE7uEYxcj+Vf??I4;z8Z>K4H=C<8LD!%-dW-{bW>WiUKh<|m4JizY(PXe2Cpn?M!9oP-~0O9vI z{eA$XK^80%;vj7YX*)Oz%3;3{|Hj9^3!oSd3GoA!{XqMFu=&q)Xb|EMMII^w$Oat!o(WT-hU-0oH4>;P z6-c6~it9g|`WL|=zP8DQLtIfT_l6qG{}WgAv-4nx?O1Rg3~TVLU!eS*ZD%8C;<71 zQ=t%c3mKIGU;!)xoSvEsl|sgMh8(DXLqhhYSNh_-?_MEKBk*b1oJKLHl>iBxwj1i;u#o*6 z5XavK`la$F6Q)8wV9*bPei-z_pdSYPFi5~4Ar8<_m;|}72#TN#&`&@=0sVwVA^XQb zGGxLmSOCia-Tqauhg`hQrbNL)pjT3`OKA}D%&AZ*d5g!v{pc=57h-_k`kXZ!E%7#+F&w2PbkN4-t!$PQK{4YS^f)Z#Da?&y(FT~k} z(_sY{yAO@pz|l*Uxm(9RCrYy&~_CGT~#b(E_S)~LS9Ya zYiPTsj`6>CfslD9=8@TTv*3`B*P}d_pmV7(pG5L`ySOZXs{P_(t01=LmU| zfN~*k#>XuLzNJRU1^B!*1$F^JZp#96Zo}sPIsSNE{=hPLay{o zVuRx+6NG#!0u~5af?^3lp3Z{ZLasvbnOLChnFb+C7YX@nHXwU06KaH9Jso&0BS0DL zYtn)JwM&Iu*BL5>EKdg7)@MSUkQ*}SwGFjGK3@!tLRKsj@-H;Lfbk0?^aVe=)c4(7ax*~4*AkvI3(m265kRFB))}2wk(7~s0MVlpz|_*UXF(}$Y%Us z&f`r16vIZ?1^b~v$gNQ@05V`Y&^ud8p&HQfB>?uma=>{d`<2;1!d!&N%1S`55?@@5 z$Zh!AmI3H&!*1I`#(!HORKXrNDC8>+NP#TKfrWt1E9FoPd*P6fuSP&Tq(L^|@YMn+ zhK;Zf8icIMfay>Ql|sIT-D}vrmIi9(zJ}m6C8&jZAzv2|3n`EVIj|54p&Y7VFB}r` z4V=9Z59qvs&Ku~wfzBJ~RL4OoFl^NoLT+csw$nq~8Q$&1u#xfKzKb{ep+U$uqhJ7J zz;u`oOQ94hp%&_eI727y!9|?60*@FXS#N+eKx&CIPZti(na) zK@~8xyABHZwgc#ux9OF)(S19Y@qZiTx9Os{E1(AU!C@ia=?p2b5K4snTMQ%vPXAUV zHcOxu>V>QoFbQ&D z5s+AI1&~1HKcxM`Y9PUnVjvkZfuuenDbGh6 zd9w@lLxYfeqF?}Iz;u`oOQ94hp%zG#>o@sv8tf7B6B7CaolhMQ2US4(-UYA>%7C`L zs_meVpP}~|dY`2-{+~_aO)e~gBB+2G*eB%YIQX2vpA-0Vg8rSLe@}rd$bmvAhicdh zhlJc00r5a``?4Vq3ZNJ^!Y(FWLW6?c?+x=`a;a zpkB!R0R=ue zKrw6t;&9C<|Bd|Lg^d5d>xKLw191Mse8ABUrBDgAfc!rsc_;;_;7}0|_z;1A#EuI| z`6K#2)(QF30HEzB66ab{{274p~lPy*=xdQiyUNP_D}`CArD2kd^U7V`HvAc@8W zpkC2!N@e_;2*^dG^b^RR4_o-jR4m{$fGki2yZKF50%XB-SOP`RC=A&dGJt)9$Fv!F zPy%~|VNQYqVBf421{a=&BN@=8z{0f2rqK0VQ76I}!d zy5~cKFk+?xPGV4sDFhtHR07HMNP|g`0|%i|7(Fv#2^`{|Dq!2IP8hKT!ss0j`0S1C zNm)<=`-IUa2H5Yjlz$)Dr(PIw2|&QOWx_a_04LW7{oc8Msseq4u)xt=?UqZ1k`a56%OoI7P1jzdz5=LSK#CzBfFcC+I7$+70hKUE9I?RWqPzse$3-!VnARrb}APaI}Ar!(!KyLtg1JN6Z-arqE15q4^ z;y@G!qByV|s$nl262|Ef5D#gP4S7%i#jp`}!G35E#u-sC05Tv47D6GELpAJ$L&8Xo zfOy6~IgK~jkOu`&3>#q=?1u(n42psQkO9+SJ}iY&sDxUm7sg-#v5*2;kOK>$5Xzw% z_QD}y42ghv#(zi}Z?Yi|mI8`HP#l8d5EN5TOo<2dQqW65FQovAVI%B<{m>wcGoxSt zWWaQo4@;pGDxntYg>jaESV&>~&&q-vSO|qs4%M(14hdsu1jIucWJ4YlKrw8DU9cY- zgpnEr10VyY!+cl@rBEr1VN6^u=Z#@YfQdV7@)kC`f!RH*Q5eHxAQ>_N<>3op8I(a4 z?16*A7~z08NQFs|3yYx0SLAh%k!QyWV+^t}$i^TWgKSI@R6q^vgTuneAmNN;$b?z2 z(Cb*~PV$iVxyzsos$egmJ{I+{sE5ajPr1Q9{T5@f8JEchb4gSdFYZkGRl*2Jb4kIJQ?N5C{M=m zL}dQUY6GH`GC+FfNG!622q@W5#Gzfz)n2alnU^g5VMh*$&6hb953S$ob z=iq0~{7&j8pbj3xM4;;9$LeF7SVaesv{md3$uVLXrzdxY^|JS>1M!gvV7 zhteQR7|YUu_GLI+RwRsvmkMJ!4wvr{#v|FnC?t`>24Sqg=23h-S}lyna^bKriV6VP z;~6CRc%?9&;LQ^ldU5Ps2vx!;jslz(mqV>ERtg~4lPSPH-*_2M%@;;V6l4O{QJ%z2` zD~t{J+JN8ZJ>|lv$QQ<6aP*h`!gyf-=MRilH5#? z%~Z1)hkUnZyp#&Fpa9CC8ukJ9Tky4IDd79%SjPWllwZzTtSuX7P; zypHngWc~(*ZxE~+qv|}UfJ4IAo+*qs;~^a|d~?4r-WmYdy|qsmHEB=|yx$Q8IZzCT zg|TxfR0-p+2|$cp$aiHxnK1Yg$#}bz@qfnw1pAwSILL&2K=na@&SD$vH)EXHTmuvZwL6a4dZK=1P^Vf;M~iebMn_7P}bsW84k z=Zgh!NElz{!eL?jqfi+8@w>l{@&6|dzgh$+e4QnXIsq8eErSZ!4F`qsO%$X6?cX#A zfQJ)Hx!uS`?|5XSz!Z?rsRD7Te_6g&A_P@^s{2okU{0}bVO_ebI zoe34f_<;m|moRkkW!t8@#pK{m@2Zb3&LUE};+sU0F z7jSek*`JaP*qlmIrbeIqI!aNQCr%eLvPQ%Y>)j+ZRG9k~yW*KaR zJ_*HIW?CE^V*JluB+QZd!aOHKnCUo6PlhbW zg#sY4bR3Ps!KfS{`%!f9=yuN0)h!Rny?TmV81XY;$$MdFtGqooJhc|0Wb>+fnZq; z!aOe-vSAUF!yaf9=J^Rg`}wq=zY+Ec^MVLShddy$3wD9$urMdZ!&F!T1e=6|3vqlQ znO;~5IK9XLnLv_UBbpc03zKU?^Wp_iD@?Ba%xs)z=L0s`)j-h6agYZ1pFAIy0rrz? zU_awOnP5}mAqy~`QUoYWL179CQ;=U03#pI|=v=ZC%77r35af~uVNQ(!5}G;*a)ilc zmpP53rd0rX)Aqn2VO~btW%#=cf0s>S{4dMn%@Qbvjj$W)g*hDu(~(UtfW5-JJWZH0 z761v&ME{Bmm<1$rMH$q>L1E6u`D}D&V>=tY*(5M~7ZCi)&VcO7ses=rOBnwv5nfp* z%$z7lhUq|{oKmQQdST9SKni37PUm3rC-nZb3=RwPs)NGJMgM9Ny1Ez$c1;%0b`1$% zn+scDpD^?Am6rjP!o1EyM%U#4j;>P;b;9Hd$Gjfr*Ovfo*Y5!W%*Al-Bv=S#up0=T zPh$Ctpd4z2c|#hYa|5dZmg25-C8Zpi!82?-J(XBEbG0UhgHTr3Fwa%m-3{L?1x! zq3Ob0MzRm5!+c>b&lKh(5sd#MCBiI3u@K>kDq%i~@nZ;|z=1ban8j0txw1l-B{+UM z3wT{clB;n1%m6^IlmO4g1NN&)vdjSqfS=})GihQxnbUNql}nj2Fhl=&2Fo zC|7(;&??4@7COLQZ;Kdx6zHQ_9|OEZ1K!aZ{h4S0$FJmryjMoVc(qoH@~L- zzfKlofB|1;;NRqm@kWstgT(kxl!)=BON`%AXovb_B*xnWy-l;>DlvXnDaP;H z#TX&x)TkKmG>CDU{nNz7y`VAE(*;k#fa!k&S!RjoLLl_MbR{lFRMm7hDFmeP=rp=*_oml$q0$gsTAeShh~!R zw&17m{A{#|F5q!Nujs-?QBMk5L>CdXs17mF#q9IuLHP_`mvmxW)LQ`7mMVHgm(_|c z$BKw(PF(cr2GMJZL~kH2KP0+}9KN7wLA~f#S@YjW;le`EuZ2a|B#Rc6f-6{?f_zYH zEs1=c&|(*|LBZlWFmy4oH>Zh~uvgM6dP`7rT`F2dZ;gnSa=up8MVu* z#jj-qlreePsAxGGgMyf!#6<7o_&(wq8KkihJ(v`|pP}xr0BiTNe?N_X zmW)c#pJyU2+B72i0C^AOfw%{HMK>rtHW0Ldqzz2;U?yrX{%_4(VRIU2&|C-~NN(;x zH^|{NT{pVGm2E6VJ=ovK{zmpUvcHM_P3&)Ce-rzg*x$qeoA@OXeTYdP%0UI15J3Wy zqAeu0kk~?EOD%$+a0~knGyTJEFxbO&XhT27MIT}Pk$m{jj4lj|Zni+Z&8%-`eRCK0 ze{)>4)ddn-DbyN90t~Q)^(`c9DFp*;34#H(u)mc7wz|OpTgltX09*UP00Gtm)C>4P zqd*rJAZUSlLDqw;2mNdW8DN_WBy6J)U+r{TLUcO~w!1-t?W}L7!S;U8Uan>KthY!u@!m#Kr3)I`i`Yyiz(_L)v5u1iw zAR$DdP#6i}??u858ti6$Hw||8g9dw8-^2PI*7t-kB>DvLPvoE)9f)BeoD?}X_U|&BNAk2E0^)TyU;=@CtPZ9rA z4yw_C7$!u2nTb*~q6?#<`^n$$FX5jiFu;BSJ3a7$f}IJ`r<0L`Dg@CB;tmjZfVcy# z=*Oh!LE;WpqXTi#h#S<8G=cgN@(z)A$Oq~lN^t)Vr->de1%(a|iAGbwd9)1#bY-If z{h~)0<_Iy*w2MB=>qd75XxQBW8b0SjA!@8 zbR-vzh>4ye;S|YyM5m{^5f^bsC^v?z8M33lu8K?qR`X0HXu({*AmpB4c!O7 zxlz#%6ltKr2Zg9YJz5b4H9r`}xafE?GLefCRO6HPf8%Y4Aci<5MgNux5AsogS~Mes zZVX~n^zVu^WTOyOs7EWp=*2L`Mb9TA6S*isHT;eI(}oCQh+|T8A{8FwqXGm^)T0^1 ze^`V;jEeq4!P-CFAZ9WR)SaZ(N7VSJ7Tn&CCPgn$_X2AdxMd$_a{oWh=b%c=DJf{e zn3zdk)L;;CF%9;NT=>w6ZY0FiROF!=E$GCMn5Mvu0@R@ctY2gy4L-!goLa(Ps+l?_ zrbU8Pix47Weul!ff<%V`&ajxt%@`E(;z}^UXDh(tG|s2hpaBdpjo1|OQwlI3=I2Vp zyu^iGa52*vVmi6g!|3LZEKW~|nVJj_D3;1b>Zq8P5_oA5IR3m3{bGJ04P9co@-QOi zObXAO6mu49X;org<`y%ZJl_AC>C{TELywrVIiFpKAQEC`cu^03x0rJ%IwudMs6i9j zLD4x}0iR-;a|JGtIJW?msQXk4j~(d25XQv3+(HI&Py`XtJ~kouEk;O|oc`MU$+0gg}$52{D&tfF{dmvWzCnXu?l3nc3}PE~nmd z_Lfs?1#2rfUJ(Q}uVl}ErBBQp0f{+-VqR5%MvRJibsk9kk_Y`_=5n4(BHvJ&*K~>b z;=Q;+wzFN#1ER=|upMiReiMf)TmHZH)xsrmbI9XK# z3a)BFJ37&W0gPZw%&!PikO439P=rdavV`6?)kb(?&k%uBwq6Q6UK|4CdyfF44~9X5;#81RTnHby zwZ-%)rcdz@_rG{t%$rldEx5S=RiNq3Z6Kh;f(vfsfku3vZ6gC?-Jz5rDqa6N(RKUpKNEER50sElT1 z#FRCo9TD_{fyxy$Ecbw6%S%uPV#|pwC$^l}^0-V9x#XO&IvVVox=N>cMb`b#cfWW0 zU3X?=Eneo0zW>V9x3Bu-FK)eRSfkVZazGB+E_;SOQw~d1dhJ;fkwemFr^!#{nEc$n z%ucsw%RW29o@39oFSj%8FWU3uCHo57ZO^wC*b8lsy~tiH&&vz;65DGpwX^JHcDB9T zUSVG;-FA+Bm3_7SB|F!?#{RN>t(|9IXJ2pMVCUN_?NxSQxy!mINzMntE^BUJz-1LD zNpoQC3~OHW#u--a6u$(W4bFp3vvfEcolVX|PK)!f^N6$AX_f8H7TG3eovlv52|C-H z?amITO?ErKaCSP6$|Fv@^O*Cvv&#uNyPZAG6HbS-*Ll*}Cv8sHdCK{vv)}1-o^}p6 z2c3v>$T{ppoi68y^NjPX)9pOxJny{V^f=RwI>($BonEKUdC7TMo(SAH%UYZ)4>^Bu zMx0a9Dq8{#v#bRdIp>`T=fmjXS(evGk|TjL=~h;B=4|W0RFxh%8i>ua+M?B0Sl1^- zQ#{s%^l17`R>q9zsw(Tci=u%$tl^~Sec!RZVnyG&+d7{V_}sl#DB5?gwJ|ArN4>Rc zO7yZHTl+7L4nAnD_-r(5yY=KHfq2;ZMzr`T>s2F=`?Pg7@WTUEUf}crYi?8{)@@Vf ztekrHowu*LKHK~0@AtS!2u(t+f0xwGX$$pp9^pBk5N>UkobEl> zT&Sxfgug{dajz~tdv`qXR?FWB*_1+v@51gqo5%bWH0e`94j#w*c|*q!E_#30cl!u= z%OB;}hEAXAAfp3X6Y{AFZF)u&jdYEl6gPbgA)h0I>=`+DN)gfEANl+so{b~N%^L9* zziBs~KOpKGw?+*gJnUiYCtndw`A(E4j6#O7rGFWof5vm@sPR*0=B>#ZKs0Zoy#Xa- zhfkica9KeC(OR|>((dPR6Ne5?{pwr}(Pl3~`S$UHT{DXstyA?U+C33yz%gO)_~GAW zy?P$c>3Cs9(ZnfJ6JOYOglH?z5_0ulMU#gYwbk4uME5T=D2&28jDO_B+2{=nf4*9D zJjJZU2Yid*T7cq6U&3<-3FY46J^^)tI|14~k1lW-2^CC&iEx6CU-#kO?|V$OheA=!tfE36nuj5nRY$AglttT38MG zRkaVHYO~r-cy$AH8_;dlZBa>`q;7|YWOZlIY3eM{-PAom_tf4aRQrea5#hCe85$C5 z@H6-k&d|t!K^Vde;h-Z7vq8@>%mF>uunhEa!>fchtTC)Xj@$4Wa*7S>L2oc%{)V>< zhd`Gbz65>JaFVzt6@=?O0xBm-!p6i=v>ASHlKly-sME$v3>9%&Eg zz0zLL`=kRXJt(1R=`HCWpg*v+Ak@~<){1bp*0PFFS&+?ymo4&8(8J`hpvTFdfIcCg zAiPTc)E-_wndf=ecA|!;D0d!MML2$#I+X|zG1WiDGq7=(7dyW2<_CS|eGXX+j5ib6 zGjOXrC%)>J; zD3m)`6Jotc_7h6g#7JzU3F;@fixNWI(=@HjCpC~F{Zb8iQ_${%n%LepXv7p@sxV!c zAveslwosn->J)VcaE$Y+Px*A6TE%Jd-1ALW==bg+K0Sk&B84dG5ebeK8n88k_2K1S3vr`S+9~BhIZhHIH@bXW_&v@&vu9Ix2YFr-^EUHN^M3Q&=J(A< z%_qz!&1cLP%$Lkp%~j?*<_G2)3un<?anABgApyWO1fAUtA&wK9WuHlN^#$ijrcaR#LK*iWRVyX(`u` zrF4%%?Jkw7$twclJifN^1*eF zQKyfRxb#-GBQM7fVNFxG?G zebMgg+KGnzYgrn|-se^-^y#`*=)R8!t$0(eKBsm%>L@ffz4jt#Z+cpJ_wOlMsIPgt z{w>!2-|BdZ(pgq5W30Dex+fX*^XZ#4SmNAarOum5sW&}bD_N{$5QvLMvdH!{S9uhaf9gk@zgSQ z(0bNBV~uxW)JI`C(((xZ?rQ6QaNm8@?)QY-E-#z;MG8}u^hpk5B)>>ury>e3{d^90 zn!Qz@Ds|}ZO5aNA6&-D<=v5q==4!d=7!tKePNlYP=YTMKHIW!XX9anI? zyF^BE6O{~sZ-l~pM$;?~kqJ#zN>?bQrxkjHlCGjH@zy6w{sa0i&@9@bw49~9$lm2# zN@+UU>~KXp`&|C^&KAJn7=jic+-DUj7DzVd16%~_|q{457b3d9%FT$q{2)_KTEl5EOh3s zX|${zWlYbNK40^BTGhIvHjYr$lXL`L?kZsMa9x!VclFLeD0rIVokOiE%YCQm+43Kv z95njx3{qI*Wzf2M)+h{8SPAyIA2-WzM@2Un^ZYo-L(Mp-t&(!yPP=l;l$o%ur>llz zwkCzgO3GmX$gkxc&p5*9`uQtdKx5xO@GRKnnv&!zP;QgS|E()8*;y_C=J?>@^B z(lFOEs)O#GE&Yc)d0^A$d$3gD?-^x2N~2^PYtEZ`SxtUnD&kGO>Ovl>w=)*8)T=bl z>bP4(+uSkHqNV=jhgv8HLF&$lvALizc%&_#rCz zU>i)JSqK-xVFFtUFr7jhSUpbh3cTVK!WFOJid5XfRK+cRfe?^3$ynIm07d6o}m}$C3=-s(L3}3t>HLM z%lU9N&X03&PA-az;aYLYTq>8r<-j)#;D&IcxCz`;ZZ@}oTg)Yn8Q%q+v7hJLw{B7t2Ujai3U0x?yMVPm(WwEPhG~u|N2V3>VLf z-;&YdcjAwP?GHKZxc5RHgy;blRX+Q!oB4uYvlA!BmHM4PB zHRIhm$$o(#a^Q`NHB0e|mVAr>pCi9fGi`=}s>-J)x8ag>;kpRjKXu2fRoJi`5D$uP ziAThb#2@4Y`3&Bo+y&M(bHpB;%n)i;86O}`CPw=Dp$=7?`&49(`%b6U?z&Fu^2pQ$ zRI`;;<09PKJLlVIBjsU|H%m#+m#fl_^C{dA50*DqUs);H>cKd<2qoR>`ADHzy45pP zp;@}sGdw-q(V5$Wx&BJ)N`HJ7 zqxqpqh4V^&7gRf)=_k|UO6D$aWu;mscwU)VNBg)dvs${Cv@^iKb0mx0AitAtAw%h_bPX9szd&F$0&CzA8N&%K&Pc{%A!LwgToyN;9D=f@ zk+XbPzAHJ$XJKaN`Iq^Z$+!GQej~ZSSMfK=cPh0?L%vr9tAfdos#sMlxui-^C6J#~ zb5--m&)T8dVdS!Qgmx^ss-2*nPO7xCwe!gz+J)LBOS*07eE4Vw*bP>W%!;Z15Ylp0E@-LT8BpEfYOV|a%K8V(x{)5eAm4M(WMaMW;& z1{;nWj?*y13BwoEY514nG;M17#PkVmZvEQ&HEm)2#(I{v#1{NIjkVse-lUz`%Ax6^ zSu_uz8EgU3OmUaEn|2rXiWM{$%ji=&kS!oORy-&ENGIA3+rFeTZC7kp=yKbywqNNA zUq9av`U>V4Hw)d|%})fv?V)g{$cRh8Vc|8-~=s>4Q+xS4h9k13Nb<}Az4TjGK3r< zPZ%H!5k?6Ua2PZj2Z4)W;@1kBg>Axa;h^xY@PTkl_)It@oE0t#KMR$@ZQ;J~SWVPw zwaW)4+E49JJJnI@7}8&MfO?2}jJilYT|HO5Q2nxcrFyM;qq;<0s@|(U zq<&9*M15TSh5EGmy!r?AWp$7*{RvDd0X?o=BVa`=A`DV=A!0j%{9#} z%{|Q{EzzpAMy;rApbgZ9YMW?VXcM$a+K$?EZML?Twx6~TIyFu^SvylZU%N=VOuJh9 zns&2xn|7ymzxHkI``V-06VR?R+6&rC+N;_s?H%m{ZH~3iolWPbbLgD9C|!)M zl`dJAs>{&j=<;*}bVGEbbQ5$_b+dH~bc=N>bZd0$bz5}Xb-Q&3b?@pv&>ho#raPrO ztGlTCS$9o$OLtHASWon7y-_df8|VY|q53BJ7WxEzlD?xpU7xM*rSGRN)Q`}Q(@)mV z)X(l2xASLO#p;50-TVhpVe$%a%zh9Sq0XBc1@Vi;wZV3=x{ZCGGfY*>La+4Y7khV6#khJ%K8 z4Idbe89p-e@t(Mt@_lF~S&aj5D?|rWn(VS;ij5 zeB&VFFyk0wk#V|lu5qF9W#dZYTH{7ziLunU*LcYIp7DtBxbX|)Y2$h055~*JO5<(g zedA*jF{w>PlW1yS3N(e9nwVOc5==>^j;3@|wyBq?pQ+F^!Zgk_*)-EM-?S*pw9K^H z^qOh2X`5-MX}{@h)BC2QrW2-Vpf}d%r>*1 z*0!yY z46+QfjIk71rd#G(7Fu4mthB7PY_ybEN-cXWhb-?|j#!RczHl$ZVdMXFV7S`)nsu{v zn{}skzx8eF`_`k@6V{W~Gu8{%OV+FK^LMNdtTiGhYDFK>Ci;mE(J4lWF=8t*Sxgl( z#2hhC93T!6M~M@}sp4#Lfw)*)A+8bEi(6pWcEk0)D}EpzX_1YSIefPWiGy&EQ0ZZ`^MewAbY-4a`9HodQ1^&GlEFl`i-!M)O0J?#?UuEf`H6 zGn%Dt?cjih}Wa$4t5+Zf@_^hXOdBhn;lR0y69dq0Uq`*GLaMDV5cY!c8=m;-{U*;1Ia}M zg2Txl{AhkO`I8^Zk0lTI@%(u5ke|p;B#-zR{0#CJzldK(9`h^s6_oO;`PG!;*Yg`G z&%e%Zp=$n3elOMX`}vbp|4_Lo?XFU(baW7WbO;@$YNBdNN2sDz z33QYyMU_G)sk*7U(aEZORX&}f8l)OTr>cgihR|uugVX7%<*Ma$rfQAKO=qdfRAqFI z>X53O&Q-mmdWX(eRj4Yc3toOKT>$?+gDz$Mow~IzXqV9S+U45iF8T&@^Rz@K=!|r$ z;@Nj8o_&wv+4m}*{h;F6%N5W5w&K~}S3LVa6wm&F;@OWVp8cPSXFsNR_D>bh{v|y7 zO?p!C>Egg@(m9 z0sd+>$<)o!%^_L3xw^Teqi&vV9`fhw=7YYeyGc61Tiqh5N;BQ`)%t3Ztu)ph>#4xK za%F|)Hp*(mZSIU!PEP#EJ$Y43l=u*(*eMW|_>*{r5b;;>1`))Y;_pN+-WC5O_@;?C zR?qqIbKPfF^>21;!q|xpdTQdx!Q<)Alc!CXOm9scF<~TqGHwEO3~0qld~t?I@BvzluWL_o8hGm?m(|xjeWIY0mQeEVw1sfpGE*I-LC+o?kt%Ic zw94A%fTh2`naak4A|4H?NyEPv)|cUPAwFE2upRp!I(4^swUH|>yJt5CN$b%aXtNe!^VvsNiHjCrIOwrF?zyaa$iXwk3uOW zN~#_`Vf0jLR8kSygJ}a+IM_XEO*@IPjDn9Wg+P(|yAQ1i3zHR^730ICl4_L{7Xpyu zR8n7e&6=j}X6`_fpYjahp{$WR-<|7HL;RFxfMZZddIT6{90FQkJ!0UK>QDr&XEjlp z37U5`9&H+!ftuP0NKsR}q8_gXMoZeY^_cBF@vLJzQD8kg8fF+fP=*a{yzRJ*O!#Qf zm<@~q4&u^*9t&@uqpY#~v~KeqW#XNyZY z6C!GVwLb~e-_+kEjg`;njwfX=GT!85ocAcl)9`wM+D`T1cz_EIM&Da-Tx*?nkxfq-7xb8Rvx!kZ4R})Z%*V(w`dZlC5jrGfp zrxZ)~w`U$*vE}cr@#H<$0?T25(V@ok&)#=pJv+K%{LkJVkIm#2aA2HzMyauYX1fU&cT4+t}xTa)tc9{Goi* zC4bDA?$t_A*GQ3cL^>)Rla5O#q%WkC(rM|8bY8kBU6L+K*Q83RO1dT8mhMRpq{ouS z#@W<1z0Joa+GLxbEzlNhbK08NqHNJP>GYSfq*SRDPCLV-Bq?1=kt5`$(f}!6j+P3g zVbTQo8`*VMJ|~TlMoHu3^YXXSWVw%gLH-U$qZj4xr6TzU`A7L@`HFl^z9HX|f0rA| z_vAmN9Ql#dORknZ(o{ROtLz$SrCl%0w40;_c8fIEF3Gue+1}9ZZ*MFuk`~*8?P1a~ zxuvv5dQI*n_r)|-IISIt^V`ube9CL69NLB`hqlmtg`wl+B6*5DU7jV+m0j{e`6c;f zdAYn&epOy87t0&v*X0uVO}SLwCGV9F$cN;21)*Z5Er&*1+a(bJ#*{5z<;)3%P+DC}m4&QX4r`4#!=B z45_2sL~bSxlKROlq#@D>`6v0Z{Ht6k-;{65cjZR%efgo(Lw+pf$+dPOO}F!QwOuEz zwi~6{cC)n5E=u$5zH(1{1A8NTpgl--NH5z%?cvf2mmDjtm-8@Yz0gzW36}I0dP5)j z2>qdWg(`40GuizenPo$fkfie<9pJ*o@*22N%B;AhCExICohm+ zlo!iOLzuTTFW7_ zQ)(x5l{(0ga+EYs>MJ*w21~=`OY$%BRr$JHCI2Shk^SU9f0d|MnSXyEau{)*Za*R|g_x}IPHA-5?z@iyp zBNfvmj{wtWVP&i2(F(=lD5FBpRLZ8I%zLM4mitr*G;`R~7luFg!WhtV<&n?jj8$?* zDLE<_8y4yK%j|iEQg6D<-k++pHwE)z-LiLP$gHjD%;Y?G9cnI~nbC69TP<56&bYr| z<7W586pDjv;KfKXV-n7_nML;@Hd{Q(kK1CA9<{YZdgN&dyPtO47N?ZNC?&9c^{r$m zt+Y~tG#l|J!6X9rE%{aidq;#iJaCrC!p`oZ2WggAi?k~M^FT%9qZaZpAmod+Zoh3I zuJ_1gj4+?sgd551f(}5_)k?0t1D^hDPDC`^;lr>lnB6Q zSCsK!K_5_7O7i|zz`2LL=^VkXBa&ctK~eF?V4%UtXhRswXD#5mArFbRRp>d$WzDDz zU>NQuFzOJ>BS>?FUISVrX($7eaDkCMXY$M&210SQvKqJHG_p}P zVc&N`_L23nSvI)uYlepGjL6~0)7e3+;1tt zjyI4|TcG0TzKl~YauKy9>EE6^{M$2|^7HjGmFG_023TMyh!3Cq`+HT>S%oi5>d&Nx z)q(34j9*Uop&jvvMk;qChI?aHBK-iqvLGl57~hyQi-<~t>&E#0#^S;=?zGY%_vq4K zO&@hXoH|c+mzGY_%?o%b;G=-g1FPMRvY^Jp9FrU?9h)8RI1W3$c6{sj!SPFwE~slz zW>9v}OF>KBgUbAULMlT;LPt9{JKuAD?7Zw=Sk|7O5#@59C<}}1S=Og)WZ8>lE6ZLj ztNXp-9sa>5)#_?{bwYJgb#irw>eTA))o)hst3K~G?riPuveThsLn%~GRnKxS+Bs1f z%%*_jfy7<2GbCV)W2$4dqr~x^`d(txKtEUzc2$P}j09x~^GWL|u4YSe>ITpsrz^ROeG?s?&IW^MrdsJ;4tzJ$(J) z=7$>}Zg^Py@YRQ_AFg`1^5H8Fmp@$gaOuM(4;Mdt>EVkHU-Hajz1h6#uc|+*{;0ZJ^?TKCRkx~cR#jEqsJdQtt?JjRD^-`Pey;kd>QdErRo_;f zullCy>#BcLRaCuQb+Bqp)vHyjt5#OMQnjpVQPupaxmB~PW>&>iMOQ^tg;d$AtT*o6 z`02)_8?GO2ym@0}<=2&`DnG5?->ODY#vzErue@`XxQ<=o0SmD4H*RQ9Rt zS=p^Jv(kS3{PkC^&%8e7`iScTuV-HKT)TU%{M!C&yRXgtb<(dzSC3w;xN5$tzT!DP zeq7|ZuyG;dg2vg$){K2HcG1`cW9N^ZJ$CBY$zzMg4jY>_w#(SGm@$_^E(JgGPqf$C z@7izKZ`!NuH|*%e{;T~b`}_9y?0f7Rd^h+m^=;>y@ z@F^e^a2kL+mjd?5IOZh6eLx3%GR5v!tpS||tOH z_z~bSXg^%QZ|?YAz;Yf#zc$GZQzCr@r=T9L_oyGbl_KDbZF}V`Y+&K01OWA6B`C+s{%a+_!fT5 zflSRhU<)7_G_LmgrT}t4{|t;ad{LMER>Bvu_r+kedf;V%*FgJ2{=Ox6IDiMR(f5)U zw5@@E@q)GuA#xf39MQG~o&cB*x*hNWz-G`W$7D!=4fIf8oFN53blRD~PCzv1#lS59 z{Xwq+9tao%`D?-cfEfT()_x8=#|zpof#-Pv_bEsKM$bSCF$8P^d;}WG831tw;63dh z-lKuQYS7?ZV+^RVFAh2W1a1Jp2=xYF2cR=(E3hja31q4V`x}F8jr)LZ2i(^SdQ@!O z-wS%ovN1-@Ko4#-hMXJE1I^k1CmO#EdL;0>01QeG&NMy&_y#l-ukm@n_n;30{|La% zYL_0fXnYTF9|dQC9{@a{&k=%w62~ym5Q_tHbWFmrOebK-(ys^E&;p) zdJ6D+0CZ$n3Va&yHR$EQ7=+_n(60c05BWQOzysvrfV>&tS0f|{9S7+^uK@V(?IV4p6vzGPGGQ{foT`;5-*r`1F!XhX%Fxwz<$)(3k)3z z`3m$=;45A*9RvOq;6h^h7(}HPOpse>Fdzi^p8yvEMuYy8kT7t?2`-qxN@ocGEH+O7 zJ_x8*$d|7goIOo3i&I5)c_r6a3tIa2nUS;yTT*!kco$bz)(a6W++T}cR&x& zXMyv)V7>sH4;X~}?|=sb(1`hG;Prq5FgiBiw*W^#gOlNyL^zbtf@K`e>H!dXlJIMQ zn~=Yy9f&)GMAV_66CsfpX{3e_YfoSpi%0|L-oPn<4xq6@B3}e70^JuF?2Ux7TKfav z^n!IL@MAzV@`n-JNdj=7M*w5?O(1_OxZ0#SD?y)z{L5D3 z;Z;1G2L_wV*es!FzY{=1&@evW7`elPeniLvC=>(ySd2itq*@KS7FYt<@iRshZ~!0y zv<|ox0179C04IAv0(YxZ03BQ?hy>9I0Jch)X*Fh6-5oSoU5yn`{U+!{V9dIDA83re z`WpZSEP<8P-vKUy#w4mM0XIOqf!P2t83`QrV4xl|=ncRQ00x6!vJsD~2+34DpkdE+ z0A9lWop|sf16yl+0s0Go8QR(q$|G>(13|Y3#*qt;hHTjVVLbGkJkZ!?p2NoL9Nx1X z2F51$9A<6%2XG1ileB#VjI(|K{69{-&t(8|P=J%!b3FiKL7xOJ0ib2uHA26=0JsU4 zjC-bcuuHy!8T#Tw!X4DPvmf*t;I{xrKyL;9C*Uj42Y|l@`~><4q4%2sqCw-D{{5E3 z#S-HC6&|n|1`yxV1mC~`7SMR{0k)72Y@mMumK7kl5k(&~P=NUU3XDMkh%W~E0EadY zz#-r3zzzU7c3nAw9^(D#8cpa)PA-$&&w4rfxA zhfF5J$Z#^+K*&t8l@yV&hH^5Uj4@s%FO!YNZDb0rx!fQl$qeIS<2s|8?`1qd#*w*v zJF=6!PhKEH$pqsT+RJ#-xQvV^^9(97ge)X4kz#72zWTfRd-$wcjT=1=$zh*Oe)VI6eN$<9WZe}ZRcSe< zez4EyvzC#s40hbF3L8*d-+}j4)`7Q*;NJeL!iFNH<&wH9svSzpur>-Cp3i43BVTFx z!uDU*5&B1J#TH5vA(w;rMGnV!rxOlH2>M}E!ZFj-Lbo^cY;_8 zad$9m6U#9vRV1HP|eL)5u1-8sUfw&m^w z){@V?ajd1e4C&le_cr>;YF?(((OPq5TrirPMKcbss@+@u$mTGO+keOmsqdp9wfn^V zQ5a--i$CKiYjDJa7*6&n-}oQ~k81a+hr`$u;vPk@ry-A`SvPAQu~*zRj~Z$<+=u*! z7^J)5U!7TA;a`5N?YVz#XM+rWJc6~k?C}t^>AwAV5PLhjI)S0Z)vY*La38Ih74=BZEMU1EmrO=lr)l9botIz^*-@Wcz zd`hAXFsR~6iK0t=vBQRoQNTGiis`f}o^PXZF1anNE0f@6=*taFFyx)DG}yN86VGSJ zR}@#<5BW@S)p81~;(x23QuoDk^$VZYPim_Eul19Z_KREkQs_jh;$FTq+D~p%Kf4JS z%*X2cXawE}vujha*_ZZ%Nc6>zWE$nbG@B}nf}enb!0V`-3Ny03I$fMv4uv%GJD4i)_B*=56ZepExzc$FWPdZVEVzPtka(MlgF$p(jP-$1TEcti zPT`zIt$$cCp%>L?X?4Z)0r>e*YlDBy2(SEVMIo{-O`UGha2sn1SRUbOFRA8uUc!Zc z_DP%2SlsZmGfWFJYeb-*{EcLup$39FD0k5z( zUa6|MKbU4vYAJ3%ly0PdR$LrPlR3S&d$>FQir^7c&uQ_K@e2HALQ@epims)yA)ppf zE1N^jm+G;6yyhJ01{7Z!O^sCa@-!vTF(hZ$wu}s_Dy(h#YIKXug+tDAUsU8zqu~Ngu2?XeCUNYABXg<4 z!gTNF6-=-~@uL-VGBm1U+$;1DvoghwRaCaY2aQrZMPn#)s$%Vo6&b4_SlEz?)vwY8 zcBos0xQiz8bW(A~UfP&WE*`U&2Kvcg;WA-Qi<-Z$41X4!*fQZ~i&OrpV%uKYfomxS z#R#e}-_Y>TaHr<+=vj2pNE${Z%6pc6>v=HX#8Lr2pqw+6F18Ptq%k5UtFRoPM$S(@ ztt<}VwvdG4$`iB)!%3e~xC5bh#HSPnQYb$0DXZ^O{6N7%vGX&!2>BIz zKcgd!E*4JwC7fgTerT*cF_zjx!ZkF6^41V*td)jyQL|q@QRO-D_JXM^xsVf{W`Dl> zE?xAAu&ns9XVYg3w${wzspp1A7S7cM()X}{2xW_36`(4_buMq4n))_1-Zp8?{I+9G zezj;p>J%DSe%Q0|tsOgP6IEo&j2rH(7ix34_|H6UD8W6NQ(-v=bLKj(`V~V&SV;q^ zJs}|{93>k$i>DaBu3M4J~||;Nq9w{E;;Q-3{Kus_?PEFg)?V< ze(M3DEqVvjD{=iIhacvb*9`b|b!_;Sxb*1eG?Iq#+iRxH+%rB_v^6V?!xTy|h5f=k zc3CRc>avj77-IDeiI0osLV|rbUu%$WkhO#gHMLYz;p{OlFMnRHlkZcri{B1Ki1d8t z`L4BN)}HY(G2{2l@?1aQfm7i~Pb|6=G%6`m!SVw?f`X&DxMU2TSb1xG^K3Gzf?s~A z@VqezGdpbKdiV=M-(ox@W}Sgc2K(P5%@7C}!M51=9O%6z~!jDUZ`nLEEv9}K^OYHDk!@XIg!@+TvAw5H)S z+~fMz^S$SkG6}{Sn7REB2UtTDJ}A6T=Gvh>3sK}j`!HTObLZvf&FkT;@cdO<k~uUl{rJhPeaVnRe5xZB2X5+4kwQ zk$Yx!N+~MN>ykO^%*OnFJFY7oV^^q}hzaR%;G=ZPW`zC@ z6a)L-SnGe&i~rP$|E3eQp$E_$bOPK|^Jp)Ug#$#k zwQBrLY;G$do2g^XG=97L$F&(5Ykzdd9q@cR_RR^c+e|r7wR2o-gW3DW*Zi`xsH1~da)-~Pz<7=5Qih_;X zJF6DEOV$|wEgHji#jC84>x`N+!nwy6AyhUy)PV>B@esi3JYgLDuIMmj%ZFQMqCSXU zVITRe?i&6O%pFAFI2Vwh)5&~nOdx0Xjpjpw)tW%w7y8aP8XuRC7$ViLC#LjGsSmwd z;Yv$d>MqVm=+`|fqD4Xfo*{j$|mbL(kWjPwUlu=>Ff9F1SA26IXEHrJO9+ z&H;t{7iAAd*ypu;JG|@<3b8T+8|?xY6cY=z!zx$ps7T&k&;Q(cd*@??(<|*eG46BD z+CRMf-!pqX8f#zog=#$-gRKZdK*}f6#Dvg9K34MKH9nkdR~6UHX*IC5K4IS2<+S12 ze|&pmM8&>cc>{YJW16l%MN_2KS%uSAK(f=!mQHcqY1Mrg zjCj%sY*mb?Y)|I@!&rd3oCc0V1Mi^BhYMrt%qDw1#*X;@Gg8K#9~0W9sl7?RRbRZ4 zA5oFE{1o*$yE-$lb#}{`p{|(OEr-Pn{dscAjQ)wVOF-)=zwX_$w{-3OI@NWZoE=e^ z6EkJ*;U!AvO^UC(k3Sw8r4R6tRSZL;?AEeM&M~Cj|DIIgboqqNH z0JbD77S^ub{Ch2Q5Ih2$fM-;Au4{gu{CPQH6_lsMLsbV3crA3?_&qb~Ei}wO+f`#$tL}(yKXj zyr_h^U$W z(yqb~t~#TXDG%(#V#pgaqOgu3j%Uu9S*##m)ecV$PT4%Qicjt{KgUVe3(i`D=SR;u z=4+n#;n?weX7bBnBPn^Y&UHogwQ!dt;t8U3V4cK1T_etrp!gtW4&$5-wQmTt04vKY zab9)0^RllzznxmzxgtDo#qi-PdO6>Hr}h?S>pC_qXqD&2>WWUY_kOc?Zfa1Q%qGdB zvzyTmM(&&6C1c@%;T-{wS9ja z9wN+#H@x;_#`U9m&J%{j)AeDw^ZP3D^VHONJT<=v=e)5-?1bGj9j)QG&*LYfLEQa= zti9EBmsP)^J#56V2WU#;V`F5Oo%)7FV%{=eh z+k_344oLy@$r7u1@>&~O3@#_b4 z$z1SFanHOR_cqV}cE?zRZA_Ff!#m)Zd~sySJRS70A%$yt5&@OeYvZ%(`x7eTJnP22Hp7(s(;m&?_`Hsb_wj366Vour~d?y;Io8oijRq_>V!$ z2e{ZIPEySocXsNW-8XulqMgr{XVbT>knw5|txhpwTeP5ZALR=Bc%6E$abrpAwdV@QZO zyhC%BAGax_b(bzFzGIKA%^y_u>&vr#{9tWM7T2_Icj)75!*{eBT=GPQSdK~*`_#Iy**_ou-DdG$-aI(b|BU}wr~sk5!aYwSKx}7O{09etZ7+*h zo>;MSFghfXdL4!m3qJFtu|kSxRGXb%mx1o~A{eOnh5nJA!Fz{ZG&h+>qnnasR z(8nvnZT4e(Db@!6@70!QE<9QY2g4b^LzwsU;lN(}&lCrSZb?P+KC?2?=k$wd*=J5x z(v;zO?L#@*VfNlL2VH3uTxi;aZe7N82~w$oJB>)6^U+IPGL{^z`fzbN{Wx`MuNIEf z(Ouj0ZWm$F2R3V;KP9u@#>pw|#=Y9h71gU_WO!OZVocZgFq6IG=nWG_Y@gCDbDK4r~94>PHy5mLvsCcxLKc_0wmz zE;bqt?s+3epBg_fT=iqx(yu(XPAyHXaQ0a~V)*jj%;MerBA{icZ^t=%&+MDiIjBum zWV_Mbo7GvF~f{hz*fhmiR z^$p}La9#NM*2;Y!ez>oqmuvCB*w}%KdsWQ(Vs-cKtG}29;?>;TS3#&&YQFPKzo1dI z9lQSchH-8A8jHHuYv-u({Q6$P8*d1`)}Qy>KL`4CHc$@t{)p-dRzxFq9E#=3g|p#e zXBQIh6;)gp??%7%4T}r(TsyFF;{k3s4W*9k<;N=jxvU%4Z}STSVq*Hgu;rz}35kO-jwgpg z!X5A75jZmxF=8P&(-=Ded=4RA=`&Aa3v_XIt2a7qORX`1G|URUhqMW^FxF&FDCk%A zo9FvmJMt?M3Sa6z?)6bI=f2%H^NUw&XQcN}@byjT&y9*HSllyraRIl;^ZAO*ZYw{V z8y=pwWMG_%yVfM9sLO^mp4`k=E>MFdC^jv|VXj@adud^8ZGb8cr%kl@i(a&Kafp?3 z;D=0q(u3;p?EFZIr6D!tp6{2b$9rBzEuvE0nkr2`)DM~Yow>D^G zvIpA@eofm3cbeHhUUg^Ik%g(jX%n(q^hgeons$jbHxPAFV3-)5)T9Bgjvnep$GNJz zJkHeE212sNx}Yn$^SMQ;yEJ6iY>0{CocF4FpsJ94@ecDwm-WH2G9nf?BhF;OPpma0 zo>g%2os;)Y&z{pWs zz>7V&*|kI7+!Qm=wJ?{PU0t$&^k8r2Wu83#zG@C`W)m83!DhmHGJ*YyFWWfD0hG`F zY4Ikmw6k2C?21bG`@I1(Hn84AAQ8F z{bFlTQc}^@;ls900y; z_3KC9SM~E`m3ZhIIo%6}Y`t0AV(-WyGiN+EcVA{8u;zm5=lgWJ)EnBVn2N#csQ8;7 zc{csqY-^nX9mi!S^lIOeR1{q~I^$o4y6F^W8mrjSAiizwxKgfd?I-lM+J*_#{0sppJX3^^qr0Gbj(Ot` zMfAQdYrX7i%DtlJwlId(%qyvvdoBC585l3*g7H!K12TjLd8em@NKhdbxTt&~X&<;+ z<(x`jJAIfW#Ut@%Ds>pUq)W#9f$?Q!&b~v&B(|F~X-L<|MN2Gwrn+8g&!Xs-Jx0=w zp8NJ@p|Y>DO_YSlIVC`us5Br6+rJwg>c{NbsFKu3tNh?&^ewc3_UK zG--0##a)xzww|(cBK0r*h(8)XV%^~3OgSf&45zPpT2KCXb#C6K3olOka$|q`HrV`x z#pqN-m(Q!Eax5V$D)~esv0MjuIb8jt=1A?95w4-PAtrAlTr?~MOo*adv9#MSo>`^P z3w9?|k)wJfI)MeD%C7WzYk|!UlP#Ez{&5@vk;weT5zJmV%gS24F+O2hVY^GILpwOi z%B*d(2gV;f$Zfy;cUuuTeAf$S;9D3RRz29tq4Nez^Bd7vjR0>L zh;evNKiKAiuNSvsUfED??f=M4gJ^@Iq{Md9_x-qUTDw+5m-qNGwCmXPF5}WeEzXqY zv(v`8x`qjQs=s`uB>US%vriTG?p=Ip_RJG&2U%*5_FOlyLx+j$dUl&JG%u?2w2k1x zW|*=Y7zlPBFtk=nY)qnZ((5%n&ewPRw4__MvXb|gvxQu}&vUF`&<<|SUk|vvkwboG zPPGg%#(jKaRg+BYS}?nUy3710XtWuA7y;(`P>n2tk?~%AhIdM2;Z%D}8%63s4%_7V zm5vaWc@rO=yJ2r`U%$1qL5H5hlk!&-w&b{0Lzeey*DK!M*ir7ZnkW~U(mk|6tS2cj zseik)ab3e3B@geKFvOM7RET=Z;t+>RDHX4;aCPxJ?Wh-Qv*L=VgKAGT3d?%4z* zUvC+qR$j~KdTJVL@EwZDdOmF9ORA)+6cZ({S5+8+ zgD8If!5G(T`wQ(6w&u-JCXdW_@?$@ECAU;=-(z(0fS3EX;8iVRy9tpU`^2;#l^N-D z<*yo@;^%Cr<=@?1xMOx_wd%uwCYht!Wi2~4qxQi5sEmZh9VTz;_aY5gUR#?#EiE9n z|J<&lQWlTz++oS0`O3^;%vHM}KDf7fonT7?3i`yALMu|oW=7EAA2Abu;1GQuu5PgB z7}Io@s(H!d6|nH$WmtE?lSjK@85+2{NEgSyfq|*4p(|s6!O5KqiP$|N7gMjr@Dl7dc(!P&)AM50%&$HEYE8UiY1y%bdOxodEu5|PU1z%}dqV!C=|%Yo5g8*>dMr;1?$jlx z#mLgB$qD(Br%lRF_)cpz>q;6mZy(xn%%tgaT`#`WDSdQmkh95tAG=u_?;5vleCE2< zOXf}-l!0+PSsto6SRU9OV_-T@9=8V^!N8=agHkC=0?R%YF&u`=PL4EQ@(TUb;}g`r zWnklk%svGznhx#VS|1SK^mKgZ2y<}jj0icYG3~#8e3D9Uh8DWy=(Of-maJU8bY3jy zNFAFM*gmaWR9JeaWWN@v5k3O%D^~RV^0W6k8~to1FQ;Gw{-0wh#Y6vZv6Soo7EG~N z3dSQ}38pwQ6k=MXnhQ^u3g$o*%oaakO9E^K_MU9(#TJV901>{?hHX8QBEJeknGT`& zi=1!mJHbg&ey)rZdt*^0Xv12@MR@Qp=_`a`> zZXKA|tpzoBTDI!bwy`5+F#mmAzu9TEQ&fd}2aiabw|`{M<#Q&rE?E>ee%7*_t}hI3 z1wB%(HYj?OuXGNv{g-8mQ==z=6tmuJot7eK`j2(0YX0bQ2{Ykrow9iPih2ZQ5{?HJ z#xjS;rt`!JdShr7PAkijk1Gx6(mglg;K9glshHRUZ#{AKUVn;c zYUB{+Ou-qZLpM}&EVz8*aVZVMBPC&p!S{Q=EzxfD_u8?gB_+sYvxUZwfT8iu*6ZG% zpRHHR|LbgH3)7>X&6Z78)x37gv)Q_6yXO5C^{)O=;q8s*=F5CRC}b85HaBATx5A#= z1V7OlY{9WtVNMX<0d@d;7@EzUsBKfWaA8^87R31zl9DDM&fh}o*fwBP*YI#`1IDB~ zcY1biDk#|G5-hui4Ms%ed3<40-e7u@1%22FC>w%FB?`M(@S(7)2kx5jq&8_kdT}9o}{1f^|Iy=Ji=Wxg+n_ zwEKik=|$bbJy|$Rq0a8<9lO;oIJ&B!dCj%fV=*ePk_s2R{(*`0-*ht38q43Hp^&qp z>^pwyI65nmgUl7h^M)?X^XGNrR*>T2KWK!bA3emSa4+JQiA0hUebvtJe)sRrzB`+H zv0uOK&1h8d!#`+@&O(aWZ5%-^j=4|W8e0*uss&r|$@_FeV|-w#tD_cABfekVkCt%! zJ%G>a3N22-R`~#L*eVwNNxM*28LUJk6c5^_!#92(6;ur-O~9uCnyiAB!2=1rlhThp zOB*_30_~-uf3wIo5&m`LV>+XOBc`#E)1-9--Q*e0<@@-?cbL%GbN_JevclY$C|?uZ zRJ+sUn}AGeJltdH;M|r`zF-$lPWkUuh4|?S)3rDp+_6LZK%VXEg5tR?`r!8CvpwI^ z$cb-^PHwQSX4)$HRp!tUZNgSX_g-E)+0%Q~Dlgx=*FE4q#sqMugW5!U2yOsiXA&OI zw%E+L)gPF1?UOr~$H{^1)6-)jqZ>OSlDox*M)!C1%lV z0I4?$7zEcGW$=pBw|*zgz6{25&C|2nmUWK#NmaON(}%T7xLK}4;cP@+2fzlz-cg3q zl%b#)S!LQeZAWbx-S+6DiyKtCjhl61O$}PVgO^IN{?b%q6?Q)P@`(i>60C_&P~t%g z=inMr+AT6?)ap?=k=CZU?b`MlnLS`(X7Ck{6PLYe-=4aye?&z8ZBr+`KCfNis=(Yg z&b;C|>-htJ!YhhPMIW>2HX7`msEb-PRvL_%)~?Lra5b59hrLWhA#NTkqmJg4s4S4< z6L(6@x=-$P^ZNRuvs%#GHKX|TlQ&K4*!cgj_8st56x;uIW_Rx3~^{LYD;t5@$l zap!pJL)L7dVRWiit&=g(`cNI#_U_dicWqpKciZI!GgrO7YGwf`1BQ>{7F-P0(~Opp zn$GZ&+(iG9XZae%dO-Pm+1 zSlMTp&-#t`uG4RtI_xU)mXWg zEqZ{7J=C&yCD!jb`^A~o4yIdwym;l_2ihndSQYEcti3NjVoYeb?AdW@*`g*b)-goV zxlJ+*&m@gt*AUBW6k3dMSWnOZzw?17&a`b;t992__dm*(UHlgxdhLoDcl4Rxx^yi2 zM8euVY}6&e3^A_+#qeASNr$`@Dc1~7AM0TOi85p}Eo8U_6=z*KYb{_cPrQEkleLW9 zV%YrEVb(YPbJjP@-~Q$61E*{Oc5hg#judzEup3DM6Qds1X4IkS)g~6RVsOs*q1*F@ zOuuDk)4cj`sw2;=UY~u~T(oHNf%$!siWV!L+n=A%g|$FjWI}I-vXu}@RQP5_Ua-jP z$y9iE`U~G>Llix=f;TO3dqR4hth|iM|0#NDx$>F+14TS{$ z%WqvSG9QzNmFit6UUUNkojR7XHkGkag=`y}SoD>0&Uyei{kvbg%$`#|T`u|zGej4o zKAT8nWRx=!DB}y0vpY}gVtvZ8r|z26u?o*e!OZV6Yka3VD{_ZC_Drb9d<6R1=%QJ8 zji4YVuPGNDCAmp~8%q|QJ^1Xh!dvRMZ&I^z`LZ!(+-nokYL4h`=edfeU=eC&`9ChJ8`DDPw>? z(B^*tC7-znZcgWXf^NgjGn|js2TLULc7^xT@je7;WbRVd)LihVfrzNse0AQ6}<(o zELt)z^)^L`sh*S?n^-5w&9cqy*q*{yxh$WoRbo%7pR#~nQO-K>dgqfP)lYe6|En(Z zkt9Cc5T4h%u_6AQB}62J|0E-5#YaRO@PM1}t(9SsMMa?q!WEf(w6)UVr|b_#KAF!_ zG6bE?&#+Sn4U!?HN?1yyfJ$G)8!Ygn__K=fG4o|qLT?Y7Q+?LW6rCKz7M+6b-@gG4bi&Ua|A;_?vAe8VVwT$RK3-NJ91A2>G zlXWafsjKvcg5yyj^WAL$mnAI;>%BeZt`z>dfs*~T@^7@*^-W2!B>*n!8^K``)jcxF zX%B33f9)<8q)SpSh`Kn_zcYegGS1DSAz)?{eyVywyASXN(S46w=Ex|Kny8y9UPJZPOw7q^iaME&dv{H0Hp9(p zZ>^eaLu|q-K9S)Ge!sG@sxIV!3)!^FIsHR_YHZ3y|aULu6s|B&pM>s z9itVD7>?EKxxB2ntlY}$49}IRqx*02j9_J!4j%f*{B||gO^At^ki05S*jebFCL-{T zsQsDhTcS=a41AzLVfYKT4akpttJVql68?D*p2V9-xPNB^elq%i^kbpno~G9WffSIV z;E|XkSis+p5DZTNKOguKo~YDyZzFsJUh=WwjsOHO9G=1-bp*So#pHmGAqkLMg3&_j zeJxji7Y%r$10$NjXE7@AfUE2DO%5EH^OqiD!!HO%0zWMYpVE;+3yZ!}X~tpmNlV7f zv9ADMf|} zyLKzx?d|gJKUw{n?Ka&zT^mrTVf`ry?&j?0hX>qJYgW_Bk67b+X0+bbwOK*!j-J@e zc8hv-?%Jyl-d}yK-7D6w)}^tnjj6m%E$^D~nc3~D4Ot`7L5y>-%$p_#Ab4h=op)|3 zS@yh76yJcH$H{r0nBOT~QA06zfrsRLZyM;uTt+hp8*nkD-+Ow3A7#59SfMT-1~hjn@Fwb!ht z*rZzb=!Z}la#;G-4R(Ko9V|5h`Hx94Yk{o3((=Ihvj@5ri-SBEfFqt`o{ zDtGMLXBF(j|M<%H{a?M$F23(F6Jtn#L~ z-Y*Q_hxenZ>pc)b4RCx~<_?47BQdZ0b9zah;AZ}KUSNRVE#_A~1G4nEk~@Xv9^F2VOZ0^G}l0AF!@!QUtO6BW&vq{pC9 zT3KwK)Cisdf-Sh65PTql5h}3|>~X_muvmz9@P*)m#qovUgAw@Pqn^;q3c>t>5PZBLP?%bftTu4L>U2(gR?uua|Ju67U1&fqS^O&UeBt zuv1Ub+m}kC&^75D%&hOsxJluebz0y_eZw;=3@*fd?%F0Y>$Ew45^omDte+fzBC{w1 zPeo;x$P|3shh^!pbt}D2R}@6=I|$#4w~6`3LnO< znX9Mp-c&Uvh+clp{ACIsh^m280jP@jqhkv=aSDTr7&x)@n-5Io11YwfiC$+iR(Ryb zg+;Oo{KYW&M-1t0etfn?RYzS8-QBc3mEBjk_6OkC2s7BJpGMWV2Drz4OJ2$9G=-Ka!lGHJ9~!nKuvPO$?S!I6}6 zg=;HEDg<~9z&$z)Bz#iK!55*cQXF6KuM&=reh)@Z3jx(4EdYF$5CG3aDfF}uP`x<5 z5P+vuVfbI#{5_Nt2|B(^g2A{KG>0$auWM$Vd-*Qph8u0+K5Zm?cLis75nTEXG1L@0 zHzdA{Em_dWhD-cvrsqE1ljWJS?&F<8sgY;ChwD&kv=AOEo*FI8?E85qJ2fD_RWL#_ zHF6_8i%?T)c=TLpxDyG$WoqO_Itp+~4Ue8D@tsH$zHn@FfgdazBA0|`n@1ABZkZY_ zA{7E$rUncwF*Wjw;|u=z;rQXH(JImc2#~1(&xD0qq>`|pb#Z(lpmhX(bZQ7GVn`6F zfd|4*v0mo#IXs(U*hF;GUgmpqcoT|Yrnv4SVnc(=FuQwaitgRVtTdNb3w7`QP7KvO zl+k@S&EC|B?{Uw>ZAw-!~jz4C}%Iuiigm@Nz8h z=Lckpn_+LU%;UT+w3n?OoPw^3&`N};0O&Jt#ba?8%KC{t$o@%}{ zpSMRyl`DZ(sKgUZYrd@50dYM^SV|uFK})5zfo8+a2k=N2Ays}9cv!8;f~U_==AmLw zV5^{-Gv&TJ@Pi&haLjq1A~El1HB=JwjvYx#{llp=SjWD{0PI1Xv5tBfp6IOt3&w0@C5=tSdUpFMWt8(&jT_h~(- zMCj|Hg<}+xrDh$(yLJ36!=ud<_)iq;cvQ`impDh5@Sh0bi;lX!c&Vu&dg^*<9g*1r zq(U1?RLG;lKv4-o3iS{Io-B?p_&*trFH4QIU}K3EcyxG12nZ=OQwZ2p9A6076oF5r zhWI-(2_eNUHJdcwoe%RTacE9iZ4jFQFYPt0NBB}2IQ)TDxZY>3Uc#4BCz98;4p_eM;;L->1(;|m*K7Wkn~L;{47FGmyT ze=0tt%|7-aT7uOE{^A6H zdvth)ES3ae0(`~sg#g@vAbfMiGX5I-z|4M>=TmVvL}&QGoc1U$pib05Tz@3Art$hg zyAyQ~o#-R;Gth;`>wih>5ORDb25{(`xD6%VkB=JM5i8c~Z| zg!)A@ZjHQdCb(TT7vs7)+QltD+HPAq)ICBt^sk5xh>Q?-(meWK(q3PqwR|E+;>mjn zdO(niuX%~wfycPaH`mEJA?`86C}wYyFDJ3$olHKH}Nu2-a12Tsxn5AaG3998NBRzwcGayUE;zlsBIhoaCejG&s+K=3ev z>JFSQ)83*bm)?*dq^NJllRS$V&D3Rd9piNrj5!9yy?S18IQV+?=8=GM!D)a2VUj@0k19Kc{)~KGNxt7R8NeAH+SHHA7Y!pR0rNd8z%7y9){mIKhyvL zA%a#RMiBy9`yScKPb9I~zM=d1*;qEf*XeEEJjO`U%XD?Q{G)`F@wioYl0T57^O-@| z$iQ#>UOqiZkHH9FV*?^gjtZw84nfiR!X0PHPu!Uuc>TVr1RfVVdkR|C9#^$cF`u855a>d~8g^vMjp zkWcTkBFN_dcivrZ=KKsE0&3eTJ+W->rps+c45xu$-e1>lkc4oH*UIb@@8iF zkLc~YEqbtfJO5X_PPx494=(D~e5Zf6vU?@_81H#+dEoHM^N(*C&feZVCT_-zF|1%w z{~0s-`|>~J%gS|>o8`%E_wcqOqPiXTpR)Ddv_l>LCo8}=DIEoTpS47tg!|hbdMgt9 z-5po61-#H&V#fWO_n`gV2L7AZGbGDNG*;qy5V52kI{!~!LM*k>0)DH_a;a9G#yT*Y z>Gg58*Q&IS-HvXwd{ut}i z#SV~^(C)MX)GAwlHC`WzQd|%?8Bn2TXQ_V_e(PT%@RK~|+h1|)sn^6ZFjuqbz(l4{Xz=vyVnk@VNj(q( z>uZdIOU$%y_?f2iT1WC$B7!^S@s@Sbs`Hn*0Vr%v+fiA#6| zy>WuqH8oJcS|+$-8=2)!@kx|8^H1^YcChyUgkKs7p@kT*@b#t0n%=a`b=~eLqdjPg zKPSZ4`0&Cnr+8&Mr?HbCNE$n==<`EjrKSp2y&P7wqm{5^zF=kJgH?}j`645&{oqhY z6+IrFgevf4`@jKfFKiQAPR8^Hya~~#-7-8Jzr2m_bxpv2$pO&mD#QorXtPmCS8!K2 z-OvOnr-6=)dp)3*K+t+)6?jw3b!gK9(9?I^*|rNBn%{lL zQz*L81pxNs?LZG(8+^cb1rdd5FFK0R>)phrNQ=?y?;ApqG=YTBJ_wAc>F4Ggdn# z@ZSi02sq-82lQ9bF(%shE}=f|h{CH#7hWj)F8>G#SH_LwxC8;|f0}xX@A7Gmy(-e$ zo9;6lJHNJQKngau6%=1=xi7+i7G{q#ybZeW@-w2N?Ks1$(Po|tBAmh>Toj_nch(ls`D$3yM@xq0(b&u!c^FssI)_Er&388=}g ztG1%Y!ROc4t~1t}@x*wn62MJVP4G(>{D>F+;8g>`uQuL1rfm==@7TO~^E2^ndkBV= zwKG2{9alWMVo9g|>uYCpSb;J-;4FWk;u3mrD~dpYFcC!!v7H1bRy)W08fhKuV9_qR zdG3F}=njErtYs*CXaQz9IO9}IJ~}ffQ3NnxN)AZw!|wOc1%QXn-!ZV+dNhbXD2R_L z?%=Cl_fO#8EsQ_TI*$)tk+@R~*% z1~5k?IH=&zIq;PAT$D*vpQK3`lA`dt1U44KUlzp2d@Kw<7yP@zc!z(`q&tHI7~#VR zl%UUUB{AePVbW^gziXQWC)iQSKF`w;#B>BvY_cva#t@F?(Xe>vd77Q*=I-+x+dv}} zvIW7s+YTnS!hz-CgE|Eh94MGbd%+3#@d&0DVLV|y8i9Xr3{)h_2h|0`HrW)*);N>mwax?!LgQq@;BW zAEcx!%u}MJTUbj6nZahcpLvy z;cqv8WSk@)jGIsk^}FGHx4Hahs)#Y>n?G~xqpO?Me&ODVOSFZwhdUb~jZ?P@?h`2d zzliL>&RDP=bysA^EYbWFnwS3~=dP!IkzC9DD!ESjRd9V>aGe@Kwh3grf8{kviQ~WW zOccM%zw$Ap%h2C=4SFS#9$GBGCrhzdA7FNm|L`^9EBilvg|E1li%l+1X!Wk1cn-D! zw+g0ph>Z9|2YXOrpC!~TS{KN*!S3xJZeO)Z{N+wrvu4e_t3{ehe`sUx(Sft-SoiP* zd~Z$uirYS#_E#vO;UtyeARKS)3j#fEFAiNO4tK}Bb#F=d?zoprgzIr{yH+}U`m19x zGB_ITn-In*41TD!gp1lHEbx$%Ql?U0MZ6*af3kXD&Z3eekd?Z z!0$yNA18D~9V9Q?x<|uL4##AR7|90mvLx7BwPg5PnIZTBDC^+AOy$t#voQ?*c31PI zKX?VU-Q4{Lugp%GAL1v>Co6=(b@_d^Ppm(ped2Cmqd;94gGAR;HnY1y4FM=Tz+UI(-1h_ly&}_+{ zg4!Dfc$NCZflRQlhH#n57kL_7Rrg}JtMn}4hx+^;q5WIt(2G31MMV0zzp+ugf?GuT zxK(HdNeoY4A!(nv8{7?%FG9&>nC>(Z-ozY@R0-4cdB_{ovsaB`)@ z-y1#x3C~FQTSoVi30}4nN(yioQDP!`fA zCBxsURx;B~Z}%{#s!AH)*F^lXLuU6Yykc%BEl{2HroxyO`~#t@%m<{4 z-ou8U5k|gkZn(lLR}S?Xv8BH-a)?0KZXUgYd^*XR2wP<{sUn;AuKSC!jmdRQbnDAz zBWiw|h6vapnnf3o#QV%))O^UMruwl^h;H3Ugw{VKGbU0+= zTjnV+i7FfiBnrN(Bu1eSLWFyWNb}aLhG^SoW?zkPfE>`t!j6Lfr{<`uSYCZSR~FgiuviM1l&D)z~sk=PR(kZ>L^@HGb>hb)2Ku@DancCyq<_K=K|06M-13<4`1sk?XjCD}al!Iu2|u_HPAq6RwT8ing4YLA`pCL*gpga8y9Z zfgyTTVPItmSK10V93sXXPaNiZq%Q?n+UMRQ@T*EVKj!ce1CS>U{S)|uwsCmaCZN&B z6Ib0P!1x3>9OAAj;2Ac&jey?|M=ceK(p&@%VYoX2{1CjWx!gkByUCyK^5-`B)5H9Q z+Iq^L+s$eLq((0(fWBsy3TdAR0ljVbLjq2oSS>80f=d=-RS10YgqYOC^|j&s96s)) z0w33e&)YeC+|;8yai~ZHZ$yKQ6fC-vC+-fLAXUK06ORi|43Kd1On~3Q?tC1hYvUcx zFd=$I9=JXQq)?9$^G+gGJVcxp|M)hgA^Y_4<7Gp3nvDJV7N@=>X zfi1#)9ZYtiSa3=cH^iLJl-rVb*h7bGAfeBjrN;}Lc)Le)$58Uh%z{vSXEpop3v?{dv zOof+DnwF|mgpL(707si$HF7P30kB`DGr9JJ`J5(P`=KUWds$QJux)0BTN%!N@jc*H zhHACTBoO~H2@K%|aZPoYvWD&fNl1dnX*XlymHM^IptJxxISSh&;NCL$989+R2FEK^ z)R;2VlifIKXF-CphmPE7lBjH`5WyOPl)6#{-(yXheo`ltPHY7U}fDD9JUdZ22< z&{_Cor7vJJg0KOB-}zzzLs7Evngj1yqNOuwZP*~-EfX*lLmSo`u$@F(1~WpxA;-w! zAbw0B_6Q>04#X`25tCh;xGP|r1q}018wORC-uws{qCPk<)?De$Ou$eZ9GL4Lz>5V8 zb-{*>Gy>zj(C(elpgQJYze~J0QQ)G?TmmuB495CVdG)k zr}W5=Zx6y8T0@U{HV7od`N~)zqR`la3AT}7F}s7XdyutX2)wO981U3sA^62`7#;^g z=`yHb4nI61+#>K^Ay`e3ha{vYUjxD0f{3W{Y?o3Cg7^EzR8;D?<40R>tFy$doMSHE zlhu`NTFP4Mn96Vup}O3x5}&9iHZl9vQflFd5OdHVvrn%+J$nz_G5*cB?szZR9KiS27HOS{F;7R_DG~G2*O*en)rljD6O0%e&Qq8dS(93kUCG>>` zTLdNgcu>z!`+#6O`g;lO&7F4Y`z5rKg>MBlGlHs>xy@E!kb_VLg(8fB(@qRt4KfJP z_q6FrLD?RupwmwLMLY5D5GKGu7#>7G0V<TWel3g~5O_y*sm{Gb|RF`Of|;#`4L zq(64v)15pN5>TFR1Pg{G~mmeUspgPp2^iZK>8D)F;4kVBl%(MQs$?fG_A$d_6`g zO_(R1hU#`eZVSveC9qmAxqSjV1k`m0pVJiqHu+zp_>G}k_ z9DPnW0laJ`+CH}Aq%n-1ZwDRWfG%8CU}q&8`7m#wby6n?Vc)Wv3GVoH=B9_0_HEXY z)}ZuTcZgpLjks3c!L^Rx!>lHJaoDw4kbC0amiX+HZ1-h6qGZMyUD$W*HQeaW5SATw zabO38uv7j6=-q$|+rMS632vI!S+)l(&;{F-fB4_9+i!K+{clh^7xd7E=nt@F?%B!_ zq3K-eC?~HHZTy%jw)pXQsi!MEwNWBl zq{KbHzw^KrO}rIT%V{y?ha~8hON*(wkSpx80$-}UaGm!@3%Sx8S}eY1CH$kd`*ul zKkJ6Rn#M(ZeVmY-l-!gnJdyR-vvTL-E6?|u<}W(0nCvuOUsU}6wHEt-Df*ez*@Q#h zdO#gTJTl1Iv}cdLR4=<-rG5>PyZSZMW{QQmoOe zBm0FL9;L~7n<)sTGPwx~SDGdzCncux?$djnU%9SuCFzpPli2;doaOf)wW<}3CpzBE zUnB%#ZB6?@HR9J^ByD0Ji&6$B%YkVYG3DJ~T)FV|mA*yO^(DsnqEGx^TS?YI_9VN& zo>c~gl(|Rjw~d(s&T{LqhYzv(_={qv9==HrXrvHLHCPY!f`6;Nl5^2Z|> zY>bu(ovhw`h`%Ui_u`bB;A_e2O=uKM>^8dMG@<@I0m9-oCkJ+#;J^i2PGG)f~9@nOE0abbg_L_RDB46hX4GYU4$TYm=_uKM=MGRd%r zlrZDIRcaa?|C5*Zf9*#W4)pLtnXR5+uks51i`H!;J04`}Eq7U6{1@?r;*B+}rS(<{ zSufPbesQ|np5W#3VTGe6Z@&VU_N*VIwpk(PtMq)y_PF>$>n=# z-r3mYd*NH$cQ+_vitBdkPqi-}2=*1J9J}aM0ys%*#nh15b%J^|HbcwJ!(nj`?Qf8s z-GKgjWYzlht5&aHZ!P@b$Q;i4_uutGfBf%-UHxA?b?o@5Q^${;D%!< z*VKl_Sb8anngYM@6#lMg8jGrj*#g0Uz5y^#Il%BYo_i*^%V9kb(H4Y8!6gl_K{F|; zjc7dO#`g#{@^^WP5T=)dQY9)N*hDc3S8S5`nOl9n%pBKc!4}IT^E+Lw>f5fX7rPti z?FruU_?u&FqF=2n#u9V~e5r6e$wLs)&NwCyrU^Kd<(a`0omD9}0P7P;x$?0i^D>?k%c%3B!3nLt->dC+&iMQ*Lo71&xPHq<- z({)_8Zum!0Pxf!tlikj~u&r z)v~SeN^88l-KbEs@UL#&#&s-@5k5k+rKn`^@4`u zj-58YIffH>n;rQCQzL8deD=md>&?;1x--_RUw+9tpDFr%8`At6)-N_@EE~MsN?C!k zPq(c;98|&~y*4i4tCNQ=WawahAFhBH!-`8`rTCH(UDukjw@rRrOsN7~3 zKv5XO;5`7Rx+C#vEk_0Q8zlrE?0bEk`lqJv4xH59(~g=4o>Ds-Nf|sLDI+OCO>x)o zpy(*cJv|j#4*A{dRee0O z+(WARP`S*1w!})fk1dJ>u=5v+>eVKg08x?l{rw^PXgx4tbu0 zJS2pUy?#A;GClBiA@)mahR@LwSToA^rBkLZJHZ;6b13JnU6g?rsYA4AI(J^vLp=wv zzJqUR+QL|Q?AXfu-1*j}@#Dwwl#T2p>)xqTWOs17gtF?4_1c$-kF(tylZw_hh_kM+ z*tqQpU$R@zByF^AZ$6RTI>u8p`G>Ymj~yQn(CWtE-QfkqXGL40i%@x0x%?!%|$R zg!Es6;ZkKf%Y;^F56X0wrMO*mvn&Jlco@o14Y#s-g7wYOadjJ)XX&q2=kg9IN%&_&WZNRvlaWu~Ksy z`ozTgmHvfOSDG3AmFKKCHcwn#YxE}S9f_iI+~;%;WtO$A&&bMc*kCK~W9y4Dts757 zXPVZ)`rylL-%$zOXg#PGx&IBD8(;$(+{ke8bSMoAv5RJ8J%Y6&wBa4NmJt?E+PDiH zT|`pJV`ImUSGaZj>!s6r43uT-ev0cOlV>db*C^J>dI^0T){ZVxWmxCT%VD=SZNB>0 zvDNuG^Og5uBt^vfzq8is9qS`n!P+)ogtKKg zz^&{3u=iDMSV)mXXf$b0STTw!z^eN*>+2&&;Cp`~()@+RtbD_WEVZWF=XvQ^M&zMCrDi7U-mtMy z_a>u`GuPxZ&-^es;9?`JZC59q5lMAs(p7648=?L++s{T>8;fRJXXaY}H^=YaEv50^ z{y8jlE{wqGiGlLkUagiZ*1UbMn%b^udLD*bY~-))wSKoI;=kY7eb@oN-oKx;Hl06o z===gwe*x<{*SdwhHP_nDx+-7$ckqG!87EGNOS5pVI?>3o0?L0x84Nler6D(=7AA%? zYf7cM;r8NnK~4kdqk}uKGJT)ACD%7#-1j|hYd`Xm^nKIrPt1IVWxtl6pr^NdXyd!q zCtI4Auaz8t?uzR+SB!R0y$3s`SEVlnl4#yTNsb@U_*Q1pOh)8 z)KvQjOTDV7DO6D+RKtdILCr~VoRJf84aun$SxEPan2eM1YPm3VuYDJ0igBWaC+zY> z3$;cG)@WnH)VJnFm}VV{xKsuT>m2*YypVxfFcf95Txg8V8H|2NUHF=|9rmVWX1HiE zkd_LFm@s=im|``{i?%b;D2xpWU_F&Wv zJs5Mjf@+D=!v?u19ZK{>xUZ;tIDX^*W1bi?$(=;u2_aW38+IWJ9d2|HPrZ ze~J}>f@O$r!OLoH_v+t>dG9xDIo*}vD>1 zD?zW5cf#8uT^`wHgvBbt0}cbS(qZ6O7v2_4UlNW(A8i!)(ChgW`x|>e3Y8v^LMfKT zt&LRZ`Z)Zgi2wDGB12LfH(YsG4=-LH$KfY%jT<0`x$LGHU!MkV+Q8eg+bVU9Q1^=n zfk>k8wy+o$Ym0O_)eISyaC!)Y0Tk+pHtPQof=faYIAIEuic^9jCE!XANL(Wnt8i^2 z8C@Soy8HS#PRxtp(qUK8Js>)XN>@y{6Bb@ycxm}Se2r+~k(!n!K)O(dgt}xzOiKu9 z$vB`lM0^~#+?bI_E@5#=xK55Z9xMqbGPFj>!jh03hG=sVsZ`;Sj2%Tw<8LRSA%<2F zznf%ybGTCB8{^vJzqIaViR^wX6qfl?a(tsb;)ErP#?UEyOUm$QmxmFRN^_m$Ez!Hy z6oXd@JVn{d%2`unSG1-SpTUH;h2_Nc=pfLkgps@>Dxp!jV8K9^%SZ-c3Y3Zy?fNip zMksAqQ=Iba6p?UYP8-b;!$-D~al-N^LP$u4!^i0zieZo8B{K|5m>V*@8Qd^0z;k4< z5gq$ziyciv{TQAori=`U(+f&A#_=GO2+`C0kK7X()0<)BC{{AA!_V1(5iR<^Q}x88P%wseItdJKi!3NqvWw$H z=19pnk$jjzlf_bnhLy@vaiSQ~1hZ7!NCnBG_WZvjYoZxPyRvkeP~Mb|W9OPZ|1VWz zM+wJEPLkb_F~WBI6YV`)j!|MFIac2&i%ar?jIpSSH}opie}Uw< zs&s}ScU}*-WW}$ej1gA*9e4g60XIWaJnKV7qyFDiKedx7RD^DEEI8!SMo=&?#@i+rpBpSX&sK2sIRPa6;pMSgm&&#mcy(;aPgDR0V{Pl5mPE zV&DIZM3x?q$RZ(cpwRVkoTMztYi_yzbF$yb%Ih1St_Y z)J+{lOA{bH7*>i)<7WgH7GX&djC)v835!d@DIU{cbt@*+;pcde?*A1-ie?x>E{^Lk zjP~G7D@yCXk_8k?!khGf$cr1|N`-O%FRY;4&=U^P&CobT-2hkK|0y9`Z_Yq45L;*(VmUw zC)WR^WpOleNu^jS8VW-sP02|dh7+p)ksb(TaTs#2E;zW3mz>yN57+TTBn`&@>k*+% zxcKh~_&YS*C}nMTJ*6To3Aw&xC1nU?h@&T>=>ONtX2(?}DHEA9#Tl2**BLtm4fX$$ zL*NK-+<84^oP2ORb2BuOKi2<}ambB-N6^jDmfQ;jZD{^?{lenJ_GXlGaBhYsxc+lo z_jiaLw>$2>8G#OsEsvi6M0PPp0l@X>QtA*(oKVRA2f=pO5&yrV0A|HVSh_P(x^j*u zOTuxI+A+W~Zh}z|xdhzEvEb$ulLkv%G5-(mtI-;UBbOEq$6`m(8`C)D9ru4qa+4Eh zC$5fw>)}e_LB==1m%4t$_$gx7=-ems|d8U{Jr5bQk zG|~6}97}GB*sh$R1ihYePJ%k2kiT;Ne?vD%ccYsZkrpL{yi?D`oT9YZH9*HbdOS4Gl@`hVlOoI~XN-i$ye4A-S8ZT){! z!~r=FMOql@IoB0z(+1-&yMvRhe~*a_ODN%PMz9^q(EUHBU;YhZdk+6U3AXP$BL0rR z|3v{OO#ch5pb5YK_rEZa%7?=BcX{NOd|Ry4C0SUd^oj(9d%rZtc&CaUWaQwvm|DJMZ(!GfXox%Q8%+(vpK84My;1Y(HZ!Ov^fxi4qWogy%L5bRO_@b;{6Xq9Kf807| ziqfm-UA21A%VWp?FngtSK(POBn+@u!=QdoMT=p*YlSy4%zA~ovT%v&;*Xa9A>veow zioJ5u{)t^snqjkf{6@h4WyA3s0Z0A`{EwsHxEAnFqTmjH8{e=6dq^OL0znobz+n_A z*h84W7ivY|I|4om3O-3M=-d3?C$+-x4G*yZBS99{;FYY4dBS1zK@_8q=g<Szm~A_PQOAVMa5gAkM)`{Evzp#j_oCWX{gS`eM3PPRu|;FbLaf}vQ1=cGrA z^O1r>o;F^`Mi|sRq^qMXbFw`=1mXD6IpJh`G=4}?$O#XnVfW)`0!N|Zu9F@L$EU(& zcPH6*!Ufn#9ql;}Wfekcgf~dbWQ>cuPQpu5D4dT}ND2s7G~9DGe6-dP?idg5J}nV+rL{&cVkoZf9=y6vO_*=pO)-4uss{?6p4Wd z6A8XpJC4!V)igJQXUadxX?j|6(g9W{$@+rTscij&oh=))afcSWm3z0ce{8WH{c+?y z)-`KjkjL%nuo8HrC+%eAlB_>ixytzKrLy|H3$@tw%$U2LReHiYx9PS!U$4r{CyM3zm?s^W22Y)C^XB{F-@uxm8j5#IioiW{r>YjIV8cSARM(suX-aAc#-< z>wy10YmB-dBW^OjL-lzNYR{E1I1#HA0gSoR*Q>l-+&C zShmct#;^^ir_Y!%{q&g=C-(2!r8V>)S^e;B)Y*N2a?K3=(eIlgjkfSnrRU_>=K5szhxonPwF##;EM z-JOc*kJ#iTmv)p=gn{)K+W{+#bLUQ<*2h7Y7mk^wa)bPwZe# z$~-rH%8`%Gp8d%Bp<;!~x8&5em05ge%XGdY=#VY`PwAWQvDR9xgUBQ7Sb|;fuv243 zQep!0=6QoVHPVJSTsPA5()IK#ukw^N<3ImlkDjx3+_HXHc0xJpN9zUFhgHUZyu$Y@hM%lgS!Y&>Rld4%-iR4E^Kv^I&PK59)*x$>Rb(w6&~5I#iFcQW zBBK$16CM&fI@KyiyGGKck!k571+r4J3_4ZHMIZGeIh2k$o2U4G{LwdMbIy+EpWpH0 zkN%I54W?=RwR6;P)&U=gb{IbDxoati`ATIm(%~%90v3jnSa(&nlNj3>U{;BFWh&$) zAdTft79xe0F0jVzKXKyB>9fXJgn!pA)$9LsHH%-xb~jkr?R%^9X=}GuA(X+`lPV&E z?L#GVI=Z(wUIQPkej zZbjEGi=x)5DeY&5UFQ^pOl;BhXBoX?Wi+j7P z`|5n4J`u0gB@eCE*_(kw+wvF+>1=_bi;;(fg9}B1QWt1Z)L(Ww>0}ID(Z^QjsM&1w4;6HCTa?i+oHer>HGi-xL0o zbq4g#-G0m6lUi6WoZypd59pJ-qd}*k{n>cS z{WnY+m`B2}cZpUH!gO5Fwoq8nYIXM)7CoSTt$bS4Q2BHPQWt%r5O@n!V;Dx{bfA(( z*(!|7Y*J07BBL$X5ueq3HM+#_B_-tH}%^0h3sc5nf*Lr*^IXJ%de=^X2`0& z9sPazFh_752u2l51``D)33dfaPB#A4ldo9(>B2tMtM^%W^kM&0zG93yI4{LW$s25r z@lREU-7^01^?TMoKK_>FbvsX*xnbs{&UI~T>YxY5V1E*piSC8vIUmBSUpw}!+Q|RC z@+og`bzf9eGi1>);9`p`j0qYh9;2Tq9jbmf%YIg-gG1t#)Ch?(@g_EAby!zd5rZPw`*iDT|-E zr_PF2EB{SyWv>2#D_U*PR&!`!I(F5-sGCb0tK?!!BhpLr7RF}ekM3+(eJ3wzcx%fV zZRs+3zK9mNMC*8M zKD%tPOT58zyn+9i=u*f7^&@Rvf=A1I4yRITZHOFQjS^eJD|T`v8KDM;z^hf{Rf@_J z;g)d1=ytD`dF@>~Q;}FxS+WkQ@EYilPk`b^iw&P?!*RDI0uFpb5a8SQum%WHz6RW@ zRk1A5;*}N!F7v}SyqAF2mT=&|Xu}Hyyp9wMOUnxWRRpxItU0-t<|4I*6qM;v`*^Xuud||cJSF2_EQl5X_S_Rbc&%=499Ne*=?T*6&eK< z9xvgBB^xk{gAlU(QCj}O^0|Vbi33+#t5ZmLJ@QnJBLK>_um!*)P_~)Cm&#Hoq_QXs z0xpiI06ySjh))ZAur3?ms!Fn93N_#+o+DV#ZM@KGy?UQk^?g<-Obt5s1~jQVy>R#B64a|*OP1$Rgjo9e7Um33KDDlyk# zYiXtGO{!Jco>Zkl?Uvpug*%>|$k~jF)tgjL-vL;id@p;_8qEikOU=DyQb+6JYrU2Z z>(!)wYFSp6x3jt{{^!f4HbV=Gf35eD;k_Eyr^A8Q(PYg+!D^)01iF`!NL<=O$xC2C-Ye)@;B^;Fahs` z2}pL`86m(!j3L;DlLfYb)KUc4@KX4v8l?zGm2lV0zy)`{T1k3HSrqb6;DTN=9PS7} z-V9SuhkHovP98!}X(Qm$0QiaEE+ZrWnwB8ILyTduXqAlEJ7EH#Xo&)BxNX3CByu-4 z#J@Ajfb|A66#`_lE#QiVvxj7iwQhm7))dDA0T&iHa0uAu{u?|F zkZ@nA0??}NDJB4(!;8xImB2rhRZ~wJ5b&54uWnOtA`W`N0oRKVFi==P@Kw}J+shEaEN1VmY2!@~rmLO@9#N-a%* z;GbFw|5RoO%Un~eDUW0C452aCq`h5+3-9f2{5yeAoBrhC%$m zSISr6@Nj$$PfgO2BJm9(2yciW_>;O#;C)fKY=s1V7+m59UbfHDLPJHa z0FG(=9^}M%;R(@-Tp|47TEm2<9zw*Z-Ocr^RUjMGGH9>~95{MGp?ez6WpQion9WXV z2aFVyU`jd+Fm#BvJH;-!gs0bor8&xYa0b5c80hsxz&*(`gd(C<(kqh$92=dZaOaE` zBdO#o;IqQvu9^OwfsAX-U)|0`R-{SwY~mlOjhg(He}= zM8M_5A<5N2`^Jt@n|PfX#HfPqDI3r~_|NJzgv1D3vI-zz3JDPX=A&?UN?o(kx0=yr zs!T%bH+M4U&=d12;%^;iVm^_)MkHCH>rR<`s5dlW@g%R6aP!M=wci^|58NW>e`1u% zc5lE0bDRjhXn}#cdVr_8{YZux=H>6STQPpyB(e#mMAv3HFv*6>i-f@puoG-vv)SAm zi3`?VO~699);XRU_!4~Y3*iEm?ZVL+h6FmuflKN~-0Qvw|+hAcf$Yxvrl64wOnTV5@o-d_*ci zF3pQ-i3UvVs6phC-4JlS00KG`9g3Jkf6&?)X$kx%Q81T_9GGcs5tD3Zh9_F>oDH93 zC%8V0%vpO5Y{Omi0`Dmu#8ebxp_oBV7W{FDf$}Tho)oNvF~}QqX_{DneE;rtD15R+y{fM|9E zgw1J_!Ucp)nr(R4bR+>2w#W$;&38OBQG>+^SQGq9dKB}i+|Z0Ifqm(?G-5(!!-E1a z6ZG}|QCrR^c5X4x2%8#;Vcn60R%wayv)UaR$f+S1I+I@YRRNb%LmTdzLh~5RZ^Zls z%R*e!e8-i6-0^suig#D&SPt{9vsypg4QI6Gh@R|tXbwW=QY)08xkWtp0B@-I(^+i< z=y;RpIf=3#O3FEjXcavoKBlo47>D_0pVP|m5t!1C7KFp>jE#?NE38ImfI!hoR%7$@ zDFXhhg!3*+hJ?Ef0sk!=POG+1wMr0_pw1P7MmU0EeiRyBmX=Ygbg#Bn z!2gtR9A0O`-Ms|-N;urL(B*PB5M6MTZ_LlyECxZ!B;oH-LJ%RG6UD)jgw$#aY9rtQ z3Fixf@T&w*!8jo@Ou${^G0n?Y>%yWjzJg!1`IIoMH%tdW2$Bd$j1;%6;e01Ca5yAZ zNh!Jw2bEMnd6W_+CB}x|Px$CUSZ#^7(h{`6(W@=Ow^v&RnjHcB0tn=Ci;`r1Xtf0f z&T1=xtq`lNVOD1?UI<9!ej#9mFkl!~+9@gneifk*CTGgsQc;_KRSB1?xtdfj6`v4L z&2FeD1jwlamBqV#r+(LtFgDTL{a@`*c8_nzMQt~Qh`U8DgiXTu>&R9y38PkyL!CrD z9){}UO+z81kWzKB6{4yXf}=XYbD~Ug8o?&}_FvYHF*e0qdPUpHrkdG*X?qQ;)VGC{-o?Jm1?_wc8k;dJjZ*rKjFHjt_C+ z835CjOeHx}8OW|2VOPxE{*QKFV6T0H9j34LXv;2Jar`+x7t_{#fuEIK+Br;HD`AUy zdT=Bk`erday%JB%#Z&Xl8s6kkQ~!pi@6LO9qjhcez%N%Hc;}EYVZC*7;JsT$eb%q` ziCuiYl{KwpyE`9O?noX!=je&qv(GG_vMpK5u~HYbZaxm<66BD=%3|%mbaavy%hF?+ zlH%{g4@~pF#&4~v#3(U_|6c#Sgv(v~kanB3&+uRx81)dYD&v;|>3rH{Q@r?7OyR-#+ZCjgUaOkAbTom;ygB zlO8x|nTeVElnO=X_$;eFJ5GPJ6IbiuVuhnW5qqOtYlCOeHZB|H@2sbMW?X?dqh1I9TCF%YSgvq=QVsV{+x-B>xk; z|Ez4a-D0(={HOH`JM`k8yfb^d@}Ini_1)1qbB?kMmd`Sd&N1d3wZ8MGRbxqqt+MRD zhpk`u687I}AZcWkJO{exC_oRE@O1-Ba%05IP<@kL4TTCVGRNP;39MI)-^eGlhWsQ{3%ViBCD|cd zT@5bh^HX?F55B6-JlHn&5)YqUm@?(?b8kF*7=Atb#&c+|<#<0cYT4+~%SNFa-~H^} zlXK>rWWUgK<8YJFetpuU4U;C34#Dt2z{$28l!y!df{c;EK)wTJMO`(?$*}XUe-4M* zOBGe8ZdeOvJ8zKg<}Y7-_K|PIZ=bQB^+-=jpGXhgAU6bDI|y6@sfSsfNM5%F?@)1_ zK80RDFPu6h)k$?QLZ|rI-}bisDs%@w=K>J~p2IM`grCBEP9ix!TunL3PeGm@sH%w^ z@lEX9Q` z{?JgA61tAxoKiI4)h}Mzy7d*(L8gdaw|@+B1a>I_PLSsz|HM^*fmVU)%^=AK;18pb zr$1PJH4r@S{Fbd(FS)n4m;GbuA8iMvKa4AsX4zl!w5?gc?)b@-(`~@MeHZ`3-);XV zs9-KpaDa58m8b#Iv-tJW0s3XbdRvQh3jX{1PIQtS0gq1Zg!=%s+O7to9T06mpuq}U zMfJ9;s-(H6q)An_{rBB;;h^pQo9`n%r_;|i03PCiKm0^z!K=-l+YrixY532bZO?~( z4~(5fJM$h4CE+B@sCp{u@D7_G?~~T_Dy?n=nX}I0F0AuLz?IrNrhDbGe8lAGKolrF;ZWtohQsP$6qBzvz_?0R(Q6v}lE7s(U!#LyQ2Diwg)tRs{`wlJ!d zdJ5H0KPt=Nx=J)4(21-EKn7oTb zK8)1J4VvZy>x!O3 zs(cvPbbkw|ZK4B|ispyY+blXsxul!p^59q!q)@JKQsp?%Z+N)5Vi?P1%5^L!9E!+t zrcY?AM0m;Ff}Z2pf@;f(Ncbh! zwTHvs*y`a5%h^M%$J;=;%%7;8gonwBTu%&!OhKlAlwOkGI;|Ea=j9cOLFcBa_gAT?A3uKH~-AH+2YHH_f0?ZLJzS*gaG$xZg^r3djkkN31L8Fh{V%uKgPH%DPcL9!#~|t zX#4U4ge{6y9npI>0|2BDtnE^*$d2!+UV~ z@Eq7+MYeIY&NyguW2FsoON!I)&Cm1sohk6mH^}F6rF=U;X_CXwX_Z_Jyxx^VA*C`^YwTkrrcpIV;u?=J;ct*Y8YC zP08@)<-@m>l+<)@NXql2JG*yxrh5a>T^DpW-TUnwN>5R<)0ve%GCji$ea!L~6{csx zCMuWHmF*vyPDpTNrH@F@bUWL=g5G02yF^{@dvk-hVcaNq`Cioiv+l#9f}do*$V9b+ zCM**reFBuaQd3hiyo0>ygwPC+^jZ4}MTx0E^k_O(@MUC1W?Cvrh(J8h-d~dyhf2K{ z(tQST)8I9ObGQYHz-Tl=iav}d*ZSEJn->+fu03q?VnwJ_M$kG$oD~7H?Mj zEZ7hk4P(!0ZXLIY+eR4VB~vOYhy2zYau6>1@g?Qc`KU8n0M=ocA_nesf_Lx7r6?dU ztY``k2X7-A$W7svfyuZA;;h#jrkuuAfyxxwAFAhdo>{y2$wcI6Y0y}gCxzw6a6hex z;U)1*DT4g=Kybfaa>aAub2C4@Ncz`cqB9w@z3Hhb2xOMe80-NRg;GIBk%`^CJIwH~ zBAgL=!s6y{f36DnBxMSx()sNJ{T2F@={G-oSFUQ>jg%CEWT!!rnW_dA%@}$|)q?a+ z9HCy@dtviHGbmnIi_3wxw8{pBjuSn=M5MgebCACVrnF~>&j)iqmDm>Gj?_mXj(>V^ zd@{pn=EbWsFLdZy4;{AoTE9GEOVdv#eh=6V&k(PVsMd5Jj6iCt@I}=5U}@=!;_4u? zADCEl(!as5g=jQ4E+T`>g3Fi}W-Y_4q7^so<3S*qX2o%vN=s6uI}|C2$A0R~C%_G2 zLofpXgag(_L@y*Ud7w@Ico~C@a;D>q#+VM6+qjv9o$WQkstpdeF{`+>+(r)ag_-#X zn`A}>Clb>vwBI&cNtECSH^V6%vDcWGZff^6gKf!7R32`LJ7I_vBR)lCFRbUNR!6}& ztGGSfwcG*jNPAdp;&9xy{gU!oWwX)V;`6=n% zMMDSxqyE%Q3gSQmiTkR!gUq94I7wp`z1sFg7yyDZ5)|aBxYT{Qajg>$+HzE9+NOyp zNjPJNv^cCuiQ#xlZ$za|C60_Zj_IN2#z{A`S9iFx=7}u5`rn zmvEfCYF~&z2XSJs53AhOd5b>kOtVnJ0&2-4Gf-Alnpz8Ec2uU~Sh8lx)ec~x2ttXK zIj2gcC8s+Ik797&>B91y*4udx*OP1FCd<)`4cv7GvqITP$Ai<5l!i|WtqOHWOuL;b zB;t9HcwCsElX|+L)W+8o6oIMklra|hN_-ZIoJ=7Ra*ahq47F0R2CyQGkTO7UAJd7% z`nQA)@x^s)L?jgt7oi*$h#`6ABpE1*lkT*fhjda^%CzJY(C4j2c?J&IaYpqUb1 zIl}!Ye9+_|l)+rIhK|@09(mqCjV?j|k|-QN34(-y*^{Pb;iOqXyNi05@R`4(Clc zYYxX1d^5*RrgMt@h{7%_#A+cg7VA3k2J5186~_=R`_I*|o))}{wE$+}+*pgDD+`;& zF!b+EME}gumFe6nIiL?)vn*v6JK~?T@eG1yJ9KbMuMAAH9-AGDJIg77E+9*m^wnspSv!)Pa~xSYwu zRBk1QcXO@Wz1&mWZ@K5W-*?5V4^Rm(P5p@29vkJas{^(%bq9_H_H0k-L%WwGvWsIZ z1$Rcu;)(y#Afl2Z)2>zIIPpJ-6kR7|(M4l?29~+7(L^xqp$SiigEMk$2Hglil`I6) z!Gq`uEZL*Kk_;mfOMxgd_Opk1`8yIx!E*YFIg&!y zrpLH!@x6{411)GBq^pY7V#`<^a2fxdUPTo0aQOLC*_NQu}niLl=)-yZweuIOcd_;*gsMwEg4R z9&bYLOz>EnhtUUFy&8Rt!?7z%Pu$9p0sf_;0o7qlpve%XmHK||SCjEi%dUzJtH4y3 z;b<6cEYC_=l^Um|e*Q)sZk@qWhaf)4iL^&v)dPz?UbQeRg)C>=K~9a@U$$VvnTm`wHxC`qnbp6VqKLv_(Y zTeHAjnED#0(_)ZJ1)|5NEiIL$9?P>caRQJ7GZxbAA=gj8x5G*t;>_@KSb0sw>SmFy z8!Id$4Tz6~rTLn+q!{?v`9yuDR7#E8QcQ@QZF_+n9fsIxrcSQ1E5VArCd?2Cgj;gA zeg05fC>%rXQWO+!!E>FPq^&YV@sm^oY$?!jf^aMSZiMB^h9JdtBCGmwI8UYOo|0(Z zZ2U0IdRklppNeGuwHJe1jAn=3EPP2On`y3TusqD~S|Q`|m}9IN-7tAzOSoNv$=WgQ zo%6@E3EMe<9uvK0gQvvY(0q6={RD0?cNLtZZ*)W{jMJq}vJLMoH4wM zxyQQAQD)l`KE#(`gfYC6)@q1hV(J|$#d9973^Mnm!P+SBCcYCW*qo&E%&A}Cy5v(i zP9GZ^&ht=2MG1mjdP%`LrO~d#M087>osk|a?~%}AH*_yr{0c(vbLqYEg;cBG!#%;B zjV3OdhDwkHyuxfHF&5LD>$L!a~>(*Pz9{#S3lcl#d zlPe)7$!r5m!K4q~=Me`!ZDe(#Cbj$@iCvtr0XW{rm|Ykpxlr4@)peq%iCx@Cr%T;9 ziydKB(s{{*bDU9!>RmZ=B;hFcW3Z~PasNUnF5!&2id?LZSpNSuTus;808D&lnr&%zpVbsk^`Hh)!uFUNubE~Iy~zA3Lp{JIaOR@q zvG;b6chZnE7rg;oOJ88}Q~s*9eYQ;(_6v@K2W^YLx*ICPp^Li8FqPZ^SD+p~@VcA8 zX;K*rTiUMO!Cw{H<5>08-3Jqz+kyw_p^Nf;$_Wu1qH~PJISQyjpmGV1#%hcF=QJ9T zl9K5O1eCL~Lhl=&gX}EEVAxV9F4Z0mXKTn0Cl*dVTf=S&z_2b*c!k+K)bgr}2|pAn zAzhlDn??3Xfd|G8*dRNem2(QgR~rb2Fs6ov8vA*bx@k`x0=@wF~&Q4Al^kKJ&49ZAdVS9-96i#A;lfl$o_HZ`azhjVvVVpI(G-!dU z!sd>j9;g#WtVS#B?bHpE{-7*P8|#1rM@lg}5=G8wBfLn{DzhP_UcFw}46>#Ut8mV= zk=2>*k#f~Ntz;zuvJm0)6hjf&8kLgHr<<OPMVK(q7O0-IMWGI=X=6$bxet5-@ z6kgBiSo_u8Sealnd&a~*B@b^7VjF}_A*>+g*Uf$-n& zGi!vd=QZq5rg2QOj=`#igN%5Y{o!eKoOuTr9R*fscIBMfgl2QsK`OIN3H6$6lS0^& zfa~g;keUsm)zpQ*QV>)%jL5naX9iVK^u$;=dND0UDkMk7LbMUSv#TUp>`eDH`{a^5 za`GyAg;k?)muNwNsxENn^c4qM)q`rGYU6}B8m=M24Xz(mkCxFOjUv08$mPlm-3uG_ z)5urwridw2mL+JJR>beNxY_=`Uc18Kjq0pX4sX=BY_vNY_qmv}6~v&0TGsz=?|~UC0@3 zw`1GS596%l3SEms!?h1U-0eB%RFvy74J8h@B z4s*l@IWP%Am@$XdAYUM>)5i0nEj<5NKtux_=kSh8;Izkfa;@iQBRWB z`=mFK#bScI2xwDMqt&laNUnm%8X9Z_VZzgDl8~I{=E^k3{>BpD10B-?7rjraC6h;S z={4vSjU-FkX9oA#agrJ>EHDCs5@=Lx(h22y^Kabj%6#zb9G#X6M>Wyt?Qkd|ULGi} zIo9X6!~i_;^9A-^%eqP*nV|bMbkP-pSzGa8TS8weHC3!Dj1a5f+s(r0$S4vpiq2HJ z!-q{Gg{yj|b^t8J&1h=Vv5d6!@1Y#lv@Hc6`W&fGf`y z6RZPT@c^!9v#E;*G79d}!o=F>eusmLX#hP27>j#?lFTG|yu*V(^e{(r00`5m`hSJc zV$9|)j1NV{Y8bpP04#De-Hg@Zm5YwYk+3e1q+vA~zqJFt#V;rNXug+ACaOU>zmZK# zYir0#&5=UAf<_hq@NaDEAqiVUjFg_`a$cQc){t;9S+}vmglM!yu~IM@o@d(C_akj(Jy{=+9 zoOi(%9y1h0!Yk_u-Z(;#!3jH0BtoLBW}UKR(3stWOPC>B7*NSHJA;DF&dNuIgHVK7GwKG z#-**WYFeUmP+UDBuHB2VoiGTxh$;lTJGG1(6{bf;=}fAy?!{=JLE=V>-=683*eiAC zI=Bd|!Bq3Xi(0ImdTUf{m>r>VqpfJ9v4u@jsd-&1%!uf`ZT9vFY6{p_nu4boitr+x z5+D~za4J0IMBJcha|mS8tRq-yf*01R2}r~Z)~j;48Z2FyYdM7^B@{yJwjQl!aG1RH zP&;_h91sno+>$lctkniV<9FEY^n^@Z^cdb8$=<7I4j%Irs`c$8%PGf|7&F_ps2pdn z!Fu7_t{eeiy9Q&k96jtI{9R6D7Xift72&Q3TxdCjZXn6t_Q-xk+b46FLh$QmqfUP+=PETL#Wcr>qD>@bP z#k!C?o21$>YRQcq^D*KXS4iJdaj;(FSr2UZxOTwlFpM>%4|Q^|=~%CR&s^o5teqyO1ujJu&=N^*_I5L8YHN5 z0;Ih41q4XLx(W`S6t zmTim4^zRBotT{mKGW}S}4aZh;ha%`BwYMf2Q_z(Hv=qZ{5-?JYC5Di11UJhs{EFxf zSqh!#+-F$59L4 z)ryDNmBPjpaSfbyg_4b9VT2rh6eGj7GYcazH6_{ULSH&+l3QzFCEHrf^$0sAQokD| z9%&(dI~9TU>>6MiQ)f4+LNslDiO-PkNGYC)A=^>e z$f&&1fE;bv)gmaHB7;Ay*E{-b>#lw_!JyiH2{W?n;@FForqQ>CLm#Lv?c72n_%rlPRqbDg z)Gc9knNE+QZo@oo-0@AQ9bdiFX=QA!mX#$qb~QpwNWIlc&f{>yi5HHeZ*;w+Za9Ie ztIUQ$u^RDvhx+9yi=#93&Ux!oM{GH*!*8%b2uyQ2*lGmb@XVYJ(}riZrAa5-OhH>m zj!X_Y`ZamMJbim5$$f+%pU;&F+n&jr8pwM)bUSC{+(>;9+xX00PM~h4kqW}MqQLp) z;W?I?qt1r`LJYho`<~(K2ZJevunaAPVIY^u#%E_%=v7)1Ha;_XkeA&_MPnJi!s2d% z?lc!rK8T|a2S;V9hbYQ+l?_A$^Y)k$OYq{a9Otw~>9nG!(4hGuNoeTHparkK}k>>Ly8GLM<`C*e71~-PQ-#LL; z-1&*GtuN{00EY7~SsLw|G(9+Xa#LXB*P}aA#ZFG@j_R`=VSYOh^ zCwkbW>YDZBnz+fFvdVrvcL(hQ5{o0+bZDs%>#HSS_z%P(8Bj5&6kNwNQ-;f&oW?ZDs??O2~L<-hiyS>uR$G%zH3B0paY>3RAy$ z=a$cZwIA6wH%hNJZWhwFN;`^+#=U>*ODk5qbnE-$ii**0+tjdLOZQ1r_|&$?-+Ytk z6MATxuJfZJbsgqk&mKs*vHDG4V8ZA4dxKFIBh>Sni8 ztR6IcbItDCq(4_1D8f-lYHMD%8t(2hd+@}9g6-MadsbdAy^Q zuG;JMY|Y9XKYVn{O58l4e`A_|y(?|gf?;!kzHrfN>Hvj_C?Hh3s=Wo?g4#fB6dJL9 zR`6q`kCESV)3$B9r0e4)Notj@;Il*TuX^k;col58_)U!3eQZ5x{UCl`a3hF)A(*Tn zzc^Uy^ZTl+>X<-AAxTeB8+uW?JtH$S<0y>Rw3Bt~8mjyDZCbc-C@9SnaGW~tv&y!A^Y6=B_I28>k(v->8aSy@F*7IJWdW2b= zCUA2)KnrT^;}go`6({5bS?Rr@u`w~PuDWS=>$nNKkB=WecRmrJN5{_sL2Ie3s3?z@ zlnd`J@g#K{Gv=1oLp~uFvlEha1JuNghLCpqttlHIzptvkuC}HE5o<)$LTybQaye@2 zt6i1@W?^H6y*taw%ge}*Rhw?UdD9I$c1S0-?ARVJfzoqRr`~t}RQPxQeN!KN=TB$f zdFSk(-f6p!|3l9W!M0x+?JoxO(AWWL?bR+&d%aODXuN3pTd(ZUzI6@#c9j;kG;5^b z=*Z!-(Azf+A2#>0mBwB}r$=|7(N`(A ze5!g@?_P8IT)AfT+CFo8YUD(x=EA@HzV}}K{XhKv4f%yXx$oY43-dvpX>-a2II#vi ztQMdxUltw;Yea|Nk>(^w#|gc)w-@N~586`ghps#-`17p(fLU8p({bhgVH ztcG{{jdf`FjnYwc;JEaIb&-Y$n-TVB(htx)X`3_{9g|iWEvOf^DVBlg^@ZWlY=0u6 zhXfEL5E0_*fc8XBpS~?u_jRq6-j~j;O~ZY!8dujRG(IZMMvrW28gWxu!^s~=tI-X& z-QG}k(}+Q~m*U3RtmDJ2x{aguJ0i$7QDIF)1dMH<21g+$4vftxn`%W_RKgg*2GDkF z;k&um78f}&Ahv<5C{%?(>}DJhVk;6yW=y*z&V;X{(}!iJ(*UpIB_}exW}P1wyX)BK z5XZ*W(aDjii3+U^)J2oQxS%zow2`|aHmycd5e0RvFMEVu@d{y_*xEo~G-;Hvb!}@; zuaIW|*Nm!~_R^#v>$nC<1J<;|I1VKj4y;*6`@<1YOWNC61yuuR1I$+3dekeF^d{gs zuHHw-)^QI3!`4GJ9KZ+~%gt&pISR0jtM_r@>Uhaeadk!OVV}@L53CtI4crJW4sBqZ zA+b?)1X{5%pcV;K$4g!Opjwtjm`d$a*+xVifhr?W8lVm*16xA`D?rV9JfgiFwm{Pg zn1VRGh zsBX3i)kOf(Qe}MbPUi!$A&Uk?v1PDXkD}ueF$0K>cW4NP#t}fY$fa>T07&l@vN9iR)rC5&ong_f&W_My^&`3Sh!%iF)(v8yPNJvwI1&o{J)QH9yeu^vo zt*>~5p0gthL7Z4JN~c37Tl2j_F*b9!C>{>e0Bj^aYRE9k;}tAeuZ!X_F7*bzKRsqA zT6cSe`W^)DMe2qO@v5!Er%}2VVyLc8Hyv2dnz*qs`^9kF6%l(CCv=O_y$kQQ?(@OG z=>ycPf29!Lh&@4Ka7N`qI6FKRbd?= zCOXPo#bg0EJSwT+s7SrCMov+BXbF};G%=)h(Ac-grE~dQIoDt9uMiD1MKIZlz*bns z8>JIw>-`O82Adyb8DSLGgoU^uB4^e$v5|xx^%z--wIz20(uu-KV}MXw=1+tZVgtZE zcL2E)ksAdf;Tqw=o#;;KfnCxA(*1b1^Z+^~nSr9ck2FI1R2qR?(x>Pb$R%8D#R#2h zDS#JKHb6!i#Q5xWwW4y+JH)^sIGG14lQLkxQSYS*wi89~Eb!Uxp@Z?5!TlhW^& zA!S#hA75EI^p?Jb`qA1Bg{pX_eR zbPh+rY_JD+jz~F*8aI`gWQ}QT%vf{=h;bdc*k1b?vJ z-9vy==j5zsQZt2j*d0X`5(2c9ux3o*a)S=d7FjJUVZ9&x`~@46bFxa{E2P1j98 zn`}}(;%(@8kJOy={l9%bM{4$<=L8-}0UO#h;kr#j4qSHP>Rpc%3w@6)S#o5_?#A@A zrgYav`p4Vsk5GPHFjyD7g8n>L*zbyIO{l+kA-844hGQ+Gzh7TnQgF@miOW{pHEVEl z@#M?0QUn2~WL-A7xOwobyH+flIQ^P}lIr^Jk8U}(VMR;s1yTB4)3hu4iM+V?i8BZG zuex-j~6)tE>{kjO&;3&%pbGrK}ApnAU}SdSq8 zxd_G;B*)(aQrKa~3DgI9sQ3AsZ1ukCD)>ocBUo-L$WP%@k?1H#d7=YGwp@S`fo6sJ zd)VRL9yWhnk@h@{AZrXBQBx1?737zT!E$J*2|;_+RXupWFPE%+<-z;k$vzi>2uBYd zk`^5)j^0R2MKrM)1d2!<$dmjZ67zyA(OJkV>swzApDbt3?x|i+<$?u#YI!{r)%U&d zV);*Tb-!Yv-vTLdK)+ObP5JFt&u-e#P;E=?*Wh#7vXjyh(ddGlsz7f~Wm0Lc3O+w8 z7<8uQXMK)m0qK%I7P3m3Hgn=@qEXDHw$k(~`67PX19> z2|U`3etC0ozv`b}n3$ASlakn@Hdv9-$A$YPHq;cBMjs4>vk8LW%LtPnT z8tU^Cx({s_li?a#xT$-pdui>ou|ZE#a-OSCw_YvvuF9{SQ!{Br|HOW&rQNd< z5=Z@YLTRtclJ$d!R*oz$&dMq-A6Yqc@cI(zoX=P24HkpetGl?|G0x$kIF&G8FKgoJ)RMy%0ZMMsH*y6JCQskVLn()(&d@B zLt-Pq@0xNRqzq&m<_r0qBEWq`e!GwT@a2J=7S-G74^U^IK=s@4q53KGxamzo8 zN97bY_erbh-M@L}@IY^Sag)n~4%lWi59n3t?$cbDGip^*dhfy%At^c7AFXgECVFh? z#c%FkcKyL+*S%GoZg(ekbD=;t>D^>6Lg`ZI3Vh?8=ofb$yF!xu2)R?FbBPy*r;4tm zY@0VfrEcf@m(6}@_GRzytV_xF!gO$nsq+%&ch6biU$E@KXQYtS_VfeG=cmulN|~RC z4$L1|S~_t4!t88x&z8o7SGOx69L|I`0JVNlL z9B!Yo3?$pdC#8BA8u>f z+OMT_aN|{n`z_x*=vey31N{?y*UjtRecpAx#Qq01rXL%$d3nFXSEUY4nK-Sysa*Qs zp_3;Mpd|P@aasyEyPy?s23h%~BZ*qb9Ign%@;k}-Sjv5$`w92Bm7x^q2BqpMf>Joy zG72?JMu-T(!o6%#skqhE6Im-x13>_d*u)b}38DiUk!e^E1tMx`c{UJ*I>0|ng{2_S zXQ0F!pt{NtRfbfVQH$sY9Vifqqox-$TLWmt;v&)E^DF8YDi`GQFN|I~di2uWo<1p_ zsuW*IAPYX|jZw=+k6!kXFFQ~|K8W{JrFyDD)pIufVj4bGJE!%l4S&1}9lL4Gn5@j~ zaT7NVT$G)$XyC?)i8ivxR&rbDa&fVom&gijqf}?v)^)2(iCxyN@|CZ{S z?v4ptax;=0yXR#3Q|3&2%A1qyE(|)n&DjNlqprgCQA%Zi^$z|)wQ>ZckL^!o7p^O+4d_}-(TO-Qh)#IE4MEj z(>$}Tbl+X#t=C=^ddcfZoz%Zab!&xp-}Y&9@!VoB`U@J5CZN})p3+0oPo*WLSOL7yzlzo{`UIGn>SBZe%~ia(s8u>-6Y%#6-hrrGo-hA-8^aGqmM2I z4om^y-~kSh1CEkGsrms(R&bYdJAebwd!UCTIJ-c4fv_SO+E!3XjL(0HJOG1+`TRAg~It6D>}G^qu5fJ_JSpcY&vbwPpiAJ5F>-x!!VL)v_7 z=nLbA9t$0_&6XaMDx_bGm)V3)$Y0uep*PVu;OQIuWwqX{%3;|)XSd?VKLP&!?B9L-`R6}k+;|N&q{xj-hW|#FK^Md5>h!Gp*tR3 zJYmv8nPEvuz`T8oljs43waV{P${6Hi<$BU{i;C-VGy3I8AOAu67KyJSUyptnxpl?3 zC^y61BRfYKK#w~Us$E-_lKSi|=g!^wJ7@Q@YoTJ62Q(8zy)@zU(Uq_oZU77l1IAr7WhukR(jRaQntthtMI2 z`4}i!~@FkD!FL8N)7yGPq?{3sLDj@Xxvg|(-~8U0 zS#_lawRsBh%I|hEK{w2hebXI0)gtPta;V4;n5Zb|wFm3LDbNe8{<~g)>uiar+pwSg zY?$=b5$S)!fBy5~QqOisFV@7@7JPa2_4`-9JY~wutM^~OI`n01>D7-c2ikHcfD7bU z0H+b;a=pNEjDo1o91!1nm}@owhQx^?SWhOV0*M%~pF?EhO=m4kV1NYlE2=3B_s?50_*X?nEng7Gy5XFS|>sysPXhWyU_2{EGCY^wlff zpBMVd^E>plGUX-Qj6Ot{qZ#Of_g_>@&r9#yhy7TRC;Gi_p`NJMfRoQXd-CM7&!Inz zC@nsS4h2g`_N#jM;c7Hdo6_e}`t?gW*Gs1ZHcgt$&)WOM6MJ{hYLkAbOb|4)Z5CfQ zdg8iu6GzwKSH4`mIvZF=HJhUnj7|#3Lk{d==|^V;L<-pK595yC9;A#Vh}*dA{FvOgW%EhlZ7Y( zt%^WVx-|hRLv%V(>4-oVRtO6NAn3=6kf3Lk8AgXcGDTsyV;^t@gkT|?SmA_0aEfH{ zkm;ePtex7=g1%r3wWn%5OhA|{>SpTxtEe~ScMLU0Otdz1Q>^W@LhJpbFeR zfIOV5+5=#*wi>2;4yp?WnRbHqsWVy+9)<9w86HZHk{Q2!`OJpmo*zk%ZbKYeiMXw6 zsvcM93manFp%HjeRzY5RYEln`cnjl3W_QoZm3Fio@h?dKK-tf~cKgBwwl`6=HPWmb zQdpAiPjL6Mi{%DxFhQ=SNn85i#-I)najJlDAB2Shy6=(nzr}b9x5(^}7Re(Y`d&;c zK*k&ECMf@@GSJFzX?}DYpdW8P&2AY%;{4>~W-kP%3WCM8#jyV##?4<1C^taLtHGBe zhkiOdqyjDu!i7kby7jCAPT9TbzB*La${(&riTQntaxxN8a&G8weQq*J%*ZL~m!F9G z9_CxiP@Nwf0+UM-X6Ij9l8H?U&-Uw-qUJ$OuRJld#hWn{<>mEB$r&*sC#6qb9vYhA zZ5jH+D@}u%i&CUs(K!?Pi9z>)EZ9_~MsQCx1+GpG>>uZ<2^J9FptzR&Xha2~Luc)a z2oLneGa$PKnitiw;HI<3Z+h*f1!KcR9E}UJj8kp79^Z2iO@IFdFOOB%>FL|YFFbT; zA^D8I-Q+;cG+I5OAv5FLxeOpmH{Xf3>e1|%MPgN2`V+B8*T@d1M9U-?Qm*`{x3~nG>wQ& za|CSx5|^UM%p*cIXi^PziDJ3fcA&3pAM<_$Ui|{WNyTML0AJb(p?HD}>o^ETfrslM z{%=h^blU4Ks_%}1MSeju-*JqH{egz`N`mum6Xtf4UL1yM+eQpSb;B;iJ4l#DA!Gw6 z+_$rKd|lo6T4@-N^TW^9e7<`1=WC<~jpKGShP0Vxg`)YXz`1qmovL~)>-|U*gos?9 zj_7s}IKi*zapiZoKF1nUHP06ZQ91rPdN zw$=2jqnO`4^}ka?w<(}p6+mpB?6#%%|R)1q@Bk8n-LiLfK>XAG;LW<{(Q8cBrs=Azmoj<^GovQEb9Tk^KnT( za8R_sf*-;PJ*j+>U2w!+S=ccaaG-!(hL{4lYksc-{s+fR&nkW3!TvjcdL0ke>rh`l zF~5HyST7!T%WXTY2&)D(w~XA~@Nr$;#|^tjh7!yy3bSMUgBC^$jWd8x$=@_?)4}QG z<OtT9CR+J#v@)|0_M zrAW5&J6ytz0-_u0Zp2(+80~86UTAtp9#egAMKAG1psflh;ei5z*|Y$XHh!VRFiAI$ zBGI&O?!XW2K-G^ybW;c!hU+6^x6N|BVBbEOV!iMZ8_@%-8wuJ*v=WE~7wjz5fQjza zQ)6W$Og4f)#{v!LX2ma(5(q5{DY0w?|5FxWcp2Ox3;_qpp`%6%5D`F;Mgc`FNts3+ zG7xTg^%T~siVKQCP1&~_%ml1|wLA9rTA=JM^y*#Zfu$LRJ0E!j7iQXg9kUgoBHXtc z!U%mwmIfgL7=$fYB#fe%OeGf36ULKp06cz(lvn^3M4|*b%&6BoVH~i1L!5nS2Gu%P zANQ07(g=Yx#Vo5~8Yi3u_9fu)zhktN=o1JHgg%dEFR?T*RAlCX1{$1PHb>U&>%j~S z=j02p69~nk%B92$<&bLm-KTx2Mi#ubuzl%1#n2s_$XRH*4&sl zol1&<##9Kz!jgp&kA>9<@Z^|-8jpVXLiRzWKZP+>xU9Kmc#a&M%^6mUo5>naER7+g zDf+$b86yXUYYxnxn9^KdActm~yHA>bfUNY8nWS;VNi`z@o^->vCP8p~sUyCqtA&K1 zUn&YP{?MyQ1aPU4->$H$Uf&Z9nNH8UA@MN+(g2Kw52oKoazkqBtqd9_Au|fj&;bBm zZAZgLY)eB1>NB)Y#)Z8x=YtH&{zE}m=%{I^3S@NsgwD2Mi{(0qfGQd=2@=gRAe&(Z zgwU5o1PiSHhl%DPGQMf$m{dh!o!1J zvWgdkzhGUOe21Stzb&wINXwjsBZe)O7V?|D&2y#C<}~r2v~56%Xe;V=0bj2$wX!iQ z(3mxUXLVyR*rP{dZjWHFv1;dn%*Onz#y(+wy>Kzt>+O;4_vD4%%E`;i`E<$95esLJ z9lUG{EVgCk_`E&P$9dT~vwGxa2mae5H|T4-KR3r${NLQ1ylh+Mq?H>-jbF2-?c=$) zWy8jn4?aS}rN>acGA_4%?=jR+-cwqAdEJP@fdfv!vZ@V*mh;DvO?n#s99THK{&IAz zSGn}t$M>Evs(1db^gtlpSCH4%4V_9&la9i3#*f;#a#BWKfe$XBt#_hs2izsy68_^! zEbf8R_XNuRn2~d$ED&-eJ)KC``854cBs>Y06G#-ejG`Jv%H`jBnbuo9MCHIPONA!j zp;GWesHk6{@gb~Va}G0ewvEa_wMpve+1%9gU_vfU*Zt9KWQ7@1x7|hgJZ~=HxoqY! zS!!otlUi5@8$oq8L`}fT6Bml)TtN6lXeZ7#Qg5#u8_4!U%2b{+(Uw$@UF*~wO2D6F zZ9R@?p(QW)=QdQOCfSnnJ>HbmLXQ*uT2a)>?-+m_4>WQ`htE5(GG?SZo|Q4IOh3gV zwIs8hOJgRIh#^vP3hWRCal?TZ^Wo)SL_{%X#N)C&M@|@MU%r6-TSb6F|B?PjmI*b` z-gX4?18}Safp+BwyhsI{-=N`pfcGCMv%)G70IQh*?MMXB^g{v-DWyX|mF$Y87#V^} z#MmjhyfNGc904^efu+!reNXP&_avWT@ESVcG-$D<^0UW}pFJ*2qAmk&e|*Wom5QVR=0~-gKTJT>g>@vtfU=#DfJc5OVW0%0fm6KGjG@_SsP!XJ=$!>xhA#ad0 z%1kgU(~!hf_Mg{wY!q2<3>_XtvatS5f^&QmWo9S~Sc~^P8G2{XIPXb>Ip z{Pf<}RHfEAQ9`$*@|4uFUC)Jn_rk6+XZLcSgHNqXt=?UlE|g5(IC0{}$>iszN#`M| z_ZhIi?aya184GF4i%m28AU_IDUeWE{hfsp_^@HcSt(YwRMf$kU%%&GVEX-Zq?=zH^ zT~e^>ziUg224)XvzR=PmZ`_6E0oenKO4t5(RY6I%bpEq`t8)uKe5<%9aCyU`srl}q zTT=J-t*cDw_VAH&=MF!dlv25RZ|atz?)<5X8ZIXQHIXaPkPgfDAjx>+;rQ7l1mD2A zn359SddGb>KlW4iPf2xwXd9%`!J1f|9+2=%3i9=yk=`^42d|ktchl9EPuaC}*VN0e z-aKdWo>B#*Y*tW(^g+Gb25u|O&tlWL1~4BWJ+GhO zI&yrq{Bgl?)-H(D)dE!XLT)$xTfItZ!BxO|aJK;s7RoHeZn(o;T^saQ*E)hOFEoT| z9bQPL_13$f#H)En{Ts9L?e@ls#>S>b_&0IbzT?vM$M+4JME-)p@+P}Iklol2hV1x< zht3%?WR9!x%f`lS6+&r+KQyATDcx6I%Ij8ZesWm)9{O)-$r4+lRCX=>$M=<9N6zLo z%eK#*yM5W3X6ZB3GxQw0hW?ajTUt^oC8Mj4+-qcV#_};^mXART`M#m&Q0h-B&MmOz zqXJyG%_prnSMgJHm)pO!P_*>6DUXH!#Oh;v;{~YLQ@tknzDGwl*NmuED=iPtX(%}?bs05)6a4e*QjJdG6ek(#6}DLac!lqN$L}o&b@*N!(%XHtt^T zVR(o6Q*gNo)7)YZHbMsh$0;Zej1Jf#C_sihbe2(}<)T|RsR=QN)bH2>Z)c0htG>7;Wa<#6RzDjsqf0mXD;u1Wbv{?*Vr@r z{7-uF>)JeF?~zrZ+a0L4U3$&Y9X1Y0A38m=j*+DFBUkuSrBB?*+1(+%WkbbcVj>Pt zXJ2oNlC5r=EzC`D&-To4r7ydW<*VPnG%IC_dwN>JOdEgBUDio#x< zq$PQU>1Dw{Vb1oc<%4RZ_3nOs%lWo)lG2XbiU#Lp3>~rS*x{?kO!oT+qh|}}dx!W& z4_el|vVWhyLzeoc_xjc@Z(h>W;vM3hRAZ6V{;RRWqGhiS9qSnCm^!U+VE%vsQs@B5 zUl#_}4?OeC0qvV4IFcOQj@oT|76gZPn>R0U2(heFA&b`y zg4E27gfl2)eNGA+=5cHCFF_1Ld6v$GCtuu5(13(y(l_Sd#vBj9A z<=U#ENuixu>}FIGB(f571B7zMEu_K`IU~t&unR&&29Z()3{!ctmN4-P9=1CO>BWD! zeyQ}~vTNTi&ak-?6OnJ^wqR;`N$(7rJTHCda?gT250Bn;bXIzb^e+!eO?71SE~!ZA zb@ixF*2c;8E2qx_AziZc&>nkMpRYhj>vH*hM^?7|IZ)LXS4?!wvdyqNoJl#bL85!z zuJ@+QesK=lAmJhVg+$wI+Z<7tSYB5d2v#_|drOwy|8(fvXYOBGoSu@$-{R>#pe$`0 zk+>5eaqKIRI6slN?Cn!4K;qV=_3c+7TvbvUCOsH7Mf3`mW|UrAJ)me>i&^M~&Mg^G zeQjyRgH%|}vO1`)sInv5J*O=(fxfa+dL=gX3ag)6QsTZ5j_WKa8M zA%%&YUYqrTRLB#s$>KEkH1{geX3@lm?$_yo;LvlBJ5{q`vd_jSmSnGu#ipEgt2R}$ z)xr7#&Dnq~bh=xT?FxcGL_t2hL7fE7p$5siRJR31Q*MivtmxOb;{HGVq-;>lvbI0R ztLdy29ges!C%UFXKf8QD-^;|_LwghssCK;1b`H7upE;@r1Omf)Im$}v23&q)QhLu~ zwslBWcV-D%igOc(wTvCsjUV@&s=Xf!pEIptSb9)u_g2&9(f_yfrqLk9OM zp0iExcr%idgjxum=(mE6=B|NVJ@$RuRY;$p|A?E*U7ml%;tIIZX@i!;d^z7M}U;NN8EEz4JHGl};(c70ZRA2XRSs_KGkWwBuQU$sHF89jbKT%d zXV!?3y#_bF^2F%Tec)XY=?x($KE zrzi89c$Q)N0Ws(VioHN==&mkH-P5TJfnnmK=8!@DGNuX450mxFC6{hbU}P!6?c5V6 z?0;luVaC$j$~!-%Y0|4mhct2lMrMMW>!EE>f0Cjm-y%P56d z?1vs`x%DY3ykcerPv>`!;>2#eBSF7`lvl92pzR=)x*7M3B0gE!H7aN@T#)yT&Px{b z2>zIsA=7R1#J($LfXg7e*ZY_>E-eu%QfMUZIG6@p~mh8$Vt z7&H!!y$zZFFC-jHg=7Qi;XBbE@0_~xk<+^_D1wBZp{XCIXx4%%RWXH1wQBfMZcmon z3l_{7FyPCFAD(;Y5c-x165j|K^DN{*fKsw^by(i$o(Cx*HQYit&Vd9;Aya{_kJXTH zHJGw`KX`I*j6!%uy+B7b&w+}aPzC-sY)sFE9gwi_;sAdTe(By+YZ#O&{OWO( zv=?$Q=u$QRre33C?QDRqQt1{NeZ;&m8#a#l@WZ?AgrtBSG?!xzS>@)qGv5@7+l4gu zF^;=<@#1-oEPSJhinY|_A3;aM|rgA|zBP2LQUzYMWnk#(dEcW?1>+uxfg^< zN&~b!ot3v9=`GI1J{P}<-|r0i0{kNB2(;p3tw>*>KdG$*eJ<{DVG^_!;6_Sckk+Ix z_-3`WuMR!*2)h$zK%E3zy6M_7aUR@H zuF3atYazsPQEpqgme4x8Ld@iSj@E7P8~eJ!^XD6$F+p4|+?g;H+97?r8m>8P!x3!B zhUYJU=UQONK@#u#WOq(rdHCslpN38RZ&fiuqcC zd}BiEEtO(sIctbk0!nTB5@tGs{A2cw=$yV&ZJ*n=Uz{(lZvA_uxH`c%fl4xNo!&=W zgfYJf!94Y-v!5??JmZAJtu8L4<*F9oHyX;b$wRq~(r2Pu7*6VQKMtiqJCFuTh3zcQ z*#^>f21?05G0b@BET|h<{YYo|W^%n3Jjhr97Q>-|pTj&&vaMqcOHFX&KU)`9iT!y` zaqFon@h|p!rR&gTtvjp5>+pKeWuVFITWOb0+g{{9NSp$9ZZMTU#($9T5tKtc^aa$1 z`+x*mKY@qxO{V%vJDW}Aq@6suol>V*MQ((KerJ1h?Spt ztVV3ez%Y&Yz0P1N{1#qtI>>K(ciPs?{9gNC?XRWLYjPbVJP&n1taWwXHq?P@w2rYI z>pD;uhcyI+YKO?ftQs=cfxjcR1J@#UXcojZ=);ssv(E72MIXYzN_ZEE@Fo}tFe6-u zm=X5}lr2|Er{r=c+991XmfQaaEFN?5xr-v)XS#mzP2o-Z7ASXfe*>$awnxi<0_9%r zZ*~tYCo`OhA74y5z-NQ}g7}dR=*pe^-=&dO<&fQ2LOKwBo!T!K`VFyP`u1!Okq&?z z%OvHPQo2z}P8^g-T;N}oFC>eYmXik6a@G(~pma3Nwup9A zYY^I_*I7r?_)+Y-zFm5qbuUsS?381#-~teoLCc+jN9M#?{uALZP!7r+9!%y0#Wd1c3h{~w#M8=IJ2ngufi?s} zXP*Tk2si2*glWPWgzIRBZHLwX2qiQOC9Gj`{V<3i+|M4&Z4BLG=%|~&lXW!orq)pm zH@Hy>>uKmsLr>*$ZmyIpdTaR+ND3W3yYbXu%5I*7%;M2PuKNdYCqoSy)u&xo75Q_@oCoDk1 zdkP@x1|c##WL|m5@mF40jSPx5cu#h)&{b1kO*~LvwQci{(D2e#ZTO7zRHEw$zY+~- zduB@aM4SCKVcEOAyL)<0oLt>)jC9jcspWsJy^TwR{4SA zWOyKKFJ=#f2(r!z<5_NuxQ83+c#b>1YEd< zvw^41@&Do+!p+=7hrpe%9pUb_Jwtd_VQii^`_!rxei+>f4L)IKz=Rf8W=|d8@1-5&k9=q>^gO~3= z%qTJP`h_kG-tY`ft1txyhB38ZWo zH{PBFe>>rK2K@a?E=^bf*OItx{5<%C;M!f>-L1~0;yD|L%EtrM1sMYx8$Qi%20cJZ`8KF8tn>c!KxMeH{%ldmPbz-?4Nr{Oz%#Cy11wlUl? z$0ly0)yICEn>&mA5Z6M5<8TA~wtvd)QagYeCxIK3B$HDD7bNe#Ui-a4w zlV=`XEoNg8e$~w6KQDeq@_C-FEEUl7utUcZge19>~iw$O>JCs<>6Qt3Yty zfxo@*`$72Ra=ERqVzCT*u;}?D z^g!#8!=kr)19zL_b?#`wM(#FoXY0=ni`5mhE~Zv=}}GVgff-{~_%@ zazvbxDBR91X}#=bv5(^hZmaD)H|flto5f%APX2e?cK!&rU0B2|A)nTvC&aD6Xf+K<3M?S5eoe&${Fl9iLt3lKU+m3O=#h%=W)`7Q)S$HbY@HCkb z@EI=u9&aPFQ2Cf_V55X`O=H$Vc2)s4sg4KmoAc7D6N2*=p8kb4(-C2#w4^wh%(dcC62> z=d0J}`}(}TulFDC@8@&*eE+yU&hzUN zyuDMGyoUzt1_*R~EpwY{pEk0U>i&leXH)+(MyKLAWS0c~f8_Z;R@||NZ&3f+JpW%d z{U6-p`41gOaF_pY@kA8KoBy|p{f9c9K*SQcKXRE&<&APe4V`MJ9HS-xnz)Rgv| z(WZE`xB1%r@BZX#^S?RdRKAQx4*h5p4gL6E9Y=mZ%rV5AKlJ0j9vdI=rFJv#O1-=r zeI$$Yi+Q|b=*Nf>@!Y1}%t@Vn@*j^4Me_d{^RLJD*ZK^K4dZM4Ki}&9^=azi#IJ>0b48-czrp+yCnLU*C8Ci(|f9;`{IOxQI9*KH~eKZW$YOpxRn%Tz}+n)Ja5r$ar9A2V=O&x7PSj zIka!cEhpP6CsU;46=VFE;jmK(8y>?1kCP+FHIASr#sfoJ8N=0WuNdbZIy`l%J#{J> zV;YSGO2mEwPK!FwRQjrM9A^g?$avaVwa&PT@DJq-!n+y6O;PI!7_(o-%9&9I>@j?> ziCa3JR|9L`t+zUPxN^b!_HM7e+iUOkvitS7jGzBedzrm^nZ0|Ny?dFxdzrm^ znZ0|Ny?dFxdl|d;zD@1v!<{d;cQ3bhFSmCuw|6hMcQ3bhFSmCuw|6g(3iD6;RPao% zWjw%rsNne=`wnk%2dXc6XXF+CnEfJpjP)Jz80&5CjJyVYOm&NoDc8FrQ!DJL6-?Fs zb84kMwUQ}k`$$x^Jyp$A=|89Z_LQH?>1pS^^}OLfimUCp)%FXkmY2r$QY**sa;UXm zUbVb%-14;j!g-pRDtVgt;W1oYywf;l>VB?gojtXV&?Z?=(DjVNLF?^TUBKQPuwQin z`&AdPV*Fjdo0v9n)mT zG}$ptc1)8U(`3gq+cC{{OtT%+Y{xX)G0k?&8xm8!@O}FQ?tP#85^k!0-}vSqFP3fg z?cQeJ?rrw%-e%wKZT9WnX5a2@_U+zAMpd@)>;`xJb9d0*9kh1`?cG6pchKG)w08&X z-9dYIklmpVjkgv157%~k_jY^tc6;}Bd-ryG_jY^Vc6;A;p2n_^?3Yyd9}kHikG!%v zxZDq=gRmWp;p$Z%8<*JcZXeiFA22oev2m6?6=Lc`3DLwkpZxP3@c{3S`CXhHH~juM z6m{UQy^1QA4NX#_hM!1A?loh$Y1QtLH$KH;?rz3#b@!+Lct=s<2nc-k&w!)tfTIcc zrF$e`Gy(5?ZmhB2CY7PJZ$ z`jBzVP!r=RaxvqnatkB>05PM>o;iES&GE#c3dVDW)-s+u^dw{Y(4mYo`7-n)AKdL= z%(HVY@z_b1+N0MVm)YZTd-U0l9d#tuczdf$DlLqXh8|-nTJvP~6vpv3Hm)UBM zq2U&lvBNDY=dgFbBpvh&@-Sv-E8|$MY`>gjAD?WGr`R*&?Bi4I@icoJZ;xl#t7qEB zF8lZ_`}kb0e!rYY$^A0jo}V#P#qrFc>ltU+$5+_%bBCHdOy$`pOAZdVveX{E_PER* zm)m2-!Mj<#-;VUz;|hCRX^++R=(opOyNRdmah*N0-Yyxi%Wts9jrQ2Y=-DsL_Q@M| z=vI4dv&WtG*kLCM*~fgrr-`BAQHdH(s#x}MoPB(>eLUJep2XFM`EM_Io!PILFwbrk z$0v~|EGOIJ@Ut8C$T<7tRK7I`%W3xUczZm<-f*UU?6Qx~vX9R`xR=O@2YH+4C8jZ+ zYtN_KGt=$DGwhj}_BhKPuNX3koIAvqc%JX!R+iY!d6wD_UVB_-kIU_`!XEFpLw)wR z!X8)JW3@f{?QykTxYjQ7v^@?#?O|DOj{$q!V2>N^vB@5r?ePtdonos!w%OxOd+e~6 zhoAPa@J7x!G(7UO5092T#@XZ1_Bh%e#|}R?$~gxsMm@tHV>jawLx(aRGjtqd($E6N zu|vbFXAgBVx(|BR@-XdS9b=|FW({rSc&2?k>)?kR&ptRDlY4Ln<6QeV@8EFE4R!&( zGvRoNoqDM~dhKzUJubJ$`|Xm?3>`t_8aqRsef;du5gw+VvrnG4#~19vFCGjr|B`*& zU>~ow$H2h><~P{$8|~vJdu+DH%?J0f+G01l#Xf%B9^bIr-D;0*b}KvV3_CgYJR|Sh zC!Y_GO5E@jE2Hi4_~A~K6YX*A@YAK7KAf8OL}G^DD@T1X>W`tWQ6a`xM}5h-X4F@V zHKV?^=fAPXy^ODp+Q+zNRIh#ftv&y}J@&cmsUH~EjQY_&{>fhW*&csktQqwyhfF2QdJjyXBazPp@MW#_?8pSW<@j@5!(JcI@si0713Hn5)b3C2A(;E=vH^ruR zi(Ewa7qyC9oPbKubyglaLBUJNa!D<^L@p)4r8IJB8GOPgY~cK|7Ln{E6oHGHk%%gU zMP?SFTjX+@y_~rmn#y6wDdzV`aw^ac0&)gKW;sEkS?M5X771s0QG)u;B_e zT#=7b(D@bhXhj$LMdmt@gmjR2E{W%ocrLlFWbR7lu4L{?=B}jHmDIYj9mDHk?tdPI z@>1YN9!gM&I<%k@eIoO8B*29%6rc<~G$4p>42aBkA_?ipK@q&D5xI)_s{&|8FZVw` zMI@i6bO8ZZC!+*h;niH>)m-5F{*CJosrL^=FuL>odF6e);70eVHQCH7hxT$q3s zk?WGdV__zkFYFLmRKfjU#OB2`v6#ulVUg?eK*!g2iWE_(s8!^KNYLO76uFTCH*y6x z3G&e+QtU>Z$j$Nairf;53J`xQxo&M2DdECOSS#^~+(!Iuog%k;2)vz*e`Dj{N--c( zT8x0m9TdHT&3CYV$MAVbY&RWp@T_m}yS)?olJl^d@A^hM%?xDGR*mF-m_cc$myP#Q=-xq*B`hrQp;Kh33#Dig@g|@gJtE79Uq}0Hpo{zeU=9auB9#=bWZ@wmA12|$Bz}YhRWS&O zJX#|1SUiY-tQmtMk7uF*T%pg6a=#qm=VeX0(_=e;7UoJd7B3Qz`;uBsJT&Dv@ga^Zy^4WQs^ z8d^OdQcE+nC8$6R+R!8X$jbeHI)#Hwko0LbKh4IcS$u}YXJV0zEEJ&<9U^OVFu#WR zHKp(&2#VD?LBTrW>ncFOx<<64U*y>|u1z7SkQJ$veF5kQy73xZ^@?*;a}NCPisqXLcG{}&t4FY;0( z5|D>tbfOm&Zit5q^=JW&HVlZY)xrGQ0+gc$G`yCWwd8!6;xDuJ{*}10o|`Ba6QS^Hy|hyU_Q`@evu93A{*JTu@tTRM-u5MMm=b#iH4dp!M^5B zkxdlZ26$meV*OaRAkwul7dLEg7=!P@pj)QG%IV{Z?Nv=#6R6tUd@9YK+I z2zrO4?d!^iF}Z-D;+F$b&2dI>23<{CT4e=$ft>*_@_aT z=(BiG^s_3oq632>-Q??LtvdtRVD59~K2Jj_>e0jf-;*k`Cle&t(D&>}LB2#Wotg9N{2VfZ{C^1Blx`n_G`5BB}RzCYOa zM=g3p22;V64+cg4j6pW4K>YqlWPtVkT_Ok4MZ&~;{vzpLNnqlyBGjM(-697Qk&k-x z^ZS7*pn;)A4D#0^ned?lAyJfK;bSlO`QN6eA_KW#p1(&{^c0jLD2l_09PucQDh^mQ zVv&b>^otTfqKE{zkc~pHIf7rxh^Rv=IuOF3D3LKp21O$&8d;2TRDqn4#7B0aUz9^A zen=8r{Ogp5xIy7VN>B-sAJT$O^zqj|I%p({MxwG%0OFzoXh)AI(X2&#!Lic~A2>dg z`9o>=F!mqTAj;wFKfITJy|(}~euO8RfnrCHXcXO#B6t)FN3!uqj*s-C9$aB;CP-q& zq6B@SSUDJe4D*ktJ3*ni6maEn?V`kIARx+7%pXO*qngnx%F%gf6vZ<-QIydn8%=Nm zohKBdRg`1s@R$x!j%DMqBssQLl;g5ML&pt>l1S3yb$HPw$_eB+At=g;#GFV>QY7+4 z8RNw8BYDTLK98j*P>CBli7SS2~Vy=t0#Rm$GOGOz5 zMM=p3^QW?YY9=a0In9N7^ocT_!s9DMNsU1c3Pd?Q85BMv5k>HG|Ig^*S4TKGlf*7I zx!81;8#HtlO-x{JLOI&d1&W_dlCuXyNz>5)<|fj}M4FmNp^3y#WdFooQO*&>BNMEh zL;iDW!TLF#PKJI_&ZWq?$)NDL`JkC|eP~9XDCsd^V|s@u=cOVSegx1f%J~#OpQ7j2 zpi7iVGBk*CVFD^a(hFPAi9S&>br6@ChHMm~9Ms4RbN{EuiZY$a=}b zNv@gXo!QC#zdQk{V8i7dARvc;9L{rUM43fGe)d;p>&U|Jai1u23P7PbU0_dc3P^fI z2J+B|HiW?X+;~uDZYJ_k3J)9R)}s|&=ojV6NF*W+*(gK>YSD}i^oo)vh({_ik&jaN z(TFyLM43n2JmTi1fqe4{Q4Zof^O=~>#QX}>q8T0N73C^6UR5PZeljwUi((L)Pi#K1 z`NZZEyMWjQ@km7`@=*#u21U6#2CQAp+BK0#Mh5r)nrsdVLGU#dV8b=_Xcna)4Ln|( z0G{4!)4?scmi249L|Mo!SxC}_JlzYuV18kzDAz@z7?tQiSd_vfWPMp#_}Z$o?B^ zM7fE5H)Vi4H`Rf?H}#29>_RSRpqQM+34xV{;()dw21N~O+HzPZhq-C1&zY5+H(JEN--$P zQw5@|qUb7$t)j^47!-<9n*?HNyF_`q76YO@lM5PJlY?ea>RceUHFS2Ka$gdBF=$zbG$q@M51RFR|ezHa2iY4Gp5KO#*XkL!!J~f}kj`kn9!K z8VkVrt0|}vWnBy^5Ef-UMb?uiK#>5)fqKw9KguZ^c!oB_!wuFv8%VsN5-sRNpC}u3 zB!H{hm<5V$EQ1dXpzy|S42aU?L=w`GgCcOXP0gTab1bq!bIt9dY@&fpG`5M0+?2=t z-^9Wul5QgDCX#L<>1!l?EdegLkq6>ls|AT)>%gEWo4M-EB->1~&ABKBahr+TOx$MT zHus9sB8W#SGLer`)Uvsy1$5TZBgz)ew~%a0CF;Q1mQGP#PptMT5mPek4Cg1gh5f>j6pIokc(mjMd4>zC78c-G-1TZTz&Lw2`Qdt8U8ySK3wv9~wZXZQbA*+QBolgJ)<5u{(&}LF^8ml^rz* zpdCF3i}Fqaa#0HA-(mh;8hAGwb!b7SDD6r7X>Csj3EN57PQvyYkg%PN?QDF{g%Z&9 zP5}+?B+<@7)S?+3qP!mouJnBhz0dmltiN9lKN`XQ_d^&Ig`e1!j%0W;7;;gJdQfl| z-S494E*jcJL%W*MfnHHQpuh)d$VMS3@PQwVXafa47!>8h7$k%IALgPM6{tmrDEw5f zbaL+LWWz@!{3sh-@kcc9aXv~>g?hB23;m+-Q@!#@BG~f@dp;>dIs9lunY~0Pp-E7<)!k{Rh#vmCP$VD+KP>W`CAS}vfB>c<` z);^>8ZqBDKGdXm7t9`^AOfzm_FH*VB}yn9*S%lh70 zc(|H<@kmA*vQda~_(8Y(+CY+hgQE1Zv6r>ppeWxuL9%a|`<7zgQtVqVY7h|RJ92*4 zDa!Zc|2`GPs6abr2L82d+`%y;@Nd6-me@cK0Sz!N9 zW$>W^L3D#=`xC(h^;e=pl%F~OncP2@B7i~e|1V7ZLV{n~gnyhH^`Z=K^wZz3+B{J6rvQhXcSd* zA_3W`5mk?eC!e7Tt)eHvs1X#7WImEcB7Nu*^^h2lCn_H0 zqDJSUMO0@J{1_0Gj}6qrSm$E{^{@_657$NY98QwM+eM9GA%=}HY>FZH2ofB@#v^(} z9YtfK*ffewM{;~5%^cY;YAkzWgXlt^s3uMEQG#kFBOUBF*=M$jYH@C5p;FYic;ui( zJZgM`sPVO;9!27#2t1muj?M(dMzc1Wz|mebf+BpRpeB@}8C{|tQw-*hCHb+$92*k# zxNPv4$Q36Nb9^fNqMqOcYbONIE$WGUTBn|v3pOUjgF;DlXah<4tU(=t8W04HpFB`q9u;vSKkKWf(B?QDJXhmf$U*_wHjZuM*fx%Bixjw#hZ0nx4lU^9)sxyM>ghTX;6fG(PzE0w5JWcy zL_NcaB%~t;Mew2q0koqBVNuVFMGD-=LkTKThZb}uF!YJ)(!sII1usZ)RzY>XGvc^o zn4ZA&ge(-G3_dgdJq;hJr*f&BM&90L>*eti9S)! z(~$rdvQQxE%=5}P@Sy=gbYno&^AnMW5|HeClAYgzPLOO8$tESh1(Ho7*`zY~t78u1 zy7Qv&U62~V~>eL(*p#tRdOeNt|5>6$dn?OFMQr&LkfrRc#5a=e(O`N+=)C+VZz=dp( z@B%Mt5I{S65EgY>EK-n(e3ZeDMzrygo)+SOtG+M>6u&S7T+M~Ws076?Y(WY8TbD(9|sK}_%d$AW&NUN zJCOi_v$Ii%a&X_W8_@=CM>erDB9VwR`Y>35<8Q; zGYh%@GYOta@XP>cVkW^e3BH`*%j1!XOyr{!RiNR^ThN7GQF8<_pyB@>?*IR51D)ki zEQhBj#}69I=>UahQD{~Y+~7)QRiG6EqRvi69xBl(>Kq-3NCWe8n4eSkZ-(#xzfb0t zi+TlDc|{}IK;gM0o11`i4wfs8>O%4?>_86&MZM06MDG7}E@UDP#qh$92DG9Ry`mPfzKBhWYS1m}VhSy86ZQHm zQTb?7EeeZz1BGskL?USNCIQV9Q}kw2aYZKB>z z!P_bHHyso$%|Q_cMZJS7yE6sp$OilFsu#7)k6uylX5Za)qTa*WJw4p(R#D5zU*00> zy#i`@mT>h;2ws|t0a2GxaCs!??!IJnh+0t$9`8>8#qVzr^?`V>{y>_j57NYg`5^AW za#1TwMCB7n^`TZ#AEvoSX#NozsEQHw(Hzu^`dAja`SbsHp{S3CMD>x(=NEMaiC0iy zWg@cSL$9dS99L7In)7NB``zdl^@%F9iTY$Jh93t+{d+82$U_-w(1LD+MXgCdI`X*x zHD#zl3%Wsqr|9^p1f(Me1t>!eg6Kw{sH=!ul>~~da)a1a1t>u!xR6yrbb|QRP7u2~ z3wiJmxY~z01VHfWPEl)f!Q<17;A)@l5cL_J(r1`|rUK32Sy>Yg60NBPF?9l-iMo7H zylzm`XIXnL6V!PwBW8}Zz@5DsLe6RMin^U#Q7%9H<9DDNaUj#T;ygq zD!KogNzxJv0$Y6O6m<*dTR7js#w`TDPUo+)@ePW-QHhYKtw|_Ei>O=u2#C6kecN(T z3--O4gGNzaf>yCiy-BJZ+~kNMPginY7o27B7c*W9R4(!fVvQ9sTS^^;hz_DLQ}QHK`v zi`qs0t_;+Qx|=+^%McXx(Pf+j+&huTH` zl1*Q-{#7;#Q30;vt2XqB`n40xf6cSd6OTO9pjXsyQbgU$`ray0_a%V1eKp+wePL01 zGf;*AIR7>sT*Y^hpxAdlQNK@s7c|;OvOd44KX64qlw(lT9~(sdDIe_nsZZ4YQc-_q z{bzFhT!J=He~CxEsK2^E+<+&RAs02G{-&b{t)l)OgGy2VaDqhqdWt&eMjo0G67^4- z`;+8<7Q>GgQTKaAJ&-19m|S7b|03VP98rgu8yXZ%8W0vuNkffj9;K557Ssf|QHV;k zpieYD!qK!m_|Ywz&PJVeeLyrvsc3v+qZz3n#_*wCvOf2+$C0e@TO?X!8^WR; zl8tgSh(|l5OSGs2i_WP)>Nk7$Ro=g=C_4&(7K3Lox7A=*WY z(Lv#uTG5W6!6S0Pz9ZN-iuh5~85I=m$Q%y?ld)L{2>;LsI5t`2BOJ}*F^==NI)p`w zXJdRww4-z+frgGM0&_>ZQ3LXfruoqoU{3-~C3K5+Oa@p#HU=fA7wtGtA_E1E^MZ|h zjH4YlC|V*{n@F+5Dm0=4{h}Su{P83@o}|aKc06k*2-tIC0$4jSALXb8^GVsDa8jpe zV^|-<{3$tT<^GRzi8hYT$1yRk041mc#Zp*H;p$Sjk`#hdNOo#0X!um-Pi6kp26UiL zw9}lRz-fN8qgS-?G&P=_JOo+C)36 zLbM5aAo%Pq(b5`3n^*=4Obmd+6Z=FvClR?||2Y&sSBD#wVBfjqPA4Xvx%5IXpWX<5 zeL+hf6z#ltq$3|*)FFr-(aw)VDkyM1Yv;4^e3DLLo}cQqNi;Z#`AH36K0`+en9ryH z@fpldW_~hxCX;7!If$R^VPT3O3E3z^9ojJ{+EnJJW`X&sB%0bInmZoMxk=*YS#bA> zb^&o0Q1AjD+7K3P8pWm+z>gO6igsZvGEj&r?ms_TYZtPRnSe}`pdOu~O{Xz_Y}Tgd zqY|y?7wsa7T||P5NPJPdX#6CsT};x8i_r+0Og@@yD=!*WhA&P6Gay^oo{Gq5M>2p%gx}A|%=ZaxP%c0^+VtfLF9@%0w$5zJP|VO$YIwYdKk% zi8|5vkx08P4+LM=05%uqBOuzMNVvfHqDr)gwpic>bBjs7n1qYjw|GFb>l2ZM64ane zw4wx1tEd>9-w@CJzkx1q@PmmPIlhrceq_>a;<1+jZKvSd`3Qjc9Xk3& zdnXl@;P~Ba(9pXaxAXm<_MTg`ohhPqq=~kR#}5ejkl;>y)F|4=B>JRNv@SZ|P2x{` zMeC-)&)N4m4eiMi?F#|Te#w5mAJlpZMf*laP_(_w?QI4*_J&2<7YpY0v40;w|7rV3 z(#u3I#lB@T-|uPP7mL=%RrYcILzZYiGS^RozmQ;{MYP{&;I~TAelHO157zmcIc<>n zKWjwW-yqrnuV~?XG@?hezgYjPL$sj;(Ip=>qAMILyi#?gLv%G6J`9Sk5ugP{*Na4V zWQoqVR(eF6=zJTcAJQj!bhhZuZqZ|EL?6YzBWp#EO#yRpRiYo2Dms6qq>pxqp1|WV zoFCIH`mqTp2f2^a(IL7gk;KOnbbJ{IIzBA=2_!qAQuGrAJ)$SEHYQE4IF*r*WLg`g9WUg-5@b_$->aG)?r&{G#(-ug}at5QCy$ z&IMea2QK3B9?|)HP|ryK@j3bMq6Ptv=(9*ZI~fGd$w8awxxJ!a(INWWba0h(IlnRq zStvy<+CkyGL@=Mnd|tQc^D@Bt{8V&_ew7=YqVpE5=kvJ0FZ$Kwy_(o-JdL6k1Vq1< zWDDy>zYc}1qVpE3FJ}IF=J{YrzoAU@8&fbK`c37c7n8hrQ1qLNMZYCe^jl*<@)8}a zmE@rU&7$8%1Gg2yhhEWdPe%bb_uL-jphxt-x!^@3LZX)@gXE>G-w}&^uy&`8TrhuE zA!xQN60Dc?iGDYQ?xwMO+DJ}ZIgQ_2FFKzy=}RcMWI*(#G`O??e(wL$77jvSlQ#w= z^)k1tT=eA`qTffi_mT9z8iYizNJKt}sbJ6jB)-2K?V>-BJ%Z#9l!Af}Q2YU!eSp0W z>WBw>9whcbetl7YunGZmiC#%SB>|NLR1&}^S$ZYwm8@5?{t)XA(ZEA)(C9-xG^0oK zhhxC}!?|GJ!|Z#QeGhkFK=en*`v~ig(EKA_(AXoMPKH6ztCEln7WhJ=R|U~4`lGQ( zLjg$mDD#gp{}}U+WuOGaKSrL%BjE-OJkI>%#PdZ;f1Cy$9}wL~13uP$G~n}s20T7C z`eEC2~tGQX1fYUZnHpt=OaSChw21AaFs;P-+8d}Y-A zjRPzM6QxEbFVOx7v$(?*Hme&|z&7=&+WB+FAtBEBe#1 zNJ9Zg_%!oRGye?p&t#wk#6LrxHIZykkJI_B$`uVemMk1)8v2EP95 z&$fyFoQ`DVpd0~&M1MXOnIOUQjpz}*o-3*+uD$|6(O)3n3vQ6_1>#<)M<;0D#U#+c zi_E{s{EN(cUSh*bF0kPxAKFB3(2;P171*IU61JNDX^Z6>)E)T zjeIt!2izz{03_PrLNPesFev&));Ct6TlA(R&`dKi&0*0uc}0KC3F^M)5UG_$!^^p;dmcuS_}uP2E92F2e<26L?(xAMlcH6G2PZ%YAhN^fRkK=fdV=xIFfV|t8e>(>Ss0Ba&>2LRo-WG{O&_o*v+6qPA!SOpZ_6{4~sT2KO=Gv1$!uB4~ z-{btfUeR}!ivE5i3eYBcM=B`R(INUS8ra32UFj$X>mS4*AJq1INb(O!(#hgSf=pDR zU-XZ&QHMd%KPd)9yMm(cX71Ax(LZye3MA@IL?IeM{O9cbycD&d=;s5X?;(b7*YrKi z?;&mv|M{B!MZD-=5d1|2c>2ER6+IM-43IG72MI!hqJNo;PH_BHDrn-X8nFJgAPM=X zN3ZBTxd@2<4g0?75`C`=G`-h{4$=3;aR2#6P~TUIkm$W6?JY!5^lxKOhHlZnOGg2C zX1?bs{hq|%lb}yWJjl`4FZvIe@QeN67$_7pTMEpe0-<;}y zw2MBNk1Di^{wGcS=@)%}3ip3M8xF)HS@bYng()7+MhR*~|BEL6qR3xt{EOIw1@MBR z2ZQLrfapUc9ZCYRLlhq>f)_OipdG{xg~cJUNP(OGIgI3SP=ZR-p#`1j6NjQB0WM^r z0A=u@0YP+QKpd(QNk~Tyir_^J0%%7M!s5_kkpj1eArB>}L>*eti9T`YIuhVQ779=X z9~uxuHwMJvAl4C!BoOcD5QpJL9!k(FjtFu@)QBUJm`E=?A#og%hgDVp#LURB=GE zm|k%lLD3^JkOMXy(JhWqPNahZqq@X#WFGnu7DsF)n$ac>lcbh_=HgPpT6`i3LE)pw zdsK%wj%MxXAUeUHf5+$;ag0s_funumNJv1fIF6x-V+O==Y&IxzTngBjn1z5ij(4I2 z?cz9r{U_w26s_VoQAaFj{KR~ep%Q)KNJ>I6%F)36PwE%Pm=t8fhemW@KpbP^L6Wg~ zVAEJH{Ad6%V|y?tj+2~7gd4di0tHSY-$~7AM+oFhjs&sE{o**;(<+Wrs>CraA0$jk zLnS)JaVm*UZ4<|7G&Vj%9H|sZ4T$6PY;l|+VC{^MIL?ek3Q9pk{8;61(Xgu#-QqYa z3FJSk6}{q^z}^Y*pq6I>MJ5!Z0<~xcjZ7f$Yy!_tfD2hDL^=E*`PpplMdDffqFhaQ`Q^b3oS;WNImeAWl%NuIXhA3X#Br{U z1kl*IStvjmd}u%r-53x@x)VuAM-GbMMGg4*&yn7a9)!hlUMy1JMjlE~i8{2P6Mf=1 zUq=F5$U*_i;6np~=*ECJCOMG=VkhxzP3jj%2G2r9JUpoknaD>es!)$sbb;W>kw^rw zlUbY0+GN%yvo?jbDI}WGj5aVoh54z>Pi4>4G-RU?ey~2Z7lYz($8i7M$sGLeqJX;; zGW{JKqd`L7sPY_r>7zl`QR$1 zSApP*Tp;3Q-PXE~cq0n#!W7EMl`LlEuC(ie$Bk;}X9(E=>l}@e z+-2nB18hgOhYd5_$U_M#QHOvyW|DL!4P2f8jxWzb0m?vJPArNL7RM}(XQhB#v+_^^ zVrG$RRtq}OCyv=V5i<9{cApH$M@~&*vGNUx;$}(FkJahcGCPt75qSR~2y3{-5RNiX)$= zdO;*y@PZ~5(7@FcxjGLVU&GUSO(u##k!vVWkPh-*8;dLi#IcY(3o}5Y3w`L~{$H1a zN^ulAkqtU6Y!SyIu5b~X7qMXx^NT3Xr{0c5T^JC@;uxfW!i$T+zQr`RxKA9{v+sKL zU0;YQG=rv!XrRai8ZRPW5ug7!ib!~aAQ{;xMIG8fp&JuHksB#;BSmg(MXxw+qR35L zf!tUM2R?_=oiP64dVDaYI?=7sz4mIBzuO2p6L+Bns#wK%ckeN;;46tMK;EWqnWr(&EnXcB94|malB5>tx4i|vsN72bHwpB`F2!@<6STJ z|Gidmbfk;p171KM5&TJmICclb@mW|Ldr0(UrZ{@C#Idgo^$3ZhH%}bj#*5=Siha*o zUz<37Wc^2S{KVdV{M;{&UyH=?Te3L*NI;i320O*EpFIaE#POF~97CQAF_aQ9)FLso zdNKIn!7xH%M0SZ09V^D6UNH`979%D_j3au*II>3!D^ZO2N-;*WH-WWd*`HV-#tF4z zj7bpVB=(-tE=Ed~7^nHgNG0EytWQW5V`97*>6xe#r*)=(06y%C=ZG{*Mv&FcMB84Pe#Gb_sVqDL8QH>Zk6pL|Vj2Ol7V%!oI zgEuDQZxk=Z9bIDF+3XSHE|QlKd^f@OP@Fdmqr6g#dnvf2RE(v$VtC8NSVqxhgJLXi z6yrW(c|S1jPY~k)3h>9)c#yTqHZdOZiSaNVK^5nZc8T#AO+8M|6*Rn(yw&9MlkW+> z{u@tHyoO{?)rqk>5d&h>GWT?u7;9R^crHVXdJ?=C5Tl__j8~Gyc(qiF^=V=Rh}}Q~ z8#vxT!VNUHp##isq`8gR@PaxUX=WqyO-`gDpNnm(;vfJLH`7FO3D~fSqMN$Kc#S4D zbG(^Ed^%=qrtoI=Yz~RhB1l9Aa#0Mfu%#Bw=s>R+TZr2dk5ptLALXd!{%>jJASA}? z$;biE!t2bvPVv_V#dsqYYZ#$6&nt0oX7W9bG#(bL#wPNgG;|})hXasBT zko28Wgv5B4eDBiWyY=W2qdgMoC_<|k@5O@S_nO7n$(mOkTzyFtuX2_WXHERgG~GWbBQugLWkabFFH@wF34;5!uK>l_rpi#ibabq~T~^u!_s zZsef^l_0LCMT~C>(Iv)S*7mZtm$kjD?PYCmC;G(Lry~I_WT60M@bRv?uYrRgx-lR| zuMLBi0HwxfI9a_+dK2b#ClAGq96LGkH_?aTJuf65gMK|4; zc*bdGp4n7-enkDm$hc$?!qms_-1J7%zS4;Gu^CZ&qP~a;6p=jJ6~o8|1C%IR3@!ZE|09eDqP#N6SmmqoWg|kBL4u`nc%C z=;NbLh(1xaM<+#(i5?q$Qgm|k$ z;fUnw#~zL-aYiqV_C_y@ULJj){82sXk%&@NDw`g7BqCl(ab`PbIA=O9cjh=}IcGcP zICGs>IOjUAbmlqdIp;gCa^^c1IInhI<1BDqTisn15nug#RYY2W^I_*B&MN1l&c~dO zJAKX-;&-leRy+Mt?|j1fr1S628s}5aRnFDUT6xm>v^*g{IiGQ^an?DXbw1~O-dQit zI$vRjhs?+iFMI5#?*_&=kT63X!ompruG8dcIn?>dg=8fh}X0ds*d5d|gSz_L1-fsTQEH&>i z?=8SXA2ch?hs=k~N6aeoQS&kLanon6 zFjtz@rr&(R^gL<)-K;U6GFO?a&06zm^BHrES!X_LK4(5})|)SwFPblz4dz<&W%CuY z(R|fhXRbE`<_2@4*~x!ru*Y%_P5@0jnJ z?dE&tPV;@U!`x+lV18(Jnje`To1d6n=5CMqsri}NZGLXT8CPPS%+IO))Cey>qslsGA+xBv*In!QP$DcXe+@w#yZwI z&Pue7w@$E5w34hb)>!K#E7>~PI>j1irC6t0r&;5zRO@u>4C_qGWu0YBu+Fy9tclh+ z*11-?b)I#;HOb1bCRr(47E8Ci3&9pAJa;#a_ zY-^5{>#?q|=2}-;dDc8@zIBzAZ!NH{wyv=XtZS`>)^%2)wa8j*U2hdxH&{1XH(ABj z&DJf}tyYP3n{~VOH>=dT!@ASD%PO<(w(hY!R=IVrwZvL#d97vEa_c^;!n)sjzvh^wjQyntVgZKtj8^%wZd9yRa+jv^@R1L^>?erddga5t+r~dr>$qKHCCPVto5Ar zyj5?#V7+L)WHnf8t(UD=tVZiqYn`>;3RoMgjaHM@Y;Ce$vo>2T))wn^>kX^b+G=gH z-n4?&Th?~#ZL7`NVZCF$YqeYNSv#%wtqyCK^?~)F)oFcXeQbT=vAV3?)~D8IR=4%J zwa5Cx3Rz!TUs+#UJ=QnYUTdG#Ykg~dXMJz=SwC1mT0dF+*3Z^2*00up^_%s(^@lZR z{b}vD4p?F9FYBN+6en>?oEoRa>2Z!YBQ7E?GVYMLsJQ4jXWXH2hs7Np7ZZ0x+^D!C z<6`4X{y)zr#>K_Q9Tj(U+~~N3xMSjujXN$bG4A-d6Ie)!8xuD+?j+uPKYk|S;IUDs zUl4KIjf+yxI(=Hx&aDx14CUd2#e z*&Po{Lk@b~hdSWyFQXA$Gv&7ff_F&EFUCwHkfF zG&{xV7fhSdl>S{rR^%aei8E5qnAmjhFA)dTb0*r&@IUUho8i%ZHhBCWRhGMs9Yqj^ z1!ld&Rp0j2<)C)b&o88x_fpcoDdKoLQ5>x%CZA)648W^6PyPigTQ1b;01UG z2Rr~V7D7T$Q{TWA(XTr5Pk(=RO_$DYq#Ih>LaLTUwI06y{q%?D$lQf89p89z`rXs7 zZQbnJ(au8E&O)_2{`AM`_fNgd;{>%$)A7SUPanN_r9Vr@zfPOmFI|_)t5SJYsvTn| z)sC@~v+mfx+B~|ZAMWED&H3{+S|7R^m*efXn{Q5Dw-<8k>;+Xjch&Lm^UdbT9kS&} zHr3rf?*7q^LVvfT$Wiw9#X@VnKbLs;@m90Em8=~(Cd-i{H$l}lkmHgMzujtX9In0J z{Qc&(|0M+5qpDd{ErM!)ydIhlu1wS=S)`>Ti=b)|R4sz4MO3wJsZNLceRFT!AJfdG z&`eePuvD#?s@6gsWe+DlO6>Ju)C8B1l9MG9ei$NJVDk3|UNCc&+i)z6IC?0k!~JfE}ccoppe^4K%asxj%k1HQ%1B`qQFEfNXZHHoMAZSJ`r@ zY`IjnTq;{Gl`WUbmP=*JrLyHx*>b6Dxm31XD%(LUVSqQZS63?m4gd#$1Hb{`0B`^} z02}}g00)2rzyaU@a0EEA!4cl5yj9bT07rl$z!BgGa0EC490861M}Q;15ugARfC5n1 zpum%jw=O{d3P1rU00p1`6o3Ly01CheFanGKBftnSvcU*18gC5|U<4QeMt~7u1Q-EE zfC*p%m;fe#319-4046q=;3ar#0+;|MfC*p%m;g=yCx8>c31H?~=2_-h-k%XB6DAWT z6DF^u$)w4I$%M&-$%M&-DIf}n0-}H@APR^AqChAR3WNfoRPJ8^Q9x7>6+{J5K~xYG zLUlmIs!BR-D6cQ|j1WO^oQb@2A5-f!TOCiBhNU#(V3@E{X5-f$- z{9VN6uF3{lRUz5L)rz%k#%jfCHe9u0H5;yr*l<-LwhdRU$lI|>N5YPT9SJ!LVdkC- zhan7IVdx6eR+zTJv=yeUFl~itD@Sl_4B{eYd&y%)QUkHf8a{b?Z^V5rmclRRuqWEHQ#T0ze`(p5g_#*m3q3eIt$y2qsczE#zd9-+N{>jB& z_&ihbw&HEogQ~YxZ(C>Yo4s%LzB6w-^R_c@```I2-nKYfzC5|@pMP*ZEiU((J4e;x z@<_CBHh=cH_qN{KM!(vKZMF92(ffRla`ekZZ%cl;K=*MIw(eP6Y3 zd-Z+IzOPz1o9}D({nEnOe7{Oq-6o1}gcg@4Tzn(6xLi&PXY=2E8N6-qHg_XdDdK(N zeZCRJH$n?X^^GXL5n4E#zv5-up&xIzUn}SHCtUmqYvFAE;uL>zwAgINSMD_TPyPY$ Ci)~u~ delta 93489 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⁣(sv1Vs30uxuhW`g0THudJ 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 CuqfgH delta 38284 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