<commit_before>#pragma once

// `krbn::manipulator_timer` can be used safely in a multi-threaded environment.

#include "boost_defs.hpp"

#include "manipulator_object_id.hpp"
#include "thread_utility.hpp"
#include "time_utility.hpp"
#include "types.hpp"
#include <boost/signals2.hpp>
#include <deque>
#include <mach/mach_time.h>

namespace krbn {
namespace manipulator {
class manipulator_timer final {
public:
  manipulator_timer(bool timer_enabled = true) : timer_enabled_(timer_enabled) {
    dispatcher_ = std::make_unique<thread_utility::dispatcher>();
  }

  ~manipulator_timer(void) {
    dispatcher_->enqueue([this] {
      // Stop `timer_` gracefully without timer_->cancel().
      timer_ = nullptr;
      timer_when_ = boost::none;
    });

    dispatcher_->terminate();
    dispatcher_ = nullptr;
  }

  void enqueue(manipulator_object_id id,
               const std::function<void(void)>& function,
               absolute_time when) {
    dispatcher_->enqueue([this, id, function, when] {
      entries_.push_back(std::make_shared<entry>(id, function, when));

      std::stable_sort(std::begin(entries_),
                       std::end(entries_),
                       [](auto& a, auto& b) {
                         return a->get_when() < b->get_when();
                       });
    });
  }

  void async_erase(manipulator_object_id id,
                   const std::function<void(void)>& erased) {
    dispatcher_->enqueue([this, id, erased] {
      entries_.erase(std::remove_if(std::begin(entries_),
                                    std::end(entries_),
                                    [&](auto&& e) {
                                      return e->get_manipulator_object_id() == id;
                                    }),
                     std::end(entries_));

      erased();
    });
  }

  void async_erase(manipulator_object_id id) {
    async_erase(id, [] {});
  }

  void async_invoke(absolute_time now) {
    dispatcher_->enqueue([this, now] {
      invoke(now);
    });
  }

private:
  class entry final {
  public:
    entry(manipulator_object_id id,
          const std::function<void(void)>& function,
          absolute_time when) : manipulator_object_id_(id),
                                function_(function),
                                when_(when) {
    }

    manipulator_object_id get_manipulator_object_id(void) const {
      return manipulator_object_id_;
    }

    absolute_time get_when(void) const {
      return when_;
    }

    void call_function(void) const {
      function_();
    }

  private:
    manipulator_object_id manipulator_object_id_;
    std::function<void(void)> function_;
    absolute_time when_;
  };

  void set_timer(absolute_time now) {
    if (entries_.empty()) {
      if (timer_) {
        timer_->cancel();
        timer_ = nullptr;
      }
      return;
    }

    auto e = entries_.front();

    if (now < e->get_when()) {
      if (timer_enabled_) {
        // Skip if timer_ is active.

        if (timer_ &&
            timer_when_ &&
            *timer_when_ == e->get_when()) {
          return;
        }

        // Update timer_.

        if (timer_) {
          timer_->cancel();
          timer_ = nullptr;
        }

        timer_when_ = e->get_when();
        timer_ = std::make_unique<thread_utility::timer>(
            time_utility::to_milliseconds(e->get_when() - now),
            thread_utility::timer::mode::once,
            [this, e] {
              dispatcher_->enqueue([this, e] {
                timer_when_ = boost::none;
                invoke(e->get_when());
              });
            });
      }
    } else {
      if (timer_) {
        timer_->cancel();
        timer_ = nullptr;
      }

      invoke(now);
    }
  }

  void invoke(absolute_time now) {
    while (true) {
      if (entries_.empty()) {
        break;
      }

      auto e = entries_.front();

      if (now < e->get_when()) {
        break;
      }

      dispatcher_->enqueue([e] {
        e->call_function();
      });

      entries_.pop_front();
    }

    set_timer(now);
  }

  std::unique_ptr<thread_utility::dispatcher> dispatcher_;
  std::deque<std::shared_ptr<entry>> entries_;
  bool timer_enabled_;
  std::unique_ptr<thread_utility::timer> timer_;
  boost::optional<absolute_time> timer_when_;
};
} // namespace manipulator
} // namespace krbn
<commit_msg>update #include<commit_after>#pragma once

// `krbn::manipulator_timer` can be used safely in a multi-threaded environment.

#include "manipulator_object_id.hpp"
#include "thread_utility.hpp"
#include "time_utility.hpp"
#include "types.hpp"
#include <deque>

namespace krbn {
namespace manipulator {
class manipulator_timer final {
public:
  manipulator_timer(bool timer_enabled = true) : timer_enabled_(timer_enabled) {
    dispatcher_ = std::make_unique<thread_utility::dispatcher>();
  }

  ~manipulator_timer(void) {
    dispatcher_->enqueue([this] {
      // Stop `timer_` gracefully without timer_->cancel().
      timer_ = nullptr;
      timer_when_ = boost::none;
    });

    dispatcher_->terminate();
    dispatcher_ = nullptr;
  }

  void enqueue(manipulator_object_id id,
               const std::function<void(void)>& function,
               absolute_time when) {
    dispatcher_->enqueue([this, id, function, when] {
      entries_.push_back(std::make_shared<entry>(id, function, when));

      std::stable_sort(std::begin(entries_),
                       std::end(entries_),
                       [](auto& a, auto& b) {
                         return a->get_when() < b->get_when();
                       });
    });
  }

  void async_erase(manipulator_object_id id,
                   const std::function<void(void)>& erased) {
    dispatcher_->enqueue([this, id, erased] {
      entries_.erase(std::remove_if(std::begin(entries_),
                                    std::end(entries_),
                                    [&](auto&& e) {
                                      return e->get_manipulator_object_id() == id;
                                    }),
                     std::end(entries_));

      erased();
    });
  }

  void async_erase(manipulator_object_id id) {
    async_erase(id, [] {});
  }

  void async_invoke(absolute_time now) {
    dispatcher_->enqueue([this, now] {
      invoke(now);
    });
  }

private:
  class entry final {
  public:
    entry(manipulator_object_id id,
          const std::function<void(void)>& function,
          absolute_time when) : manipulator_object_id_(id),
                                function_(function),
                                when_(when) {
    }

    manipulator_object_id get_manipulator_object_id(void) const {
      return manipulator_object_id_;
    }

    absolute_time get_when(void) const {
      return when_;
    }

    void call_function(void) const {
      function_();
    }

  private:
    manipulator_object_id manipulator_object_id_;
    std::function<void(void)> function_;
    absolute_time when_;
  };

  void set_timer(absolute_time now) {
    if (entries_.empty()) {
      if (timer_) {
        timer_->cancel();
        timer_ = nullptr;
      }
      return;
    }

    auto e = entries_.front();

    if (now < e->get_when()) {
      if (timer_enabled_) {
        // Skip if timer_ is active.

        if (timer_ &&
            timer_when_ &&
            *timer_when_ == e->get_when()) {
          return;
        }

        // Update timer_.

        if (timer_) {
          timer_->cancel();
          timer_ = nullptr;
        }

        timer_when_ = e->get_when();
        timer_ = std::make_unique<thread_utility::timer>(
            time_utility::to_milliseconds(e->get_when() - now),
            thread_utility::timer::mode::once,
            [this, e] {
              dispatcher_->enqueue([this, e] {
                timer_when_ = boost::none;
                invoke(e->get_when());
              });
            });
      }
    } else {
      if (timer_) {
        timer_->cancel();
        timer_ = nullptr;
      }

      invoke(now);
    }
  }

  void invoke(absolute_time now) {
    while (true) {
      if (entries_.empty()) {
        break;
      }

      auto e = entries_.front();

      if (now < e->get_when()) {
        break;
      }

      dispatcher_->enqueue([e] {
        e->call_function();
      });

      entries_.pop_front();
    }

    set_timer(now);
  }

  std::unique_ptr<thread_utility::dispatcher> dispatcher_;
  std::deque<std::shared_ptr<entry>> entries_;
  bool timer_enabled_;
  std::unique_ptr<thread_utility::timer> timer_;
  boost::optional<absolute_time> timer_when_;
};
} // namespace manipulator
} // namespace krbn
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: SlsFocusManager.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: kz $ $Date: 2005-01-13 17:28:46 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef SD_SLIDESORTER_FOCUS_MANAGER_HXX
#define SD_SLIDESORTER_FOCUS_MANAGER_HXX

#include <sal/types.h>

namespace sd { namespace slidesorter { namespace model {
class PageDescriptor;
} } }

namespace sd { namespace slidesorter { namespace controller {

class SlideSorterController;

/** This class manages the focus of the slide sorter.  There is the focus
    page which is or is not focused.  Initialized to point to the first page
    it can be set to other pages by using the MoveFocus() method.  The
    focused state of the focus page can be toggled with the ToggleFocus()
    method.
*/
class FocusManager
{
public:
    /** Create a new focus manager that operates on the pages of the model
        associated with the given controller.  The focus page is set to the
        first page.  Focused state is off.
    */
    FocusManager (SlideSorterController& rController);

    ~FocusManager (void);

    enum FocusMoveDirection
    {
        FMD_NONE,
        FMD_LEFT,
        FMD_RIGHT,
        FMD_UP,
        FMD_DOWN
    };

    /** Move the focus from the currently focused page to one that is
        displayed adjacent to it, either vertically or horizontally.
        @param eDirection
            Direction in which to move the focus.  Wrap arround is done
            differently when moving vertically or horizontally.  Vertical
            wrap arround takes place in the same column, i.e. when you are
            in the top row and move up you come out in the bottom row in the
            same column.  Horizontal wrap arround moves to the next
            (FMD_RIGHT) or previous (FMD_LEFT) page.  Moving to the right
            from the last page goes to the first page and vice versa.
            When FMD_NONE is given, the current page index is checked for
            being valid.  If it is not, then it is set to the nearest valid
            page index.
    */
    void MoveFocus (FocusMoveDirection eDirection);

    /** Show the focus indicator of the current slide.
    */
    void ShowFocus (void);

    /** Hide the focus indicator.
    */
    void HideFocus (void);

    /** Toggle the focused state of the current slide.
        @return
            Returns the focused state of the focus page after the call.
    */
    bool ToggleFocus (void);

    /** Return whether the window managed by the called focus manager has
        the input focus of the application.
    */
    bool HasFocus (void) const;

    /** Return the descriptor of the page that currently has the focus.
        @return
            When there is no page that currently has the focus then NULL is
            returned.
    */
    model::PageDescriptor* GetFocusedPageDescriptor (void) const;

    /** Return the index of the page that currently has the focus as it is
        accepted by the slide sorter model.
        @return
            When there is no page that currently has the focus then -1 is
            returned.
    */
    sal_Int32 GetFocusedPageIndex (void) const;

    /** Set the focus to the page with the given index.  This does not make
        the focus visible.
        @param nPageIndex
            Index of a page as it is accepted by the slide sorter model.
            The index is not checked for validity.
    */
    void FocusPage (sal_Int32 nPageIndex);

    /** Return <TRUE/> when the focus inidcator is currently shown.  A
        prerequisite is that the window managed by this focus manager has
        the input focus as indicated by a <TRUE/> return value of
        HasFocus().  It is not necessary that the focus indicator is
        visible.  It may have been scrolled outside the visible area.
    */
    bool IsFocusShowing (void) const;

    /** Create an instance of this class to temporarily hide the focus
        indicator.  It is restored to its former visibility state when the
        FocusHider is destroyed.
    */
    class FocusHider
    {
    public:
        FocusHider (FocusManager&);
        ~FocusHider (void);
    private:
        bool mbFocusVisible;
        FocusManager& mrManager;
    };

private:
    /// The controller that is used for accessing the pages.
    SlideSorterController& mrController;

    /** Index of the page that may be focused.  It is -1 when the model
        contains no page.
    */
    sal_Int32 mnPageIndex;

    /** This flag indicates whether the page pointed to by mpFocusDescriptor
        has the focus.
    */
    bool mbPageIsFocused;

    /** Reset the focus state of the given descriptor and request a repaint
        so that the focus indicator is hidden.
        @param pDescriptor
            When NULL is given then the call is ignored.
    */
    void HideFocusIndicator (model::PageDescriptor* pDescriptor);

    /** Set the focus state of the given descriptor, scroll it into the
        visible area and request a repaint so that the focus indicator is
        made visible.
        @param pDescriptor
            When NULL is given then the call is ignored.
    */
    void ShowFocusIndicator (model::PageDescriptor* pDescriptor);
};

} } } // end of namespace ::sd::slidesorter::controller

#endif

<commit_msg>INTEGRATION: CWS impress29 (1.2.186); FILE MERGED 2005/01/13 10:18:45 af 1.2.186.1: #i32465# Added new SetFocusedPage() method in two variants.<commit_after>/*************************************************************************
 *
 *  $RCSfile: SlsFocusManager.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2005-01-25 15:34:40 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef SD_SLIDESORTER_FOCUS_MANAGER_HXX
#define SD_SLIDESORTER_FOCUS_MANAGER_HXX

#include <sal/types.h>

namespace sd { namespace slidesorter { namespace model {
class PageDescriptor;
} } }

namespace sd { namespace slidesorter { namespace controller {

class SlideSorterController;

/** This class manages the focus of the slide sorter.  There is the focus
    page which is or is not focused.  Initialized to point to the first page
    it can be set to other pages by using the MoveFocus() method.  The
    focused state of the focus page can be toggled with the ToggleFocus()
    method.
*/
class FocusManager
{
public:
    /** Create a new focus manager that operates on the pages of the model
        associated with the given controller.  The focus page is set to the
        first page.  Focused state is off.
    */
    FocusManager (SlideSorterController& rController);

    ~FocusManager (void);

    enum FocusMoveDirection
    {
        FMD_NONE,
        FMD_LEFT,
        FMD_RIGHT,
        FMD_UP,
        FMD_DOWN
    };

    /** Move the focus from the currently focused page to one that is
        displayed adjacent to it, either vertically or horizontally.
        @param eDirection
            Direction in which to move the focus.  Wrap arround is done
            differently when moving vertically or horizontally.  Vertical
            wrap arround takes place in the same column, i.e. when you are
            in the top row and move up you come out in the bottom row in the
            same column.  Horizontal wrap arround moves to the next
            (FMD_RIGHT) or previous (FMD_LEFT) page.  Moving to the right
            from the last page goes to the first page and vice versa.
            When FMD_NONE is given, the current page index is checked for
            being valid.  If it is not, then it is set to the nearest valid
            page index.
    */
    void MoveFocus (FocusMoveDirection eDirection);

    /** Show the focus indicator of the current slide.
    */
    void ShowFocus (void);

    /** Hide the focus indicator.
    */
    void HideFocus (void);

    /** Toggle the focused state of the current slide.
        @return
            Returns the focused state of the focus page after the call.
    */
    bool ToggleFocus (void);

    /** Return whether the window managed by the called focus manager has
        the input focus of the application.
    */
    bool HasFocus (void) const;

    /** Return the descriptor of the page that currently has the focus.
        @return
            When there is no page that currently has the focus then NULL is
            returned.
    */
    model::PageDescriptor* GetFocusedPageDescriptor (void) const;

    /** Return the index of the page that currently has the focus as it is
        accepted by the slide sorter model.
        @return
            When there is no page that currently has the focus then -1 is
            returned.
    */
    sal_Int32 GetFocusedPageIndex (void) const;

    /** DEPRECATED. (Use equivalent SetFocusedPage(sal_Int32) instead.

        Set the focus to the page with the given index.  This does not make
        the focus visible.
        @param nPageIndex
            Index of a page as it is accepted by the slide sorter model.
            The index is not checked for validity.
    */
    void FocusPage (sal_Int32 nPageIndex);

    /** Set the focused page to the one described by the given page
        descriptor.  The visibility of the focus indicator is not modified.
        @param rDescriptor
            One of the page descriptors that are currently managed by the
            SlideSorterModel.
    */
    void SetFocusedPage (const model::PageDescriptor& rDescriptor);

    /** Set the focused page to the one described by the given page
        index.  The visibility of the focus indicator is not modified.
        @param nPageIndex
            A valid page index that is understood by the SlideSorterModel.
    */
    void SetFocusedPage (sal_Int32 nPageIndex);

    /** Return <TRUE/> when the focus inidcator is currently shown.  A
        prerequisite is that the window managed by this focus manager has
        the input focus as indicated by a <TRUE/> return value of
        HasFocus().  It is not necessary that the focus indicator is
        visible.  It may have been scrolled outside the visible area.
    */
    bool IsFocusShowing (void) const;

    /** Create an instance of this class to temporarily hide the focus
        indicator.  It is restored to its former visibility state when the
        FocusHider is destroyed.
    */
    class FocusHider
    {
    public:
        FocusHider (FocusManager&);
        ~FocusHider (void);
    private:
        bool mbFocusVisible;
        FocusManager& mrManager;
    };

private:
    /// The controller that is used for accessing the pages.
    SlideSorterController& mrController;

    /** Index of the page that may be focused.  It is -1 when the model
        contains no page.
    */
    sal_Int32 mnPageIndex;

    /** This flag indicates whether the page pointed to by mpFocusDescriptor
        has the focus.
    */
    bool mbPageIsFocused;

    /** Reset the focus state of the given descriptor and request a repaint
        so that the focus indicator is hidden.
        @param pDescriptor
            When NULL is given then the call is ignored.
    */
    void HideFocusIndicator (model::PageDescriptor* pDescriptor);

    /** Set the focus state of the given descriptor, scroll it into the
        visible area and request a repaint so that the focus indicator is
        made visible.
        @param pDescriptor
            When NULL is given then the call is ignored.
    */
    void ShowFocusIndicator (model::PageDescriptor* pDescriptor);
};

} } } // end of namespace ::sd::slidesorter::controller

#endif

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: RecentlyUsedMasterPages.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: kz $ $Date: 2006-04-26 20:53:11 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef SD_TOOLPANEL_CONTROLS_RECENTLY_USED_MASTER_PAGES_HXX
#define SD_TOOLPANEL_CONTROLS_RECENTLY_USED_MASTER_PAGES_HXX

#include "tools/SdGlobalResourceContainer.hxx"
#include <osl/mutex.hxx>
#include <tools/link.hxx>
#include <vcl/image.hxx>
#include <vector>
#include <tools/string.hxx>

#include "DrawDocShell.hxx"
#include "MasterPageContainer.hxx"

#ifndef _COM_SUN_STAR_UNO_XINTERFACE_HPP_
#include <com/sun/star/uno/XInterface.hpp>
#endif

class SdPage;

namespace sd {
class MasterPageObserverEvent;
}

namespace sd { namespace toolpanel { namespace controls {

/** This singleton holds a list of the most recently used master pages.
*/
class RecentlyUsedMasterPages
    : public SdGlobalResource
{
public:
    /** Return the single instance of this class.
    */
    static RecentlyUsedMasterPages& Instance (void);

    void AddEventListener (const Link& rEventListener);
    void RemoveEventListener (const Link& rEventListener);

    int GetMasterPageCount (void) const;
    MasterPageContainer::Token GetTokenForIndex (sal_uInt32 nIndex) const;

private:
    /** The single instance of this class.  It is created on demand when
        Instance() is called for the first time.
    */
    static RecentlyUsedMasterPages* mpInstance;

    ::std::vector<Link> maListeners;

    class MasterPageList;
    ::std::auto_ptr<MasterPageList> mpMasterPages;
    unsigned long int mnMaxListSize;
    ::boost::shared_ptr<MasterPageContainer> mpContainer;

    RecentlyUsedMasterPages (void);
    virtual ~RecentlyUsedMasterPages (void);

    /** Call this method after a new object has been created.
    */
    void LateInit (void);

    /// The copy constructor is not implemented.  Do not use!
    RecentlyUsedMasterPages (const RecentlyUsedMasterPages&);

    /// The assignment operator is not implemented.  Do not use!
    RecentlyUsedMasterPages& operator= (const RecentlyUsedMasterPages&);

    void SendEvent (void);
    DECL_LINK(MasterPageChangeListener, MasterPageObserverEvent*);
    DECL_LINK(MasterPageContainerChangeListener, MasterPageContainerChangeEvent*);

    /** Add a descriptor for the specified master page to the end of the
        list of most recently used master pages.  When the page is already a
        member of that list the associated descriptor is moved to the end of
        the list to make it the most recently used entry.
        @param bMakePersistent
            When <TRUE/> is given then the new list of recently used master
            pages is written back into the configuration to make it
            persistent.  Giving <FALSE/> to ommit this is used while loading
            the persistent list from the configuration.
    */
    void AddMasterPage (
        MasterPageContainer::Token aToken,
        bool bMakePersistent = true);

    /** Load the list of recently used master pages from the registry where
        it was saved to make it persistent.
    */
    void LoadPersistentValues (void);

    /** Save the list of recently used master pages to the registry to make
        it presistent.
    */
    void SavePersistentValues (void);

    ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface>
        OpenConfiguration (
            const ::rtl::OUString& rsRootName,
            bool bReadOnly);
    ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface>
        GetConfigurationNode (
            const ::com::sun::star::uno::Reference<
            ::com::sun::star::uno::XInterface>& xRoot,
          const ::rtl::OUString& sPathToNode);

    void ResolveList (void);
};

} } } // end of namespace ::sd::toolpanel::controls

#endif
<commit_msg>INTEGRATION: CWS components1 (1.7.52); FILE MERGED 2006/08/22 12:26:19 af 1.7.52.1: #i68075# Moved configuration handling to new ConfigurationAccess class.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: RecentlyUsedMasterPages.hxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: rt $ $Date: 2007-04-03 16:23:04 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef SD_TOOLPANEL_CONTROLS_RECENTLY_USED_MASTER_PAGES_HXX
#define SD_TOOLPANEL_CONTROLS_RECENTLY_USED_MASTER_PAGES_HXX

#include "tools/SdGlobalResourceContainer.hxx"
#include <osl/mutex.hxx>
#include <tools/link.hxx>
#include <vcl/image.hxx>
#include <vector>
#include <tools/string.hxx>

#include "DrawDocShell.hxx"
#include "MasterPageContainer.hxx"

#ifndef _COM_SUN_STAR_UNO_XINTERFACE_HPP_
#include <com/sun/star/uno/XInterface.hpp>
#endif

class SdPage;

namespace sd {
class MasterPageObserverEvent;
}

namespace sd { namespace toolpanel { namespace controls {

/** This singleton holds a list of the most recently used master pages.
*/
class RecentlyUsedMasterPages
    : public SdGlobalResource
{
public:
    /** Return the single instance of this class.
    */
    static RecentlyUsedMasterPages& Instance (void);

    void AddEventListener (const Link& rEventListener);
    void RemoveEventListener (const Link& rEventListener);

    int GetMasterPageCount (void) const;
    MasterPageContainer::Token GetTokenForIndex (sal_uInt32 nIndex) const;

private:
    /** The single instance of this class.  It is created on demand when
        Instance() is called for the first time.
    */
    static RecentlyUsedMasterPages* mpInstance;

    ::std::vector<Link> maListeners;

    class MasterPageList;
    ::std::auto_ptr<MasterPageList> mpMasterPages;
    unsigned long int mnMaxListSize;
    ::boost::shared_ptr<MasterPageContainer> mpContainer;

    RecentlyUsedMasterPages (void);
    virtual ~RecentlyUsedMasterPages (void);

    /** Call this method after a new object has been created.
    */
    void LateInit (void);

    /// The copy constructor is not implemented.  Do not use!
    RecentlyUsedMasterPages (const RecentlyUsedMasterPages&);

    /// The assignment operator is not implemented.  Do not use!
    RecentlyUsedMasterPages& operator= (const RecentlyUsedMasterPages&);

    void SendEvent (void);
    DECL_LINK(MasterPageChangeListener, MasterPageObserverEvent*);
    DECL_LINK(MasterPageContainerChangeListener, MasterPageContainerChangeEvent*);

    /** Add a descriptor for the specified master page to the end of the
        list of most recently used master pages.  When the page is already a
        member of that list the associated descriptor is moved to the end of
        the list to make it the most recently used entry.
        @param bMakePersistent
            When <TRUE/> is given then the new list of recently used master
            pages is written back into the configuration to make it
            persistent.  Giving <FALSE/> to ommit this is used while loading
            the persistent list from the configuration.
    */
    void AddMasterPage (
        MasterPageContainer::Token aToken,
        bool bMakePersistent = true);

    /** Load the list of recently used master pages from the registry where
        it was saved to make it persistent.
    */
    void LoadPersistentValues (void);

    /** Save the list of recently used master pages to the registry to make
        it presistent.
    */
    void SavePersistentValues (void);

    void ResolveList (void);
};

} } } // end of namespace ::sd::toolpanel::controls

#endif
<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file LexLua.cxx
 ** Lexer for Lua language.
 **
 ** Written by Paul Winwood.
 ** Folder by Alexey Yutkin.
 **/

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <fcntl.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

inline bool isLuaOperator(char ch) {
	if (isalnum(ch))
		return false;
	// '.' left out as it is used to make up numbers
	if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
	        ch == '(' || ch == ')' || ch == '=' ||
	        ch == '{' || ch == '}' || ch == '~' ||
	        ch == '[' || ch == ']' || ch == ';' ||
	        ch == '<' || ch == '>' || ch == ',' ||
	        ch == '.' || ch == '^' || ch == '%' || ch == ':')
		return true;
	return false;
}

static void classifyWordLua(unsigned int start,
                            unsigned int end,
                            WordList	&keywords,
                            Accessor	&styler) {
	char s[100];
	bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');

	for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
		s[i] = styler[start + i];
		s[i + 1] = '\0';
	}

	char chAttr = SCE_LUA_IDENTIFIER;

	if (wordIsNumber)
		chAttr = SCE_LUA_NUMBER;
	else {
		if (keywords.InList(s)) {
			chAttr = SCE_LUA_WORD;
		}
	}
	styler.ColourTo(end, chAttr);
}

static void ColouriseLuaDoc(unsigned int startPos,
                            int length,
                            int initStyle,
                            WordList *keywordlists[],
                            Accessor &styler) {

	WordList &keywords = *keywordlists[0];

	styler.StartAt(startPos);
	styler.GetLine(startPos);

	int state = initStyle;
	char chPrev = ' ';
	char chNext = styler[startPos];
	unsigned int lengthDoc = startPos + length;
	bool firstChar = true;
	int literalString = 0;

	styler.StartSegment(startPos);
	for (unsigned int i = startPos; i <= lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		if (styler.IsLeadByte(ch)) {
			chNext = styler.SafeGetCharAt(i + 2);
			chPrev = ' ';
			i += 1;
			continue;
		}

		if (state == SCE_LUA_STRINGEOL) {
			if (ch != '\r' && ch != '\n') {
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_DEFAULT;
			}
		}

		if (state == SCE_LUA_LITERALSTRING && ch == '[' && chNext == '[') {
			literalString++;
		} else if (state == SCE_LUA_DEFAULT) {
			if (ch == '-' && chNext == '-') {
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_COMMENTLINE;
			} else if (ch == '[' && chNext == '[') {
				state = SCE_LUA_LITERALSTRING;
				literalString = 1;
			} else if (ch == '\"') {
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_STRING;
			} else if (ch == '\'') {
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_CHARACTER;
			} else if (ch == '$' && firstChar) {
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_PREPROCESSOR;
			} else if (ch == '#' && firstChar)	// Should be only on the first line of the file! Cannot be tested here
			{
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_COMMENTLINE;
			} else if (isLuaOperator(ch)) {
				styler.ColourTo(i - 1, state);
				styler.ColourTo(i, SCE_LUA_OPERATOR);
			} else if (iswordstart(ch)) {
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_WORD;
			}
		} else if (state == SCE_LUA_WORD) {
			if (!iswordchar(ch)) {
				classifyWordLua(styler.GetStartSegment(), i - 1, keywords, styler);
				state = SCE_LUA_DEFAULT;
				if (ch == '[' && chNext == '[') {
					literalString = 1;
					state = SCE_LUA_LITERALSTRING;
				} else if (ch == '-' && chNext == '-') {
					state = SCE_LUA_COMMENTLINE;
				} else if (ch == '\"') {
					state = SCE_LUA_STRING;
				} else if (ch == '\'') {
					state = SCE_LUA_CHARACTER;
				} else if (ch == '$' && firstChar) {
					state = SCE_LUA_PREPROCESSOR;
				} else if (isLuaOperator(ch)) {
					styler.ColourTo(i, SCE_LUA_OPERATOR);
				}
			} else if (ch == '.' && chNext == '.') {
				classifyWordLua(styler.GetStartSegment(), i - 1, keywords, styler);
				styler.ColourTo(i, SCE_LUA_OPERATOR);
				state = SCE_LUA_DEFAULT;
			}
		} else {
			if (state == SCE_LUA_LITERALSTRING) {
				if (ch == ']' && (chPrev == ']') && (--literalString == 0)) {
					styler.ColourTo(i, state);
					state = SCE_LUA_DEFAULT;
				}
			} else if (state == SCE_LUA_PREPROCESSOR) {
				if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
					styler.ColourTo(i - 1, state);
					state = SCE_LUA_DEFAULT;
				}
			} else if (state == SCE_LUA_COMMENTLINE) {
				if (ch == '\r' || ch == '\n') {
					styler.ColourTo(i - 1, state);
					state = SCE_LUA_DEFAULT;
				}
			} else if (state == SCE_LUA_STRING) {
				if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
					styler.ColourTo(i - 1, state);
					state = SCE_LUA_STRINGEOL;
				} else if (ch == '\\') {
					if (chNext == '\"' || chNext == '\\') {
						i++;
						ch = chNext;
						chNext = styler.SafeGetCharAt(i + 1);
					}
				} else if (ch == '\"') {
					styler.ColourTo(i, state);
					state = SCE_LUA_DEFAULT;
					i++;
					ch = chNext;
					chNext = styler.SafeGetCharAt(i + 1);
				}
			} else if (state == SCE_LUA_CHARACTER) {
				if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
					styler.ColourTo(i - 1, state);
					state = SCE_LUA_STRINGEOL;
				} else if (ch == '\\') {
					if (chNext == '\'' || chNext == '\\') {
						i++;
						ch = chNext;
						chNext = styler.SafeGetCharAt(i + 1);
					}
				} else if (ch == '\'') {
					styler.ColourTo(i, state);
					state = SCE_LUA_DEFAULT;
					i++;
					ch = chNext;
					chNext = styler.SafeGetCharAt(i + 1);
				}
			}

			if (state == SCE_LUA_DEFAULT) {
				if (ch == '-' && chNext == '-') {
					state = SCE_LUA_COMMENTLINE;
				} else if (ch == '\"') {
					state = SCE_LUA_STRING;
				} else if (ch == '\'') {
					state = SCE_LUA_CHARACTER;
				} else if (ch == '$' && firstChar) {
					state = SCE_LUA_PREPROCESSOR;
				} else if (iswordstart(ch)) {
					state = SCE_LUA_WORD;
				} else if (isLuaOperator(ch)) {
					styler.ColourTo(i, SCE_LUA_OPERATOR);
				}
			}
		}
		chPrev = ch;
		firstChar = (ch == '\r' || ch == '\n');
	}
	styler.ColourTo(lengthDoc - 1, state);
}

static void FoldLuaDoc(unsigned int startPos, int length, int initStyle, WordList *[],
                       Accessor &styler) {
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	int style = initStyle;
	char s[10];
	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (style == SCE_LUA_WORD)
			if ( ch == 'e' || ch == 't' || ch == 'd' || ch == 'f') {
				for (unsigned int j = 0; j < 8; j++) {
					if (!iswordchar(styler[i + j])) break;
					s[j] = styler[i + j];
					s[j + 1] = '\0';
				}

				if ((strcmp(s, "then") == 0) || (strcmp(s, "do") == 0)
				        || (strcmp(s, "function") == 0))
					levelCurrent++;
				if (strcmp(s, "end") == 0) levelCurrent--;
			}

		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

LexerModule lmLua(SCLEX_LUA, ColouriseLuaDoc, "lua", FoldLuaDoc);
<commit_msg>Simplified because of warnings.<commit_after>// Scintilla source code edit control
/** @file LexLua.cxx
 ** Lexer for Lua language.
 **
 ** Written by Paul Winwood.
 ** Folder by Alexey Yutkin.
 **/

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <fcntl.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

inline bool isLuaOperator(char ch) {
	if (isalnum(ch))
		return false;
	// '.' left out as it is used to make up numbers
	if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
	        ch == '(' || ch == ')' || ch == '=' ||
	        ch == '{' || ch == '}' || ch == '~' ||
	        ch == '[' || ch == ']' || ch == ';' ||
	        ch == '<' || ch == '>' || ch == ',' ||
	        ch == '.' || ch == '^' || ch == '%' || ch == ':')
		return true;
	return false;
}

static void classifyWordLua(unsigned int start,
                            unsigned int end,
                            WordList	&keywords,
                            Accessor	&styler) {
	char s[100];
	bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');

	for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
		s[i] = styler[start + i];
		s[i + 1] = '\0';
	}

	char chAttr = SCE_LUA_IDENTIFIER;

	if (wordIsNumber)
		chAttr = SCE_LUA_NUMBER;
	else {
		if (keywords.InList(s)) {
			chAttr = SCE_LUA_WORD;
		}
	}
	styler.ColourTo(end, chAttr);
}

static void ColouriseLuaDoc(unsigned int startPos,
                            int length,
                            int initStyle,
                            WordList *keywordlists[],
                            Accessor &styler) {

	WordList &keywords = *keywordlists[0];

	styler.StartAt(startPos);
	styler.GetLine(startPos);

	int state = initStyle;
	char chPrev = ' ';
	char chNext = styler[startPos];
	unsigned int lengthDoc = startPos + length;
	bool firstChar = true;
	int literalString = 0;

	styler.StartSegment(startPos);
	for (unsigned int i = startPos; i <= lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		if (styler.IsLeadByte(ch)) {
			chNext = styler.SafeGetCharAt(i + 2);
			chPrev = ' ';
			i += 1;
			continue;
		}

		if (state == SCE_LUA_STRINGEOL) {
			if (ch != '\r' && ch != '\n') {
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_DEFAULT;
			}
		}

		if (state == SCE_LUA_LITERALSTRING && ch == '[' && chNext == '[') {
			literalString++;
		} else if (state == SCE_LUA_DEFAULT) {
			if (ch == '-' && chNext == '-') {
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_COMMENTLINE;
			} else if (ch == '[' && chNext == '[') {
				state = SCE_LUA_LITERALSTRING;
				literalString = 1;
			} else if (ch == '\"') {
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_STRING;
			} else if (ch == '\'') {
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_CHARACTER;
			} else if (ch == '$' && firstChar) {
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_PREPROCESSOR;
			} else if (ch == '#' && firstChar)	// Should be only on the first line of the file! Cannot be tested here
			{
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_COMMENTLINE;
			} else if (isLuaOperator(ch)) {
				styler.ColourTo(i - 1, state);
				styler.ColourTo(i, SCE_LUA_OPERATOR);
			} else if (iswordstart(ch)) {
				styler.ColourTo(i - 1, state);
				state = SCE_LUA_WORD;
			}
		} else if (state == SCE_LUA_WORD) {
			if (!iswordchar(ch)) {
				classifyWordLua(styler.GetStartSegment(), i - 1, keywords, styler);
				state = SCE_LUA_DEFAULT;
				if (ch == '[' && chNext == '[') {
					literalString = 1;
					state = SCE_LUA_LITERALSTRING;
				} else if (ch == '-' && chNext == '-') {
					state = SCE_LUA_COMMENTLINE;
				} else if (ch == '\"') {
					state = SCE_LUA_STRING;
				} else if (ch == '\'') {
					state = SCE_LUA_CHARACTER;
				} else if (ch == '$' && firstChar) {
					state = SCE_LUA_PREPROCESSOR;
				} else if (isLuaOperator(ch)) {
					styler.ColourTo(i, SCE_LUA_OPERATOR);
				}
			} else if (ch == '.' && chNext == '.') {
				classifyWordLua(styler.GetStartSegment(), i - 1, keywords, styler);
				styler.ColourTo(i, SCE_LUA_OPERATOR);
				state = SCE_LUA_DEFAULT;
			}
		} else {
			if (state == SCE_LUA_LITERALSTRING) {
				if (ch == ']' && (chPrev == ']') && (--literalString == 0)) {
					styler.ColourTo(i, state);
					state = SCE_LUA_DEFAULT;
				}
			} else if (state == SCE_LUA_PREPROCESSOR) {
				if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
					styler.ColourTo(i - 1, state);
					state = SCE_LUA_DEFAULT;
				}
			} else if (state == SCE_LUA_COMMENTLINE) {
				if (ch == '\r' || ch == '\n') {
					styler.ColourTo(i - 1, state);
					state = SCE_LUA_DEFAULT;
				}
			} else if (state == SCE_LUA_STRING) {
				if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
					styler.ColourTo(i - 1, state);
					state = SCE_LUA_STRINGEOL;
				} else if (ch == '\\') {
					if (chNext == '\"' || chNext == '\\') {
						i++;
						ch = chNext;
						chNext = styler.SafeGetCharAt(i + 1);
					}
				} else if (ch == '\"') {
					styler.ColourTo(i, state);
					state = SCE_LUA_DEFAULT;
					i++;
					ch = chNext;
					chNext = styler.SafeGetCharAt(i + 1);
				}
			} else if (state == SCE_LUA_CHARACTER) {
				if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
					styler.ColourTo(i - 1, state);
					state = SCE_LUA_STRINGEOL;
				} else if (ch == '\\') {
					if (chNext == '\'' || chNext == '\\') {
						i++;
						ch = chNext;
						chNext = styler.SafeGetCharAt(i + 1);
					}
				} else if (ch == '\'') {
					styler.ColourTo(i, state);
					state = SCE_LUA_DEFAULT;
					i++;
					ch = chNext;
					chNext = styler.SafeGetCharAt(i + 1);
				}
			}

			if (state == SCE_LUA_DEFAULT) {
				if (ch == '-' && chNext == '-') {
					state = SCE_LUA_COMMENTLINE;
				} else if (ch == '\"') {
					state = SCE_LUA_STRING;
				} else if (ch == '\'') {
					state = SCE_LUA_CHARACTER;
				} else if (ch == '$' && firstChar) {
					state = SCE_LUA_PREPROCESSOR;
				} else if (iswordstart(ch)) {
					state = SCE_LUA_WORD;
				} else if (isLuaOperator(ch)) {
					styler.ColourTo(i, SCE_LUA_OPERATOR);
				}
			}
		}
		chPrev = ch;
		firstChar = (ch == '\r' || ch == '\n');
	}
	styler.ColourTo(lengthDoc - 1, state);
}

static void FoldLuaDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
                       Accessor &styler) {
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	int styleNext = styler.StyleAt(startPos);
	char s[10];
	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (style == SCE_LUA_WORD)
			if ( ch == 'e' || ch == 't' || ch == 'd' || ch == 'f') {
				for (unsigned int j = 0; j < 8; j++) {
					if (!iswordchar(styler[i + j])) break;
					s[j] = styler[i + j];
					s[j + 1] = '\0';
				}

				if ((strcmp(s, "then") == 0) || (strcmp(s, "do") == 0)
				        || (strcmp(s, "function") == 0))
					levelCurrent++;
				if (strcmp(s, "end") == 0) levelCurrent--;
			}

		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

LexerModule lmLua(SCLEX_LUA, ColouriseLuaDoc, "lua", FoldLuaDoc);
<|endoftext|>


<commit_before>#include "RenderingSystem.h"
#include "../Components/TransformComponent.h"
#include "../Components/CameraComponent.h"
#include "../Components/ModelComponent.h"
#include "../../Rendering/RenderSurface.h"
#include "../../Rendering/Camera.h"
#include "../../Rendering/Mesh.h"
#include "../../Rendering/Model.h"
#include "../../Rendering/VertexBuffer.h"
#include "../../Rendering/IndexBuffer.h"
#include "../../Rendering/Program.h"
#include "../../Rendering/Texture.h"
#include "../../Rendering/Material.h"

void updateLodData(LodData& lodData, std::size_t totalLods, float minDist, float maxDist, float transTime, float distanceToCamera, float dt)
{
	if (totalLods == 1)
		return;

	totalLods -= 1;
	if (totalLods < 0)
		totalLods = 0;

	const float factor = 1.0f - math::clamp((maxDist - distanceToCamera) / (maxDist - minDist), 0.0f, 1.0f);
	const int lod = (int)math::lerp(0.0f, static_cast<float>(totalLods), factor);
	if (lodData.targetLodIndex != lod && lodData.targetLodIndex == lodData.currentLodIndex)
		lodData.targetLodIndex = lod;

	if (lodData.currentLodIndex != lodData.targetLodIndex)
		lodData.currentTime += dt;

	if (lodData.currentTime >= transTime)
	{
		lodData.currentLodIndex = lodData.targetLodIndex;
		lodData.currentTime = 0.0f;
	}
}

void RenderingSystem::frameRender(EntityManager &entities, EventManager &events, TimeDelta dt)
{
	entities.each<CameraComponent>([this, &entities, dt](
		Entity ce,
		CameraComponent& cameraComponent
		)
	{
		const auto gBufferSurface = cameraComponent.getGBufferSurface();
		const auto camera = cameraComponent.getCamera();
		const auto viewId = gBufferSurface->getId();
		auto& cameraLods = mLodDataMap[ce];

		{
			RenderSurfaceScope surfaceScope(gBufferSurface);
			gBufferSurface->clear();

			gfx::setViewTransform(viewId, &camera->getView(), &camera->getProj());

			entities.each<TransformComponent, ModelComponent>([this, &cameraLods, camera, dt, viewId](
				Entity e,
				TransformComponent& transformComponent,
				ModelComponent& modelComponent
				)
			{
				const auto& model = modelComponent.getModel();
				if (!model.isValid())
					return;

				const auto& worldTransform = transformComponent.getTransform();
				const auto clip_planes = math::vec2(camera->getNearClip(), camera->getFarClip());

				auto& lodData = cameraLods[e];
				const auto transitionTime = model.getTransitionTime();
				const auto minDistance = model.getMinDistance();
				const auto maxDistance = model.getMaxDistance();
				const auto lodCount = model.getLods().size();
				const auto currentTime = lodData.currentTime;
				const auto currentLodIndex = lodData.currentLodIndex;
				const auto targetLodIndex = lodData.targetLodIndex;

				auto material = model.getMaterialForGroup({});
				if (!material)
					return;

				const auto hMeshCurr = model.getLod(currentLodIndex);
				if (!hMeshCurr)
					return;

				const auto& frustum = camera->getFrustum();
				const auto& bounds = hMeshCurr->aabb;

				float t = 0;
				const auto rayOrigin = camera->getPosition();
				const auto invWorld = math::inverse(worldTransform);
				const auto objectRayOrigin = invWorld.transformCoord(rayOrigin);
				const auto objectRayDirection = math::normalize(bounds.getCenter() - objectRayOrigin);
				bounds.intersect(objectRayOrigin, objectRayDirection, t);

				// Compute final object space intersection point.
				auto intersectionPoint = objectRayOrigin + (objectRayDirection * t);

				// transform intersection point back into world space to compute
				// the final intersection distance.
				intersectionPoint = worldTransform.transformCoord(intersectionPoint);
				const float distance = math::length(intersectionPoint - rayOrigin);
				updateLodData(
					lodData,
					lodCount,
					minDistance,
					maxDistance,
					transitionTime,
					distance,
					dt);
				// Test the bounding box of the mesh
				if (!math::frustum::testOBB(frustum, bounds, worldTransform))
					return;

				const auto params = math::vec3{
					0.0f,
					-1.0f,
					(transitionTime - currentTime) / transitionTime
				};

				const auto paramsInv = math::vec3{
					1.0f,
					1.0f,
					currentTime / transitionTime
				};

				material->setUniform("u_camera_wpos", &camera->getPosition());
				material->setUniform("u_camera_clip_planes", &clip_planes);
				material->setUniform("u_lod_params", &params);
				material->submit();

				// Set render states.
				const auto states = material->getRenderStates();

				auto program = material->getProgram();

				hMeshCurr->submit(viewId, program->handle, worldTransform, states);

				if (currentTime != 0.0f)
				{
					material->setUniform("u_lod_params", &paramsInv);
					material->submit();

					const auto hMeshTarget = model.getLod(targetLodIndex);
					if (!hMeshTarget)
						return;
					hMeshTarget->submit(viewId, program->handle, worldTransform, states);
				}

			});

		}

		{
			auto surface = cameraComponent.getRenderSurface();
			RenderSurfaceScope scope(surface);

			//this will change soon
		}

	});

}

void RenderingSystem::receive(const EntityDestroyedEvent &event)
{
	mLodDataMap.erase(event.entity);
	for (auto& pair : mLodDataMap)
	{
		pair.second.erase(event.entity);
	}
}

void RenderingSystem::configure(EventManager &events)
{
	events.subscribe<EntityDestroyedEvent>(*this);
}
<commit_msg>cleanup<commit_after>#include "RenderingSystem.h"
#include "../Components/TransformComponent.h"
#include "../Components/CameraComponent.h"
#include "../Components/ModelComponent.h"
#include "../../Rendering/RenderSurface.h"
#include "../../Rendering/Camera.h"
#include "../../Rendering/Mesh.h"
#include "../../Rendering/Model.h"
#include "../../Rendering/VertexBuffer.h"
#include "../../Rendering/IndexBuffer.h"
#include "../../Rendering/Program.h"
#include "../../Rendering/Texture.h"
#include "../../Rendering/Material.h"

void updateLodData(LodData& lodData, std::size_t totalLods, float minDist, float maxDist, float transTime, float distanceToCamera, float dt)
{
	if (totalLods == 1)
		return;

	totalLods -= 1;
	if (totalLods < 0)
		totalLods = 0;

	const float factor = 1.0f - math::clamp((maxDist - distanceToCamera) / (maxDist - minDist), 0.0f, 1.0f);
	const int lod = (int)math::lerp(0.0f, static_cast<float>(totalLods), factor);
	if (lodData.targetLodIndex != lod && lodData.targetLodIndex == lodData.currentLodIndex)
		lodData.targetLodIndex = lod;

	if (lodData.currentLodIndex != lodData.targetLodIndex)
		lodData.currentTime += dt;

	if (lodData.currentTime >= transTime)
	{
		lodData.currentLodIndex = lodData.targetLodIndex;
		lodData.currentTime = 0.0f;
	}
}

void RenderingSystem::frameRender(EntityManager &entities, EventManager &events, TimeDelta dt)
{
	entities.each<CameraComponent>([this, &entities, dt](
		Entity ce,
		CameraComponent& cameraComponent
		)
	{
		const auto gBufferSurface = cameraComponent.getGBufferSurface();
		const auto camera = cameraComponent.getCamera();
		const auto viewId = gBufferSurface->getId();
		auto& cameraLods = mLodDataMap[ce];

		{
			RenderSurfaceScope surfaceScope(gBufferSurface);
			gBufferSurface->clear();

			gfx::setViewTransform(viewId, &camera->getView(), &camera->getProj());

			entities.each<TransformComponent, ModelComponent>([this, &cameraLods, camera, dt, viewId](
				Entity e,
				TransformComponent& transformComponent,
				ModelComponent& modelComponent
				)
			{
				const auto& model = modelComponent.getModel();
				if (!model.isValid())
					return;

				const auto& worldTransform = transformComponent.getTransform();
				const auto clip_planes = math::vec2(camera->getNearClip(), camera->getFarClip());

				auto& lodData = cameraLods[e];
				const auto transitionTime = model.getTransitionTime();
				const auto minDistance = model.getMinDistance();
				const auto maxDistance = model.getMaxDistance();
				const auto lodCount = model.getLods().size();
				const auto currentTime = lodData.currentTime;
				const auto currentLodIndex = lodData.currentLodIndex;
				const auto targetLodIndex = lodData.targetLodIndex;

				auto material = model.getMaterialForGroup({});
				if (!material)
					return;

				const auto hMeshCurr = model.getLod(currentLodIndex);
				if (!hMeshCurr)
					return;

				const auto& frustum = camera->getFrustum();
				const auto& bounds = hMeshCurr->aabb;

				float t = 0;
				const auto rayOrigin = camera->getPosition();
				const auto invWorld = math::inverse(worldTransform);
				const auto objectRayOrigin = invWorld.transformCoord(rayOrigin);
				const auto objectRayDirection = math::normalize(bounds.getCenter() - objectRayOrigin);
				bounds.intersect(objectRayOrigin, objectRayDirection, t);

				// Compute final object space intersection point.
				auto intersectionPoint = objectRayOrigin + (objectRayDirection * t);

				// transform intersection point back into world space to compute
				// the final intersection distance.
				intersectionPoint = worldTransform.transformCoord(intersectionPoint);
				const float distance = math::length(intersectionPoint - rayOrigin);
				updateLodData(
					lodData,
					lodCount,
					minDistance,
					maxDistance,
					transitionTime,
					distance,
					dt);
				// Test the bounding box of the mesh
				if (!math::frustum::testOBB(frustum, bounds, worldTransform))
					return;

				const auto params = math::vec3{
					0.0f,
					-1.0f,
					(transitionTime - currentTime) / transitionTime
				};

				const auto paramsInv = math::vec3{
					1.0f,
					1.0f,
					currentTime / transitionTime
				};

				material->setUniform("u_camera_wpos", &camera->getPosition());
				material->setUniform("u_camera_clip_planes", &clip_planes);
				material->setUniform("u_lod_params", &params);
				material->submit();

				// Set render states.
				const auto states = material->getRenderStates();

				auto program = material->getProgram();

				hMeshCurr->submit(viewId, program->handle, worldTransform, states);

				if (currentTime != 0.0f)
				{
					material->setUniform("u_lod_params", &paramsInv);
					material->submit();

					const auto hMeshTarget = model.getLod(targetLodIndex);
					if (!hMeshTarget)
						return;
					hMeshTarget->submit(viewId, program->handle, worldTransform, states);
				}

			});

		}

		{
			auto surface = cameraComponent.getRenderSurface();
			RenderSurfaceScope scope(surface);

			//this will change soon
			gfx::blit(surface->getId(), gfx::getTexture(surface->getBufferRaw()->handle), 0, 0, gfx::getTexture(surface->getBufferRaw()->handle));
		}

	});

}

void RenderingSystem::receive(const EntityDestroyedEvent &event)
{
	mLodDataMap.erase(event.entity);
	for (auto& pair : mLodDataMap)
	{
		pair.second.erase(event.entity);
	}
}

void RenderingSystem::configure(EventManager &events)
{
	events.subscribe<EntityDestroyedEvent>(*this);
}
<|endoftext|>


<commit_before><commit_msg>ant bool is not 0/1<commit_after><|endoftext|>


<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbImage.h"
#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"
#include "otbMultiToMonoChannelExtractROI.h"
#include "itkRescaleIntensityImageFilter.h"

//  Software Guide : BeginCommandLineArgs
//    INPUTS: {ROI_QB_MUL_1.png}
//    OUTPUTS: {InnerProductPCAOutput.tif}, {PrettyInnerProductPCAOutput1.png}, {PrettyInnerProductPCAOutput2.png}, {PrettyInnerProductPCAOutput3.png}
//    3
//  Software Guide : EndCommandLineArgs

// Software Guide : BeginLatex
//
// This example illustrates the use of the
// \doxygen{otb}{InnerProductPCAImageFilter}.
// This filter computes a Principal Component Analysis using an
// efficient method based on the inner product in order to compute the
// covariance matrix.
//
// The first step required to use this filter is to include its header file.
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "otbInnerProductPCAImageFilter.h"
// Software Guide : EndCodeSnippet

int main( int argc, char* argv[] )
{
  typedef double PixelType;
  const unsigned int Dimension = 2;
  const char * inputFileName = argv[1];
  const char * outputFilename = argv[2];
  const unsigned int numberOfPrincipalComponentsRequired(atoi(argv[6]));

  // Software Guide : BeginLatex
  //
  // We start by defining the types for the images and the reader and
  // the writer. We choose to work with a \doxygen{otb}{VectorImage},
  // since we will produce a multi-channel image (the principal
  // components) from a multi-channel input image.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef otb::VectorImage<PixelType,Dimension> ImageType;
  typedef otb::ImageFileReader< ImageType >     ReaderType;
  typedef otb::ImageFileWriter< ImageType >     WriterType;
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // We instantiate now the image reader and we set the image file name.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  ReaderType::Pointer     reader     = ReaderType::New();
  reader->SetFileName(inputFileName);
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // We define the type for the filter. It is templated over the input
  // and the output image types. We the instantiate the filter.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef otb::InnerProductPCAImageFilter<ImageType,ImageType> PCAFilterType;
  PCAFilterType::Pointer     pcafilter     = PCAFilterType::New();

  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // The only parameter needed for the PCA is the number of principal
  // components required as output. We can choose to get less PCs than
  // the number of input bands.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet

  pcafilter->SetNumberOfPrincipalComponentsRequired(
                                    numberOfPrincipalComponentsRequired);

  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // We now instantiate the writer and set the file name for the
  // output image.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet

  WriterType::Pointer     writer     = WriterType::New();
  writer->SetFileName(outputFilename);

  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // We finally plug the pipeline and trigger the PCA computation with
  // the method \code{Update()} of the writer.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet

  pcafilter->SetInput(reader->GetOutput());
  writer->SetInput(pcafilter->GetOutput());

  writer->Update();

  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  // Figure~\ref{fig:INNERPRODUCTPCA_FILTER} shows the result of applying
  // the key point density filter to an image using the SIFT
  // detector.
  // \begin{figure}
  // \center
  // \includegraphics[width=0.25\textwidth]{ROI_QB_MUL_1.eps}
  // \includegraphics[width=0.25\textwidth]{PrettyInnerProductPCAOutput1.eps}
  // \includegraphics[width=0.25\textwidth]{PrettyInnerProductPCAOutput2.eps}
  // \includegraphics[width=0.25\textwidth]{PrettyInnerProductPCAOutput3.eps}
  // \itkcaption[Inner Product PCA Filter]{Result of applying the
  // \doxygen{otb}{InnerProductPCAImageFilter} to an image. From left
  // to right and top to bottom:
  // original image, first PC, second PC, third PC.}
  // \label{fig:INNERPRODUCTPCA_FILTER}
  // \end{figure}
  //
  //  Software Guide : EndLatex

  typedef otb::Image<PixelType,Dimension> MonoImageType;

  typedef otb::MultiToMonoChannelExtractROI< PixelType, PixelType >
                                                    ExtractROIFilterType;

  typedef otb::Image<unsigned char, 2> OutputImageType;
  typedef otb::ImageFileWriter< OutputImageType >  WriterType2;
  typedef itk::RescaleIntensityImageFilter< MonoImageType, OutputImageType> RescalerType;

  for(unsigned int cpt=0 ; cpt < numberOfPrincipalComponentsRequired ; cpt++)
  {
    ExtractROIFilterType::Pointer extractROIFilter = ExtractROIFilterType::New();
    RescalerType::Pointer rescaler = RescalerType::New();

    WriterType2::Pointer     writer2     = WriterType2::New();
    extractROIFilter->SetInput(pcafilter->GetOutput());
    extractROIFilter->SetChannel(cpt+1);

    rescaler->SetInput( extractROIFilter->GetOutput());
    rescaler->SetOutputMinimum(0);
    rescaler->SetOutputMaximum(255);

    writer2->SetInput(rescaler->GetOutput());
    writer2->SetFileName(argv[cpt+3]);
    writer2->Update();
  }

  return EXIT_SUCCESS;
}
<commit_msg>DOC: correction of text<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "otbImage.h"
#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include "otbImageFileWriter.h"
#include "otbMultiToMonoChannelExtractROI.h"
#include "itkRescaleIntensityImageFilter.h"

//  Software Guide : BeginCommandLineArgs
//    INPUTS: {ROI_QB_MUL_1.png}
//    OUTPUTS: {InnerProductPCAOutput.tif}, {PrettyInnerProductPCAOutput1.png}, {PrettyInnerProductPCAOutput2.png}, {PrettyInnerProductPCAOutput3.png}
//    3
//  Software Guide : EndCommandLineArgs

// Software Guide : BeginLatex
//
// This example illustrates the use of the
// \doxygen{otb}{InnerProductPCAImageFilter}.
// This filter computes a Principal Component Analysis using an
// efficient method based on the inner product in order to compute the
// covariance matrix.
//
// The first step required to use this filter is to include its header file.
//
// Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "otbInnerProductPCAImageFilter.h"
// Software Guide : EndCodeSnippet

int main( int argc, char* argv[] )
{
  typedef double PixelType;
  const unsigned int Dimension = 2;
  const char * inputFileName = argv[1];
  const char * outputFilename = argv[2];
  const unsigned int numberOfPrincipalComponentsRequired(atoi(argv[6]));

  // Software Guide : BeginLatex
  //
  // We start by defining the types for the images and the reader and
  // the writer. We choose to work with a \doxygen{otb}{VectorImage},
  // since we will produce a multi-channel image (the principal
  // components) from a multi-channel input image.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef otb::VectorImage<PixelType,Dimension> ImageType;
  typedef otb::ImageFileReader< ImageType >     ReaderType;
  typedef otb::ImageFileWriter< ImageType >     WriterType;
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // We instantiate now the image reader and we set the image file name.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  ReaderType::Pointer     reader     = ReaderType::New();
  reader->SetFileName(inputFileName);
  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // We define the type for the filter. It is templated over the input
  // and the output image types. We the instantiate the filter.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet
  typedef otb::InnerProductPCAImageFilter<ImageType,ImageType> PCAFilterType;
  PCAFilterType::Pointer     pcafilter     = PCAFilterType::New();

  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // The only parameter needed for the PCA is the number of principal
  // components required as output. We can choose to get less PCs than
  // the number of input bands.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet

  pcafilter->SetNumberOfPrincipalComponentsRequired(
                                    numberOfPrincipalComponentsRequired);

  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // We now instantiate the writer and set the file name for the
  // output image.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet

  WriterType::Pointer     writer     = WriterType::New();
  writer->SetFileName(outputFilename);

  // Software Guide : EndCodeSnippet
  // Software Guide : BeginLatex
  //
  // We finally plug the pipeline and trigger the PCA computation with
  // the method \code{Update()} of the writer.
  //
  // Software Guide : EndLatex

  // Software Guide : BeginCodeSnippet

  pcafilter->SetInput(reader->GetOutput());
  writer->SetInput(pcafilter->GetOutput());

  writer->Update();

  // Software Guide : EndCodeSnippet

  //  Software Guide : BeginLatex
  // Figure~\ref{fig:INNERPRODUCTPCA_FILTER} shows the result of applying
  // the PCA to a 3 band RGB image.
  // \begin{figure}
  // \center
  // \includegraphics[width=0.25\textwidth]{ROI_QB_MUL_1.eps}
  // \includegraphics[width=0.25\textwidth]{PrettyInnerProductPCAOutput1.eps}
  // \includegraphics[width=0.25\textwidth]{PrettyInnerProductPCAOutput2.eps}
  // \includegraphics[width=0.25\textwidth]{PrettyInnerProductPCAOutput3.eps}
  // \itkcaption[Inner Product PCA Filter]{Result of applying the
  // \doxygen{otb}{InnerProductPCAImageFilter} to an image. From left
  // to right and top to bottom:
  // original image, first PC, second PC, third PC.}
  // \label{fig:INNERPRODUCTPCA_FILTER}
  // \end{figure}
  //
  //  Software Guide : EndLatex

  typedef otb::Image<PixelType,Dimension> MonoImageType;

  typedef otb::MultiToMonoChannelExtractROI< PixelType, PixelType >
                                                    ExtractROIFilterType;

  typedef otb::Image<unsigned char, 2> OutputImageType;
  typedef otb::ImageFileWriter< OutputImageType >  WriterType2;
  typedef itk::RescaleIntensityImageFilter< MonoImageType, OutputImageType> RescalerType;

  for(unsigned int cpt=0 ; cpt < numberOfPrincipalComponentsRequired ; cpt++)
  {
    ExtractROIFilterType::Pointer extractROIFilter = ExtractROIFilterType::New();
    RescalerType::Pointer rescaler = RescalerType::New();

    WriterType2::Pointer     writer2     = WriterType2::New();
    extractROIFilter->SetInput(pcafilter->GetOutput());
    extractROIFilter->SetChannel(cpt+1);

    rescaler->SetInput( extractROIFilter->GetOutput());
    rescaler->SetOutputMinimum(0);
    rescaler->SetOutputMaximum(255);

    writer2->SetInput(rescaler->GetOutput());
    writer2->SetFileName(argv[cpt+3]);
    writer2->Update();
  }

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007-2008 Digital Bazaar, Inc.  All rights reserved.
 */
#include "db/crypto/BigDecimal.h"

#include <sstream>

using namespace std;
using namespace db::crypto;

BigDecimal::BigDecimal(long double value)
{
   initialize();

   if(value != 0)
   {
      *this = value;
   }
}

BigDecimal::BigDecimal(double value)
{
   initialize();

   if(value != 0)
   {
      *this = value;
   }
}

BigDecimal::BigDecimal(long long value)
{
   initialize();

   if(value != 0)
   {
      *this = value;
   }
}

BigDecimal::BigDecimal(unsigned long long value)
{
   initialize();

   if(value != 0)
   {
      *this = value;
   }
}

BigDecimal::BigDecimal(int value)
{
   initialize();

   if(value != 0)
   {
      *this = value;
   }
}

BigDecimal::BigDecimal(unsigned int value)
{
   initialize();

   if(value != 0)
   {
      *this = value;
   }
}

BigDecimal::BigDecimal(const char* value)
{
   initialize();
   *this = value;
}

BigDecimal::BigDecimal(const string& value)
{
   initialize();
   *this = value;
}

BigDecimal::BigDecimal(const BigDecimal& copy)
{
   initialize();
   mSignificand = copy.mSignificand;
   mExponent = copy.mExponent;
}

BigDecimal::~BigDecimal()
{
}

void BigDecimal::initialize()
{
   mExponent = 0;
   mPrecision = 10;
   mRoundingMode = HalfUp;
}

void BigDecimal::setExponent(int exponent)
{
   if(exponent > mExponent)
   {
      // multiply significand by power difference
      BigInteger ten(10);
      mSignificand *= ten.pow(exponent - mExponent);
   }

   mExponent = exponent;
}

void BigDecimal::synchronizeExponents(BigDecimal& bd1, BigDecimal& bd2)
{
   // only do work if exponents are different
   if(bd1.mExponent != bd2.mExponent)
   {
      // use the larger exponent to retain precision
      if(bd1.mExponent > bd2.mExponent)
      {
         bd2.setExponent(bd1.mExponent);
      }
      else
      {
         bd1.setExponent(bd2.mExponent);
      }
   }
}

BigDecimal& BigDecimal::operator=(const BigDecimal& rhs)
{
   mSignificand = rhs.mSignificand;
   mExponent = rhs.mExponent;
   return *this;
}

BigDecimal& BigDecimal::operator=(long double rhs)
{
   // convert double to string
   ostringstream oss;
   oss << rhs;
   return *this = oss.str();
}

BigDecimal& BigDecimal::operator=(double rhs)
{
   // convert double to string
   ostringstream oss;
   oss << rhs;
   return *this = oss.str();
}

BigDecimal& BigDecimal::operator=(long long rhs)
{
   // convert long to string
   char temp[22];
   snprintf(temp, 22, "%lli", rhs);
   return *this = temp;
}

BigDecimal& BigDecimal::operator=(unsigned long long rhs)
{
   // convert long to string
   char temp[22];
   snprintf(temp, 22, "%llu", rhs);
   return *this = temp;
}

BigDecimal& BigDecimal::operator=(int rhs)
{
   // convert int to string
   char temp[12];
   snprintf(temp, 12, "%i", rhs);
   return *this = temp;
}

BigDecimal& BigDecimal::operator=(unsigned int rhs)
{
   // convert int to string
   char temp[12];
   snprintf(temp, 12, "%u", rhs);
   return *this = temp;
}

BigDecimal& BigDecimal::operator=(const char* rhs)
{
   *this = string(rhs);
   return *this;
}

BigDecimal& BigDecimal::operator=(const string& rhs)
{
   string temp;

   // find decimal point
   unsigned int dot = rhs.rfind('.');
   if(dot != string::npos)
   {
      // check for scientific notation
      unsigned int e = rhs.rfind('e');
      if(e != string::npos && e != rhs.length() - 2)
      {
         // parse exponent
         mExponent = -strtoll(rhs.c_str() + e + 1, NULL, 10);

         // add number of places between the e and the decimal point
         mExponent += e - dot - 1;

         // remove decimal point and e
         temp.append(rhs.substr(0, dot));
         temp.append(rhs.substr(dot + 1, e - dot));
      }
      else
      {
         // set exponent to the number of places between dot and end of string
         mExponent = rhs.length() - dot - 1;

         // remove decimal point
         temp.append(rhs.substr(0, dot));
         if(dot != rhs.length() - 1)
         {
            temp.append(rhs.substr(dot + 1));
         }
      }
   }
   else
   {
      // no decimal point, set exponent to 0
      mExponent = 0;
      temp = rhs;
   }

   // parse significand
   mSignificand = temp;

   // if exponent is negative, scale the significand so the exponent is zero
   if(mExponent < 0)
   {
      mExponent = -mExponent;
      BigInteger ten(10);
      mSignificand *= ten.pow(mExponent);
      mExponent = 0;
   }

   return *this;
}

bool BigDecimal::operator==(const BigDecimal& rhs)
{
   BigDecimal temp = rhs;
   synchronizeExponents(*this, temp);
   return this->mSignificand == temp.mSignificand;
}

bool BigDecimal::operator==(long double rhs)
{
   return getDouble() == rhs;
}

bool BigDecimal::operator!=(const BigDecimal& rhs)
{
   return !(*this == rhs);
}

bool BigDecimal::operator!=(long double rhs)
{
   return !(*this == rhs);
}

bool BigDecimal::operator<(const BigDecimal& rhs)
{
   bool rval = false;

   if(isNegative() && !rhs.isNegative())
   {
      rval = true;
   }
   else if(isNegative() == rhs.isNegative())
   {
      BigDecimal temp = rhs;
      synchronizeExponents(*this, temp);
      if(mSignificand < temp.mSignificand)
      {
         rval = true;
      }
   }

   return rval;
}

bool BigDecimal::operator>(const BigDecimal& rhs)
{
   bool rval = false;

   if(!isNegative() && rhs.isNegative())
   {
      rval = true;
   }
   else if(isNegative() == rhs.isNegative())
   {
      BigDecimal temp = rhs;
      synchronizeExponents(*this, temp);
      if(mSignificand > temp.mSignificand)
      {
         rval = true;
      }
   }

   return rval;
}

bool BigDecimal::operator<=(const BigDecimal& rhs)
{
   return *this < rhs || *this == rhs;
}

bool BigDecimal::operator>=(const BigDecimal& rhs)
{
   return *this > rhs || *this == rhs;
}

BigDecimal BigDecimal::operator+(const BigDecimal& rhs)
{
   BigDecimal rval = *this;
   BigDecimal temp = rhs;
   synchronizeExponents(rval, temp);
   rval.mSignificand += temp.mSignificand;
   return rval;
}

BigDecimal BigDecimal::operator-(const BigDecimal& rhs)
{
   BigDecimal rval = *this;
   BigDecimal temp = rhs;
   synchronizeExponents(rval, temp);
   rval.mSignificand -= temp.mSignificand;
   return rval;
}

BigDecimal BigDecimal::operator*(const BigDecimal& rhs)
{
   BigDecimal rval = *this;

   // perform multiplication and then add exponents
   rval.mSignificand *= rhs.mSignificand;
   rval.mExponent += rhs.mExponent;

   return rval;
}

BigDecimal BigDecimal::operator/(const BigDecimal& rhs)
{
   BigDecimal rval = *this;

   // add the divisor's exponent to the dividend so that when a division is
   // performed, the exponents subtract to reproduce the original scale
   rval.setExponent(rval.mExponent + rhs.mExponent);

   // do division with remainder
   BigDecimal remainder;
   rval.mSignificand.divide(
      rhs.mSignificand, rval.mSignificand, remainder.mSignificand);

   // see if there is a remainder to add to the result
   if(remainder.mSignificand != 0)
   {
      // determine if the remainder should be rounded up
      bool roundUp = (mRoundingMode == Up) ? true : false;
      if(mRoundingMode == HalfUp)
      {
         // if twice the remainder is greater than or equal to the divisor,
         // then it is at least half as large as the divisor
         if((remainder.mSignificand + remainder.mSignificand).absCompare(
            rhs.mSignificand) >= 0)
         {
            roundUp = true;
         }
      }

      // raise remainder to digits of precision (taking into account the
      // remainder has the same scale as the dividend rval)
      unsigned int digits = 0;
      if(mPrecision - rval.mExponent > 0)
      {
         digits = mPrecision - rval.mExponent;
         BigInteger ten(10);
         remainder.mSignificand *= ten.pow(digits);
      }

      // perform division on significand
      remainder.mSignificand /= rhs.mSignificand;

      // set remainder exponent to digits of precision
      remainder.mExponent = mPrecision;

      // round up if appropriate
      if(roundUp)
      {
         BigDecimal bd;
         bd.mSignificand = 1;
         bd.mExponent = mPrecision;
         rval += bd;
      }

      // add remainder
      rval += remainder;
   }

   return rval;
}

BigDecimal BigDecimal::operator%(const BigDecimal& rhs)
{
   BigDecimal rval = *this;
   BigDecimal temp = rhs;
   synchronizeExponents(rval, temp);
   rval.mSignificand %= temp.mSignificand;
   return rval;
}

BigDecimal& BigDecimal::operator+=(const BigDecimal& rhs)
{
   *this = *this + rhs;
   return *this;
}

BigDecimal& BigDecimal::operator-=(const BigDecimal& rhs)
{
   *this = *this - rhs;
   return *this;
}

BigDecimal& BigDecimal::operator*=(const BigDecimal& rhs)
{
   *this = *this * rhs;
   return *this;
}

BigDecimal& BigDecimal::operator/=(const BigDecimal& rhs)
{
   *this = *this / rhs;
   return *this;
}

BigDecimal& BigDecimal::operator%=(const BigDecimal& rhs)
{
   *this = *this % rhs;
   return *this;
}

bool BigDecimal::isZero() const
{
   return mSignificand.isZero();
}

void BigDecimal::setNegative(bool negative)
{
   mSignificand.setNegative(negative);
}

bool BigDecimal::isNegative() const
{
   return mSignificand.isNegative();
}

long double BigDecimal::getDouble() const
{
   // get value as a string
   // parse long double
   return strtold(toString().c_str(), NULL);
}

void BigDecimal::setPrecision(unsigned int precision, RoundingMode roundingMode)
{
   mPrecision = precision;
   mRoundingMode = roundingMode;
}

unsigned int BigDecimal::getPrecision()
{
   return mPrecision;
}

void BigDecimal::round()
{
   // write out to a string
   string str = toString();

   // find exponent
   unsigned int dot = str.rfind('.');
   if(dot != string::npos)
   {
      // determine if there are more digits than the precision allows
      if(str.length() - (dot + 1) > mPrecision)
      {
         // get the extra digits
         string extra = str.substr(dot + 1 + mPrecision);

         // set new exponent by subtracting extra length
         mExponent -= extra.length();

         // truncate significand
         mSignificand = (str.substr(0, dot) + str.substr(dot + 1, mExponent));

         // round significand according to rounding mode
         if(mRoundingMode == Up)
         {
            // must round up if there is anything but a zero in extra
            bool round = false;
            for(const char* ptr = extra.c_str(); *ptr != 0 && !round; ptr++)
            {
               if(*ptr != '0')
               {
                  round = true;
               }
            }

            if(round)
            {
               // add 1 with the same exponent
               BigDecimal bd = 1;
               bd.mExponent = mExponent;
               *this += bd;
            }
         }
         else if(mRoundingMode == HalfUp)
         {
            if(extra.at(0) > '4' && extra.at(0) <= '9')
            {
               // add 1 with the same exponent
               BigDecimal bd = 1;
               bd.mExponent = mExponent;
               *this += bd;
            }
         }
      }
   }
}

string BigDecimal::toString() const
{
   // write out significand
   string str = mSignificand.toString();

   if(mExponent < 0)
   {
      // append zeros
      int zeros = -mExponent - str.length();
      if(zeros > 0)
      {
         str.append(0, zeros, '0');
      }
      else
      {
         // insert decimal point
         str.insert(str.length() + mExponent, 1, '.');
      }
   }
   else if(mExponent > 0)
   {
      // prepend zeros
      int zeros = mExponent - str.length();
      if(zeros > 0)
      {
         str.insert(0, zeros, '0');
      }

      if((unsigned int)mExponent == str.length())
      {
         // prepend "0."
         str.insert(0, 1, '.');
         str.insert(0, 1, '0');
      }
      else
      {
         // insert decimal point
         str.insert(str.length() - mExponent, 1, '.');
      }
   }

   return str;
}

ostream& operator<<(ostream& os, const BigDecimal& bd)
{
   os << bd.toString();
   return os;
}

istream& operator>>(istream& is, BigDecimal& bd)
{
   string str;
   is >> str;
   bd = str;
   return is;
}
<commit_msg>Fixed bug where toString() for negative small numbers was incorrect.<commit_after>/*
 * Copyright (c) 2007-2008 Digital Bazaar, Inc.  All rights reserved.
 */
#include "db/crypto/BigDecimal.h"

#include <sstream>

using namespace std;
using namespace db::crypto;

BigDecimal::BigDecimal(long double value)
{
   initialize();

   if(value != 0)
   {
      *this = value;
   }
}

BigDecimal::BigDecimal(double value)
{
   initialize();

   if(value != 0)
   {
      *this = value;
   }
}

BigDecimal::BigDecimal(long long value)
{
   initialize();

   if(value != 0)
   {
      *this = value;
   }
}

BigDecimal::BigDecimal(unsigned long long value)
{
   initialize();

   if(value != 0)
   {
      *this = value;
   }
}

BigDecimal::BigDecimal(int value)
{
   initialize();

   if(value != 0)
   {
      *this = value;
   }
}

BigDecimal::BigDecimal(unsigned int value)
{
   initialize();

   if(value != 0)
   {
      *this = value;
   }
}

BigDecimal::BigDecimal(const char* value)
{
   initialize();
   *this = value;
}

BigDecimal::BigDecimal(const string& value)
{
   initialize();
   *this = value;
}

BigDecimal::BigDecimal(const BigDecimal& copy)
{
   initialize();
   mSignificand = copy.mSignificand;
   mExponent = copy.mExponent;
}

BigDecimal::~BigDecimal()
{
}

void BigDecimal::initialize()
{
   mExponent = 0;
   mPrecision = 10;
   mRoundingMode = HalfUp;
}

void BigDecimal::setExponent(int exponent)
{
   if(exponent > mExponent)
   {
      // multiply significand by power difference
      BigInteger ten(10);
      mSignificand *= ten.pow(exponent - mExponent);
   }

   mExponent = exponent;
}

void BigDecimal::synchronizeExponents(BigDecimal& bd1, BigDecimal& bd2)
{
   // only do work if exponents are different
   if(bd1.mExponent != bd2.mExponent)
   {
      // use the larger exponent to retain precision
      if(bd1.mExponent > bd2.mExponent)
      {
         bd2.setExponent(bd1.mExponent);
      }
      else
      {
         bd1.setExponent(bd2.mExponent);
      }
   }
}

BigDecimal& BigDecimal::operator=(const BigDecimal& rhs)
{
   mSignificand = rhs.mSignificand;
   mExponent = rhs.mExponent;
   return *this;
}

BigDecimal& BigDecimal::operator=(long double rhs)
{
   // convert double to string
   ostringstream oss;
   oss << rhs;
   return *this = oss.str();
}

BigDecimal& BigDecimal::operator=(double rhs)
{
   // convert double to string
   ostringstream oss;
   oss << rhs;
   return *this = oss.str();
}

BigDecimal& BigDecimal::operator=(long long rhs)
{
   // convert long to string
   char temp[22];
   snprintf(temp, 22, "%lli", rhs);
   return *this = temp;
}

BigDecimal& BigDecimal::operator=(unsigned long long rhs)
{
   // convert long to string
   char temp[22];
   snprintf(temp, 22, "%llu", rhs);
   return *this = temp;
}

BigDecimal& BigDecimal::operator=(int rhs)
{
   // convert int to string
   char temp[12];
   snprintf(temp, 12, "%i", rhs);
   return *this = temp;
}

BigDecimal& BigDecimal::operator=(unsigned int rhs)
{
   // convert int to string
   char temp[12];
   snprintf(temp, 12, "%u", rhs);
   return *this = temp;
}

BigDecimal& BigDecimal::operator=(const char* rhs)
{
   *this = string(rhs);
   return *this;
}

BigDecimal& BigDecimal::operator=(const string& rhs)
{
   string temp;

   // find decimal point
   unsigned int dot = rhs.rfind('.');
   if(dot != string::npos)
   {
      // check for scientific notation
      unsigned int e = rhs.rfind('e');
      if(e != string::npos && e != rhs.length() - 2)
      {
         // parse exponent
         mExponent = -strtoll(rhs.c_str() + e + 1, NULL, 10);

         // add number of places between the e and the decimal point
         mExponent += e - dot - 1;

         // remove decimal point and e
         temp.append(rhs.substr(0, dot));
         temp.append(rhs.substr(dot + 1, e - dot));
      }
      else
      {
         // set exponent to the number of places between dot and end of string
         mExponent = rhs.length() - dot - 1;

         // remove decimal point
         temp.append(rhs.substr(0, dot));
         if(dot != rhs.length() - 1)
         {
            temp.append(rhs.substr(dot + 1));
         }
      }
   }
   else
   {
      // no decimal point, set exponent to 0
      mExponent = 0;
      temp = rhs;
   }

   // parse significand
   mSignificand = temp;

   // if exponent is negative, scale the significand so the exponent is zero
   if(mExponent < 0)
   {
      mExponent = -mExponent;
      BigInteger ten(10);
      mSignificand *= ten.pow(mExponent);
      mExponent = 0;
   }

   return *this;
}

bool BigDecimal::operator==(const BigDecimal& rhs)
{
   BigDecimal temp = rhs;
   synchronizeExponents(*this, temp);
   return this->mSignificand == temp.mSignificand;
}

bool BigDecimal::operator==(long double rhs)
{
   return getDouble() == rhs;
}

bool BigDecimal::operator!=(const BigDecimal& rhs)
{
   return !(*this == rhs);
}

bool BigDecimal::operator!=(long double rhs)
{
   return !(*this == rhs);
}

bool BigDecimal::operator<(const BigDecimal& rhs)
{
   bool rval = false;

   if(isNegative() && !rhs.isNegative())
   {
      rval = true;
   }
   else if(isNegative() == rhs.isNegative())
   {
      BigDecimal temp = rhs;
      synchronizeExponents(*this, temp);
      if(mSignificand < temp.mSignificand)
      {
         rval = true;
      }
   }

   return rval;
}

bool BigDecimal::operator>(const BigDecimal& rhs)
{
   bool rval = false;

   if(!isNegative() && rhs.isNegative())
   {
      rval = true;
   }
   else if(isNegative() == rhs.isNegative())
   {
      BigDecimal temp = rhs;
      synchronizeExponents(*this, temp);
      if(mSignificand > temp.mSignificand)
      {
         rval = true;
      }
   }

   return rval;
}

bool BigDecimal::operator<=(const BigDecimal& rhs)
{
   return *this < rhs || *this == rhs;
}

bool BigDecimal::operator>=(const BigDecimal& rhs)
{
   return *this > rhs || *this == rhs;
}

BigDecimal BigDecimal::operator+(const BigDecimal& rhs)
{
   BigDecimal rval = *this;
   BigDecimal temp = rhs;
   synchronizeExponents(rval, temp);
   rval.mSignificand += temp.mSignificand;
   return rval;
}

BigDecimal BigDecimal::operator-(const BigDecimal& rhs)
{
   BigDecimal rval = *this;
   BigDecimal temp = rhs;
   synchronizeExponents(rval, temp);
   rval.mSignificand -= temp.mSignificand;
   return rval;
}

BigDecimal BigDecimal::operator*(const BigDecimal& rhs)
{
   BigDecimal rval = *this;

   // perform multiplication and then add exponents
   rval.mSignificand *= rhs.mSignificand;
   rval.mExponent += rhs.mExponent;

   return rval;
}

BigDecimal BigDecimal::operator/(const BigDecimal& rhs)
{
   BigDecimal rval = *this;

   // add the divisor's exponent to the dividend so that when a division is
   // performed, the exponents subtract to reproduce the original scale
   rval.setExponent(rval.mExponent + rhs.mExponent);

   // do division with remainder
   BigDecimal remainder;
   rval.mSignificand.divide(
      rhs.mSignificand, rval.mSignificand, remainder.mSignificand);

   // see if there is a remainder to add to the result
   if(remainder.mSignificand != 0)
   {
      // determine if the remainder should be rounded up
      bool roundUp = (mRoundingMode == Up) ? true : false;
      if(mRoundingMode == HalfUp)
      {
         // if twice the remainder is greater than or equal to the divisor,
         // then it is at least half as large as the divisor
         if((remainder.mSignificand + remainder.mSignificand).absCompare(
            rhs.mSignificand) >= 0)
         {
            roundUp = true;
         }
      }

      // raise remainder to digits of precision (taking into account the
      // remainder has the same scale as the dividend rval)
      unsigned int digits = 0;
      if(mPrecision - rval.mExponent > 0)
      {
         digits = mPrecision - rval.mExponent;
         BigInteger ten(10);
         remainder.mSignificand *= ten.pow(digits);
      }

      // perform division on significand
      remainder.mSignificand /= rhs.mSignificand;

      // set remainder exponent to digits of precision
      remainder.mExponent = mPrecision;

      // round up if appropriate
      if(roundUp)
      {
         BigDecimal bd;
         bd.mSignificand = 1;
         bd.mExponent = mPrecision;
         rval += bd;
      }

      // add remainder
      rval += remainder;
   }

   return rval;
}

BigDecimal BigDecimal::operator%(const BigDecimal& rhs)
{
   BigDecimal rval = *this;
   BigDecimal temp = rhs;
   synchronizeExponents(rval, temp);
   rval.mSignificand %= temp.mSignificand;
   return rval;
}

BigDecimal& BigDecimal::operator+=(const BigDecimal& rhs)
{
   *this = *this + rhs;
   return *this;
}

BigDecimal& BigDecimal::operator-=(const BigDecimal& rhs)
{
   *this = *this - rhs;
   return *this;
}

BigDecimal& BigDecimal::operator*=(const BigDecimal& rhs)
{
   *this = *this * rhs;
   return *this;
}

BigDecimal& BigDecimal::operator/=(const BigDecimal& rhs)
{
   *this = *this / rhs;
   return *this;
}

BigDecimal& BigDecimal::operator%=(const BigDecimal& rhs)
{
   *this = *this % rhs;
   return *this;
}

bool BigDecimal::isZero() const
{
   return mSignificand.isZero();
}

void BigDecimal::setNegative(bool negative)
{
   mSignificand.setNegative(negative);
}

bool BigDecimal::isNegative() const
{
   return mSignificand.isNegative();
}

long double BigDecimal::getDouble() const
{
   // get value as a string
   // parse long double
   return strtold(toString().c_str(), NULL);
}

void BigDecimal::setPrecision(unsigned int precision, RoundingMode roundingMode)
{
   mPrecision = precision;
   mRoundingMode = roundingMode;
}

unsigned int BigDecimal::getPrecision()
{
   return mPrecision;
}

void BigDecimal::round()
{
   // write out to a string
   string str = toString();

   // find exponent
   unsigned int dot = str.rfind('.');
   if(dot != string::npos)
   {
      // determine if there are more digits than the precision allows
      if(str.length() - (dot + 1) > mPrecision)
      {
         // get the extra digits
         string extra = str.substr(dot + 1 + mPrecision);

         // set new exponent by subtracting extra length
         mExponent -= extra.length();

         // truncate significand
         mSignificand = (str.substr(0, dot) + str.substr(dot + 1, mExponent));

         // round significand according to rounding mode
         if(mRoundingMode == Up)
         {
            // must round up if there is anything but a zero in extra
            bool round = false;
            for(const char* ptr = extra.c_str(); *ptr != 0 && !round; ptr++)
            {
               if(*ptr != '0')
               {
                  round = true;
               }
            }

            if(round)
            {
               // add 1 with the same exponent
               BigDecimal bd = 1;
               bd.mExponent = mExponent;
               *this += bd;
            }
         }
         else if(mRoundingMode == HalfUp)
         {
            if(extra.at(0) > '4' && extra.at(0) <= '9')
            {
               // add 1 with the same exponent
               BigDecimal bd = 1;
               bd.mExponent = mExponent;
               *this += bd;
            }
         }
      }
   }
}

string BigDecimal::toString() const
{
   // write out significand
   string str = mSignificand.toString();

   // erase negative sign
   if(mSignificand.isNegative())
   {
      str.erase(0, 1);
   }

   if(mExponent < 0)
   {
      // append zeros
      int zeros = -mExponent - str.length();
      if(zeros > 0)
      {
         str.append(0, zeros, '0');
      }
      else
      {
         // insert decimal point
         str.insert(str.length() + mExponent, 1, '.');
      }
   }
   else if(mExponent > 0)
   {
      // prepend zeros
      int zeros = mExponent - str.length();
      if(zeros > 0)
      {
         str.insert(0, zeros, '0');
      }

      if((unsigned int)mExponent == str.length())
      {
         // prepend "0."
         str.insert(0, 1, '.');
         str.insert(0, 1, '0');
      }
      else
      {
         // insert decimal point
         str.insert(str.length() - mExponent, 1, '.');
      }
   }

   // insert negative sign
   if(mSignificand.isNegative())
   {
      str.insert(0, 1, '-');
   }

   return str;
}

ostream& operator<<(ostream& os, const BigDecimal& bd)
{
   os << bd.toString();
   return os;
}

istream& operator>>(istream& is, BigDecimal& bd)
{
   string str;
   is >> str;
   bd = str;
   return is;
}
<|endoftext|>