<commit_before>/// \file TWebWindowsManager.cxx
/// \ingroup WebGui ROOT7
/// \author Sergey Linev <s.linev@gsi.de>
/// \date 2017-10-16
/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
/// is welcome!

/*************************************************************************
 * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#pragma GCC diagnostic ignored "-Wall"
#pragma GCC diagnostic ignored "-Wunused-parameter"

#include "ROOT/TWebWindowsManager.hxx"

#include <ROOT/TLogger.hxx>

#include <cassert>
#include <cstdio>

#include "THttpServer.h"
#include "THttpWSHandler.h"

#include "TSystem.h"
#include "TRandom.h"
#include "TString.h"
#include "TStopwatch.h"
#include "TApplication.h"
#include "TTimer.h"
#include "RConfigure.h"

/** \class ROOT::Experimental::TWebWindowManager
\ingroup webdisplay

Central instance to create and show web-based windows like Canvas or FitPanel.

Manager responsible to creating THttpServer instance, which is used for TWebWindow's
communication with clients.

Method TWebWindowsManager::Show() used to show window in specified location.
*/

//////////////////////////////////////////////////////////////////////////////////////////
/// Returns default window manager
/// Used to display all standard ROOT elements like TCanvas or TFitPanel

std::shared_ptr<ROOT::Experimental::TWebWindowsManager> &ROOT::Experimental::TWebWindowsManager::Instance()
{
   static std::shared_ptr<TWebWindowsManager> sInstance = std::make_shared<ROOT::Experimental::TWebWindowsManager>();
   return sInstance;
}

//////////////////////////////////////////////////////////////////////////////////////////
/// window manager constructor
/// Required here for correct usage of unique_ptr<THttpServer>

ROOT::Experimental::TWebWindowsManager::TWebWindowsManager() = default;

//////////////////////////////////////////////////////////////////////////////////////////
/// window manager destructor
/// Required here for correct usage of unique_ptr<THttpServer>

ROOT::Experimental::TWebWindowsManager::~TWebWindowsManager()
{
}

//////////////////////////////////////////////////////////////////////////////////////////
/// Creates http server, if required - with real http engine (civetweb)

bool ROOT::Experimental::TWebWindowsManager::CreateHttpServer(bool with_http)
{
   if (!fServer)
      fServer = std::make_unique<THttpServer>("dummy");

   if (!with_http || (fAddr.length() > 0))
      return true;

   // gServer = new THttpServer("http:8080?loopback&websocket_timeout=10000");

   int http_port = 0;
   const char *ports = gSystem->Getenv("WEBGUI_PORT");
   if (ports)
      http_port = std::atoi(ports);
   if (!http_port)
      gRandom->SetSeed(0);

   for (int ntry = 0; ntry < 100; ++ntry) {
      if (!http_port)
         http_port = (int)(8800 + 1000 * gRandom->Rndm(1));

      // TODO: ensure that port can be used
      // TODO: replace TString::Format with more adequate implementation like
      // https://stackoverflow.com/questions/4668760
      if (fServer->CreateEngine(TString::Format("http:%d?websocket_timeout=10000", http_port))) {
         fAddr = "http://localhost:";
         fAddr.append(std::to_string(http_port));
         return true;
      }

      http_port = 0;
   }

   return false;
}

//////////////////////////////////////////////////////////////////////////////////////////
/// Creates new window
/// To show window, TWebWindow::Show() have to be called

std::shared_ptr<ROOT::Experimental::TWebWindow> ROOT::Experimental::TWebWindowsManager::CreateWindow(bool batch_mode)
{
   if (!CreateHttpServer()) {
      R__ERROR_HERE("WebDisplay") << "Cannot create http server when creating window";
      return nullptr;
   }

   std::shared_ptr<ROOT::Experimental::TWebWindow> win = std::make_shared<ROOT::Experimental::TWebWindow>();

   if (!win) {
      R__ERROR_HERE("WebDisplay") << "Fail to create TWebWindow instance";
      return nullptr;
   }

   win->SetBatchMode(batch_mode);

   win->SetId(++fIdCnt); // set unique ID

   // fDisplays.push_back(win);

   win->fMgr = Instance();

   win->CreateWSHandler();

   fServer->Register("/web7gui", (THttpWSHandler *)win->fWSHandler.get());

   return win;
}

//////////////////////////////////////////////////////////////////////////////////////////
/// Release all references to specified window
/// Called from TWebWindow destructor

void ROOT::Experimental::TWebWindowsManager::Unregister(ROOT::Experimental::TWebWindow &win)
{
   // TODO: close all active connections of the window

   if (win.fWSHandler)
      fServer->Unregister((THttpWSHandler *)win.fWSHandler.get());

   //   for (auto displ = fDisplays.begin(); displ != fDisplays.end(); displ++) {
   //      if (displ->get() == win) {
   //         fDisplays.erase(displ);
   //         break;
   //      }
   //   }
}

//////////////////////////////////////////////////////////////////////////
/// Provide URL address to access specified window from inside or from remote

std::string ROOT::Experimental::TWebWindowsManager::GetUrl(ROOT::Experimental::TWebWindow &win, bool remote)
{
   if (!fServer) {
      R__ERROR_HERE("WebDisplay") << "Server instance not exists when requesting window URL";
      return "";
   }

   std::string addr = "/web7gui/";

   addr.append(((THttpWSHandler *)win.fWSHandler.get())->GetName());

   if (win.IsBatchMode())
      addr.append("/?batch_mode");
   else
      addr.append("/");

   if (remote) {
      if (!CreateHttpServer(true)) {
         R__ERROR_HERE("WebDisplay") << "Fail to start real HTTP server when requesting URL";
         return "";
      }

      addr = fAddr + addr;
   }

   return addr;
}

//////////////////////////////////////////////////////////////////////////
/// Show window in specified location
/// Parameter "where" specifies that kind of window display should be used. Possible values:
///
///      cef - Chromium Embeded Framework, local display, local communication
///      qt5 - Qt5 WebEngine (when running via rootqt5), local display, local communication
///  browser - default system web-browser, communication via random http port from range 8800 - 9800
///  chrome  - use Google Chrome web browser (requires at least v60), supports headless mode,
///            preferable display kind if cef is not available
/// chromium - open-source flawor of chrome, available on most Linux distributions
///   native - either any available local display or default browser
///   <prog> - any program name which will be started instead of default browser, like firefox or /usr/bin/opera
///            one could use following parameters:
///               $url - URL address of the widget
///                 $w - widget width
///                 $h - widget height
///
///  If allowed, same window can be displayed several times (like for TCanvas)

bool ROOT::Experimental::TWebWindowsManager::Show(ROOT::Experimental::TWebWindow &win, const std::string &_where)
{
   if (!fServer) {
      R__ERROR_HERE("WebDisplay") << "Server instance not exists to show window";
      return false;
   }

   THttpWSHandler *handler = (THttpWSHandler *)win.fWSHandler.get();
   bool batch_mode = win.IsBatchMode();

   TString addr;
   addr.Form("/web7gui/%s/%s", handler->GetName(), (batch_mode ? "?batch_mode" : ""));

   std::string where = _where;
   if (where.empty()) {
      const char *cwhere = gSystem->Getenv("WEBGUI_WHERE");
      if (cwhere)
         where = cwhere;
   }

   bool is_native = where.empty() || (where == "native"), is_qt5 = (where == "qt5"), is_cef = (where == "cef"),
        is_chrome = (where == "chrome") || (where == "chromium");

   if (batch_mode) {
      if (!is_cef && !is_chrome) {
         R__ERROR_HERE("WebDisplay") << "To use batch mode 'cef' or 'chromium' should be configured as output";
         return false;
      }
      if (is_cef) {
         const char *displ = gSystem->Getenv("DISPLAY");
         if (!displ || (*displ == 0)) {
            R__ERROR_HERE("WebDisplay") << "For a time been in batch mode DISPLAY variable should be set. See "
                                           "gui/webdisplay/Readme.md for more info";
            return false;
         }
      }
   }

   Func_t symbol_qt5 = gSystem->DynFindSymbol("*", "webgui_start_browser_in_qt5");

   if ((is_native && symbol_qt5) || is_qt5) {
//#ifdef R__HAS_QT5WEBENGINE
      if (!symbol_qt5) {
         gSystem->Load("libROOTQt5WebDisplay");
         symbol_qt5 = gSystem->DynFindSymbol("*", "webgui_start_browser_in_qt5");
      }
//#endif
      if (symbol_qt5) {
         typedef void (*FunctionQt5)(const char *, void *, bool, unsigned, unsigned);
         printf("Show canvas in Qt5 window:  %s\n", addr.Data());
         FunctionQt5 func = (FunctionQt5)symbol_qt5;
         func(addr.Data(), fServer.get(), batch_mode, win.GetWidth(), win.GetHeight());
         return true;
      }
   }

   // TODO: one should try to load CEF libraries only when really needed
   // probably, one should create separate DLL with CEF-related code
   Func_t symbol_cef = gSystem->DynFindSymbol("*", "webgui_start_browser_in_cef3");
   const char *cef_path = gSystem->Getenv("CEF_PATH");
   const char *rootsys = gSystem->Getenv("ROOTSYS");
   if (cef_path && !gSystem->AccessPathName(cef_path) && rootsys && (is_native || is_cef)) {

// #ifdef R__HAS_CEF
      if (!symbol_cef) {
         gSystem->Load("libROOTCefDisplay");
         // TODO: make minimal C++ interface here
         symbol_cef = gSystem->DynFindSymbol("*", "webgui_start_browser_in_cef3");
      }
// #endif

      if (symbol_cef) {

         typedef void (*FunctionCef3)(const char *, void *, bool, const char *, const char *, unsigned, unsigned);

         printf("Show canvas in CEF window:  %s\n", addr.Data());

         FunctionCef3 func = (FunctionCef3)symbol_cef;
         func(addr.Data(), fServer.get(), batch_mode, rootsys, cef_path, win.GetWidth(), win.GetHeight());

         return true;
      }
   }

   if (!CreateHttpServer(true)) {
      R__ERROR_HERE("WebDisplay") << "Fail to start real HTTP server";
      return false;
   }

   addr = fAddr + addr;

   TString exec;

   if (is_chrome) {
      // see https://peter.sh/experiments/chromium-command-line-switches/
      exec = where.c_str();
      if (batch_mode) {
         int debug_port = (int)(9800 + 1000 * gRandom->Rndm(1)); // debug port required to keep chrome running
         exec.Append(Form(" --headless --disable-gpu --disable-webgl --remote-debugging-port=%d ", debug_port));
      } else {
         if (win.GetWidth() && win.GetHeight())
            exec.Append(TString::Format(" --window-size=%u,%u", win.GetWidth(), win.GetHeight()));
         exec.Append(" --app="); // use app mode
      }
      exec.Append("\'");
      exec.Append(addr.Data());
      exec.Append("\' &");
   } else if (!is_native && !is_cef && !is_qt5 && (where != "browser")) {
      if (where.find("$") != std::string::npos) {
         exec = where.c_str();
         exec.ReplaceAll("$url", addr);
         exec.ReplaceAll("$w", std::to_string(win.GetWidth() ? win.GetWidth() : 800).c_str());
         exec.ReplaceAll("$h", std::to_string(win.GetHeight() ? win.GetHeight() : 600).c_str());
      } else {
         exec.Form("%s %s &", where.c_str(), addr.Data());
         // if (batch_mode) exec.Append(" --headless");
      }
   } else if (gSystem->InheritsFrom("TMacOSXSystem")) {
      exec.Form("open \'%s\'", addr.Data());
   } else {
      exec.Form("xdg-open \'%s\' &", addr.Data());
   }

   printf("Show canvas in browser with cmd:  %s\n", exec.Data());

   gSystem->Exec(exec);

   return true;
}

//////////////////////////////////////////////////////////////////////////
/// Waits until provided check function or lambdas returns non-zero value
/// Runs application mainloop and short sleeps in-between
/// timelimit (in seconds) defines how long to wait (0 - forever)
/// Function has following signature: int func(double spent_tm)
/// Parameter spent_tm is time in seconds, which already spent inside function
/// Waiting will be continued, if function returns zero.
/// First non-zero value breaks waiting loop and result is returned (or 0 if time is expired).

int ROOT::Experimental::TWebWindowsManager::WaitFor(WebWindowWaitFunc_t check, double timelimit)
{
   TStopwatch tm;
   tm.Start();
   double spent(0);
   int res(0), cnt(0);

   while ((res = check(spent)) == 0) {
      gSystem->ProcessEvents();
      gSystem->Sleep(10);

      spent = tm.RealTime();
      tm.Continue();
      if ((timelimit > 0) && (spent > timelimit))
         return 0;
      cnt++;
   }
   printf("WAITING RES %d tm %4.2f cnt %d\n", res, spent, cnt);

   return res;
}

//////////////////////////////////////////////////////////////////////////
/// Terminate http server and ROOT application

void ROOT::Experimental::TWebWindowsManager::Terminate()
{
   if (fServer)
      fServer->SetTerminate();

   // use timer to avoid situation when calling object is deleted by terminate
   if (gApplication)
      TTimer::SingleShot(100, "TApplication", gApplication, "Terminate()");
}
<commit_msg>webgui: use new definitions from RConfigure.h<commit_after>/// \file TWebWindowsManager.cxx
/// \ingroup WebGui ROOT7
/// \author Sergey Linev <s.linev@gsi.de>
/// \date 2017-10-16
/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
/// is welcome!

/*************************************************************************
 * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#pragma GCC diagnostic ignored "-Wall"
#pragma GCC diagnostic ignored "-Wunused-parameter"

#include "ROOT/TWebWindowsManager.hxx"

#include <ROOT/TLogger.hxx>

#include <cassert>
#include <cstdio>

#include "THttpServer.h"
#include "THttpWSHandler.h"

#include "TSystem.h"
#include "TRandom.h"
#include "TString.h"
#include "TStopwatch.h"
#include "TApplication.h"
#include "TTimer.h"
#include "RConfigure.h"

/** \class ROOT::Experimental::TWebWindowManager
\ingroup webdisplay

Central instance to create and show web-based windows like Canvas or FitPanel.

Manager responsible to creating THttpServer instance, which is used for TWebWindow's
communication with clients.

Method TWebWindowsManager::Show() used to show window in specified location.
*/

//////////////////////////////////////////////////////////////////////////////////////////
/// Returns default window manager
/// Used to display all standard ROOT elements like TCanvas or TFitPanel

std::shared_ptr<ROOT::Experimental::TWebWindowsManager> &ROOT::Experimental::TWebWindowsManager::Instance()
{
   static std::shared_ptr<TWebWindowsManager> sInstance = std::make_shared<ROOT::Experimental::TWebWindowsManager>();
   return sInstance;
}

//////////////////////////////////////////////////////////////////////////////////////////
/// window manager constructor
/// Required here for correct usage of unique_ptr<THttpServer>

ROOT::Experimental::TWebWindowsManager::TWebWindowsManager() = default;

//////////////////////////////////////////////////////////////////////////////////////////
/// window manager destructor
/// Required here for correct usage of unique_ptr<THttpServer>

ROOT::Experimental::TWebWindowsManager::~TWebWindowsManager()
{
}

//////////////////////////////////////////////////////////////////////////////////////////
/// Creates http server, if required - with real http engine (civetweb)

bool ROOT::Experimental::TWebWindowsManager::CreateHttpServer(bool with_http)
{
   if (!fServer)
      fServer = std::make_unique<THttpServer>("dummy");

   if (!with_http || (fAddr.length() > 0))
      return true;

   // gServer = new THttpServer("http:8080?loopback&websocket_timeout=10000");

   int http_port = 0;
   const char *ports = gSystem->Getenv("WEBGUI_PORT");
   if (ports)
      http_port = std::atoi(ports);
   if (!http_port)
      gRandom->SetSeed(0);

   for (int ntry = 0; ntry < 100; ++ntry) {
      if (!http_port)
         http_port = (int)(8800 + 1000 * gRandom->Rndm(1));

      // TODO: ensure that port can be used
      // TODO: replace TString::Format with more adequate implementation like
      // https://stackoverflow.com/questions/4668760
      if (fServer->CreateEngine(TString::Format("http:%d?websocket_timeout=10000", http_port))) {
         fAddr = "http://localhost:";
         fAddr.append(std::to_string(http_port));
         return true;
      }

      http_port = 0;
   }

   return false;
}

//////////////////////////////////////////////////////////////////////////////////////////
/// Creates new window
/// To show window, TWebWindow::Show() have to be called

std::shared_ptr<ROOT::Experimental::TWebWindow> ROOT::Experimental::TWebWindowsManager::CreateWindow(bool batch_mode)
{
   if (!CreateHttpServer()) {
      R__ERROR_HERE("WebDisplay") << "Cannot create http server when creating window";
      return nullptr;
   }

   std::shared_ptr<ROOT::Experimental::TWebWindow> win = std::make_shared<ROOT::Experimental::TWebWindow>();

   if (!win) {
      R__ERROR_HERE("WebDisplay") << "Fail to create TWebWindow instance";
      return nullptr;
   }

   win->SetBatchMode(batch_mode);

   win->SetId(++fIdCnt); // set unique ID

   // fDisplays.push_back(win);

   win->fMgr = Instance();

   win->CreateWSHandler();

   fServer->Register("/web7gui", (THttpWSHandler *)win->fWSHandler.get());

   return win;
}

//////////////////////////////////////////////////////////////////////////////////////////
/// Release all references to specified window
/// Called from TWebWindow destructor

void ROOT::Experimental::TWebWindowsManager::Unregister(ROOT::Experimental::TWebWindow &win)
{
   // TODO: close all active connections of the window

   if (win.fWSHandler)
      fServer->Unregister((THttpWSHandler *)win.fWSHandler.get());

   //   for (auto displ = fDisplays.begin(); displ != fDisplays.end(); displ++) {
   //      if (displ->get() == win) {
   //         fDisplays.erase(displ);
   //         break;
   //      }
   //   }
}

//////////////////////////////////////////////////////////////////////////
/// Provide URL address to access specified window from inside or from remote

std::string ROOT::Experimental::TWebWindowsManager::GetUrl(ROOT::Experimental::TWebWindow &win, bool remote)
{
   if (!fServer) {
      R__ERROR_HERE("WebDisplay") << "Server instance not exists when requesting window URL";
      return "";
   }

   std::string addr = "/web7gui/";

   addr.append(((THttpWSHandler *)win.fWSHandler.get())->GetName());

   if (win.IsBatchMode())
      addr.append("/?batch_mode");
   else
      addr.append("/");

   if (remote) {
      if (!CreateHttpServer(true)) {
         R__ERROR_HERE("WebDisplay") << "Fail to start real HTTP server when requesting URL";
         return "";
      }

      addr = fAddr + addr;
   }

   return addr;
}

//////////////////////////////////////////////////////////////////////////
/// Show window in specified location
/// Parameter "where" specifies that kind of window display should be used. Possible values:
///
///      cef - Chromium Embeded Framework, local display, local communication
///      qt5 - Qt5 WebEngine (when running via rootqt5), local display, local communication
///  browser - default system web-browser, communication via random http port from range 8800 - 9800
///  chrome  - use Google Chrome web browser (requires at least v60), supports headless mode,
///            preferable display kind if cef is not available
/// chromium - open-source flawor of chrome, available on most Linux distributions
///   native - either any available local display or default browser
///   <prog> - any program name which will be started instead of default browser, like firefox or /usr/bin/opera
///            one could use following parameters:
///               $url - URL address of the widget
///                 $w - widget width
///                 $h - widget height
///
///  If allowed, same window can be displayed several times (like for TCanvas)

bool ROOT::Experimental::TWebWindowsManager::Show(ROOT::Experimental::TWebWindow &win, const std::string &_where)
{
   if (!fServer) {
      R__ERROR_HERE("WebDisplay") << "Server instance not exists to show window";
      return false;
   }

   THttpWSHandler *handler = (THttpWSHandler *)win.fWSHandler.get();
   bool batch_mode = win.IsBatchMode();

   TString addr;
   addr.Form("/web7gui/%s/%s", handler->GetName(), (batch_mode ? "?batch_mode" : ""));

   std::string where = _where;
   if (where.empty()) {
      const char *cwhere = gSystem->Getenv("WEBGUI_WHERE");
      if (cwhere)
         where = cwhere;
   }

   bool is_native = where.empty() || (where == "native"), is_qt5 = (where == "qt5"), is_cef = (where == "cef"),
        is_chrome = (where == "chrome") || (where == "chromium");

   if (batch_mode) {
      if (!is_cef && !is_chrome) {
         R__ERROR_HERE("WebDisplay") << "To use batch mode 'cef' or 'chromium' should be configured as output";
         return false;
      }
      if (is_cef) {
         const char *displ = gSystem->Getenv("DISPLAY");
         if (!displ || (*displ == 0)) {
            R__ERROR_HERE("WebDisplay") << "For a time been in batch mode DISPLAY variable should be set. See "
                                           "gui/webdisplay/Readme.md for more info";
            return false;
         }
      }
   }

#ifdef R__HAS_CEFWEB

   const char *cef_path = gSystem->Getenv("CEF_PATH");
   const char *rootsys = gSystem->Getenv("ROOTSYS");
   if (cef_path && !gSystem->AccessPathName(cef_path) && rootsys && (is_native || is_cef)) {

      Func_t symbol_cef = gSystem->DynFindSymbol("*", "webgui_start_browser_in_cef3");

      if (!symbol_cef) {
         gSystem->Load("libROOTCefDisplay");
         // TODO: make minimal C++ interface here
         symbol_cef = gSystem->DynFindSymbol("*", "webgui_start_browser_in_cef3");
      }

      if (symbol_cef) {
         typedef void (*FunctionCef3)(const char *, void *, bool, const char *, const char *, unsigned, unsigned);
         printf("Show canvas in CEF window:  %s\n", addr.Data());
         FunctionCef3 func = (FunctionCef3)symbol_cef;
         func(addr.Data(), fServer.get(), batch_mode, rootsys, cef_path, win.GetWidth(), win.GetHeight());
         return true;
      }
   }

#endif

#ifdef R__HAS_QT5WEB

   if (is_native || is_qt5) {
      Func_t symbol_qt5 = gSystem->DynFindSymbol("*", "webgui_start_browser_in_qt5");

      if (!symbol_qt5) {
         gSystem->Load("libROOTQt5WebDisplay");
         symbol_qt5 = gSystem->DynFindSymbol("*", "webgui_start_browser_in_qt5");
      }
      if (symbol_qt5) {
         typedef void (*FunctionQt5)(const char *, void *, bool, unsigned, unsigned);
         printf("Show canvas in Qt5 window:  %s\n", addr.Data());
         FunctionQt5 func = (FunctionQt5)symbol_qt5;
         func(addr.Data(), fServer.get(), batch_mode, win.GetWidth(), win.GetHeight());
         return true;
      }
   }
#endif

   if (!CreateHttpServer(true)) {
      R__ERROR_HERE("WebDisplay") << "Fail to start real HTTP server";
      return false;
   }

   addr = fAddr + addr;

   TString exec;

   if (is_chrome) {
      // see https://peter.sh/experiments/chromium-command-line-switches/
      exec = where.c_str();
      if (batch_mode) {
         int debug_port = (int)(9800 + 1000 * gRandom->Rndm(1)); // debug port required to keep chrome running
         exec.Append(Form(" --headless --disable-gpu --disable-webgl --remote-debugging-port=%d ", debug_port));
      } else {
         if (win.GetWidth() && win.GetHeight())
            exec.Append(TString::Format(" --window-size=%u,%u", win.GetWidth(), win.GetHeight()));
         exec.Append(" --app="); // use app mode
      }
      exec.Append("\'");
      exec.Append(addr.Data());
      exec.Append("\' &");
   } else if (!is_native && !is_cef && !is_qt5 && (where != "browser")) {
      if (where.find("$") != std::string::npos) {
         exec = where.c_str();
         exec.ReplaceAll("$url", addr);
         exec.ReplaceAll("$w", std::to_string(win.GetWidth() ? win.GetWidth() : 800).c_str());
         exec.ReplaceAll("$h", std::to_string(win.GetHeight() ? win.GetHeight() : 600).c_str());
      } else {
         exec.Form("%s %s &", where.c_str(), addr.Data());
         // if (batch_mode) exec.Append(" --headless");
      }
   } else if (gSystem->InheritsFrom("TMacOSXSystem")) {
      exec.Form("open \'%s\'", addr.Data());
   } else {
      exec.Form("xdg-open \'%s\' &", addr.Data());
   }

   printf("Show canvas in browser with cmd:  %s\n", exec.Data());

   gSystem->Exec(exec);

   return true;
}

//////////////////////////////////////////////////////////////////////////
/// Waits until provided check function or lambdas returns non-zero value
/// Runs application mainloop and short sleeps in-between
/// timelimit (in seconds) defines how long to wait (0 - forever)
/// Function has following signature: int func(double spent_tm)
/// Parameter spent_tm is time in seconds, which already spent inside function
/// Waiting will be continued, if function returns zero.
/// First non-zero value breaks waiting loop and result is returned (or 0 if time is expired).

int ROOT::Experimental::TWebWindowsManager::WaitFor(WebWindowWaitFunc_t check, double timelimit)
{
   TStopwatch tm;
   tm.Start();
   double spent(0);
   int res(0), cnt(0);

   while ((res = check(spent)) == 0) {
      gSystem->ProcessEvents();
      gSystem->Sleep(10);

      spent = tm.RealTime();
      tm.Continue();
      if ((timelimit > 0) && (spent > timelimit))
         return 0;
      cnt++;
   }
   printf("WAITING RES %d tm %4.2f cnt %d\n", res, spent, cnt);

   return res;
}

//////////////////////////////////////////////////////////////////////////
/// Terminate http server and ROOT application

void ROOT::Experimental::TWebWindowsManager::Terminate()
{
   if (fServer)
      fServer->SetTerminate();

   // use timer to avoid situation when calling object is deleted by terminate
   if (gApplication)
      TTimer::SingleShot(100, "TApplication", gApplication, "Terminate()");
}
<|endoftext|>


<commit_before>/* -*- C++ -*-
 *
 *  ONScripter_file.cpp - FILE I/O of ONScripter
 *
 *  Copyright (c) 2001-2014 Ogapee. All rights reserved.
 *
 *  ogapee@aqua.dti2.ne.jp
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "ONScripter.h"

#if defined(LINUX) || defined(MACOSX) || defined(IOS)
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#elif defined(WIN32)
#include <windows.h>
#elif defined(MACOS9)
#include <DateTimeUtils.h>
#include <Files.h>
extern "C" void c2pstrcpy(Str255 dst, const char *src);	//#include <TextUtils.h>
#elif defined(PSP)
#include <pspiofilemgr.h>
#endif

#define SAVEFILE_MAGIC_NUMBER "ONS"
#define SAVEFILE_VERSION_MAJOR 2
#define SAVEFILE_VERSION_MINOR 8

#define READ_LENGTH 4096

void ONScripter::searchSaveFile( SaveFileInfo &save_file_info, int no )
{
    char file_name[256];

    script_h.getStringFromInteger( save_file_info.sjis_no, no, (num_save_file >= 10)?2:1 );
#if defined(LINUX) || defined(MACOSX) || defined(IOS)
#ifdef ANDROID
    sprintf( file_name, "%s%ssave%d.dat", root_writable?root_writable:"",
		save_dir?save_dir:archive_path, no );
#else
    sprintf( file_name, "%ssave%d.dat", save_dir?save_dir:archive_path, no );
#endif
    struct stat buf;
    struct tm *tm;
    if ( stat( file_name, &buf ) != 0 ){
        save_file_info.valid = false;
        return;
    }
    time_t mtime = buf.st_mtime;
    tm = localtime( &mtime );

    save_file_info.month  = tm->tm_mon + 1;
    save_file_info.day    = tm->tm_mday;
    save_file_info.hour   = tm->tm_hour;
    save_file_info.minute = tm->tm_min;
#elif defined(WIN32)
    sprintf( file_name, "%ssave%d.dat", save_dir?save_dir:archive_path, no );
    HANDLE  handle;
    FILETIME    tm, ltm;
    SYSTEMTIME  stm;

#if defined(WINCE)
    WCHAR file_nameW[256];
    MultiByteToWideChar(CP_ACP, 0, file_name, -1, file_nameW, 256);
    handle = CreateFile( file_nameW, GENERIC_READ, 0, NULL,
                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
#else
    handle = CreateFile( file_name, GENERIC_READ, 0, NULL,
                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
#endif
    if ( handle == INVALID_HANDLE_VALUE ){
        save_file_info.valid = false;
        return;
    }

    GetFileTime( handle, NULL, NULL, &tm );
    FileTimeToLocalFileTime( &tm, &ltm );
    FileTimeToSystemTime( &ltm, &stm );
    CloseHandle( handle );

    save_file_info.month  = stm.wMonth;
    save_file_info.day    = stm.wDay;
    save_file_info.hour   = stm.wHour;
    save_file_info.minute = stm.wMinute;
#elif defined(MACOS9)
    sprintf( file_name, "%ssave%d.dat", save_dir?save_dir:archive_path, no );
    CInfoPBRec  pb;
    Str255      p_file_name;
    FSSpec      file_spec;
    DateTimeRec tm;
    c2pstrcpy( p_file_name, file_name );
    if ( FSMakeFSSpec(0, 0, p_file_name, &file_spec) != noErr ){
        save_file_info.valid = false;
        return;
    }
    pb.hFileInfo.ioNamePtr = file_spec.name;
    pb.hFileInfo.ioVRefNum = file_spec.vRefNum;
    pb.hFileInfo.ioFDirIndex = 0;
    pb.hFileInfo.ioDirID = file_spec.parID;
    if (PBGetCatInfoSync(&pb) != noErr) {
        save_file_info.valid = false;
        return;
    }
    SecondsToDate( pb.hFileInfo.ioFlMdDat, &tm );
    save_file_info.month  = tm.month;
    save_file_info.day    = tm.day;
    save_file_info.hour   = tm.hour;
    save_file_info.minute = tm.minute;
#elif defined(PSP)
    sprintf( file_name, "%ssave%d.dat", save_dir?save_dir:archive_path, no );
    SceIoStat buf;
    if ( sceIoGetstat(file_name, &buf)<0 ){
        save_file_info.valid = false;
        return;
    }

    save_file_info.month  = buf.st_mtime.month;
    save_file_info.day    = buf.st_mtime.day;
    save_file_info.hour   = buf.st_mtime.hour;
    save_file_info.minute = buf.st_mtime.minute;
#else
    sprintf( file_name, "save%d.dat", no );
    FILE *fp;
#ifdef ANDROID
    if ( (fp = fopen( file_name, "rb", true, true )) == NULL ){
#else
    if ( (fp = fopen( file_name, "rb", true )) == NULL ){
#endif
        save_file_info.valid = false;
        return;
    }
    fclose( fp );

    save_file_info.month  = 1;
    save_file_info.day    = 1;
    save_file_info.hour   = 0;
    save_file_info.minute = 0;
#endif
    save_file_info.valid = true;
    script_h.getStringFromInteger( save_file_info.sjis_month,  save_file_info.month,  2 );
    script_h.getStringFromInteger( save_file_info.sjis_day,    save_file_info.day,    2 );
    script_h.getStringFromInteger( save_file_info.sjis_hour,   save_file_info.hour,   2 );
    script_h.getStringFromInteger( save_file_info.sjis_minute, save_file_info.minute, 2, true );
}

char *ONScripter::readSaveStrFromFile( int no )
{
    char filename[32];
    sprintf( filename, "save%d.dat", no );
    size_t len = loadFileIOBuf( filename );
    if (len == 0){
        loge( stderr, "readSaveStrFromFile: can't open save file %s\n", filename );
        return NULL;
    }

    int p = len - 1;
    if ( p < 3 || file_io_buf[p] != '*' || file_io_buf[p-1] != '"' ) return NULL;
    p -= 2;

    while( file_io_buf[p] != '"' && p>0 ) p--;
    if ( file_io_buf[p] != '"' ) return NULL;

    len = len - p - 3;
    char *buf = new char[len+1];

    unsigned int i;
    for (i=0 ; i<len ; i++)
        buf[i] = file_io_buf[p+i+1];
    buf[i] = 0;

    return buf;
}

int ONScripter::loadSaveFile( int no )
{
    char filename[32];
    sprintf( filename, "save%d.dat", no );
    if (loadFileIOBuf( filename ) == 0){
        loge( stderr, "can't open save file %s\n", filename );
        return -1;
    }

    /* ---------------------------------------- */
    /* Load magic number */
    int i;
    for ( i=0 ; i<(int)strlen( SAVEFILE_MAGIC_NUMBER ) ; i++ )
        if ( readChar() != SAVEFILE_MAGIC_NUMBER[i] ) break;

    if ( i != (int)strlen( SAVEFILE_MAGIC_NUMBER ) ){
        file_io_buf_ptr = 0;
        logv("Save file version is unknown\n" );
        return loadSaveFile2( SAVEFILE_VERSION_MAJOR*100 + SAVEFILE_VERSION_MINOR );
    }

    int file_version = readChar() * 100;
    file_version += readChar();
    logv("Save file version is %d.%d\n", file_version/100, file_version%100 );
    if ( file_version > SAVEFILE_VERSION_MAJOR*100 + SAVEFILE_VERSION_MINOR ){
        loge( stderr, "Save file is newer than %d.%d, please use the latest ONScripter.\n", SAVEFILE_VERSION_MAJOR, SAVEFILE_VERSION_MINOR );
        return -1;
    }

    if ( file_version >= 200 )
        return loadSaveFile2( file_version );

    logw( stderr, "Save file is too old.\n");

    return -1;
}

void ONScripter::saveMagicNumber( bool output_flag )
{
    for ( unsigned int i=0 ; i<strlen( SAVEFILE_MAGIC_NUMBER ) ; i++ )
        writeChar( SAVEFILE_MAGIC_NUMBER[i], output_flag );
    writeChar( SAVEFILE_VERSION_MAJOR, output_flag );
    writeChar( SAVEFILE_VERSION_MINOR, output_flag );
}

int ONScripter::saveSaveFile( bool write_to_disk, int no, const char *savestr )
{
    // make save data structure on memory
    if (!write_to_disk || (saveon_flag && internal_saveon_flag)){
        file_io_buf_ptr = 0;
        saveMagicNumber( false );
        saveSaveFile2( false );
        allocFileIOBuf();
        saveMagicNumber( true );
        saveSaveFile2( true );
        save_data_len = file_io_buf_ptr;
        memcpy(save_data_buf, file_io_buf, save_data_len);
    }

    if (write_to_disk){
        saveAll();

        char filename[32];
        sprintf( filename, "save%d.dat", no );

        memcpy(file_io_buf, save_data_buf, save_data_len);
        file_io_buf_ptr = save_data_len;
        if (saveFileIOBuf( filename, 0, savestr )){
            loge( stderr, "can't open save file %s for writing\n", filename );
            return -1;
        }

        size_t magic_len = strlen(SAVEFILE_MAGIC_NUMBER)+2;
        sprintf( filename, RELATIVEPATH "sav%csave%d.dat", DELIMITER, no );
        if (saveFileIOBuf( filename, magic_len, savestr ))
            logw( stderr, "can't open save file %s for writing (not an error)\n", filename );
    }

    return 0;
}
<commit_msg>When unable to file save file, do not make exception<commit_after>/* -*- C++ -*-
 *
 *  ONScripter_file.cpp - FILE I/O of ONScripter
 *
 *  Copyright (c) 2001-2014 Ogapee. All rights reserved.
 *
 *  ogapee@aqua.dti2.ne.jp
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "ONScripter.h"

#if defined(LINUX) || defined(MACOSX) || defined(IOS)
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#elif defined(WIN32)
#include <windows.h>
#elif defined(MACOS9)
#include <DateTimeUtils.h>
#include <Files.h>
extern "C" void c2pstrcpy(Str255 dst, const char *src);	//#include <TextUtils.h>
#elif defined(PSP)
#include <pspiofilemgr.h>
#endif

#define SAVEFILE_MAGIC_NUMBER "ONS"
#define SAVEFILE_VERSION_MAJOR 2
#define SAVEFILE_VERSION_MINOR 8

#define READ_LENGTH 4096

void ONScripter::searchSaveFile( SaveFileInfo &save_file_info, int no )
{
    char file_name[256];

    script_h.getStringFromInteger( save_file_info.sjis_no, no, (num_save_file >= 10)?2:1 );
#if defined(LINUX) || defined(MACOSX) || defined(IOS)
#ifdef ANDROID
    sprintf( file_name, "%s%ssave%d.dat", root_writable?root_writable:"",
		save_dir?save_dir:archive_path, no );
#else
    sprintf( file_name, "%ssave%d.dat", save_dir?save_dir:archive_path, no );
#endif
    struct stat buf;
    struct tm *tm;
    if ( stat( file_name, &buf ) != 0 ){
        save_file_info.valid = false;
        return;
    }
    time_t mtime = buf.st_mtime;
    tm = localtime( &mtime );

    save_file_info.month  = tm->tm_mon + 1;
    save_file_info.day    = tm->tm_mday;
    save_file_info.hour   = tm->tm_hour;
    save_file_info.minute = tm->tm_min;
#elif defined(WIN32)
    sprintf( file_name, "%ssave%d.dat", save_dir?save_dir:archive_path, no );
    HANDLE  handle;
    FILETIME    tm, ltm;
    SYSTEMTIME  stm;

#if defined(WINCE)
    WCHAR file_nameW[256];
    MultiByteToWideChar(CP_ACP, 0, file_name, -1, file_nameW, 256);
    handle = CreateFile( file_nameW, GENERIC_READ, 0, NULL,
                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
#else
    handle = CreateFile( file_name, GENERIC_READ, 0, NULL,
                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
#endif
    if ( handle == INVALID_HANDLE_VALUE ){
        save_file_info.valid = false;
        return;
    }

    GetFileTime( handle, NULL, NULL, &tm );
    FileTimeToLocalFileTime( &tm, &ltm );
    FileTimeToSystemTime( &ltm, &stm );
    CloseHandle( handle );

    save_file_info.month  = stm.wMonth;
    save_file_info.day    = stm.wDay;
    save_file_info.hour   = stm.wHour;
    save_file_info.minute = stm.wMinute;
#elif defined(MACOS9)
    sprintf( file_name, "%ssave%d.dat", save_dir?save_dir:archive_path, no );
    CInfoPBRec  pb;
    Str255      p_file_name;
    FSSpec      file_spec;
    DateTimeRec tm;
    c2pstrcpy( p_file_name, file_name );
    if ( FSMakeFSSpec(0, 0, p_file_name, &file_spec) != noErr ){
        save_file_info.valid = false;
        return;
    }
    pb.hFileInfo.ioNamePtr = file_spec.name;
    pb.hFileInfo.ioVRefNum = file_spec.vRefNum;
    pb.hFileInfo.ioFDirIndex = 0;
    pb.hFileInfo.ioDirID = file_spec.parID;
    if (PBGetCatInfoSync(&pb) != noErr) {
        save_file_info.valid = false;
        return;
    }
    SecondsToDate( pb.hFileInfo.ioFlMdDat, &tm );
    save_file_info.month  = tm.month;
    save_file_info.day    = tm.day;
    save_file_info.hour   = tm.hour;
    save_file_info.minute = tm.minute;
#elif defined(PSP)
    sprintf( file_name, "%ssave%d.dat", save_dir?save_dir:archive_path, no );
    SceIoStat buf;
    if ( sceIoGetstat(file_name, &buf)<0 ){
        save_file_info.valid = false;
        return;
    }

    save_file_info.month  = buf.st_mtime.month;
    save_file_info.day    = buf.st_mtime.day;
    save_file_info.hour   = buf.st_mtime.hour;
    save_file_info.minute = buf.st_mtime.minute;
#else
    sprintf( file_name, "save%d.dat", no );
    FILE *fp;
#ifdef ANDROID
    if ( (fp = fopen( file_name, "rb", true, true )) == NULL ){
#else
    if ( (fp = fopen( file_name, "rb", true )) == NULL ){
#endif
        save_file_info.valid = false;
        return;
    }
    fclose( fp );

    save_file_info.month  = 1;
    save_file_info.day    = 1;
    save_file_info.hour   = 0;
    save_file_info.minute = 0;
#endif
    save_file_info.valid = true;
    script_h.getStringFromInteger( save_file_info.sjis_month,  save_file_info.month,  2 );
    script_h.getStringFromInteger( save_file_info.sjis_day,    save_file_info.day,    2 );
    script_h.getStringFromInteger( save_file_info.sjis_hour,   save_file_info.hour,   2 );
    script_h.getStringFromInteger( save_file_info.sjis_minute, save_file_info.minute, 2, true );
}

char *ONScripter::readSaveStrFromFile( int no )
{
    char filename[32];
    sprintf( filename, "save%d.dat", no );
    size_t len = loadFileIOBuf( filename );
    if (len == 0){
        loge( stderr, "readSaveStrFromFile: can't open save file %s\n", filename );
        return NULL;
    }

    int p = len - 1;
    if ( p < 3 || file_io_buf[p] != '*' || file_io_buf[p-1] != '"' ) return NULL;
    p -= 2;

    while( file_io_buf[p] != '"' && p>0 ) p--;
    if ( file_io_buf[p] != '"' ) return NULL;

    len = len - p - 3;
    char *buf = new char[len+1];

    unsigned int i;
    for (i=0 ; i<len ; i++)
        buf[i] = file_io_buf[p+i+1];
    buf[i] = 0;

    return buf;
}

int ONScripter::loadSaveFile( int no )
{
    char filename[32];
    sprintf( filename, "save%d.dat", no );
    if (loadFileIOBuf( filename ) == 0){
        logw( stderr, "can't open save file %s\n", filename );
        return -1;
    }

    /* ---------------------------------------- */
    /* Load magic number */
    int i;
    for ( i=0 ; i<(int)strlen( SAVEFILE_MAGIC_NUMBER ) ; i++ )
        if ( readChar() != SAVEFILE_MAGIC_NUMBER[i] ) break;

    if ( i != (int)strlen( SAVEFILE_MAGIC_NUMBER ) ){
        file_io_buf_ptr = 0;
        logv("Save file version is unknown\n" );
        return loadSaveFile2( SAVEFILE_VERSION_MAJOR*100 + SAVEFILE_VERSION_MINOR );
    }

    int file_version = readChar() * 100;
    file_version += readChar();
    logv("Save file version is %d.%d\n", file_version/100, file_version%100 );
    if ( file_version > SAVEFILE_VERSION_MAJOR*100 + SAVEFILE_VERSION_MINOR ){
        loge( stderr, "Save file is newer than %d.%d, please use the latest ONScripter.\n", SAVEFILE_VERSION_MAJOR, SAVEFILE_VERSION_MINOR );
        return -1;
    }

    if ( file_version >= 200 )
        return loadSaveFile2( file_version );

    logw( stderr, "Save file is too old.\n");

    return -1;
}

void ONScripter::saveMagicNumber( bool output_flag )
{
    for ( unsigned int i=0 ; i<strlen( SAVEFILE_MAGIC_NUMBER ) ; i++ )
        writeChar( SAVEFILE_MAGIC_NUMBER[i], output_flag );
    writeChar( SAVEFILE_VERSION_MAJOR, output_flag );
    writeChar( SAVEFILE_VERSION_MINOR, output_flag );
}

int ONScripter::saveSaveFile( bool write_to_disk, int no, const char *savestr )
{
    // make save data structure on memory
    if (!write_to_disk || (saveon_flag && internal_saveon_flag)){
        file_io_buf_ptr = 0;
        saveMagicNumber( false );
        saveSaveFile2( false );
        allocFileIOBuf();
        saveMagicNumber( true );
        saveSaveFile2( true );
        save_data_len = file_io_buf_ptr;
        memcpy(save_data_buf, file_io_buf, save_data_len);
    }

    if (write_to_disk){
        saveAll();

        char filename[32];
        sprintf( filename, "save%d.dat", no );

        memcpy(file_io_buf, save_data_buf, save_data_len);
        file_io_buf_ptr = save_data_len;
        if (saveFileIOBuf( filename, 0, savestr )){
            loge( stderr, "can't open save file %s for writing\n", filename );
            return -1;
        }

        size_t magic_len = strlen(SAVEFILE_MAGIC_NUMBER)+2;
        sprintf( filename, RELATIVEPATH "sav%csave%d.dat", DELIMITER, no );
        if (saveFileIOBuf( filename, magic_len, savestr ))
            logw( stderr, "can't open save file %s for writing (not an error)\n", filename );
    }

    return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <windows.h>
#include <tchar.h>

#include "base/at_exit.h"
#include "base/command_line.h"
#include "chrome/app/breakpad_win.h"
#include "chrome/app/client_util.h"
#include "chrome/app/metro_driver_win.h"
#include "content/public/app/startup_helper_win.h"
#include "content/public/common/result_codes.h"
#include "sandbox/src/sandbox_factory.h"

int RunChrome(HINSTANCE instance) {
  bool exit_now = true;
  // We restarted because of a previous crash. Ask user if we should relaunch.
  if (ShowRestartDialogIfCrashed(&exit_now)) {
    if (exit_now)
      return content::RESULT_CODE_NORMAL_EXIT;
  }

  // Initialize the sandbox services.
  sandbox::SandboxInterfaceInfo sandbox_info = {0};
  content::InitializeSandboxInfo(&sandbox_info);

  // The exit manager is in charge of calling the dtors of singletons.
  base::AtExitManager exit_manager;

  // Initialize the commandline singleton from the environment.
  CommandLine::Init(0, NULL);

  // Load and launch the chrome dll. *Everything* happens inside.
  MainDllLoader* loader = MakeMainDllLoader();
  int rc = loader->Launch(instance, &sandbox_info);
  loader->RelaunchChromeBrowserWithNewCommandLineIfNeeded();
  delete loader;
  return rc;
}

int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prev, wchar_t*, int) {
  MetroDriver metro_driver;
  if (metro_driver.in_metro_mode())
    return metro_driver.RunInMetro(instance, &RunChrome);
  // Not in metro mode, proceed as normal.
  return RunChrome(instance);
}
<commit_msg>Fix the launch via metro_driver<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <windows.h>
#include <tchar.h>

#include "base/at_exit.h"
#include "base/command_line.h"
#include "chrome/app/breakpad_win.h"
#include "chrome/app/client_util.h"
#include "chrome/app/metro_driver_win.h"
#include "content/public/app/startup_helper_win.h"
#include "content/public/common/result_codes.h"
#include "sandbox/src/sandbox_factory.h"

int RunChrome(HINSTANCE instance) {
  bool exit_now = true;
  // We restarted because of a previous crash. Ask user if we should relaunch.
  if (ShowRestartDialogIfCrashed(&exit_now)) {
    if (exit_now)
      return content::RESULT_CODE_NORMAL_EXIT;
  }

  // Initialize the sandbox services.
  sandbox::SandboxInterfaceInfo sandbox_info = {0};
  content::InitializeSandboxInfo(&sandbox_info);

  // Load and launch the chrome dll. *Everything* happens inside.
  MainDllLoader* loader = MakeMainDllLoader();
  int rc = loader->Launch(instance, &sandbox_info);
  loader->RelaunchChromeBrowserWithNewCommandLineIfNeeded();
  delete loader;
  return rc;
}

int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prev, wchar_t*, int) {
  // Initialize the commandline singleton from the environment.
  CommandLine::Init(0, NULL);
  // The exit manager is in charge of calling the dtors of singletons.
  base::AtExitManager exit_manager;

  MetroDriver metro_driver;
  if (metro_driver.in_metro_mode())
    return metro_driver.RunInMetro(instance, &RunChrome);
  // Not in metro mode, proceed as normal.
  return RunChrome(instance);
}
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/history/snippet.h"

#include <algorithm>

#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "base/string_util.h"
#include "unicode/brkiter.h"
#include "unicode/utext.h"
#include "unicode/utf8.h"

namespace {

bool PairFirstLessThan(const Snippet::MatchPosition& a,
                       const Snippet::MatchPosition& b) {
  return a.first < b.first;
}

// Combines all pairs after offset in match_positions that are contained
// or touch the pair at offset.
void CoalescePositionsFrom(size_t offset,
                           Snippet::MatchPositions* match_positions) {
  DCHECK(offset < match_positions->size());
  Snippet::MatchPosition& pair((*match_positions)[offset]);
  ++offset;
  while (offset < match_positions->size() &&
         pair.second >= (*match_positions)[offset].first) {
    pair.second = std::max(pair.second, (*match_positions)[offset].second);
    match_positions->erase(match_positions->begin() + offset);
  }
}

// Makes sure there is a pair in match_positions that contains the specified
// range. This keeps the pairs ordered in match_positions by first, and makes
// sure none of the pairs in match_positions touch each other.
void AddMatch(size_t start,
              size_t end,
              Snippet::MatchPositions* match_positions) {
  DCHECK(start < end);
  DCHECK(match_positions);
  Snippet::MatchPosition pair(start, end);
  if (match_positions->empty()) {
    match_positions->push_back(pair);
    return;
  }
  // There's at least one match. Find the position of the new match,
  // potentially extending pairs around it.
  Snippet::MatchPositions::iterator i =
      std::lower_bound(match_positions->begin(), match_positions->end(),
                       pair, &PairFirstLessThan);
  if (i != match_positions->end() && i->first == start) {
    // Match not at the end and there is already a pair with the same
    // start.
    if (end > i->second) {
      // New pair extends beyond existing pair. Extend existing pair and
      // coalesce matches after it.
      i->second = end;
      CoalescePositionsFrom(i - match_positions->begin(), match_positions);
    } // else case, new pair completely contained in existing pair, nothing
      // to do.
  } else if (i == match_positions->begin()) {
    // Match at the beginning and the first pair doesn't have the same
    // start. Insert new pair and coalesce matches after it.
    match_positions->insert(i, pair);
    CoalescePositionsFrom(0, match_positions);
  } else {
    // Not at the beginning (but may be at the end).
    --i;
    if (start <= i->second && end > i->second) {
      // Previous element contains match. Extend it and coalesce.
      i->second = end;
      CoalescePositionsFrom(i - match_positions->begin(), match_positions);
    } else if (end > i->second) {
      // Region doesn't touch previous element. See if region touches current
      // element.
      ++i;
      if (i == match_positions->end() || end < i->first) {
        match_positions->insert(i, pair);
      } else {
        i->first = start;
        i->second = end;
        CoalescePositionsFrom(i - match_positions->begin(), match_positions);
      }
    }
  }
}

// Converts an index in a utf8 string into the index in the corresponding wide
// string and returns the wide index. This is intended to be called in a loop
// iterating through a utf8 string.
//
// utf8_string: the utf8 string.
// utf8_length: length of the utf8 string.
// offset: the utf8 offset to convert.
// utf8_pos: current offset in the utf8 string. This is modified and on return
//           matches offset.
// wide_pos: current index in the wide string. This is the same as the return
//           value.
size_t AdvanceAndReturnWidePos(const char* utf8_string,
                               int32_t utf8_length,
                               int32_t offset,
                               int32_t* utf8_pos,
                               size_t* wide_pos) {
  DCHECK(offset >= *utf8_pos && offset <= utf8_length);

  UChar32 wide_char;
  while (*utf8_pos < offset) {
    U8_NEXT(utf8_string, *utf8_pos, utf8_length, wide_char);
    *wide_pos += (wide_char <= 0xFFFF) ? 1 : 2;
  }
  return *wide_pos;
}

// Given a character break iterator over a UTF-8 string, set the iterator
// position to |*utf8_pos| and move by |count| characters. |count| can
// be either positive or negative.
void MoveByNGraphemes(BreakIterator* bi, int count, size_t* utf8_pos) {
  // Ignore the return value. A side effect of the current position
  // being set at or following |*utf8_pos| is exploited here.
  // It's simpler than calling following(n) and then previous().
  // isBoundary() is not very fast, but should be good enough for the
  // snippet generation. If not, revisit the way we scan in ComputeSnippet.
  bi->isBoundary(*utf8_pos);
  bi->next(count);
  *utf8_pos = static_cast<size_t>(bi->current());
}

// The amount of context to include for a given hit. Note that it's counted
// in terms of graphemes rather than bytes.
const int kSnippetContext = 50;

// Returns true if next match falls within a snippet window
// from the previous match. The window size is counted in terms
// of graphemes rather than bytes in UTF-8.
bool IsNextMatchWithinSnippetWindow(BreakIterator* bi,
                                    size_t previous_match_end,
                                    size_t next_match_start) {
  // If it's within a window in terms of bytes, it's certain
  // that it's within a window in terms of graphemes as well.
  if (next_match_start < previous_match_end + kSnippetContext)
    return true;
  bi->isBoundary(previous_match_end);
  // An alternative to this is to call |bi->next()| at most
  // kSnippetContext times, compare |bi->current()| with |next_match_start|
  // after each call and return early if possible. There are other
  // heuristics to speed things up if necessary, but it's not likely that
  // we need to bother.
  bi->next(kSnippetContext);
  int64 current = bi->current();
  return (next_match_start < static_cast<uint64>(current) ||
          current == BreakIterator::DONE);
}

}  // namespace

// static
void Snippet::ExtractMatchPositions(const std::string& offsets_str,
                                    const std::string& column_num,
                                    MatchPositions* match_positions) {
  DCHECK(match_positions);
  if (offsets_str.empty())
    return;
  std::vector<std::string> offsets;
  SplitString(offsets_str, ' ', &offsets);
  // SQLite offsets are sets of four integers:
  //   column, query term, match offset, match length
  // Matches within a string are marked by (start, end) pairs.
  for (size_t i = 0; i < offsets.size() - 3; i += 4) {
    if (offsets[i] != column_num)
      continue;
    const size_t start = atoi(offsets[i + 2].c_str());
    const size_t end = start + atoi(offsets[i + 3].c_str());
    AddMatch(start, end, match_positions);
  }
}

// static
void Snippet::ConvertMatchPositionsToWide(
    const std::string& utf8_string,
    Snippet::MatchPositions* match_positions) {
  DCHECK(match_positions);
  int32_t utf8_pos = 0;
  size_t wide_pos = 0;
  const char* utf8_cstring = utf8_string.c_str();
  const int32_t utf8_length = static_cast<int32_t>(utf8_string.size());
  for (Snippet::MatchPositions::iterator i = match_positions->begin();
       i != match_positions->end(); ++i) {
    i->first = AdvanceAndReturnWidePos(utf8_cstring, utf8_length,
                                       i->first, &utf8_pos, &wide_pos);
    i->second = AdvanceAndReturnWidePos(utf8_cstring, utf8_length,
                                        i->second, &utf8_pos, &wide_pos);
  }
}

void Snippet::ComputeSnippet(const MatchPositions& match_positions,
                             const std::string& document) {
  // The length of snippets we try to produce.
  // We can generate longer snippets but stop once we cross kSnippetMaxLength.
  const size_t kSnippetMaxLength = 200;
  const std::wstring kEllipsis = L" ... ";

  UText* document_utext = NULL;
  UErrorCode status = U_ZERO_ERROR;
  document_utext = utext_openUTF8(document_utext, document.data(),
                                  document.size(), &status);
  // Locale does not matter because there's no per-locale customization
  // for character iterator.
  scoped_ptr<BreakIterator> bi(
    BreakIterator::createCharacterInstance(Locale::getDefault(), status));
  bi->setText(document_utext, status);
  DCHECK(U_SUCCESS(status));

  // We build the snippet by iterating through the matches and then grabbing
  // context around each match.  If matches are near enough each other (within
  // kSnippetContext), we skip the "..." between them.
  std::wstring snippet;
  size_t start = 0;
  for (size_t i = 0; i < match_positions.size(); ++i) {
    // Some shorter names for the current match.
    const size_t match_start = match_positions[i].first;
    const size_t match_end = match_positions[i].second;

    // Add the context, if any, to show before the match.
    size_t context_start = match_start;
    MoveByNGraphemes(bi.get(), -kSnippetContext, &context_start);
    start = std::max(start, context_start);
    if (start < match_start) {
      if (start > 0)
        snippet += kEllipsis;
      snippet += UTF8ToWide(document.substr(start, match_start - start));
    }

    // Add the match.
    const size_t first = snippet.size();
    snippet += UTF8ToWide(document.substr(match_start,
                                          match_end - match_start));
    matches_.push_back(std::make_pair(first, snippet.size()));

    // Compute the context, if any, to show after the match.
    size_t end;
    // Check if the next match falls within our snippet window.
    if (i + 1 < match_positions.size() &&
        IsNextMatchWithinSnippetWindow(bi.get(), match_end,
            match_positions[i + 1].first)) {
      // Yes, it's within the window.  Make the end context extend just up
      // to the next match.
      end = match_positions[i + 1].first;
      snippet += UTF8ToWide(document.substr(match_end, end - match_end));
    } else {
      // No, there's either no next match or the next match is too far away.
      end = match_end;
      MoveByNGraphemes(bi.get(), kSnippetContext, &end);
      snippet += UTF8ToWide(document.substr(match_end, end - match_end));
      if (end < document.size())
        snippet += kEllipsis;
    }
    start = end;

    // Stop here if we have enough snippet computed.
    if (snippet.size() >= kSnippetMaxLength)
      break;
  }

  utext_close(document_utext);
  swap(text_, snippet);
}
<commit_msg>Linux: Add CHECKs to track down source of history std::string out of range exceptions. BUG=http://crbug.com/15261<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/history/snippet.h"

#include <algorithm>

#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "base/string_util.h"
#include "unicode/brkiter.h"
#include "unicode/utext.h"
#include "unicode/utf8.h"

namespace {

bool PairFirstLessThan(const Snippet::MatchPosition& a,
                       const Snippet::MatchPosition& b) {
  return a.first < b.first;
}

// Combines all pairs after offset in match_positions that are contained
// or touch the pair at offset.
void CoalescePositionsFrom(size_t offset,
                           Snippet::MatchPositions* match_positions) {
  DCHECK(offset < match_positions->size());
  Snippet::MatchPosition& pair((*match_positions)[offset]);
  ++offset;
  while (offset < match_positions->size() &&
         pair.second >= (*match_positions)[offset].first) {
    pair.second = std::max(pair.second, (*match_positions)[offset].second);
    match_positions->erase(match_positions->begin() + offset);
  }
}

// Makes sure there is a pair in match_positions that contains the specified
// range. This keeps the pairs ordered in match_positions by first, and makes
// sure none of the pairs in match_positions touch each other.
void AddMatch(size_t start,
              size_t end,
              Snippet::MatchPositions* match_positions) {
  DCHECK(start < end);
  DCHECK(match_positions);
  Snippet::MatchPosition pair(start, end);
  if (match_positions->empty()) {
    match_positions->push_back(pair);
    return;
  }
  // There's at least one match. Find the position of the new match,
  // potentially extending pairs around it.
  Snippet::MatchPositions::iterator i =
      std::lower_bound(match_positions->begin(), match_positions->end(),
                       pair, &PairFirstLessThan);
  if (i != match_positions->end() && i->first == start) {
    // Match not at the end and there is already a pair with the same
    // start.
    if (end > i->second) {
      // New pair extends beyond existing pair. Extend existing pair and
      // coalesce matches after it.
      i->second = end;
      CoalescePositionsFrom(i - match_positions->begin(), match_positions);
    } // else case, new pair completely contained in existing pair, nothing
      // to do.
  } else if (i == match_positions->begin()) {
    // Match at the beginning and the first pair doesn't have the same
    // start. Insert new pair and coalesce matches after it.
    match_positions->insert(i, pair);
    CoalescePositionsFrom(0, match_positions);
  } else {
    // Not at the beginning (but may be at the end).
    --i;
    if (start <= i->second && end > i->second) {
      // Previous element contains match. Extend it and coalesce.
      i->second = end;
      CoalescePositionsFrom(i - match_positions->begin(), match_positions);
    } else if (end > i->second) {
      // Region doesn't touch previous element. See if region touches current
      // element.
      ++i;
      if (i == match_positions->end() || end < i->first) {
        match_positions->insert(i, pair);
      } else {
        i->first = start;
        i->second = end;
        CoalescePositionsFrom(i - match_positions->begin(), match_positions);
      }
    }
  }
}

// Converts an index in a utf8 string into the index in the corresponding wide
// string and returns the wide index. This is intended to be called in a loop
// iterating through a utf8 string.
//
// utf8_string: the utf8 string.
// utf8_length: length of the utf8 string.
// offset: the utf8 offset to convert.
// utf8_pos: current offset in the utf8 string. This is modified and on return
//           matches offset.
// wide_pos: current index in the wide string. This is the same as the return
//           value.
size_t AdvanceAndReturnWidePos(const char* utf8_string,
                               int32_t utf8_length,
                               int32_t offset,
                               int32_t* utf8_pos,
                               size_t* wide_pos) {
  DCHECK(offset >= *utf8_pos && offset <= utf8_length);

  UChar32 wide_char;
  while (*utf8_pos < offset) {
    U8_NEXT(utf8_string, *utf8_pos, utf8_length, wide_char);
    *wide_pos += (wide_char <= 0xFFFF) ? 1 : 2;
  }
  return *wide_pos;
}

// Given a character break iterator over a UTF-8 string, set the iterator
// position to |*utf8_pos| and move by |count| characters. |count| can
// be either positive or negative.
void MoveByNGraphemes(BreakIterator* bi, int count, size_t* utf8_pos) {
  // Ignore the return value. A side effect of the current position
  // being set at or following |*utf8_pos| is exploited here.
  // It's simpler than calling following(n) and then previous().
  // isBoundary() is not very fast, but should be good enough for the
  // snippet generation. If not, revisit the way we scan in ComputeSnippet.
  bi->isBoundary(*utf8_pos);
  bi->next(count);
  *utf8_pos = static_cast<size_t>(bi->current());
}

// The amount of context to include for a given hit. Note that it's counted
// in terms of graphemes rather than bytes.
const int kSnippetContext = 50;

// Returns true if next match falls within a snippet window
// from the previous match. The window size is counted in terms
// of graphemes rather than bytes in UTF-8.
bool IsNextMatchWithinSnippetWindow(BreakIterator* bi,
                                    size_t previous_match_end,
                                    size_t next_match_start) {
  // If it's within a window in terms of bytes, it's certain
  // that it's within a window in terms of graphemes as well.
  if (next_match_start < previous_match_end + kSnippetContext)
    return true;
  bi->isBoundary(previous_match_end);
  // An alternative to this is to call |bi->next()| at most
  // kSnippetContext times, compare |bi->current()| with |next_match_start|
  // after each call and return early if possible. There are other
  // heuristics to speed things up if necessary, but it's not likely that
  // we need to bother.
  bi->next(kSnippetContext);
  int64 current = bi->current();
  return (next_match_start < static_cast<uint64>(current) ||
          current == BreakIterator::DONE);
}

}  // namespace

// static
void Snippet::ExtractMatchPositions(const std::string& offsets_str,
                                    const std::string& column_num,
                                    MatchPositions* match_positions) {
  DCHECK(match_positions);
  if (offsets_str.empty())
    return;
  std::vector<std::string> offsets;
  SplitString(offsets_str, ' ', &offsets);
  // SQLite offsets are sets of four integers:
  //   column, query term, match offset, match length
  // Matches within a string are marked by (start, end) pairs.
  for (size_t i = 0; i < offsets.size() - 3; i += 4) {
    if (offsets[i] != column_num)
      continue;
    const size_t start = atoi(offsets[i + 2].c_str());
    const size_t end = start + atoi(offsets[i + 3].c_str());
    // Switch to DCHECK after debugging http://crbug.com/15261.
    CHECK(end >= start);
    AddMatch(start, end, match_positions);
  }
}

// static
void Snippet::ConvertMatchPositionsToWide(
    const std::string& utf8_string,
    Snippet::MatchPositions* match_positions) {
  DCHECK(match_positions);
  int32_t utf8_pos = 0;
  size_t wide_pos = 0;
  const char* utf8_cstring = utf8_string.c_str();
  const int32_t utf8_length = static_cast<int32_t>(utf8_string.size());
  for (Snippet::MatchPositions::iterator i = match_positions->begin();
       i != match_positions->end(); ++i) {
    i->first = AdvanceAndReturnWidePos(utf8_cstring, utf8_length,
                                       i->first, &utf8_pos, &wide_pos);
    i->second = AdvanceAndReturnWidePos(utf8_cstring, utf8_length,
                                        i->second, &utf8_pos, &wide_pos);
  }
}

void Snippet::ComputeSnippet(const MatchPositions& match_positions,
                             const std::string& document) {
  // The length of snippets we try to produce.
  // We can generate longer snippets but stop once we cross kSnippetMaxLength.
  const size_t kSnippetMaxLength = 200;
  const std::wstring kEllipsis = L" ... ";

  UText* document_utext = NULL;
  UErrorCode status = U_ZERO_ERROR;
  document_utext = utext_openUTF8(document_utext, document.data(),
                                  document.size(), &status);
  // Locale does not matter because there's no per-locale customization
  // for character iterator.
  scoped_ptr<BreakIterator> bi(
    BreakIterator::createCharacterInstance(Locale::getDefault(), status));
  bi->setText(document_utext, status);
  DCHECK(U_SUCCESS(status));

  // We build the snippet by iterating through the matches and then grabbing
  // context around each match.  If matches are near enough each other (within
  // kSnippetContext), we skip the "..." between them.
  std::wstring snippet;
  size_t start = 0;
  for (size_t i = 0; i < match_positions.size(); ++i) {
    // Some shorter names for the current match.
    const size_t match_start = match_positions[i].first;
    const size_t match_end = match_positions[i].second;

    // Switch to DCHECK after debugging http://crbug.com/15261.
    CHECK(match_end > match_start);
    CHECK(match_end <= document.size());

    // Add the context, if any, to show before the match.
    size_t context_start = match_start;
    MoveByNGraphemes(bi.get(), -kSnippetContext, &context_start);
    start = std::max(start, context_start);
    if (start < match_start) {
      if (start > 0)
        snippet += kEllipsis;
      // Switch to DCHECK after debugging http://crbug.com/15261.
      CHECK(start < document.size());
      snippet += UTF8ToWide(document.substr(start, match_start - start));
    }

    // Add the match.
    const size_t first = snippet.size();
    snippet += UTF8ToWide(document.substr(match_start,
                                          match_end - match_start));
    matches_.push_back(std::make_pair(first, snippet.size()));

    // Compute the context, if any, to show after the match.
    size_t end;
    // Check if the next match falls within our snippet window.
    if (i + 1 < match_positions.size() &&
        IsNextMatchWithinSnippetWindow(bi.get(), match_end,
            match_positions[i + 1].first)) {
      // Yes, it's within the window.  Make the end context extend just up
      // to the next match.
      end = match_positions[i + 1].first;
      // Switch to DCHECK after debugging http://crbug.com/15261.
      CHECK(end >= match_end);
      CHECK(end <= document.size());
      snippet += UTF8ToWide(document.substr(match_end, end - match_end));
    } else {
      // No, there's either no next match or the next match is too far away.
      end = match_end;
      MoveByNGraphemes(bi.get(), kSnippetContext, &end);
      // Switch to DCHECK after debugging http://crbug.com/15261.
      CHECK(end >= match_end);
      CHECK(end <= document.size());
      snippet += UTF8ToWide(document.substr(match_end, end - match_end));
      if (end < document.size())
        snippet += kEllipsis;
    }
    start = end;

    // Stop here if we have enough snippet computed.
    if (snippet.size() >= kSnippetMaxLength)
      break;
  }

  utext_close(document_utext);
  swap(text_, snippet);
}
<|endoftext|>


<commit_before><commit_msg>Check return values for ReadInt in SSL manager<commit_after><|endoftext|>


<commit_before>/*$Id$
 *
 * This source file is a part of the Berlin Project.
 * Copyright (C) 1999 Stefan Seefeld <stefan@berlin-consortium.org>
 * http://www.berlin-consortium.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
 * MA 02139, USA.
 */

#include <Prague/Sys/Tracer.hh>
#include <Warsaw/config.hh>
#include <Warsaw/Server.hh>
#include <Warsaw/ClientContext.hh>
#include <Warsaw/Trigger.hh>
#include <Warsaw/resolve.hh>
#include <Berlin/ImplVar.hh>
#include <Berlin/CommandImpl.hh>
#include <Berlin/RefCountVar.hh>
#include "Desktop/DesktopKitImpl.hh"
#include "Desktop/WindowImpl.hh"
#include "Desktop/Pulldown.hh"
#include "Desktop/Manipulator.hh"

using namespace Prague;
using namespace Warsaw;

DesktopKitImpl::DesktopKitImpl(const std::string &id, const Warsaw::Kit::PropertySeq &p)
  : KitImpl(id, p) {}
DesktopKitImpl::~DesktopKitImpl() {}
void DesktopKitImpl::bind(ServerContext_ptr context)
{
  Trace trace("DesktopKitImpl::bind");
  KitImpl::bind(context);
  CORBA::Object_var object = context->get_singleton("IDL:Warsaw/Desktop:1.0");
  _desktop = Desktop::_narrow(object);
  _desktop->increment();
  Warsaw::Kit::PropertySeq props;
  props.length(0);
  _layout  = resolve_kit<LayoutKit>(context, "IDL:Warsaw/LayoutKit:1.0", props);
  _tool    = resolve_kit<ToolKit>(context, "IDL:Warsaw/ToolKit:1.0", props);
  _widget  = resolve_kit<WidgetKit>(context, "IDL:Warsaw/WidgetKit:1.0", props);
  _text    = resolve_kit<TextKit>(context, "IDL:Warsaw/TextKit:1.0", props);
  _command = resolve_kit<CommandKit>(context, "IDL:Warsaw/CommandKit:1.0", props);

  ClientContext_var client = context->client();
  _exit = client->exit();
}

Desktop_ptr DesktopKitImpl::desk()
{
  return RefCount_var<Warsaw::Desktop>::increment(_desktop);
}

Window_ptr DesktopKitImpl::shell(Controller_ptr g, Warsaw::ClientContext_ptr n)
{
  Trace trace("DesktopKitImpl::shell");
  WindowImpl *window = new WindowImpl;
  activate(window);
  Window_var wptr = window->_this();

  Graphic::Requisition req;
  // GraphicImpl::init_requisiton(req) not needed as we init
  // everything manualy!
  req.preserve_aspect = false;

  req.x.defined = true;
  req.x.minimum = 200.;
  req.x.natural = 200.;
  req.x.maximum = 200.;
  req.x.align = 0.;

  req.y.defined = true;
  req.y.minimum = 0.;
  req.y.natural = 0.;
  req.y.maximum = _layout->fill();
  req.y.align = 0.;

  req.z.defined = false;

  RefCount_var<Graphic> exitgraphic = _layout->glue_requisition(req);
  Trigger_var tbexit = _widget->button(exitgraphic, _exit);

  Command_var mover = move(wptr);
  ToolKit::FrameSpec spec;
  spec.brightness(0.5); spec._d(ToolKit::outset);

  Unistring const * const title = n->application_title();
  RefCount_var<Graphic> titletext = _text->chunk(*title);
  delete title;

  RefCount_var<Graphic> titlebox = _layout->hbox();
  titlebox->append_graphic(RefCount_var<Graphic>(_tool->rgb(titletext, 0., 0., 0.)));
  titlebox->append_graphic(RefCount_var<Graphic>(_layout->hfill()));
  RefCount_var<Graphic> tbframe = _tool->frame(titlebox, 20., spec, true);

  RefCount_var<Graphic> tbdragger = _tool->dragger(tbframe, mover);
  Graphic_var top = _layout->hbox_align_elements(0);

  top->append_graphic(tbdragger);
  top->append_graphic(tbexit);
  req.y.minimum = 40.;
  req.y.natural = 40.;
  req.y.maximum = 40.;
  Command_var lresize = move_resize(wptr, 1.0, 0.0, Window::left|Window::bottom);
  RefCount_var<Graphic> lframe = _tool->frame(RefCount_var<Graphic>(_layout->glue_requisition(req)), 20., spec, true);
  RefCount_var<Graphic> ldragger = _tool->dragger(lframe, lresize);

  req.x.minimum = 0.;
  req.x.natural = 0.;
  req.x.maximum = _layout->fill();
  req.y.minimum = 40.;
  req.y.natural = 40.;
  req.y.maximum = 40.;
  Command_var bresize = move_resize(wptr, 0.0, 0.0, Window::bottom);
  RefCount_var<Graphic> bframe = _tool->frame(RefCount_var<Graphic>(_layout->glue_requisition(req)), 20., spec, true);
  RefCount_var<Graphic> bdragger = _tool->dragger(bframe, bresize);

  req.x.minimum = 200.;
  req.x.natural = 200.;
  req.x.maximum = 200.;
  req.y.minimum = 40.;
  req.y.natural = 40.;
  req.y.maximum = 40.;
  Command_var rresize = move_resize(wptr, 0.0, 0.0, Window::right|Window::bottom);
  RefCount_var<Graphic> rframe = _tool->frame(RefCount_var<Graphic>(_layout->glue_requisition(req)), 20., spec, true);
  RefCount_var<Graphic> rdragger = _tool->dragger(rframe, rresize);

  RefCount_var<Graphic> vbox = _layout->vbox();
  RefCount_var<Graphic> hbox = _layout->hbox();
  hbox->append_graphic(ldragger);
  hbox->append_graphic(bdragger);
  hbox->append_graphic(rdragger);
  vbox->append_graphic(top);
  vbox->append_graphic(RefCount_var<Graphic>(_layout->align(g, 0., 0.)));
  vbox->append_graphic(hbox);
  RefCount_var<Graphic> background = _tool->rgb(vbox, 0.7, 0.7, 0.7);
  wptr->body(background);
  /*
   * FIXME: we need to take care to include the window control elements
   *        into the control graph too...
   *        - stefan
   */
  wptr->append_controller(g);
  window->insert(_desktop);
  _desktop->append_controller(wptr);
  wptr->mapped(true);
  return wptr._retn();
}

Window_ptr DesktopKitImpl::transient(Controller_ptr g)
{
  Trace trace("DesktopKitImpl::transient");
  WindowImpl *window = new WindowImpl();
  activate(window);
  Window_var wptr = window->_this();
  ToolKit::FrameSpec spec;
  spec.brightness(0.5); spec._d(ToolKit::outset);

  Graphic::Requisition req;
  // GraphicImpl::init_requisiton(req) not needed as we init
  // everything manualy!
  req.preserve_aspect = false;

  req.x.defined = true;
  req.x.minimum = 0.;
  req.x.natural = 0.;
  req.x.maximum = _layout->fill();
  req.x.align = 0.;

  req.y.defined = true;
  req.y.minimum = 200.;
  req.y.natural = 200.;
  req.y.maximum = 200.;
  req.y.align = 0;

  req.z.defined = false;

  Command_var mover = move(wptr);
  RefCount_var<Graphic> tbframe = _tool->frame(RefCount_var<Graphic>(_layout->glue_requisition(req)), 20., spec, true);
  RefCount_var<Graphic> tbdragger = _tool->dragger(tbframe, mover);

  req.x.defined = true;
  req.x.minimum = 200.;
  req.x.natural = 200.;
  req.x.maximum = 200.;
  req.x.align = 0.;

  RefCount_var<Graphic> printgraphic = _layout->glue_requisition(req);
  Command_var print = _command->print(g);
  Trigger_var tbprint = _widget->button(printgraphic, print);

  req.x.minimum = 200.;
  req.x.natural = 200.;
  req.x.maximum = 200.;
  req.y.minimum = 40.;
  req.y.natural = 40.;
  req.y.maximum = 40.;
  Command_var lresize = move_resize(wptr, 1.0, 0.0, Window::left|Window::bottom);
  RefCount_var<Graphic> lframe = _tool->frame(RefCount_var<Graphic>(_layout->glue_requisition(req)), 20., spec, true);
  RefCount_var<Graphic> ldragger = _tool->dragger(lframe, lresize);

  req.x.minimum = 0.;
  req.x.natural = 0.;
  req.x.maximum = _layout->fill();
  req.y.minimum = 40.;
  req.y.natural = 40.;
  req.y.maximum = 40.;
  Command_var bresize = move_resize(wptr, 0.0, 0.0, Window::bottom);
  RefCount_var<Graphic> bframe = _tool->frame(RefCount_var<Graphic>(_layout->glue_requisition(req)), 20., spec, true);
  RefCount_var<Graphic> bdragger = _tool->dragger(bframe, bresize);

  req.x.minimum = 200.;
  req.x.natural = 200.;
  req.x.maximum = 200.;
  req.y.minimum = 40.;
  req.y.natural = 40.;
  req.y.maximum = 40.;
  Command_var rresize = move_resize(wptr, 0.0, 0.0, Window::right|Window::bottom);
  RefCount_var<Graphic> rframe = _tool->frame(RefCount_var<Graphic>(_layout->glue_requisition(req)), 20., spec, true);
  RefCount_var<Graphic> rdragger = _tool->dragger(rframe, rresize);

  RefCount_var<Graphic> vbox = _layout->vbox();
  RefCount_var<Graphic> hbox1 = _layout->hbox();
  hbox1->append_graphic(tbprint);
  hbox1->append_graphic(tbdragger);
  RefCount_var<Graphic> hbox = _layout->hbox();
  hbox->append_graphic(ldragger);
  hbox->append_graphic(bdragger);
  hbox->append_graphic(rdragger);
  vbox->append_graphic(hbox1);
  vbox->append_graphic(RefCount_var<Graphic>(_layout->align(g, 0., 0.)));
  vbox->append_graphic(hbox);
  RefCount_var<Graphic> background = _tool->rgb(vbox, 0.7, 0.7, 0.7);
  wptr->body(background);
  /*
   * FIXME: we need to take care to include the window control elements
   *        into the control graph too...
   *        - stefan
   */
  wptr->append_controller(g);
  window->insert(_desktop);
  _desktop->append_controller(wptr);
  return wptr._retn();
}

Window_ptr DesktopKitImpl::pulldown(Controller_ptr g)
{
  Trace trace("DesktopKitImpl::pulldown");
  Pulldown *menu = new Pulldown();
  activate(menu);
  Window_var wptr = menu->_this();
  ToolKit::FrameSpec spec;
  spec.brightness(0.5); spec._d(ToolKit::outset);

  RefCount_var<Graphic> outset = _tool->frame(g, 20., spec, true);
  RefCount_var<Graphic> background = _tool->rgb(outset, 0.7, 0.7, 0.7);
  wptr->body(background);
  wptr->append_controller(g);
  menu->insert(_desktop);
  _desktop->append_controller(wptr);
  return wptr._retn();
}

Command_ptr DesktopKitImpl::move(Warsaw::Window_ptr window)
{
  Manipulator *manipulator = new Mover(window);
  activate(manipulator);
  return manipulator->_this();
}

Command_ptr DesktopKitImpl::resize(Warsaw::Window_ptr window)
{
  Manipulator *manipulator = new Resizer(window);
  activate(manipulator);
  return manipulator->_this();
}

Command_ptr DesktopKitImpl::move_resize(Warsaw::Window_ptr window, Warsaw::Alignment x, Warsaw::Alignment y, CORBA::Short border)
{
  Manipulator *manipulator = new MoveResizer(window, _desktop, x, y, border);
  activate(manipulator);
  return manipulator->_this();
}

Command_ptr DesktopKitImpl::relayer(Warsaw::Window_ptr window)
{
  Manipulator *manipulator = new Relayerer(window);
  activate(manipulator);
  return manipulator->_this();
}

Command_ptr DesktopKitImpl::map(Warsaw::Window_ptr window, CORBA::Boolean flag)
{
  Manipulator *manipulator;
  if (flag) manipulator = new Mapper(window);
  else manipulator = new Unmapper(window);
  activate(manipulator);
  return manipulator->_this();
}

extern "C" KitImpl *load()
{
  static std::string properties[] = {"implementation", "DesktopKitImpl"};
  return create_kit<DesktopKitImpl> ("IDL:Warsaw/DesktopKit:1.0", properties, 2);
}
<commit_msg>Make printing look much better. Nota bene, the real fix needs some new logic in the Window to make the output look correct (including resizing).<commit_after>/*$Id$
 *
 * This source file is a part of the Berlin Project.
 * Copyright (C) 1999 Stefan Seefeld <stefan@berlin-consortium.org>
 * http://www.berlin-consortium.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
 * MA 02139, USA.
 */

#include <Prague/Sys/Tracer.hh>
#include <Warsaw/config.hh>
#include <Warsaw/Server.hh>
#include <Warsaw/ClientContext.hh>
#include <Warsaw/Trigger.hh>
#include <Warsaw/resolve.hh>
#include <Berlin/ImplVar.hh>
#include <Berlin/CommandImpl.hh>
#include <Berlin/RefCountVar.hh>
#include "Desktop/DesktopKitImpl.hh"
#include "Desktop/WindowImpl.hh"
#include "Desktop/Pulldown.hh"
#include "Desktop/Manipulator.hh"

using namespace Prague;
using namespace Warsaw;

DesktopKitImpl::DesktopKitImpl(const std::string &id, const Warsaw::Kit::PropertySeq &p)
  : KitImpl(id, p) {}
DesktopKitImpl::~DesktopKitImpl() {}
void DesktopKitImpl::bind(ServerContext_ptr context)
{
  Trace trace("DesktopKitImpl::bind");
  KitImpl::bind(context);
  CORBA::Object_var object = context->get_singleton("IDL:Warsaw/Desktop:1.0");
  _desktop = Desktop::_narrow(object);
  _desktop->increment();
  Warsaw::Kit::PropertySeq props;
  props.length(0);
  _layout  = resolve_kit<LayoutKit>(context, "IDL:Warsaw/LayoutKit:1.0", props);
  _tool    = resolve_kit<ToolKit>(context, "IDL:Warsaw/ToolKit:1.0", props);
  _widget  = resolve_kit<WidgetKit>(context, "IDL:Warsaw/WidgetKit:1.0", props);
  _text    = resolve_kit<TextKit>(context, "IDL:Warsaw/TextKit:1.0", props);
  _command = resolve_kit<CommandKit>(context, "IDL:Warsaw/CommandKit:1.0", props);

  ClientContext_var client = context->client();
  _exit = client->exit();
}

Desktop_ptr DesktopKitImpl::desk()
{
  return RefCount_var<Warsaw::Desktop>::increment(_desktop);
}

Window_ptr DesktopKitImpl::shell(Controller_ptr g, Warsaw::ClientContext_ptr n)
{
  Trace trace("DesktopKitImpl::shell");
  WindowImpl *window = new WindowImpl;
  activate(window);
  Window_var wptr = window->_this();

  Graphic::Requisition req;
  // GraphicImpl::init_requisiton(req) not needed as we init
  // everything manualy!
  req.preserve_aspect = false;

  req.x.defined = true;
  req.x.minimum = 200.;
  req.x.natural = 200.;
  req.x.maximum = 200.;
  req.x.align = 0.;

  req.y.defined = true;
  req.y.minimum = 0.;
  req.y.natural = 0.;
  req.y.maximum = _layout->fill();
  req.y.align = 0.;

  req.z.defined = false;

  RefCount_var<Graphic> exitgraphic = _layout->glue_requisition(req);
  Trigger_var tbexit = _widget->button(exitgraphic, _exit);

  Command_var mover = move(wptr);
  ToolKit::FrameSpec spec;
  spec.brightness(0.5); spec._d(ToolKit::outset);

  Unistring const * const title = n->application_title();
  RefCount_var<Graphic> titletext = _text->chunk(*title);
  delete title;

  RefCount_var<Graphic> titlebox = _layout->hbox();
  titlebox->append_graphic(RefCount_var<Graphic>(_tool->rgb(titletext, 0., 0., 0.)));
  titlebox->append_graphic(RefCount_var<Graphic>(_layout->hfill()));
  RefCount_var<Graphic> tbframe = _tool->frame(titlebox, 20., spec, true);

  RefCount_var<Graphic> tbdragger = _tool->dragger(tbframe, mover);
  Graphic_var top = _layout->hbox_align_elements(0);

  top->append_graphic(tbdragger);
  top->append_graphic(tbexit);
  req.y.minimum = 40.;
  req.y.natural = 40.;
  req.y.maximum = 40.;
  Command_var lresize = move_resize(wptr, 1.0, 0.0, Window::left|Window::bottom);
  RefCount_var<Graphic> lframe = _tool->frame(RefCount_var<Graphic>(_layout->glue_requisition(req)), 20., spec, true);
  RefCount_var<Graphic> ldragger = _tool->dragger(lframe, lresize);

  req.x.minimum = 0.;
  req.x.natural = 0.;
  req.x.maximum = _layout->fill();
  req.y.minimum = 40.;
  req.y.natural = 40.;
  req.y.maximum = 40.;
  Command_var bresize = move_resize(wptr, 0.0, 0.0, Window::bottom);
  RefCount_var<Graphic> bframe = _tool->frame(RefCount_var<Graphic>(_layout->glue_requisition(req)), 20., spec, true);
  RefCount_var<Graphic> bdragger = _tool->dragger(bframe, bresize);

  req.x.minimum = 200.;
  req.x.natural = 200.;
  req.x.maximum = 200.;
  req.y.minimum = 40.;
  req.y.natural = 40.;
  req.y.maximum = 40.;
  Command_var rresize = move_resize(wptr, 0.0, 0.0, Window::right|Window::bottom);
  RefCount_var<Graphic> rframe = _tool->frame(RefCount_var<Graphic>(_layout->glue_requisition(req)), 20., spec, true);
  RefCount_var<Graphic> rdragger = _tool->dragger(rframe, rresize);

  RefCount_var<Graphic> vbox = _layout->vbox();
  RefCount_var<Graphic> hbox = _layout->hbox();
  hbox->append_graphic(ldragger);
  hbox->append_graphic(bdragger);
  hbox->append_graphic(rdragger);
  vbox->append_graphic(top);
  vbox->append_graphic(RefCount_var<Graphic>(_layout->align(g, 0., 0.)));
  vbox->append_graphic(hbox);
  RefCount_var<Graphic> background = _tool->rgb(vbox, 0.7, 0.7, 0.7);
  wptr->body(background);
  /*
   * FIXME: we need to take care to include the window control elements
   *        into the control graph too...
   *        - stefan
   */
  wptr->append_controller(g);
  window->insert(_desktop);
  _desktop->append_controller(wptr);
  wptr->mapped(true);
  return wptr._retn();
}

Window_ptr DesktopKitImpl::transient(Controller_ptr g)
{
  Trace trace("DesktopKitImpl::transient");
  WindowImpl *window = new WindowImpl();
  activate(window);
  Window_var wptr = window->_this();
  ToolKit::FrameSpec spec;
  spec.brightness(0.5); spec._d(ToolKit::outset);

  Graphic::Requisition req;
  // GraphicImpl::init_requisiton(req) not needed as we init
  // everything manualy!
  req.preserve_aspect = false;

  req.x.defined = true;
  req.x.minimum = 0.;
  req.x.natural = 0.;
  req.x.maximum = _layout->fill();
  req.x.align = 0.;

  req.y.defined = true;
  req.y.minimum = 200.;
  req.y.natural = 200.;
  req.y.maximum = 200.;
  req.y.align = 0;

  req.z.defined = false;

  Command_var mover = move(wptr);
  RefCount_var<Graphic> tbframe = _tool->frame(RefCount_var<Graphic>(_layout->glue_requisition(req)), 20., spec, true);
  RefCount_var<Graphic> tbdragger = _tool->dragger(tbframe, mover);

  req.x.defined = true;
  req.x.minimum = 200.;
  req.x.natural = 200.;
  req.x.maximum = 200.;
  req.x.align = 0.;

  RefCount_var<Graphic> printgraphic = _layout->glue_requisition(req);
  Command_var print = _command->print(_tool->rgb(_layout->align(g, 0., 0.), 0.7, 0.7, 0.7));
  Trigger_var tbprint = _widget->button(printgraphic, print);

  req.x.minimum = 200.;
  req.x.natural = 200.;
  req.x.maximum = 200.;
  req.y.minimum = 40.;
  req.y.natural = 40.;
  req.y.maximum = 40.;
  Command_var lresize = move_resize(wptr, 1.0, 0.0, Window::left|Window::bottom);
  RefCount_var<Graphic> lframe = _tool->frame(RefCount_var<Graphic>(_layout->glue_requisition(req)), 20., spec, true);
  RefCount_var<Graphic> ldragger = _tool->dragger(lframe, lresize);

  req.x.minimum = 0.;
  req.x.natural = 0.;
  req.x.maximum = _layout->fill();
  req.y.minimum = 40.;
  req.y.natural = 40.;
  req.y.maximum = 40.;
  Command_var bresize = move_resize(wptr, 0.0, 0.0, Window::bottom);
  RefCount_var<Graphic> bframe = _tool->frame(RefCount_var<Graphic>(_layout->glue_requisition(req)), 20., spec, true);
  RefCount_var<Graphic> bdragger = _tool->dragger(bframe, bresize);

  req.x.minimum = 200.;
  req.x.natural = 200.;
  req.x.maximum = 200.;
  req.y.minimum = 40.;
  req.y.natural = 40.;
  req.y.maximum = 40.;
  Command_var rresize = move_resize(wptr, 0.0, 0.0, Window::right|Window::bottom);
  RefCount_var<Graphic> rframe = _tool->frame(RefCount_var<Graphic>(_layout->glue_requisition(req)), 20., spec, true);
  RefCount_var<Graphic> rdragger = _tool->dragger(rframe, rresize);

  RefCount_var<Graphic> vbox = _layout->vbox();
  RefCount_var<Graphic> hbox1 = _layout->hbox();
  hbox1->append_graphic(tbprint);
  hbox1->append_graphic(tbdragger);
  RefCount_var<Graphic> hbox = _layout->hbox();
  hbox->append_graphic(ldragger);
  hbox->append_graphic(bdragger);
  hbox->append_graphic(rdragger);
  vbox->append_graphic(hbox1);
  vbox->append_graphic(RefCount_var<Graphic>(_layout->align(g, 0., 0.)));
  vbox->append_graphic(hbox);
  RefCount_var<Graphic> background = _tool->rgb(vbox, 0.7, 0.7, 0.7);
  wptr->body(background);
  /*
   * FIXME: we need to take care to include the window control elements
   *        into the control graph too...
   *        - stefan
   */
  wptr->append_controller(g);
  window->insert(_desktop);
  _desktop->append_controller(wptr);
  return wptr._retn();
}

Window_ptr DesktopKitImpl::pulldown(Controller_ptr g)
{
  Trace trace("DesktopKitImpl::pulldown");
  Pulldown *menu = new Pulldown();
  activate(menu);
  Window_var wptr = menu->_this();
  ToolKit::FrameSpec spec;
  spec.brightness(0.5); spec._d(ToolKit::outset);

  RefCount_var<Graphic> outset = _tool->frame(g, 20., spec, true);
  RefCount_var<Graphic> background = _tool->rgb(outset, 0.7, 0.7, 0.7);
  wptr->body(background);
  wptr->append_controller(g);
  menu->insert(_desktop);
  _desktop->append_controller(wptr);
  return wptr._retn();
}

Command_ptr DesktopKitImpl::move(Warsaw::Window_ptr window)
{
  Manipulator *manipulator = new Mover(window);
  activate(manipulator);
  return manipulator->_this();
}

Command_ptr DesktopKitImpl::resize(Warsaw::Window_ptr window)
{
  Manipulator *manipulator = new Resizer(window);
  activate(manipulator);
  return manipulator->_this();
}

Command_ptr DesktopKitImpl::move_resize(Warsaw::Window_ptr window, Warsaw::Alignment x, Warsaw::Alignment y, CORBA::Short border)
{
  Manipulator *manipulator = new MoveResizer(window, _desktop, x, y, border);
  activate(manipulator);
  return manipulator->_this();
}

Command_ptr DesktopKitImpl::relayer(Warsaw::Window_ptr window)
{
  Manipulator *manipulator = new Relayerer(window);
  activate(manipulator);
  return manipulator->_this();
}

Command_ptr DesktopKitImpl::map(Warsaw::Window_ptr window, CORBA::Boolean flag)
{
  Manipulator *manipulator;
  if (flag) manipulator = new Mapper(window);
  else manipulator = new Unmapper(window);
  activate(manipulator);
  return manipulator->_this();
}

extern "C" KitImpl *load()
{
  static std::string properties[] = {"implementation", "DesktopKitImpl"};
  return create_kit<DesktopKitImpl> ("IDL:Warsaw/DesktopKit:1.0", properties, 2);
}
<|endoftext|>