Full Code of kirkshoop/twitter for AI

master 5b762490c396 cached
33 files
106.3 MB
591.2k tokens
612 symbols
1 requests
Download .txt
Showing preview only (2,094K chars total). Download the full file or copy to clipboard to get everything.
Repository: kirkshoop/twitter
Branch: master
Commit: 5b762490c396
Files: 33
Total size: 106.3 MB

Directory structure:
gitextract_vt6hakd8/

├── .gitignore
├── CMakeLists.txt
├── FindSDL2_mixer.cmake
├── Findjsoncpp.cmake
├── Findrange-v3.cmake
├── Findrxcpp.cmake
├── LICENSE
├── LICENSE_OFL.txt
├── README.md
├── future.cpp
├── imgui/
│   ├── LICENSE.txt
│   ├── imconfig.h
│   ├── imgui.cpp
│   ├── imgui.h
│   ├── imgui_demo.cpp
│   ├── imgui_draw.cpp
│   ├── imgui_impl_sdl_gl3.cpp
│   ├── imgui_impl_sdl_gl3.h
│   ├── imgui_internal.h
│   ├── stb_rect_pack.h
│   ├── stb_textedit.h
│   └── stb_truetype.h
├── imgui.ini
├── main.cpp
├── model.h
├── rxcurl.h
├── rximgui.h
├── seahawkandeagles.json
├── shared.cmake
├── tweets.h
├── tweetsample.json
├── tweetsample.txt
└── util.h

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
CMakeCache.txt
CMakeFiles
CMakeScripts
Makefile
cmake_install.cmake
install_manifest.txt
CTestTestfile.cmake
unix/*
build/*
.vscode/*


================================================
FILE: CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.2 FATAL_ERROR)

get_filename_component(SAMPLE_PROJECT "${CMAKE_CURRENT_SOURCE_DIR}" NAME)

project(${SAMPLE_PROJECT} LANGUAGES C CXX)

MESSAGE( STATUS "Location: " ${CMAKE_CURRENT_SOURCE_DIR} )

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}")

set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Export compilation data-base

# Target for fetching packages
add_custom_target(fetch_packages)

include(FindPackageHandleStandardArgs)

include(${CMAKE_CURRENT_SOURCE_DIR}/shared.cmake)

find_path(LIBOAUTH_INCLUDE_DIR oauth.h
	PATH_SUFFIXES liboauth)

find_library(LIBOAUTH_LIBRARY NAMES oauth)

set(LIBOAUTH_LIBRARIES ${LIBOAUTH_LIBRARY})
set(LIBOAUTH_INCLUDE_DIRS ${LIBOAUTH_INCLUDE_DIR})

find_package_handle_standard_args(liboauth DEFAULT_MSG
	LIBOAUTH_LIBRARY LIBOAUTH_INCLUDE_DIR)
mark_as_advanced(LIBOAUTH INCLUDE_DIR LIBOAUTH_LIBRARY)

MESSAGE( STATUS "LIBOAUTH_INCLUDE_DIRS: " ${LIBOAUTH_INCLUDE_DIRS} )

find_package(CURL REQUIRED)
MESSAGE( STATUS "CURL_INCLUDE_DIRS: " ${CURL_INCLUDE_DIRS} )

find_package(OpenGL REQUIRED)
MESSAGE( STATUS "OPENGL_INCLUDE_DIR: " ${OPENGL_INCLUDE_DIR} )
MESSAGE( STATUS "OPENGL_LIBRARIES: " ${OPENGL_LIBRARIES} )

find_package(GLEW REQUIRED)
MESSAGE( STATUS "GLEW_INCLUDE_DIRS: " ${GLEW_INCLUDE_DIRS} )
MESSAGE( STATUS "GLEW_LIBRARIES: " ${GLEW_LIBRARIES} )
if (GLEW_FOUND AND GLEW_CONFIG)
if (NOT DEFINED GLEW_INCLUDE_DIRS OR NOT DEFINED GLEW_LIBRARIES)
MESSAGE( FATAL_ERROR "found a bad GLEW_CONFIG: " ${GLEW_CONFIG} )
endif()
endif()

find_package(SDL2 REQUIRED)
string(STRIP ${SDL2_LIBRARIES} SDL2_LIBRARIES)

MESSAGE( STATUS "SDL2_INCLUDE_DIRS: " ${SDL2_INCLUDE_DIRS} )
MESSAGE( STATUS "SDL2_LIBRARIES: " ${SDL2_LIBRARIES} )

find_package(SDL2_mixer REQUIRED)
#string(STRIP ${SDLMIXER_LIBRARIES} SDLMIXER_LIBRARIES)

MESSAGE( STATUS "SDLMIXER_INCLUDE_DIR: " ${SDLMIXER_INCLUDE_DIR} )

find_package(range-v3 REQUIRED)
MESSAGE( STATUS "range-v3_INCLUDE_DIRS: " ${range-v3_INCLUDE_DIR} )

find_package(rxcpp REQUIRED)
MESSAGE( STATUS "rxcpp_INCLUDE_DIRS: " ${rxcpp_INCLUDE_DIR} )

find_package(jsoncpp REQUIRED)
MESSAGE( STATUS "jsoncpp_INCLUDE_DIR: " ${jsoncpp_INCLUDE_DIR} )

# define the sources
set(SAMPLE_SOURCES
    ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_draw.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_demo.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/imgui/imgui_impl_sdl_gl3.cpp
)

# define the resources
set(SAMPLE_RESOURCES
    ${CMAKE_CURRENT_SOURCE_DIR}/imgui.ini
    ${CMAKE_CURRENT_SOURCE_DIR}/NotoMono-Regular.ttf
    ${CMAKE_CURRENT_SOURCE_DIR}/NotoSansSymbols-Regular.ttf
    ${CMAKE_CURRENT_SOURCE_DIR}/dot.wav
)

add_executable(${SAMPLE_PROJECT} ${SAMPLE_SOURCES} ${SAMPLE_RESOURCES})

target_compile_options(${SAMPLE_PROJECT} PUBLIC ${SHARED_COMPILE_OPTIONS})
target_compile_features(${SAMPLE_PROJECT} PUBLIC ${SHARED_COMPILE_FEATURES})

target_include_directories(${SAMPLE_PROJECT} PUBLIC 
    ${rxcpp_INCLUDE_DIR} 
    ${range-v3_INCLUDE_DIR} 
    ${LIBOAUTH_INCLUDE_DIRS} 
    ${CURL_INCLUDE_DIRS} 
    ${OPENGL_INCLUDE_DIR} 
    ${SDL2_INCLUDE_DIRS} 
    ${SDLMIXER_INCLUDE_DIR} 
    ${GLEW_INCLUDE_DIR} 
    ${jsoncpp_INCLUDE_DIR})

target_link_libraries(${SAMPLE_PROJECT} 
    ${CMAKE_THREAD_LIBS_INIT} 
    ${LIBOAUTH_LIBRARY} 
    ${CURL_LIBRARIES} 
    ${OPENGL_LIBRARIES} 
    ${SDL2_LIBRARIES} 
    ${SDLMIXER_LIBRARY} 
    ${GLEW_LIBRARIES})

set_target_properties(${SAMPLE_PROJECT} PROPERTIES MACOSX_BUNDLE TRUE)
set_target_properties(${SAMPLE_PROJECT} PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME TwitterAnalysis)
set_target_properties(${SAMPLE_PROJECT} PROPERTIES MACOSX_BUNDLE_COPYRIGHT "Copyright 2017 Kirk Shoop")

set_source_files_properties(${SAMPLE_RESOURCES} PROPERTIES 
    HEADER_FILE_ONLY ON
    MACOSX_PACKAGE_LOCATION Resources)

# set(Boost_USE_STATIC_LIBS OFF)
# set(Boost_USE_MULTITHREADED ON)
# set(Boost_USE_STATIC_RUNTIME OFF)
# find_package(Boost COMPONENTS thread) 

# MESSAGE( STATUS "Boost_VERSION: " ${Boost_VERSION} )

# set(FUTURE_PROJECT
#     future)

# add_executable(${FUTURE_PROJECT} future.cpp ${SAMPLE_RESOURCES})

# target_compile_options(${FUTURE_PROJECT} PUBLIC ${SHARED_COMPILE_OPTIONS})
# target_compile_features(${FUTURE_PROJECT} PUBLIC ${SHARED_COMPILE_FEATURES})
# target_compile_definitions(${FUTURE_PROJECT} PUBLIC 
#     BOOST_THREAD_VERSION=4 
#     BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION=1)

# target_include_directories(${FUTURE_PROJECT} SYSTEM PUBLIC 
#     ${Boost_INCLUDE_DIRS}
#     ${range-v3_INCLUDE_DIR} 
#     ${LIBOAUTH_INCLUDE_DIRS} 
#     ${CURL_INCLUDE_DIRS}
#     ${jsoncpp_INCLUDE_DIR})

# target_link_libraries(${FUTURE_PROJECT} 
#     ${Boost_LIBRARIES}
#     ${CMAKE_THREAD_LIBS_INIT} 
#     ${LIBOAUTH_LIBRARY} 
#     ${CURL_LIBRARIES})

# configure unit tests via CTest
enable_testing()
set(CTEST_CONFIGURATION_TYPE "${JOB_BUILD_CONFIGURATION}")

add_test(NAME RunTests
     WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
     COMMAND ${SAMPLE_PROJECT} ${TEST_ARGS})


================================================
FILE: FindSDL2_mixer.cmake
================================================
# https://raw.githubusercontent.com/ksterker/adonthell/master/config/FindSDL2_mixer.cmake
#
# this module look for SDL2_Mixer (http://www.libsdl.org) support
# it will define the following values
#
# SDLMIXER_INCLUDE_DIR  = where SDL_mixer.h can be found
# SDLMIXER_LIBRARY      = the library to link against SDL2_mixer
# SDLMIXER_FOUND        = set to 1 if SDL2_mixer is found
#

IF(SDL2_Mixer_INCLUDE_DIRS)

  FIND_PATH(SDLMIXER_INCLUDE_DIR SDL2/SDL_mixer.h ${SDL2_Mixer_INCLUDE_DIRS})
  FIND_LIBRARY(SDLMIXER_LIBRARY SDL2_mixer ${SDL2_Mixer_LIBRARY_DIRS})

ELSE(SDL2_Mixer_INCLUDE_DIRS)

  SET(TRIAL_LIBRARY_PATHS
    $ENV{SDL2_MIXER_HOME}/lib
    /usr/lib
    /usr/local/lib
    /sw/lib
  ) 
  SET(TRIAL_INCLUDE_PATHS
    $ENV{SDL2_MIXER_HOME}/include/SDL2
    /usr/include/SDL2
    /usr/local/include/SDL2
    /sw/include/SDL2
  ) 

  FIND_LIBRARY(SDLMIXER_LIBRARY SDL2_mixer ${TRIAL_LIBRARY_PATHS})
  FIND_PATH(SDLMIXER_INCLUDE_DIR SDL_mixer.h ${TRIAL_INCLUDE_PATHS})

ENDIF(SDL2_Mixer_INCLUDE_DIRS)

IF(SDLMIXER_INCLUDE_DIR AND SDLMIXER_LIBRARY)
  SET(SDLMIXER_FOUND 1 CACHE BOOL "Found SDL2_Mixer library")
ELSE(SDLMIXER_INCLUDE_DIR AND SDLMIXER_LIBRARY)
  SET(SDLMIXER_FOUND 0 CACHE BOOL "Not found SDL2_Mixer library")
ENDIF(SDLMIXER_INCLUDE_DIR AND SDLMIXER_LIBRARY)

MARK_AS_ADVANCED(
  SDLMIXER_INCLUDE_DIR 
  SDLMIXER_LIBRARY 
  SDLMIXER_FOUND
)

================================================
FILE: Findjsoncpp.cmake
================================================
# Copyright Gonzalo Brito Gadeschi 2015
# Copyright Kirk Shoop 2017
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#
# Find the jsoncpp include directory
# The following variables are set if jsoncpp is found.
#  jsoncpp_FOUND        - True when the jsoncpp include directory is found.
#  jsoncpp_INCLUDE_DIR  - The path to where the meta include files are.
# If jsoncpp is not found, jsoncpp_FOUND is set to false.

# https://github.com/gnzlbg/ndtree/blob/master/cmake/

find_package(PkgConfig)

if(NOT EXISTS "${jsoncpp_INCLUDE_DIR}")
  find_path(jsoncpp_INCLUDE_DIR
    NAMES json.hpp 
    DOC "jsoncpp library header files"
    )
endif()

if(EXISTS "${jsoncpp_INCLUDE_DIR}/json.hpp")
  include(FindPackageHandleStandardArgs)
  mark_as_advanced(jsoncpp_INCLUDE_DIR)
else()
  include(ExternalProject)
  ExternalProject_Add(jsoncpp
    GIT_REPOSITORY https://github.com/nlohmann/json.git
    TIMEOUT 5
    CMAKE_ARGS -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}
    PREFIX "${CMAKE_CURRENT_BINARY_DIR}"
    CONFIGURE_COMMAND "" # Disable configure step
    BUILD_COMMAND "" # Disable build step
    INSTALL_COMMAND "" # Disable install step
    UPDATE_COMMAND "" # Disable update step: clones the project only once
    )
  
  # Specify include dir
  ExternalProject_Get_Property(jsoncpp source_dir)
  set(jsoncpp_INCLUDE_DIR ${source_dir}/include)
endif()

if(EXISTS "${jsoncpp_INCLUDE_DIR}")
  set(jsoncpp_FOUND 1)
else()
  set(jsoncpp_FOUND 0)
endif()


================================================
FILE: Findrange-v3.cmake
================================================
# Copyright Gonzalo Brito Gadeschi 2015
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#
# Find the range-v3 include directory
# The following variables are set if range-v3 is found.
#  range-v3_FOUND        - True when the range-v3 include directory is found.
#  range-v3_INCLUDE_DIR  - The path to where the meta include files are.
# If range-v3 is not found, range-v3_FOUND is set to false.

# https://github.com/gnzlbg/ndtree/blob/master/cmake/Findrange-v3.cmake

find_package(PkgConfig)

if(NOT EXISTS "${range-v3_INCLUDE_DIR}")
  find_path(range-v3_INCLUDE_DIR
    NAMES range/v3/range.hpp 
    DOC "range-v3 library header files"
    )
endif()

if(EXISTS "${range-v3_INCLUDE_DIR}")
  include(FindPackageHandleStandardArgs)
  mark_as_advanced(range-v3_INCLUDE_DIR)
else()
  include(ExternalProject)
  ExternalProject_Add(range-v3
    GIT_REPOSITORY https://github.com/ericniebler/range-v3.git
    TIMEOUT 5
    CMAKE_ARGS -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}
    PREFIX "${CMAKE_CURRENT_BINARY_DIR}"
    CONFIGURE_COMMAND "" # Disable configure step
    BUILD_COMMAND "" # Disable build step
    INSTALL_COMMAND "" # Disable install step
    UPDATE_COMMAND "" # Disable update step: clones the project only once
    )
  
  # Specify include dir
  ExternalProject_Get_Property(range-v3 source_dir)
  set(range-v3_INCLUDE_DIR ${source_dir}/include)
endif()

if(EXISTS "${range-v3_INCLUDE_DIR}")
  set(range-v3_FOUND 1)
else()
  set(range-v3_FOUND 0)
endif()


================================================
FILE: Findrxcpp.cmake
================================================
# Copyright Gonzalo Brito Gadeschi 2015
# Copyright Kirk Shoop 2016
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#
# Find the rxcpp include directory
# The following variables are set if rxcpp is found.
#  rxcpp_FOUND        - True when the rxcpp include directory is found.
#  rxcpp_INCLUDE_DIR  - The path to where the meta include files are.
# If rxcpp is not found, rxcpp_FOUND is set to false.

# https://github.com/gnzlbg/ndtree/blob/master/cmake/Findrange-v3.cmake

find_package(PkgConfig)

if(NOT EXISTS "${rxcpp_INCLUDE_DIR}")
  find_path(rxcpp_INCLUDE_DIR
    NAMES rxcpp/rx.hpp 
    DOC "rxcpp library header files"
    )
endif()

if(EXISTS "${rxcpp_INCLUDE_DIR}")
  include(FindPackageHandleStandardArgs)
  mark_as_advanced(rxcpp_INCLUDE_DIR)
else()
  include(ExternalProject)
  ExternalProject_Add(rxcpp
    GIT_REPOSITORY https://github.com/Reactive-Extensions/RxCpp.git
    TIMEOUT 5
    CMAKE_ARGS -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}
    PREFIX "${CMAKE_CURRENT_BINARY_DIR}"
    CONFIGURE_COMMAND "" # Disable configure step
    BUILD_COMMAND "" # Disable build step
    INSTALL_COMMAND "" # Disable install step
    UPDATE_COMMAND "" # Disable update step: clones the project only once
    )
  
  # Specify include dir
  ExternalProject_Get_Property(rxcpp source_dir)
  set(rxcpp_INCLUDE_DIR ${source_dir}/Rx/v2/src)
endif()

if(EXISTS "${rxcpp_INCLUDE_DIR}")
  set(rxcpp_FOUND 1)
else()
  set(rxcpp_FOUND 0)
endif()


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2016 Kirk Shoop

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: LICENSE_OFL.txt
================================================
This Font Software is licensed under the SIL Open Font License,
Version 1.1.

This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL

-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------

PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font
creation efforts of academic and linguistic communities, and to
provide a free and open framework in which fonts may be shared and
improved in partnership with others.

The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply to
any document created using the fonts or their derivatives.

DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.

"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).

"Original Version" refers to the collection of Font Software
components as distributed by the Copyright Holder(s).

"Modified Version" refers to any derivative made by adding to,
deleting, or substituting -- in part or in whole -- any of the
components of the Original Version, by changing formats or by porting
the Font Software to a new environment.

"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.

PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed,
modify, redistribute, and sell modified and unmodified copies of the
Font Software, subject to the following conditions:

1) Neither the Font Software nor any of its individual components, in
Original or Modified Versions, may be sold by itself.

2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.

3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the
corresponding Copyright Holder. This restriction only applies to the
primary font name as presented to the users.

4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.

5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created using
the Font Software.

TERMINATION
This license becomes null and void if any of the above conditions are
not met.

DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.


================================================
FILE: README.md
================================================
# twitter

### rxcpp example of live twitter analysis

[![president-elect](https://img.youtube.com/vi/QFcy-jQpvBg/0.jpg)](https://www.youtube.com/watch?v=QFcy-jQpvBg)

This project was inspired by a [talk](https://blog.niallconnaughton.com/2016/10/25/ndc-sydney-talk/) by @nconnaughton - [github](https://github.com/NiallConnaughton/rx-realtime-twitter), [twitter](https://twitter.com/nconnaughton) 

The goal for this app is to show rxcpp usage and explore machine learning on live data.

This app demonstrates how multi-thread code can be written using rxcpp to hide all the primitives. thread, mutex, etc.. are all hidden behind the algorithms.

CMake is used for the build. There are dependencies on several libraries. (curl, oauth, sdl2, opengl, GLEW, nlohmann/json, Range-v3)

This project has only been built and tested on OS X, but it should be portable to other environments.

Here is a video of an older version running during the seahawks vs eagales game
[![baldwin pass to wilson](https://img.youtube.com/vi/QkvCzShHyVU/0.jpg)](https://www.youtube.com/watch?v=QkvCzShHyVU)

I also uploaded a video of an even older version of the app running on election night 2016
[![election 2016 live twitter](https://img.youtube.com/vi/ewvW4fYE4aQ/0.jpg)](https://www.youtube.com/watch?v=ewvW4fYE4aQ)


================================================
FILE: future.cpp
================================================
/*
 * Getting timelines by Twitter Streaming API
 * from: https://gist.github.com/komasaru/9c78a278f6916548f146
 */
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <sstream>
#include <fstream>
#include <regex>
#include <random>
#include <string>
#include <unordered_set>
#include <unordered_map>

using namespace std;
using namespace std::chrono;

#include <boost/thread.hpp>
using boost::async;
using boost::future;
using boost::promise;

#include <oauth.h>
#include <curl/curl.h>

#include <range/v3/all.hpp>

#include <json.hpp>
using json=nlohmann::json;

enum class Split {
    KeepDelimiter,
    RemoveDelimiter,
    OnlyDelimiter
};
auto split = [](string s, string d, Split m = Split::KeepDelimiter){
    regex delim(d);
    cregex_token_iterator cursor(&s[0], &s[0] + s.size(), delim, m == Split::KeepDelimiter ? initializer_list<int>({-1, 0}) : (m == Split::RemoveDelimiter ? initializer_list<int>({-1}) : initializer_list<int>({0})));
    cregex_token_iterator end;
    vector<string> splits(cursor, end);
    return splits;
};

auto isEndOfTweet = [](const string& s){
    if (s.size() < 2) return false;
    auto it0 = s.begin() + (s.size() - 2);
    auto it1 = s.begin() + (s.size() - 1);
    return *it0 == '\r' && *it1 == '\n';
};

inline string tweettext(const json& tweet) {
    if (!!tweet.count("extended_tweet")) {
        auto ex = tweet["extended_tweet"];
        if (!!ex.count("full_text") && ex["full_text"].is_string()) {
            return ex["full_text"];
        }
    }
    if (!!tweet.count("text") && tweet["text"].is_string()) {
        return tweet["text"];
    }
    return {};
}

inline string tolower(string s) {
    transform(s.begin(), s.end(), s.begin(), [=](char c){return std::tolower(c);});
    return s;
}

inline vector<string> splitwords(const string& text) {

    static const unordered_set<string> ignoredWords{
    // added
    "rt", "like", "just", "tomorrow", "new", "year", "month", "day", "today", "make", "let", "want", "did", "going", "good", "really", "know", "people", "got", "life", "need", "say", "doing", "great", "right", "time", "best", "happy", "stop", "think", "world", "watch", "gonna", "remember", "way",
    "better", "team", "check", "feel", "talk", "hurry", "look", "live", "home", "game", "run", "i'm", "you're", "person", "house", "real", "thing", "lol", "has", "things", "that's", "thats", "fine", "i've", "you've", "y'all", "didn't", "said", "come", "coming", "haven't", "won't", "can't", "don't", 
    "shouldn't", "hasn't", "doesn't", "i'd", "it's", "i'll", "what's", "we're", "you'll", "let's'", "lets", "vs", "win", "says", "tell", "follow", "comes", "look", "looks", "post", "join", "add", "does", "went", "sure", "wait", "seen", "told", "yes", "video", "lot", "looks", "long",
    "e280a6", "\xe2\x80\xa6",
    // http://xpo6.com/list-of-english-stop-words/
    "a", "about", "above", "above", "across", "after", "afterwards", "again", "against", "all", "almost", "alone", "along", "already", "also","although","always","am","among", "amongst", "amoungst", "amount",  "an", "and", "another", "any","anyhow","anyone","anything","anyway", "anywhere", "are", "around", "as",  "at", "back","be","became", "because","become","becomes", "becoming", "been", "before", "beforehand", "behind", "being", "below", "beside", "besides", "between", "beyond", "bill", "both", "bottom","but", "by", "call", "can", "cannot", "cant", "co", "con", "could", "couldnt", "cry", "de", "describe", "detail", "do", "done", "down", "due", "during", "each", "eg", "eight", "either", "eleven","else", "elsewhere", "empty", "enough", "etc", "even", "ever", "every", "everyone", "everything", "everywhere", "except", "few", "fifteen", "fify", "fill", "find", "fire", "first", "five", "for", "former", "formerly", "forty", "found", "four", "from", "front", "full", "further", "get", "give", "go", "had", "has", "hasnt", "have", "he", "hence", "her", "here", "hereafter", "hereby", "herein", "hereupon", "hers", "herself", "him", "himself", "his", "how", "however", "hundred", "ie", "if", "in", "inc", "indeed", "interest", "into", "is", "it", "its", "itself", "keep", "last", "latter", "latterly", "least", "less", "ltd", "made", "many", "may", "me", "meanwhile", "might", "mill", "mine", "more", "moreover", "most", "mostly", "move", "much", "must", "my", "myself", "name", "namely", "neither", "never", "nevertheless", "next", "nine", "no", "nobody", "none", "noone", "nor", "not", "nothing", "now", "nowhere", "of", "off", "often", "on", "once", "one", "only", "onto", "or", "other", "others", "otherwise", "our", "ours", "ourselves", "out", "over", "own","part", "per", "perhaps", "please", "put", "rather", "re", "same", "see", "seem", "seemed", "seeming", "seems", "serious", "several", "she", "should", "show", "side", "since", "sincere", "six", "sixty", "so", "some", "somehow", "someone", "something", "sometime", "sometimes", "somewhere", "still", "such", "system", "take", "ten", "than", "that", "the", "their", "them", "themselves", "then", "thence", "there", "thereafter", "thereby", "therefore", "therein", "thereupon", "these", "they", "thickv", "thin", "third", "this", "those", "though", "three", "through", "throughout", "thru", "thus", "to", "together", "too", "top", "toward", "towards", "twelve", "twenty", "two", "un", "under", "until", "up", "upon", "us", "very", "via", "was", "we", "well", "were", "what", "whatever", "when", "whence", "whenever", "where", "whereafter", "whereas", "whereby", "wherein", "whereupon", "wherever", "whether", "which", "while", "whither", "who", "whoever", "whole", "whom", "whose", "why", "will", "with", "within", "without", "would", "yet", "you", "your", "yours", "yourself", "yourselves", "the"};

    static const string delimiters = R"(\s+)";
    auto words = split(text, delimiters, Split::RemoveDelimiter);

    // exclude entities, urls and some punct from this words list

    static const regex ignore(R"((\xe2\x80\xa6)|(&[\w]+;)|((http|ftp|https)://[\w-]+(.[\w-]+)+([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?))");
    static const regex expletives(R"(\x66\x75\x63\x6B|\x73\x68\x69\x74|\x64\x61\x6D\x6E)");

    for (auto& word: words) {
        while (!word.empty() && (word.front() == '.' || word.front() == '(' || word.front() == '\'' || word.front() == '\"')) word.erase(word.begin());
        while (!word.empty() && (word.back() == ':' || word.back() == ',' || word.back() == ')' || word.back() == '\'' || word.back() == '\"')) word.resize(word.size() - 1);
        if (!word.empty() && word.front() == '@') continue;
        word = regex_replace(tolower(word), ignore, "");
        if (!word.empty() && word.front() != '#') {
            while (!word.empty() && ispunct(word.front())) word.erase(word.begin());
            while (!word.empty() && ispunct(word.back())) word.resize(word.size() - 1);
        }
        word = regex_replace(word, expletives, "<expletive>");
    }

    words.erase(std::remove_if(words.begin(), words.end(), [=](const string& w){
        return !(w.size() > 2 && ignoredWords.find(w) == ignoredWords.end());
    }), words.end());

    words |= 
        ranges::action::sort |
        ranges::action::unique;

    return words;
}

template<typename T>
struct It
{
    bool end;
    struct Cursor : public enable_shared_from_this<Cursor>
    {
        promise<It<T>> p;
        T v;
        mutex m;
        condition_variable ready;
        atomic_bool gate;

        void set_value(T v) {
            unique_lock<mutex> guard(m);
//            cerr << "+" << flush;
            this->v = v;
            gate = false;
            p.set_value(It<T>(this->shared_from_this()));
//            cerr << "=" << flush;
            ready.wait(guard, [this](){
                return !!gate;
            });
//            cerr << "_" << flush;
        }
    };
    shared_ptr<Cursor> v;

    It() : end(true) {}
    explicit It(shared_ptr<Cursor> v) : end(false), v(v) {
//        cerr << "-" << flush;
    }
    explicit It(nullptr_t) : end(false), v(make_shared<Cursor>()) {
//        cerr << "^" << flush;
    }

    future<It<T>> operator++() {
//        cerr << "#" << flush;
        promise<It<T>> p;
        v->p = std::move(p);
        v->gate = true;
        v->ready.notify_all();
//        cerr << "@" << flush;
        return v->p.get_future();
    }

    T& operator*() {
//        cerr << "*" << flush;
        return v->v;
    }

//    friend bool operator == (const It<T>&, const It<T>&);
};
template<typename T>
inline bool operator == (const It<T>& l, const It<T>& r) {
    return (l.end && r.end) || (!l.end && !r.end && l.v.get() == r.v.get());
}
template<typename T>
inline bool operator != (const It<T>& l, const It<T>& r) {
    return !(l == r);
}

template<typename T>
inline future<void> each(future<It<T>> next, It<T> end, function<void(It<T>, It<T>)> f) {
//    cerr << "`" << flush;
    return next.then([=](future<It<T>> v){
        auto cursor = v.get();
//        cerr << "{" << flush;
        f(cursor, end);
//        cerr << "}" << flush;
        if (cursor == end) {
//            cerr << "$" << flush;
            promise<void> p;
            p.set_value();
            return p.get_future();
        }
//        cerr << "?" << flush;
        auto next = ++cursor;
//        cerr << "%" << flush;
        return each(std::move(next), end, f);
    }).unwrap();
}

size_t fncCallback(char* ptr, size_t size, size_t nmemb, It<string>::Cursor* cursor) {
    int iRealSize = size * nmemb;
    string str;
    str.append(ptr, iRealSize);
//    cerr << "." << flush;
    cursor->set_value(str);
    return iRealSize;
}

class Proc
{
    const char* cUrl;
    const char* cConsKey;
    const char* cConsSec;
    const char* cAtokKey;
    const char* cAtokSec;
    CURL        *curl;
    char*       cSignedUrl;
    It<string>  cursor;
public:
    Proc(const char*, const char*, const char*, const char*, const char*);
    void execProc();

    future<It<string>> begin();
    It<string> end();
};

// Constructor
Proc::Proc(
    const char* cUrl,
    const char* cConsKey, const char* cConsSec,
    const char* cAtokKey, const char* cAtokSec) : cursor(nullptr)
{
    this->cUrl     = cUrl;
    this->cConsKey = cConsKey;
    this->cConsSec = cConsSec;
    this->cAtokKey = cAtokKey;
    this->cAtokSec = cAtokSec;
}

void Proc::execProc()
{
    // ==== cURL Initialization
    curl_global_init(CURL_GLOBAL_ALL);
    curl = curl_easy_init();
    if (!curl) {
        cout << "[ERROR] curl_easy_init" << endl;
        curl_global_cleanup();
        return;
    }

    // ==== cURL Setting
    // - URL, POST parameters, OAuth signing method, HTTP method, OAuth keys
    cSignedUrl = oauth_sign_url2(
        cUrl, NULL, OA_HMAC, "GET",
        cConsKey, cConsSec, cAtokKey, cAtokSec
    );
    // - URL
    curl_easy_setopt(curl, CURLOPT_URL, cSignedUrl);
    // - User agent name
    curl_easy_setopt(curl, CURLOPT_USERAGENT, "mk-mode BOT");
    // - HTTP STATUS >=400 ---> ERROR
    curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
    // - Callback function
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fncCallback);
    // - Write data
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)cursor.v.get());

    // ==== Execute
    int iStatus = curl_easy_perform(curl);
    if (!iStatus)
        cout << "[ERROR] curl_easy_perform: STATUS=" << iStatus << endl;

    // ==== cURL Cleanup
    curl_easy_cleanup(curl);
    curl_global_cleanup();
}

future<It<string>> Proc::begin() {
//    cerr << boolalpha << !!cursor.v;
    return cursor.v->p.get_future();
}

It<string> Proc::end() {
    return It<string>();
}

string settingsFile;
json settings;

int main(int /*argc*/, const char *argv[])
{
    auto exefile = string{argv[0]};
    
    cerr << "exe = " << exefile.c_str() << endl;

    auto exedir = exefile.substr(0, exefile.find_last_of('/'));

    cerr << "dir = " << exedir.c_str() << endl;

    auto exeparent = exedir.substr(0, exedir.find_last_of('/'));

    cerr << "parent = " << exeparent.c_str() << endl;

    settingsFile = exedir + "/settings.json";

    cerr << "settings = " << settingsFile.c_str() << endl;

    ifstream i(settingsFile);
    if (i.good()) {
        i >> settings;
    }

    string CONS_KEY = settings["ConsumerKey"];
    string CONS_SEC = settings["ConsumerSecret"];
    string ATOK_KEY = settings["AccessTokenKey"];
    string ATOK_SEC = settings["AccessTokenSecret"];

    // ==== Constants - URL
    const char *URL = "https://stream.twitter.com/1.1/statuses/sample.json?language=en";

    // ==== Instantiation
    Proc objProc(URL, CONS_KEY.c_str(), CONS_SEC.c_str(), ATOK_KEY.c_str(), ATOK_SEC.c_str());

    using Handler = function<void(const string&, const vector<string>&)>;
    vector<Handler> handlers;

    struct Stat {
        int count;
        unordered_map<string, int> words;
    };
    auto start = steady_clock::now();
    auto keep = seconds(60);
    auto every = seconds(5);
    deque<Stat> stat;
    stat.resize(keep/every);
    handlers.push_back(Handler{[&](const string& , const vector<string>& w) -> void {

        auto end = steady_clock::now();

        if (end - start > keep) {
            start += every;
            stat.pop_front();
            stat.resize(keep/every);
        }

        ++stat.back().count;
        for (auto& word : w) {
            ++stat.back().words[word];
        }

        int count = 0;
        unordered_map<string, int> words;
        for (auto& s : stat) {
            count += s.count;
            for(auto& word : s.words) {
                words[word.first] += word.second;
            }
        }

        vector<pair<string, int>> top = words |
            ranges::view::transform([&](const pair<string, int>& word){
                return word;
            });

        top |=
            ranges::action::sort([](const pair<string, int>& l, const pair<string, int>& r){
                return l.second > r.second;
            });

        top.resize(min(int(top.size()), 10));

        cout << count << " - ";
        for(auto& t : top){
            cout << t.first << ", ";
        }
        cout << endl;
        //cout << endl << t << endl;
    }});

    string partial;

    auto e = 
        each(objProc.begin(), objProc.end(), function<void(It<string>, It<string>)>{
            [&](It<string> c, It<string> e) {
                if (c != e) {
                    //
                    // split chunks and group into tweets
                    string chunk = partial + *c;
                    partial.clear();
                    auto chunks = split(chunk, "\r\n");
                    string line;
                    for (auto& chunk : chunks){
                        if (!isEndOfTweet(chunk)) {
                            line = chunk;
                            partial = chunk;
                            continue;
                        }
                        partial.clear();
                        //cerr << line.substr(0, 3) << " .. " << line.substr(max(0, int(line.size())-3)) << endl;
                        try {
                            //
                            // parse tweets
                            auto text = tweettext(json::parse(line));
                            auto words = splitwords(text);

                            //
                            // publish tweets - multicast
                            for(auto& f : handlers) {
                                f(text, words);
                            }
                        } catch (const exception& ex){
                            cerr << ex.what() << endl;
                        }
                    }
                }
            }
        });

    objProc.execProc();

    return 0;
}

================================================
FILE: imgui/LICENSE.txt
================================================
The MIT License (MIT)

Copyright (c) 2014-2015 Omar Cornut and ImGui contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: imgui/imconfig.h
================================================
//-----------------------------------------------------------------------------
// USER IMPLEMENTATION
// This file contains compile-time options for ImGui.
// Other options (memory allocation overrides, callbacks, etc.) can be set at runtime via the ImGuiIO structure - ImGui::GetIO().
//-----------------------------------------------------------------------------

#pragma once

//---- Define assertion handler. Defaults to calling assert().
//#define IM_ASSERT(_EXPR)  MyAssert(_EXPR)

//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows.
//#define IMGUI_API __declspec( dllexport )
//#define IMGUI_API __declspec( dllimport )

//---- Include imgui_user.h at the end of imgui.h
//#define IMGUI_INCLUDE_IMGUI_USER_H

//---- Don't implement default handlers for Windows (so as not to link with OpenClipboard() and others Win32 functions)
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS

//---- Don't implement test window functionality (ShowTestWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty)
//---- It is very strongly recommended to NOT disable the test windows. Please read the comment at the top of imgui_demo.cpp to learn why.
//#define IMGUI_DISABLE_TEST_WINDOWS

//---- Don't define obsolete functions names. Consider enabling from time to time or when updating to reduce like hood of using already obsolete function/names
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS

//---- Pack colors to BGRA instead of RGBA (remove need to post process vertex buffer in back ends)
//#define IMGUI_USE_BGRA_PACKED_COLOR

//---- Implement STB libraries in a namespace to avoid conflicts
//#define IMGUI_STB_NAMESPACE     ImGuiStb

//---- Define constructor and implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4.
/*
#define IM_VEC2_CLASS_EXTRA                                                 \
        ImVec2(const MyVec2& f) { x = f.x; y = f.y; }                       \
        operator MyVec2() const { return MyVec2(x,y); }

#define IM_VEC4_CLASS_EXTRA                                                 \
        ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; }     \
        operator MyVec4() const { return MyVec4(x,y,z,w); }
*/

//---- Use 32-bit vertex indices (instead of default: 16-bit) to allow meshes with more than 64K vertices
//#define ImDrawIdx unsigned int

//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
//---- e.g. create variants of the ImGui::Value() helper for your low-level math types, or your own widgets/helpers.
/*
namespace ImGui
{
    void    Value(const char* prefix, const MyMatrix44& v, const char* float_format = NULL);
}
*/



================================================
FILE: imgui/imgui.cpp
================================================
// dear imgui, v1.51
// (main code and documentation)

// See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code.
// Newcomers, read 'Programmer guide' below for notes on how to setup ImGui in your codebase.
// Get latest version at https://github.com/ocornut/imgui
// Releases change-log at https://github.com/ocornut/imgui/releases
// Gallery (please post your screenshots/video there!): https://github.com/ocornut/imgui/issues/772
// Developed by Omar Cornut and every direct or indirect contributors to the GitHub.
// This library is free but I need your support to sustain development and maintenance.
// If you work for a company, please consider financial support, e.g: https://www.patreon.com/imgui

/*

 Index
 - MISSION STATEMENT
 - END-USER GUIDE
 - PROGRAMMER GUIDE (read me!)
   - Read first
   - How to update to a newer version of ImGui
   - Getting started with integrating ImGui in your code/engine
 - API BREAKING CHANGES (read me when you update!)
 - ISSUES & TODO LIST
 - FREQUENTLY ASKED QUESTIONS (FAQ), TIPS
   - How can I help?
   - What is ImTextureID and how do I display an image?
   - I integrated ImGui in my engine and the text or lines are blurry..
   - I integrated ImGui in my engine and some elements are clipping or disappearing when I move windows around..
   - How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on labels/IDs.
   - How can I tell when ImGui wants my mouse/keyboard inputs VS when I can pass them to my application?
   - How can I load a different font than the default?
   - How can I easily use icons in my application?
   - How can I load multiple fonts?
   - How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic?
   - How can I preserve my ImGui context across reloading a DLL? (loss of the global/static variables)
   - How can I use the drawing facilities without an ImGui window? (using ImDrawList API)
 - ISSUES & TODO-LIST
 - CODE


 MISSION STATEMENT
 =================

 - Easy to use to create code-driven and data-driven tools
 - Easy to use to create ad hoc short-lived tools and long-lived, more elaborate tools
 - Easy to hack and improve
 - Minimize screen real-estate usage
 - Minimize setup and maintenance
 - Minimize state storage on user side
 - Portable, minimize dependencies, run on target (consoles, phones, etc.)
 - Efficient runtime and memory consumption (NB- we do allocate when "growing" content - creating a window / opening a tree node for the first time, etc. - but a typical frame won't allocate anything)

 Designed for developers and content-creators, not the typical end-user! Some of the weaknesses includes:
 - Doesn't look fancy, doesn't animate
 - Limited layout features, intricate layouts are typically crafted in code


 END-USER GUIDE
 ==============

 - Double-click title bar to collapse window
 - Click upper right corner to close a window, available when 'bool* p_open' is passed to ImGui::Begin()
 - Click and drag on lower right corner to resize window
 - Click and drag on any empty space to move window
 - Double-click/double-tap on lower right corner grip to auto-fit to content
 - TAB/SHIFT+TAB to cycle through keyboard editable fields
 - Use mouse wheel to scroll
 - Use CTRL+mouse wheel to zoom window contents (if io.FontAllowScaling is true)
 - CTRL+Click on a slider or drag box to input value as text
 - Text editor:
   - Hold SHIFT or use mouse to select text.
   - CTRL+Left/Right to word jump
   - CTRL+Shift+Left/Right to select words
   - CTRL+A our Double-Click to select all
   - CTRL+X,CTRL+C,CTRL+V to use OS clipboard
   - CTRL+Z,CTRL+Y to undo/redo
   - ESCAPE to revert text to its original value
   - You can apply arithmetic operators +,*,/ on numerical values. Use +- to subtract (because - would set a negative value!)
   - Controls are automatically adjusted for OSX to match standard OSX text editing operations.


 PROGRAMMER GUIDE
 ================

 READ FIRST

 - Read the FAQ below this section!
 - Your code creates the UI, if your code doesn't run the UI is gone! == very dynamic UI, no construction/destructions steps, less data retention on your side, no state duplication, less sync, less bugs.
 - Call and read ImGui::ShowTestWindow() for demo code demonstrating most features.
 - You can learn about immediate-mode gui principles at http://www.johno.se/book/imgui.html or watch http://mollyrocket.com/861

 HOW TO UPDATE TO A NEWER VERSION OF IMGUI

 - Overwrite all the sources files except for imconfig.h (if you have made modification to your copy of imconfig.h)
 - Read the "API BREAKING CHANGES" section (below). This is where we list occasional API breaking changes. 
   If a function/type has been renamed / or marked obsolete, try to fix the name in your code before it is permanently removed from the public API.
   If you have a problem with a missing function/symbols, search for its name in the code, there will likely be a comment about it. 
   Please report any issue to the GitHub page!
 - Try to keep your copy of dear imgui reasonably up to date.

 GETTING STARTED WITH INTEGRATING IMGUI IN YOUR CODE/ENGINE

 - Add the ImGui source files to your projects, using your preferred build system. It is recommended you build the .cpp files as part of your project and not as a library.
 - You can later customize the imconfig.h file to tweak some compilation time behavior, such as integrating imgui types with your own maths types.
 - See examples/ folder for standalone sample applications. To understand the integration process, you can read examples/opengl2_example/ because it is short, 
   then switch to the one more appropriate to your use case.
 - You may be able to grab and copy a ready made imgui_impl_*** file from the examples/.
 - When using ImGui, your programming IDE if your friend: follow the declaration of variables, functions and types to find comments about them.

 - Init: retrieve the ImGuiIO structure with ImGui::GetIO() and fill the fields marked 'Settings': at minimum you need to set io.DisplaySize (application resolution).
   Later on you will fill your keyboard mapping, clipboard handlers, and other advanced features but for a basic integration you don't need to worry about it all.
 - Init: call io.Fonts->GetTexDataAsRGBA32(...), it will build the font atlas texture, then load the texture pixels into graphics memory.
 - Every frame:
    - In your main loop as early a possible, fill the IO fields marked 'Input' (e.g. mouse position, buttons, keyboard info, etc.)
    - Call ImGui::NewFrame() to begin the imgui frame
    - You can use any ImGui function you want between NewFrame() and Render()
    - Call ImGui::Render() as late as you can to end the frame and finalize render data. it will call your io.RenderDrawListFn handler.
       (if you don't need to render, you still need to call Render() and ignore the callback, or call EndFrame() instead. if you call neither some aspects of windows focusing/moving will appear broken.)
 - All rendering information are stored into command-lists until ImGui::Render() is called.
 - ImGui never touches or knows about your GPU state. the only function that knows about GPU is the RenderDrawListFn handler that you provide.
 - Effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render" phases of your own application.
 - Refer to the examples applications in the examples/ folder for instruction on how to setup your code.
 - A minimal application skeleton may be:

     // Application init
     ImGuiIO& io = ImGui::GetIO();
     io.DisplaySize.x = 1920.0f;
     io.DisplaySize.y = 1280.0f;
     io.RenderDrawListsFn = MyRenderFunction;  // Setup a render function, or set to NULL and call GetDrawData() after Render() to access the render data.
     // TODO: Fill others settings of the io structure later.

     // Load texture atlas (there is a default font so you don't need to care about choosing a font yet)
     unsigned char* pixels;
     int width, height;
     io.Fonts->GetTexDataAsRGBA32(pixels, &width, &height);
     // TODO: At this points you've got the texture data and you need to upload that your your graphic system:
     MyTexture* texture = MyEngine::CreateTextureFromMemoryPixels(pixels, width, height, TEXTURE_TYPE_RGBA)
     // TODO: Store your texture pointer/identifier (whatever your engine uses) in 'io.Fonts->TexID'. This will be passed back to your via the renderer.
     io.Fonts->TexID = (void*)texture;

     // Application main loop
     while (true)
     {
        // Setup low-level inputs (e.g. on Win32, GetKeyboardState(), or write to those fields from your Windows message loop handlers, etc.)
        ImGuiIO& io = ImGui::GetIO();
        io.DeltaTime = 1.0f/60.0f;
        io.MousePos = mouse_pos;
        io.MouseDown[0] = mouse_button_0;
        io.MouseDown[1] = mouse_button_1;

        // Call NewFrame(), after this point you can use ImGui::* functions anytime
        ImGui::NewFrame();

        // Most of your application code here
        MyGameUpdate(); // may use any ImGui functions, e.g. ImGui::Begin("My window"); ImGui::Text("Hello, world!"); ImGui::End();
        MyGameRender(); // may use any ImGui functions as well!
     
        // Render & swap video buffers
        ImGui::Render();
        SwapBuffers();
     }

 - A minimal render function skeleton may be:

    void void MyRenderFunction(ImDrawData* draw_data)(ImDrawData* draw_data)
    {
       // TODO: Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled
       // TODO: Setup viewport, orthographic projection matrix
       // TODO: Setup shader: vertex { float2 pos, float2 uv, u32 color }, fragment shader sample color from 1 texture, multiply by vertex color.
       for (int n = 0; n < draw_data->CmdListsCount; n++)
       {
          const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;  // vertex buffer generated by ImGui
          const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;   // index buffer generated by ImGui
          for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
          {
             const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
             if (pcmd->UserCallback)
             {
                 pcmd->UserCallback(cmd_list, pcmd);
             }
             else
             {
                 // Render 'pcmd->ElemCount/3' texture triangles
                 MyEngineBindTexture(pcmd->TextureId);
                 MyEngineScissor((int)pcmd->ClipRect.x, (int)pcmd->ClipRect.y, (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y));
                 MyEngineDrawIndexedTriangles(pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer, vtx_buffer);
             }
             idx_buffer += pcmd->ElemCount;
          }
       }
    }

 - The examples/ folders contains many functional implementation of the pseudo-code above.
 - When calling NewFrame(), the 'io.WantCaptureMouse'/'io.WantCaptureKeyboard'/'io.WantTextInput' flags are updated. 
   They tell you if ImGui intends to use your inputs. So for example, if 'io.WantCaptureMouse' is set you would typically want to hide 
   mouse inputs from the rest of your application. Read the FAQ below for more information about those flags.



 API BREAKING CHANGES
 ====================

 Occasionally introducing changes that are breaking the API. The breakage are generally minor and easy to fix.
 Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code.
 Also read releases logs https://github.com/ocornut/imgui/releases for more details.

 - 2017/08/22 (1.51) - renamed IsItemHoveredRect() to IsItemRectHovered(). Kept inline redirection function (will obsolete).
                     - renamed IsMouseHoveringAnyWindow() to IsAnyWindowHovered() for consistency. Kept inline redirection function (will obsolete).
                     - renamed IsMouseHoveringWindow() to IsWindowRectHovered() for consistency. Kept inline redirection function (will obsolete).
 - 2017/08/20 (1.51) - renamed GetStyleColName() to GetStyleColorName() for consistency.
 - 2017/08/20 (1.51) - added PushStyleColor(ImGuiCol idx, ImU32 col) overload, which _might_ cause an "ambiguous call" compilation error if you are using ImColor() with implicit cast. Cast to ImU32 or ImVec4 explicily to fix.
 - 2017/08/15 (1.51) - marked the weird IMGUI_ONCE_UPON_A_FRAME helper macro as obsolete. prefer using the more explicit ImGuiOnceUponAFrame.
 - 2017/08/15 (1.51) - changed parameter order for BeginPopupContextWindow() from (const char*,int buttons,bool also_over_items) to (const char*,int buttons,bool also_over_items). Note that most calls relied on default parameters completely.
 - 2017/08/13 (1.51) - renamed ImGuiCol_Columns*** to ImGuiCol_Separator***. Kept redirection enums (will obsolete).
 - 2017/08/11 (1.51) - renamed ImGuiSetCond_*** types and flags to ImGuiCond_***. Kept redirection enums (will obsolete).
 - 2017/08/09 (1.51) - removed ValueColor() helpers, they are equivalent to calling Text(label) + SameLine() + ColorButton().
 - 2017/08/08 (1.51) - removed ColorEditMode() and ImGuiColorEditMode in favor of ImGuiColorEditFlags and parameters to the various Color*() functions. The SetColorEditOptions() allows to initialize default but the user can still change them with right-click context menu.
                     - changed prototype of 'ColorEdit4(const char* label, float col[4], bool show_alpha = true)' to 'ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0)', where passing flags = 0x01 is a safe no-op (hello dodgy backward compatibility!). - check and run the demo window, under "Color/Picker Widgets", to understand the various new options.
                     - changed prototype of rarely used 'ColorButton(ImVec4 col, bool small_height = false, bool outline_border = true)' to 'ColorButton(const char* desc_id, ImVec4 col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0,0))'
 - 2017/07/20 (1.51) - removed IsPosHoveringAnyWindow(ImVec2), which was partly broken and misleading. ASSERT + redirect user to io.WantCaptureMouse
 - 2017/05/26 (1.50) - removed ImFontConfig::MergeGlyphCenterV in favor of a more multipurpose ImFontConfig::GlyphOffset.
 - 2017/05/01 (1.50) - renamed ImDrawList::PathFill() (rarely used directly) to ImDrawList::PathFillConvex() for clarity.
 - 2016/11/06 (1.50) - BeginChild(const char*) now applies the stack id to the provided label, consistently with other functions as it should always have been. It shouldn't affect you unless (extremely unlikely) you were appending multiple times to a same child from different locations of the stack id. If that's the case, generate an id with GetId() and use it instead of passing string to BeginChild().
 - 2016/10/15 (1.50) - avoid 'void* user_data' parameter to io.SetClipboardTextFn/io.GetClipboardTextFn pointers. We pass io.ClipboardUserData to it.
 - 2016/09/25 (1.50) - style.WindowTitleAlign is now a ImVec2 (ImGuiAlign enum was removed). set to (0.5f,0.5f) for horizontal+vertical centering, (0.0f,0.0f) for upper-left, etc.
 - 2016/07/30 (1.50) - SameLine(x) with x>0.0f is now relative to left of column/group if any, and not always to left of window. This was sort of always the intent and hopefully breakage should be minimal.
 - 2016/05/12 (1.49) - title bar (using ImGuiCol_TitleBg/ImGuiCol_TitleBgActive colors) isn't rendered over a window background (ImGuiCol_WindowBg color) anymore. 
                       If your TitleBg/TitleBgActive alpha was 1.0f or you are using the default theme it will not affect you. 
                       However if your TitleBg/TitleBgActive alpha was <1.0f you need to tweak your custom theme to readjust for the fact that we don't draw a WindowBg background behind the title bar.
                       This helper function will convert an old TitleBg/TitleBgActive color into a new one with the same visual output, given the OLD color and the OLD WindowBg color.
                           ImVec4 ConvertTitleBgCol(const ImVec4& win_bg_col, const ImVec4& title_bg_col)
                           {
                               float new_a = 1.0f - ((1.0f - win_bg_col.w) * (1.0f - title_bg_col.w)), k = title_bg_col.w / new_a;
                               return ImVec4((win_bg_col.x * win_bg_col.w + title_bg_col.x) * k, (win_bg_col.y * win_bg_col.w + title_bg_col.y) * k, (win_bg_col.z * win_bg_col.w + title_bg_col.z) * k, new_a);
                           }
                       If this is confusing, pick the RGB value from title bar from an old screenshot and apply this as TitleBg/TitleBgActive. Or you may just create TitleBgActive from a tweaked TitleBg color.
 - 2016/05/07 (1.49) - removed confusing set of GetInternalState(), GetInternalStateSize(), SetInternalState() functions. Now using CreateContext(), DestroyContext(), GetCurrentContext(), SetCurrentContext().
 - 2016/05/02 (1.49) - renamed SetNextTreeNodeOpened() to SetNextTreeNodeOpen(), no redirection.
 - 2016/05/01 (1.49) - obsoleted old signature of CollapsingHeader(const char* label, const char* str_id = NULL, bool display_frame = true, bool default_open = false) as extra parameters were badly designed and rarely used. You can replace the "default_open = true" flag in new API with CollapsingHeader(label, ImGuiTreeNodeFlags_DefaultOpen).
 - 2016/04/26 (1.49) - changed ImDrawList::PushClipRect(ImVec4 rect) to ImDraw::PushClipRect(Imvec2 min,ImVec2 max,bool intersect_with_current_clip_rect=false). Note that higher-level ImGui::PushClipRect() is preferable because it will clip at logic/widget level, whereas ImDrawList::PushClipRect() only affect your renderer.
 - 2016/04/03 (1.48) - removed style.WindowFillAlphaDefault setting which was redundant. Bake default BG alpha inside style.Colors[ImGuiCol_WindowBg] and all other Bg color values. (ref github issue #337).
 - 2016/04/03 (1.48) - renamed ImGuiCol_TooltipBg to ImGuiCol_PopupBg, used by popups/menus and tooltips. popups/menus were previously using ImGuiCol_WindowBg. (ref github issue #337)
 - 2016/03/21 (1.48) - renamed GetWindowFont() to GetFont(), GetWindowFontSize() to GetFontSize(). Kept inline redirection function (will obsolete).
 - 2016/03/02 (1.48) - InputText() completion/history/always callbacks: if you modify the text buffer manually (without using DeleteChars()/InsertChars() helper) you need to maintain the BufTextLen field. added an assert.
 - 2016/01/23 (1.48) - fixed not honoring exact width passed to PushItemWidth(), previously it would add extra FramePadding.x*2 over that width. if you had manual pixel-perfect alignment in place it might affect you.
 - 2015/12/27 (1.48) - fixed ImDrawList::AddRect() which used to render a rectangle 1 px too large on each axis.
 - 2015/12/04 (1.47) - renamed Color() helpers to ValueColor() - dangerously named, rarely used and probably to be made obsolete.
 - 2015/08/29 (1.45) - with the addition of horizontal scrollbar we made various fixes to inconsistencies with dealing with cursor position.
                       GetCursorPos()/SetCursorPos() functions now include the scrolled amount. It shouldn't affect the majority of users, but take note that SetCursorPosX(100.0f) puts you at +100 from the starting x position which may include scrolling, not at +100 from the window left side.
                       GetContentRegionMax()/GetWindowContentRegionMin()/GetWindowContentRegionMax() functions allow include the scrolled amount. Typically those were used in cases where no scrolling would happen so it may not be a problem, but watch out!
 - 2015/08/29 (1.45) - renamed style.ScrollbarWidth to style.ScrollbarSize
 - 2015/08/05 (1.44) - split imgui.cpp into extra files: imgui_demo.cpp imgui_draw.cpp imgui_internal.h that you need to add to your project.
 - 2015/07/18 (1.44) - fixed angles in ImDrawList::PathArcTo(), PathArcToFast() (introduced in 1.43) being off by an extra PI for no justifiable reason
 - 2015/07/14 (1.43) - add new ImFontAtlas::AddFont() API. For the old AddFont***, moved the 'font_no' parameter of ImFontAtlas::AddFont** functions to the ImFontConfig structure.
                       you need to render your textured triangles with bilinear filtering to benefit from sub-pixel positioning of text.
 - 2015/07/08 (1.43) - switched rendering data to use indexed rendering. this is saving a fair amount of CPU/GPU and enables us to get anti-aliasing for a marginal cost.
                       this necessary change will break your rendering function! the fix should be very easy. sorry for that :(
                     - if you are using a vanilla copy of one of the imgui_impl_XXXX.cpp provided in the example, you just need to update your copy and you can ignore the rest.
                     - the signature of the io.RenderDrawListsFn handler has changed!
                            ImGui_XXXX_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count)
                       became:
                            ImGui_XXXX_RenderDrawLists(ImDrawData* draw_data).
                              argument   'cmd_lists'        -> 'draw_data->CmdLists'
                              argument   'cmd_lists_count'  -> 'draw_data->CmdListsCount'
                              ImDrawList 'commands'         -> 'CmdBuffer'
                              ImDrawList 'vtx_buffer'       -> 'VtxBuffer'
                              ImDrawList  n/a               -> 'IdxBuffer' (new)
                              ImDrawCmd  'vtx_count'        -> 'ElemCount'
                              ImDrawCmd  'clip_rect'        -> 'ClipRect'
                              ImDrawCmd  'user_callback'    -> 'UserCallback'
                              ImDrawCmd  'texture_id'       -> 'TextureId'
                     - each ImDrawList now contains both a vertex buffer and an index buffer. For each command, render ElemCount/3 triangles using indices from the index buffer.
                     - if you REALLY cannot render indexed primitives, you can call the draw_data->DeIndexAllBuffers() method to de-index the buffers. This is slow and a waste of CPU/GPU. Prefer using indexed rendering!
                     - refer to code in the examples/ folder or ask on the GitHub if you are unsure of how to upgrade. please upgrade!
 - 2015/07/10 (1.43) - changed SameLine() parameters from int to float.
 - 2015/07/02 (1.42) - renamed SetScrollPosHere() to SetScrollFromCursorPos(). Kept inline redirection function (will obsolete).
 - 2015/07/02 (1.42) - renamed GetScrollPosY() to GetScrollY(). Necessary to reduce confusion along with other scrolling functions, because positions (e.g. cursor position) are not equivalent to scrolling amount.
 - 2015/06/14 (1.41) - changed ImageButton() default bg_col parameter from (0,0,0,1) (black) to (0,0,0,0) (transparent) - makes a difference when texture have transparence
 - 2015/06/14 (1.41) - changed Selectable() API from (label, selected, size) to (label, selected, flags, size). Size override should have been rarely be used. Sorry!
 - 2015/05/31 (1.40) - renamed GetWindowCollapsed() to IsWindowCollapsed() for consistency. Kept inline redirection function (will obsolete).
 - 2015/05/31 (1.40) - renamed IsRectClipped() to IsRectVisible() for consistency. Note that return value is opposite! Kept inline redirection function (will obsolete).
 - 2015/05/27 (1.40) - removed the third 'repeat_if_held' parameter from Button() - sorry! it was rarely used and inconsistent. Use PushButtonRepeat(true) / PopButtonRepeat() to enable repeat on desired buttons.
 - 2015/05/11 (1.40) - changed BeginPopup() API, takes a string identifier instead of a bool. ImGui needs to manage the open/closed state of popups. Call OpenPopup() to actually set the "open" state of a popup. BeginPopup() returns true if the popup is opened.
 - 2015/05/03 (1.40) - removed style.AutoFitPadding, using style.WindowPadding makes more sense (the default values were already the same).
 - 2015/04/13 (1.38) - renamed IsClipped() to IsRectClipped(). Kept inline redirection function until 1.50.
 - 2015/04/09 (1.38) - renamed ImDrawList::AddArc() to ImDrawList::AddArcFast() for compatibility with future API
 - 2015/04/03 (1.38) - removed ImGuiCol_CheckHovered, ImGuiCol_CheckActive, replaced with the more general ImGuiCol_FrameBgHovered, ImGuiCol_FrameBgActive.
 - 2014/04/03 (1.38) - removed support for passing -FLT_MAX..+FLT_MAX as the range for a SliderFloat(). Use DragFloat() or Inputfloat() instead.
 - 2015/03/17 (1.36) - renamed GetItemBoxMin()/GetItemBoxMax()/IsMouseHoveringBox() to GetItemRectMin()/GetItemRectMax()/IsMouseHoveringRect(). Kept inline redirection function until 1.50.
 - 2015/03/15 (1.36) - renamed style.TreeNodeSpacing to style.IndentSpacing, ImGuiStyleVar_TreeNodeSpacing to ImGuiStyleVar_IndentSpacing
 - 2015/03/13 (1.36) - renamed GetWindowIsFocused() to IsWindowFocused(). Kept inline redirection function until 1.50.
 - 2015/03/08 (1.35) - renamed style.ScrollBarWidth to style.ScrollbarWidth (casing)
 - 2015/02/27 (1.34) - renamed OpenNextNode(bool) to SetNextTreeNodeOpened(bool, ImGuiSetCond). Kept inline redirection function until 1.50.
 - 2015/02/27 (1.34) - renamed ImGuiSetCondition_*** to ImGuiSetCond_***, and _FirstUseThisSession becomes _Once.
 - 2015/02/11 (1.32) - changed text input callback ImGuiTextEditCallback return type from void-->int. reserved for future use, return 0 for now.
 - 2015/02/10 (1.32) - renamed GetItemWidth() to CalcItemWidth() to clarify its evolving behavior
 - 2015/02/08 (1.31) - renamed GetTextLineSpacing() to GetTextLineHeightWithSpacing()
 - 2015/02/01 (1.31) - removed IO.MemReallocFn (unused)
 - 2015/01/19 (1.30) - renamed ImGuiStorage::GetIntPtr()/GetFloatPtr() to GetIntRef()/GetIntRef() because Ptr was conflicting with actual pointer storage functions.
 - 2015/01/11 (1.30) - big font/image API change! now loads TTF file. allow for multiple fonts. no need for a PNG loader.
              (1.30) - removed GetDefaultFontData(). uses io.Fonts->GetTextureData*() API to retrieve uncompressed pixels.
                       this sequence:
                           const void* png_data;
                           unsigned int png_size;
                           ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size);
                           // <Copy to GPU>
                       became:
                           unsigned char* pixels;
                           int width, height;
                           io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
                           // <Copy to GPU>
                           io.Fonts->TexID = (your_texture_identifier);
                       you now have much more flexibility to load multiple TTF fonts and manage the texture buffer for internal needs.
                       it is now recommended that you sample the font texture with bilinear interpolation.
              (1.30) - added texture identifier in ImDrawCmd passed to your render function (we can now render images). make sure to set io.Fonts->TexID.
              (1.30) - removed IO.PixelCenterOffset (unnecessary, can be handled in user projection matrix)
              (1.30) - removed ImGui::IsItemFocused() in favor of ImGui::IsItemActive() which handles all widgets
 - 2014/12/10 (1.18) - removed SetNewWindowDefaultPos() in favor of new generic API SetNextWindowPos(pos, ImGuiSetCondition_FirstUseEver)
 - 2014/11/28 (1.17) - moved IO.Font*** options to inside the IO.Font-> structure (FontYOffset, FontTexUvForWhite, FontBaseScale, FontFallbackGlyph)
 - 2014/11/26 (1.17) - reworked syntax of IMGUI_ONCE_UPON_A_FRAME helper macro to increase compiler compatibility
 - 2014/11/07 (1.15) - renamed IsHovered() to IsItemHovered()
 - 2014/10/02 (1.14) - renamed IMGUI_INCLUDE_IMGUI_USER_CPP to IMGUI_INCLUDE_IMGUI_USER_INL and imgui_user.cpp to imgui_user.inl (more IDE friendly)
 - 2014/09/25 (1.13) - removed 'text_end' parameter from IO.SetClipboardTextFn (the string is now always zero-terminated for simplicity)
 - 2014/09/24 (1.12) - renamed SetFontScale() to SetWindowFontScale()
 - 2014/09/24 (1.12) - moved IM_MALLOC/IM_REALLOC/IM_FREE preprocessor defines to IO.MemAllocFn/IO.MemReallocFn/IO.MemFreeFn
 - 2014/08/30 (1.09) - removed IO.FontHeight (now computed automatically)
 - 2014/08/30 (1.09) - moved IMGUI_FONT_TEX_UV_FOR_WHITE preprocessor define to IO.FontTexUvForWhite
 - 2014/08/28 (1.09) - changed the behavior of IO.PixelCenterOffset following various rendering fixes


 ISSUES & TODO-LIST
 ==================
 See TODO.txt


 FREQUENTLY ASKED QUESTIONS (FAQ), TIPS
 ======================================

 Q: How can I help?
 A: - If you are experienced enough with ImGui and with C/C++, look at the todo list and see how you want/can help!
    - Become a Patron/donate! Convince your company to become a Patron or provide serious funding for development time! See http://www.patreon.com/imgui

 Q: What is ImTextureID and how do I display an image?
 A: ImTextureID is a void* used to pass renderer-agnostic texture references around until it hits your render function.
    ImGui knows nothing about what those bits represent, it just passes them around. It is up to you to decide what you want the void* to carry!
    It could be an identifier to your OpenGL texture (cast GLuint to void*), a pointer to your custom engine material (cast MyMaterial* to void*), etc.
    At the end of the chain, your renderer takes this void* to cast it back into whatever it needs to select a current texture to render.
    Refer to examples applications, where each renderer (in a imgui_impl_xxxx.cpp file) is treating ImTextureID as a different thing.
    (c++ tip: OpenGL uses integers to identify textures. You can safely store an integer into a void*, just cast it to void*, don't take it's address!)
    To display a custom image/texture within an ImGui window, you may use ImGui::Image(), ImGui::ImageButton(), ImDrawList::AddImage() functions.
    ImGui will generate the geometry and draw calls using the ImTextureID that you passed and which your renderer can use.
    It is your responsibility to get textures uploaded to your GPU.

 Q: I integrated ImGui in my engine and the text or lines are blurry..
 A: In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f).
    Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension.

 Q: I integrated ImGui in my engine and some elements are clipping or disappearing when I move windows around..
 A: Most likely you are mishandling the clipping rectangles in your render function. Rectangles provided by ImGui are defined as (x1=left,y1=top,x2=right,y2=bottom) and NOT as (x1,y1,width,height).

 Q: Can I have multiple widgets with the same label? Can I have widget without a label?
 A: Yes. A primer on the use of labels/IDs in ImGui..

   - Elements that are not clickable, such as Text() items don't need an ID.

   - Interactive widgets require state to be carried over multiple frames (most typically ImGui often needs to remember what is the "active" widget).
     to do so they need a unique ID. unique ID are typically derived from a string label, an integer index or a pointer.

       Button("OK");        // Label = "OK",     ID = hash of "OK"
       Button("Cancel");    // Label = "Cancel", ID = hash of "Cancel"

   - ID are uniquely scoped within windows, tree nodes, etc. so no conflict can happen if you have two buttons called "OK" in two different windows
     or in two different locations of a tree.

   - If you have a same ID twice in the same location, you'll have a conflict:

       Button("OK");
       Button("OK");           // ID collision! Both buttons will be treated as the same.

     Fear not! this is easy to solve and there are many ways to solve it!

   - When passing a label you can optionally specify extra unique ID information within string itself. This helps solving the simpler collision cases.
     use "##" to pass a complement to the ID that won't be visible to the end-user:

       Button("Play");         // Label = "Play",   ID = hash of "Play"
       Button("Play##foo1");   // Label = "Play",   ID = hash of "Play##foo1" (different from above)
       Button("Play##foo2");   // Label = "Play",   ID = hash of "Play##foo2" (different from above)

   - If you want to completely hide the label, but still need an ID:

       Checkbox("##On", &b);   // Label = "",       ID = hash of "##On" (no label!)

   - Occasionally/rarely you might want change a label while preserving a constant ID. This allows you to animate labels.
     For example you may want to include varying information in a window title bar (and windows are uniquely identified by their ID.. obviously)
     Use "###" to pass a label that isn't part of ID:

       Button("Hello###ID";   // Label = "Hello",  ID = hash of "ID"
       Button("World###ID";   // Label = "World",  ID = hash of "ID" (same as above)

       sprintf(buf, "My game (%f FPS)###MyGame");
       Begin(buf);            // Variable label,   ID = hash of "MyGame"

   - Use PushID() / PopID() to create scopes and avoid ID conflicts within the same Window.
     This is the most convenient way of distinguishing ID if you are iterating and creating many UI elements.
     You can push a pointer, a string or an integer value. Remember that ID are formed from the concatenation of everything in the ID stack!

       for (int i = 0; i < 100; i++)
       {
         PushID(i);
         Button("Click");   // Label = "Click",  ID = hash of integer + "label" (unique)
         PopID();
       }

       for (int i = 0; i < 100; i++)
       {
         MyObject* obj = Objects[i];
         PushID(obj);
         Button("Click");   // Label = "Click",  ID = hash of pointer + "label" (unique)
         PopID();
       }

       for (int i = 0; i < 100; i++)
       {
         MyObject* obj = Objects[i];
         PushID(obj->Name);
         Button("Click");   // Label = "Click",  ID = hash of string + "label" (unique)
         PopID();
       }

   - More example showing that you can stack multiple prefixes into the ID stack:

       Button("Click");     // Label = "Click",  ID = hash of "Click"
       PushID("node");
       Button("Click");     // Label = "Click",  ID = hash of "node" + "Click"
         PushID(my_ptr);
           Button("Click"); // Label = "Click",  ID = hash of "node" + ptr + "Click"
         PopID();
       PopID();

   - Tree nodes implicitly creates a scope for you by calling PushID().

       Button("Click");     // Label = "Click",  ID = hash of "Click"
       if (TreeNode("node"))
       {
         Button("Click");   // Label = "Click",  ID = hash of "node" + "Click"
         TreePop();
       }

   - When working with trees, ID are used to preserve the open/close state of each tree node.
     Depending on your use cases you may want to use strings, indices or pointers as ID.
      e.g. when displaying a single object that may change over time (1-1 relationship), using a static string as ID will preserve your node open/closed state when the targeted object change.
      e.g. when displaying a list of objects, using indices or pointers as ID will preserve the node open/closed state differently. experiment and see what makes more sense!

 Q: How can I tell when ImGui wants my mouse/keyboard inputs VS when I can pass them to my application?
 A: You can read the 'io.WantCaptureMouse'/'io.WantCaptureKeyboard'/'ioWantTextInput' flags from the ImGuiIO structure. 
    - When 'io.WantCaptureMouse' or 'io.WantCaptureKeyboard' flags are set you may want to discard/hide the inputs from the rest of your application.
    - When 'io.WantTextInput' is set to may want to notify your OS to popup an on-screen keyboard, if available (e.g. on a mobile phone, or console without a keyboard).
    Preferably read the flags after calling ImGui::NewFrame() to avoid them lagging by one frame. But reading those flags before calling NewFrame() is also generally ok, 
    as the bool toggles fairly rarely and you don't generally expect to interact with either ImGui or your application during the same frame when that transition occurs.
    ImGui is tracking dragging and widget activity that may occur outside the boundary of a window, so 'io.WantCaptureMouse' is more accurate and correct than checking if a window is hovered.
    (Advanced note: text input releases focus on Return 'KeyDown', so the following Return 'KeyUp' event that your application receive will typically have 'io.WantCaptureKeyboard=false'. 
     Depending on your application logic it may or not be inconvenient. You might want to track which key-downs were for ImGui (e.g. with an array of bool) and filter out the corresponding key-ups.)

 Q: How can I load a different font than the default? (default is an embedded version of ProggyClean.ttf, rendered at size 13)
 A: Use the font atlas to load the TTF/OTF file you want:

      ImGuiIO& io = ImGui::GetIO();
      io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels);
      io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()

 Q: How can I easily use icons in my application?
 A: The most convenient and practical way is to merge an icon font such as FontAwesome inside you main font. Then you can refer to icons within your strings.
    Read 'How can I load multiple fonts?' and the file 'extra_fonts/README.txt' for instructions.

 Q: How can I load multiple fonts?
 A: Use the font atlas to pack them into a single texture:
    (Read extra_fonts/README.txt and the code in ImFontAtlas for more details.)

      ImGuiIO& io = ImGui::GetIO();
      ImFont* font0 = io.Fonts->AddFontDefault();
      ImFont* font1 = io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels);
      ImFont* font2 = io.Fonts->AddFontFromFileTTF("myfontfile2.ttf", size_in_pixels);
      io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8()
      // the first loaded font gets used by default
      // use ImGui::PushFont()/ImGui::PopFont() to change the font at runtime

      // Options
      ImFontConfig config;
      config.OversampleH = 3;
      config.OversampleV = 1;
      config.GlyphOffset.y -= 2.0f;      // Move everything by 2 pixels up
      config.GlyphExtraSpacing.x = 1.0f; // Increase spacing between characters
      io.Fonts->LoadFromFileTTF("myfontfile.ttf", size_pixels, &config);

      // Combine multiple fonts into one (e.g. for icon fonts)
      ImWchar ranges[] = { 0xf000, 0xf3ff, 0 };
      ImFontConfig config;
      config.MergeMode = true;
      io.Fonts->AddFontDefault();
      io.Fonts->LoadFromFileTTF("fontawesome-webfont.ttf", 16.0f, &config, ranges); // Merge icon font
      io.Fonts->LoadFromFileTTF("myfontfile.ttf", size_pixels, NULL, &config, io.Fonts->GetGlyphRangesJapanese()); // Merge japanese glyphs

 Q: How can I display and input non-Latin characters such as Chinese, Japanese, Korean, Cyrillic?
 A: When loading a font, pass custom Unicode ranges to specify the glyphs to load. 

      // Add default Japanese ranges
      io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, io.Fonts->GetGlyphRangesJapanese());
   
      // Or create your own custom ranges (e.g. for a game you can feed your entire game script and only build the characters the game need)
      ImVector<ImWchar> ranges;
      ImFontAtlas::GlyphRangesBuilder builder;
      builder.AddText("Hello world");                        // Add a string (here "Hello world" contains 7 unique characters)
      builder.AddChar(0x7262);                               // Add a specific character
      builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // Add one of the default ranges
      builder.BuildRanges(&ranges);                          // Build the final result (ordered ranges with all the unique characters submitted)
      io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, ranges.Data);

    All your strings needs to use UTF-8 encoding. In C++11 you can encode a string literal in UTF-8 by using the u8"hello" syntax. 
    Specifying literal in your source code using a local code page (such as CP-923 for Japanese or CP-1251 for Cyrillic) will NOT work!
    Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8.

    Text input: it is up to your application to pass the right character code to io.AddInputCharacter(). The applications in examples/ are doing that.
    For languages using IME, on Windows you can copy the Hwnd of your application to io.ImeWindowHandle. The default implementation of io.ImeSetInputScreenPosFn() on Windows will set your IME position correctly.

 Q: How can I preserve my ImGui context across reloading a DLL? (loss of the global/static variables)
 A: Create your own context 'ctx = CreateContext()' + 'SetCurrentContext(ctx)' and your own font atlas 'ctx->GetIO().Fonts = new ImFontAtlas()' so you don't rely on the default globals.

 Q: How can I use the drawing facilities without an ImGui window? (using ImDrawList API)
 A: The easiest way is to create a dummy window. Call Begin() with NoTitleBar|NoResize|NoMove|NoScrollbar|NoSavedSettings|NoInputs flag, zero background alpha, 
    then retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like.
    You can also perfectly create a standalone ImDrawList instance _but_ you need ImGui to be initialized because ImDrawList pulls from ImGui data to retrieve the coordinates of the white pixel.

 - tip: the construct 'IMGUI_ONCE_UPON_A_FRAME { ... }' will run the block of code only once a frame. You can use it to quickly add custom UI in the middle of a deep nested inner loop in your code.
 - tip: you can create widgets without a Begin()/End() block, they will go in an implicit window called "Debug"
 - tip: you can call Begin() multiple times with the same name during the same frame, it will keep appending to the same window. this is also useful to set yourself in the context of another window (to get/set other settings)
 - tip: you can call Render() multiple times (e.g for VR renders).
 - tip: call and read the ShowTestWindow() code in imgui_demo.cpp for more example of how to use ImGui!

*/

#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif

#include "imgui.h"
#define IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_PLACEMENT_NEW
#include "imgui_internal.h"

#include <ctype.h>      // toupper, isprint
#include <stdlib.h>     // NULL, malloc, free, qsort, atoi
#include <stdio.h>      // vsnprintf, sscanf, printf
#include <limits.h>     // INT_MIN, INT_MAX
#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
#include <stddef.h>     // intptr_t
#else
#include <stdint.h>     // intptr_t
#endif

#ifdef _MSC_VER
#pragma warning (disable: 4127) // condition expression is constant
#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff)
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
#endif

// Clang warnings with -Weverything
#ifdef __clang__
#pragma clang diagnostic ignored "-Wunknown-pragmas"        // warning : unknown warning group '-Wformat-pedantic *'        // not all warnings are known by all clang versions.. so ignoring warnings triggers new warnings on some configuration. great!
#pragma clang diagnostic ignored "-Wold-style-cast"         // warning : use of old-style cast                              // yes, they are more terse.
#pragma clang diagnostic ignored "-Wfloat-equal"            // warning : comparing floating point with == or != is unsafe   // storing and comparing against same constants (typically 0.0f) is ok.
#pragma clang diagnostic ignored "-Wformat-nonliteral"      // warning : format string is not a string literal              // passing non-literal to vsnformat(). yes, user passing incorrect format strings can crash the code.
#pragma clang diagnostic ignored "-Wexit-time-destructors"  // warning : declaration requires an exit-time destructor       // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals.
#pragma clang diagnostic ignored "-Wglobal-constructors"    // warning : declaration requires a global destructor           // similar to above, not sure what the exact difference it.
#pragma clang diagnostic ignored "-Wsign-conversion"        // warning : implicit conversion changes signedness             //
#pragma clang diagnostic ignored "-Wformat-pedantic"        // warning : format specifies type 'void *' but the argument has type 'xxxx *' // unreasonable, would lead to casting every %p arg to void*. probably enabled by -pedantic. 
#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int' //
#elif defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wunused-function"          // warning: 'xxxx' defined but not used
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"      // warning: cast to pointer from integer of different size
#pragma GCC diagnostic ignored "-Wformat"                   // warning: format '%p' expects argument of type 'void*', but argument 6 has type 'ImGuiWindow*'
#pragma GCC diagnostic ignored "-Wdouble-promotion"         // warning: implicit conversion from 'float' to 'double' when passing argument to function
#pragma GCC diagnostic ignored "-Wconversion"               // warning: conversion to 'xxxx' from 'xxxx' may alter its value
#pragma GCC diagnostic ignored "-Wcast-qual"                // warning: cast from type 'xxxx' to type 'xxxx' casts away qualifiers
#pragma GCC diagnostic ignored "-Wformat-nonliteral"        // warning: format not a string literal, format string not checked
#pragma GCC diagnostic ignored "-Wsuggest-attribute=format"
#endif

//-------------------------------------------------------------------------
// Forward Declarations
//-------------------------------------------------------------------------

static void             LogRenderedText(const ImVec2& ref_pos, const char* text, const char* text_end = NULL);

static void             PushMultiItemsWidths(int components, float w_full = 0.0f);
static float            GetDraggedColumnOffset(int column_index);

static bool             IsKeyPressedMap(ImGuiKey key, bool repeat = true);

static ImFont*          GetDefaultFont();
static void             SetCurrentFont(ImFont* font);
static void             SetCurrentWindow(ImGuiWindow* window);
static void             SetWindowScrollY(ImGuiWindow* window, float new_scroll_y);
static void             SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond);
static void             SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond);
static void             SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond);
static ImGuiWindow*     FindHoveredWindow(ImVec2 pos, bool excluding_childs);
static ImGuiWindow*     CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags);
static inline bool      IsWindowContentHoverable(ImGuiWindow* window);
static void             ClearSetNextWindowData();
static void             CheckStacksSize(ImGuiWindow* window, bool write);
static void             Scrollbar(ImGuiWindow* window, bool horizontal);

static void             AddDrawListToRenderList(ImVector<ImDrawList*>& out_render_list, ImDrawList* draw_list);
static void             AddWindowToRenderList(ImVector<ImDrawList*>& out_render_list, ImGuiWindow* window);
static void             AddWindowToSortedBuffer(ImVector<ImGuiWindow*>& out_sorted_windows, ImGuiWindow* window);

static ImGuiIniData*    FindWindowSettings(const char* name);
static ImGuiIniData*    AddWindowSettings(const char* name);
static void             LoadIniSettingsFromDisk(const char* ini_filename);
static void             SaveIniSettingsToDisk(const char* ini_filename);
static void             MarkIniSettingsDirty(ImGuiWindow* window);

static ImRect           GetVisibleRect();

static bool             BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags);
static void             CloseInactivePopups();
static void             ClosePopupToLevel(int remaining);
static void             ClosePopup(ImGuiID id);
static ImGuiWindow*     GetFrontMostModalRootWindow();
static ImVec2           FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec2& size, int* last_dir, const ImRect& rect_to_avoid);

static bool             InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data);
static int              InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end);
static ImVec2           InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining = NULL, ImVec2* out_offset = NULL, bool stop_on_new_line = false);

static inline void      DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, const char* display_format, char* buf, int buf_size);
static inline void      DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, int decimal_precision, char* buf, int buf_size);
static void             DataTypeApplyOp(ImGuiDataType data_type, int op, void* value1, const void* value2);
static bool             DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* scalar_format);

//-----------------------------------------------------------------------------
// Platform dependent default implementations
//-----------------------------------------------------------------------------

static const char*      GetClipboardTextFn_DefaultImpl(void* user_data);
static void             SetClipboardTextFn_DefaultImpl(void* user_data, const char* text);
static void             ImeSetInputScreenPosFn_DefaultImpl(int x, int y);

//-----------------------------------------------------------------------------
// Context
//-----------------------------------------------------------------------------

// Default font atlas storage.
// New contexts always point by default to this font atlas. It can be changed by reassigning the GetIO().Fonts variable.
static ImFontAtlas      GImDefaultFontAtlas;

// Default context storage + current context pointer.
// Implicitely used by all ImGui functions. Always assumed to be != NULL. Change to a different context by calling ImGui::SetCurrentContext()
// If you are hot-reloading this code in a DLL you will lose the static/global variables. Create your own context+font atlas instead of relying on those default (see FAQ entry "How can I preserve my ImGui context across reloading a DLL?").
// ImGui is currently not thread-safe because of this variable. If you want thread-safety to allow N threads to access N different contexts, you might work around it by:
// - Having multiple instances of the ImGui code compiled inside different namespace (easiest/safest, if you have a finite number of contexts)
// - or: Changing this variable to be TLS. You may #define GImGui in imconfig.h for further custom hackery. Future development aim to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586
#ifndef GImGui
static ImGuiContext     GImDefaultContext;
ImGuiContext*           GImGui = &GImDefaultContext;
#endif

//-----------------------------------------------------------------------------
// User facing structures
//-----------------------------------------------------------------------------

ImGuiStyle::ImGuiStyle()
{
    Alpha                   = 1.0f;             // Global alpha applies to everything in ImGui
    WindowPadding           = ImVec2(8,8);      // Padding within a window
    WindowMinSize           = ImVec2(32,32);    // Minimum window size
    WindowRounding          = 9.0f;             // Radius of window corners rounding. Set to 0.0f to have rectangular windows
    WindowTitleAlign        = ImVec2(0.0f,0.5f);// Alignment for title bar text
    ChildWindowRounding     = 0.0f;             // Radius of child window corners rounding. Set to 0.0f to have rectangular child windows
    FramePadding            = ImVec2(4,3);      // Padding within a framed rectangle (used by most widgets)
    FrameRounding           = 0.0f;             // Radius of frame corners rounding. Set to 0.0f to have rectangular frames (used by most widgets).
    ItemSpacing             = ImVec2(8,4);      // Horizontal and vertical spacing between widgets/lines
    ItemInnerSpacing        = ImVec2(4,4);      // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label)
    TouchExtraPadding       = ImVec2(0,0);      // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much!
    IndentSpacing           = 21.0f;            // Horizontal spacing when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2).
    ColumnsMinSpacing       = 6.0f;             // Minimum horizontal spacing between two columns
    ScrollbarSize           = 16.0f;            // Width of the vertical scrollbar, Height of the horizontal scrollbar
    ScrollbarRounding       = 9.0f;             // Radius of grab corners rounding for scrollbar
    GrabMinSize             = 10.0f;            // Minimum width/height of a grab box for slider/scrollbar
    GrabRounding            = 0.0f;             // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs.
    ButtonTextAlign         = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text.
    DisplayWindowPadding    = ImVec2(22,22);    // Window positions are clamped to be visible within the display area by at least this amount. Only covers regular windows.
    DisplaySafeAreaPadding  = ImVec2(4,4);      // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows.
    AntiAliasedLines        = true;             // Enable anti-aliasing on lines/borders. Disable if you are really short on CPU/GPU.
    AntiAliasedShapes       = true;             // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.)
    CurveTessellationTol    = 1.25f;            // Tessellation tolerance. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality.

    Colors[ImGuiCol_Text]                   = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
    Colors[ImGuiCol_TextDisabled]           = ImVec4(0.60f, 0.60f, 0.60f, 1.00f);
    Colors[ImGuiCol_WindowBg]               = ImVec4(0.00f, 0.00f, 0.00f, 0.70f);
    Colors[ImGuiCol_ChildWindowBg]          = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
    Colors[ImGuiCol_PopupBg]                = ImVec4(0.05f, 0.05f, 0.10f, 0.90f);
    Colors[ImGuiCol_Border]                 = ImVec4(0.70f, 0.70f, 0.70f, 0.40f);
    Colors[ImGuiCol_BorderShadow]           = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
    Colors[ImGuiCol_FrameBg]                = ImVec4(0.80f, 0.80f, 0.80f, 0.30f);   // Background of checkbox, radio button, plot, slider, text input
    Colors[ImGuiCol_FrameBgHovered]         = ImVec4(0.90f, 0.80f, 0.80f, 0.40f);
    Colors[ImGuiCol_FrameBgActive]          = ImVec4(0.90f, 0.65f, 0.65f, 0.45f);
    Colors[ImGuiCol_TitleBg]                = ImVec4(0.27f, 0.27f, 0.54f, 0.83f);
    Colors[ImGuiCol_TitleBgCollapsed]       = ImVec4(0.40f, 0.40f, 0.80f, 0.20f);
    Colors[ImGuiCol_TitleBgActive]          = ImVec4(0.32f, 0.32f, 0.63f, 0.87f);
    Colors[ImGuiCol_MenuBarBg]              = ImVec4(0.40f, 0.40f, 0.55f, 0.80f);
    Colors[ImGuiCol_ScrollbarBg]            = ImVec4(0.20f, 0.25f, 0.30f, 0.60f);
    Colors[ImGuiCol_ScrollbarGrab]          = ImVec4(0.40f, 0.40f, 0.80f, 0.30f);
    Colors[ImGuiCol_ScrollbarGrabHovered]   = ImVec4(0.40f, 0.40f, 0.80f, 0.40f);
    Colors[ImGuiCol_ScrollbarGrabActive]    = ImVec4(0.80f, 0.50f, 0.50f, 0.40f);
    Colors[ImGuiCol_ComboBg]                = ImVec4(0.20f, 0.20f, 0.20f, 0.99f);
    Colors[ImGuiCol_CheckMark]              = ImVec4(0.90f, 0.90f, 0.90f, 0.50f);
    Colors[ImGuiCol_SliderGrab]             = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
    Colors[ImGuiCol_SliderGrabActive]       = ImVec4(0.80f, 0.50f, 0.50f, 1.00f);
    Colors[ImGuiCol_Button]                 = ImVec4(0.67f, 0.40f, 0.40f, 0.60f);
    Colors[ImGuiCol_ButtonHovered]          = ImVec4(0.67f, 0.40f, 0.40f, 1.00f);
    Colors[ImGuiCol_ButtonActive]           = ImVec4(0.80f, 0.50f, 0.50f, 1.00f);
    Colors[ImGuiCol_Header]                 = ImVec4(0.40f, 0.40f, 0.90f, 0.45f);
    Colors[ImGuiCol_HeaderHovered]          = ImVec4(0.45f, 0.45f, 0.90f, 0.80f);
    Colors[ImGuiCol_HeaderActive]           = ImVec4(0.53f, 0.53f, 0.87f, 0.80f);
    Colors[ImGuiCol_Separator]              = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);
    Colors[ImGuiCol_SeparatorHovered]       = ImVec4(0.60f, 0.60f, 0.70f, 1.00f);
    Colors[ImGuiCol_SeparatorActive]        = ImVec4(0.70f, 0.70f, 0.90f, 1.00f);
    Colors[ImGuiCol_ResizeGrip]             = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
    Colors[ImGuiCol_ResizeGripHovered]      = ImVec4(1.00f, 1.00f, 1.00f, 0.60f);
    Colors[ImGuiCol_ResizeGripActive]       = ImVec4(1.00f, 1.00f, 1.00f, 0.90f);
    Colors[ImGuiCol_CloseButton]            = ImVec4(0.50f, 0.50f, 0.90f, 0.50f);
    Colors[ImGuiCol_CloseButtonHovered]     = ImVec4(0.70f, 0.70f, 0.90f, 0.60f);
    Colors[ImGuiCol_CloseButtonActive]      = ImVec4(0.70f, 0.70f, 0.70f, 1.00f);
    Colors[ImGuiCol_PlotLines]              = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
    Colors[ImGuiCol_PlotLinesHovered]       = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
    Colors[ImGuiCol_PlotHistogram]          = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
    Colors[ImGuiCol_PlotHistogramHovered]   = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
    Colors[ImGuiCol_TextSelectedBg]         = ImVec4(0.00f, 0.00f, 1.00f, 0.35f);
    Colors[ImGuiCol_ModalWindowDarkening]   = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);
}

ImGuiIO::ImGuiIO()
{
    // Most fields are initialized with zero
    memset(this, 0, sizeof(*this));

    // Settings
    DisplaySize = ImVec2(-1.0f, -1.0f);
    DeltaTime = 1.0f/60.0f;
    IniSavingRate = 5.0f;
    IniFilename = "imgui.ini";
    LogFilename = "imgui_log.txt";
    Fonts = &GImDefaultFontAtlas;
    FontGlobalScale = 1.0f;
    FontDefault = NULL;
    DisplayFramebufferScale = ImVec2(1.0f, 1.0f);
    MousePos = ImVec2(-1,-1);
    MousePosPrev = ImVec2(-1,-1);
    MouseDoubleClickTime = 0.30f;
    MouseDoubleClickMaxDist = 6.0f;
    MouseDragThreshold = 6.0f;
    for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++)
        MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f;
    for (int i = 0; i < IM_ARRAYSIZE(KeysDownDuration); i++)
        KeysDownDuration[i] = KeysDownDurationPrev[i] = -1.0f;
    for (int i = 0; i < ImGuiKey_COUNT; i++)
        KeyMap[i] = -1;
    KeyRepeatDelay = 0.250f;
    KeyRepeatRate = 0.050f;
    UserData = NULL;

    // User functions
    RenderDrawListsFn = NULL;
    MemAllocFn = malloc;
    MemFreeFn = free;
    GetClipboardTextFn = GetClipboardTextFn_DefaultImpl;   // Platform dependent default implementations
    SetClipboardTextFn = SetClipboardTextFn_DefaultImpl;
    ClipboardUserData = NULL;
    ImeSetInputScreenPosFn = ImeSetInputScreenPosFn_DefaultImpl;
    ImeWindowHandle = NULL;

    // Set OS X style defaults based on __APPLE__ compile time flag
#ifdef __APPLE__
    OSXBehaviors = true;
#endif
}

// Pass in translated ASCII characters for text input.
// - with glfw you can get those from the callback set in glfwSetCharCallback()
// - on Windows you can get those using ToAscii+keyboard state, or via the WM_CHAR message
void ImGuiIO::AddInputCharacter(ImWchar c)
{
    const int n = ImStrlenW(InputCharacters);
    if (n + 1 < IM_ARRAYSIZE(InputCharacters))
    {
        InputCharacters[n] = c;
        InputCharacters[n+1] = '\0';
    }
}

void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars)
{
    // We can't pass more wchars than ImGuiIO::InputCharacters[] can hold so don't convert more
    const int wchars_buf_len = sizeof(ImGuiIO::InputCharacters) / sizeof(ImWchar);
    ImWchar wchars[wchars_buf_len];
    ImTextStrFromUtf8(wchars, wchars_buf_len, utf8_chars, NULL);
    for (int i = 0; i < wchars_buf_len && wchars[i] != 0; i++)
        AddInputCharacter(wchars[i]);
}

//-----------------------------------------------------------------------------
// HELPERS
//-----------------------------------------------------------------------------

#define IM_F32_TO_INT8_UNBOUND(_VAL)    ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f)))   // Unsaturated, for display purpose 
#define IM_F32_TO_INT8_SAT(_VAL)        ((int)(ImSaturate(_VAL) * 255.0f + 0.5f))               // Saturated, always output 0..255

// Play it nice with Windows users. Notepad in 2015 still doesn't display text data with Unix-style \n.
#ifdef _WIN32
#define IM_NEWLINE "\r\n"
#else
#define IM_NEWLINE "\n"
#endif

ImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& p)
{
    ImVec2 ap = p - a;
    ImVec2 ab_dir = b - a;
    float ab_len = sqrtf(ab_dir.x * ab_dir.x + ab_dir.y * ab_dir.y);
    ab_dir *= 1.0f / ab_len;
    float dot = ap.x * ab_dir.x + ap.y * ab_dir.y;
    if (dot < 0.0f)
        return a;
    if (dot > ab_len)
        return b;
    return a + ab_dir * dot;
}

bool ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p)
{
    bool b1 = ((p.x - b.x) * (a.y - b.y) - (p.y - b.y) * (a.x - b.x)) < 0.0f;
    bool b2 = ((p.x - c.x) * (b.y - c.y) - (p.y - c.y) * (b.x - c.x)) < 0.0f;
    bool b3 = ((p.x - a.x) * (c.y - a.y) - (p.y - a.y) * (c.x - a.x)) < 0.0f;
    return ((b1 == b2) && (b2 == b3));
}

void ImTriangleBarycentricCoords(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p, float& out_u, float& out_v, float& out_w)
{
    ImVec2 v0 = b - a;
    ImVec2 v1 = c - a;
    ImVec2 v2 = p - a;
    const float denom = v0.x * v1.y - v1.x * v0.y;
    out_v = (v2.x * v1.y - v1.x * v2.y) / denom;
    out_w = (v0.x * v2.y - v2.x * v0.y) / denom;
    out_u = 1.0f - out_v - out_w;
}

ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p)
{
    ImVec2 proj_ab = ImLineClosestPoint(a, b, p);
    ImVec2 proj_bc = ImLineClosestPoint(b, c, p);
    ImVec2 proj_ca = ImLineClosestPoint(c, a, p);
    float dist2_ab = ImLengthSqr(p - proj_ab);
    float dist2_bc = ImLengthSqr(p - proj_bc);
    float dist2_ca = ImLengthSqr(p - proj_ca);
    float m = ImMin(dist2_ab, ImMin(dist2_bc, dist2_ca));
    if (m == dist2_ab)
        return proj_ab;
    if (m == dist2_bc)
        return proj_bc;
    return proj_ca;
}

int ImStricmp(const char* str1, const char* str2)
{
    int d;
    while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; }
    return d;
}

int ImStrnicmp(const char* str1, const char* str2, int count)
{
    int d = 0;
    while (count > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; count--; }
    return d;
}

void ImStrncpy(char* dst, const char* src, int count)
{
    if (count < 1) return;
    strncpy(dst, src, (size_t)count);
    dst[count-1] = 0;
}

char* ImStrdup(const char *str)
{
    size_t len = strlen(str) + 1;
    void* buff = ImGui::MemAlloc(len);
    return (char*)memcpy(buff, (const void*)str, len);
}

int ImStrlenW(const ImWchar* str)
{
    int n = 0;
    while (*str++) n++;
    return n;
}

const ImWchar* ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin) // find beginning-of-line
{
    while (buf_mid_line > buf_begin && buf_mid_line[-1] != '\n')
        buf_mid_line--;
    return buf_mid_line;
}

const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end)
{
    if (!needle_end)
        needle_end = needle + strlen(needle);

    const char un0 = (char)toupper(*needle);
    while ((!haystack_end && *haystack) || (haystack_end && haystack < haystack_end))
    {
        if (toupper(*haystack) == un0)
        {
            const char* b = needle + 1;
            for (const char* a = haystack + 1; b < needle_end; a++, b++)
                if (toupper(*a) != toupper(*b))
                    break;
            if (b == needle_end)
                return haystack;
        }
        haystack++;
    }
    return NULL;
}

// MSVC version appears to return -1 on overflow, whereas glibc appears to return total count (which may be >= buf_size). 
// Ideally we would test for only one of those limits at runtime depending on the behavior the vsnprintf(), but trying to deduct it at compile time sounds like a pandora can of worm.
int ImFormatString(char* buf, int buf_size, const char* fmt, ...)
{
    IM_ASSERT(buf_size > 0);
    va_list args;
    va_start(args, fmt);
    int w = vsnprintf(buf, buf_size, fmt, args);
    va_end(args);
    if (w == -1 || w >= buf_size)
        w = buf_size - 1;
    buf[w] = 0;
    return w;
}

int ImFormatStringV(char* buf, int buf_size, const char* fmt, va_list args)
{
    IM_ASSERT(buf_size > 0);
    int w = vsnprintf(buf, buf_size, fmt, args);
    if (w == -1 || w >= buf_size)
        w = buf_size - 1;
    buf[w] = 0;
    return w;
}

// Pass data_size==0 for zero-terminated strings
// FIXME-OPT: Replace with e.g. FNV1a hash? CRC32 pretty much randomly access 1KB. Need to do proper measurements.
ImU32 ImHash(const void* data, int data_size, ImU32 seed)
{
    static ImU32 crc32_lut[256] = { 0 };
    if (!crc32_lut[1])
    {
        const ImU32 polynomial = 0xEDB88320;
        for (ImU32 i = 0; i < 256; i++)
        {
            ImU32 crc = i;
            for (ImU32 j = 0; j < 8; j++)
                crc = (crc >> 1) ^ (ImU32(-int(crc & 1)) & polynomial);
            crc32_lut[i] = crc;
        }
    }

    seed = ~seed;
    ImU32 crc = seed;
    const unsigned char* current = (const unsigned char*)data;

    if (data_size > 0)
    {
        // Known size
        while (data_size--)
            crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ *current++];
    }
    else
    {
        // Zero-terminated string
        while (unsigned char c = *current++)
        {
            // We support a syntax of "label###id" where only "###id" is included in the hash, and only "label" gets displayed.
            // Because this syntax is rarely used we are optimizing for the common case.
            // - If we reach ### in the string we discard the hash so far and reset to the seed.
            // - We don't do 'current += 2; continue;' after handling ### to keep the code smaller.
            if (c == '#' && current[0] == '#' && current[1] == '#')
                crc = seed;
            crc = (crc >> 8) ^ crc32_lut[(crc & 0xFF) ^ c];
        }
    }
    return ~crc;
}

//-----------------------------------------------------------------------------
// ImText* helpers
//-----------------------------------------------------------------------------

// Convert UTF-8 to 32-bits character, process single character input.
// Based on stb_from_utf8() from github.com/nothings/stb/
// We handle UTF-8 decoding error by skipping forward.
int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end)
{
    unsigned int c = (unsigned int)-1;
    const unsigned char* str = (const unsigned char*)in_text;
    if (!(*str & 0x80))
    {
        c = (unsigned int)(*str++);
        *out_char = c;
        return 1;
    }
    if ((*str & 0xe0) == 0xc0)
    {
        *out_char = 0xFFFD; // will be invalid but not end of string
        if (in_text_end && in_text_end - (const char*)str < 2) return 1;
        if (*str < 0xc2) return 2;
        c = (unsigned int)((*str++ & 0x1f) << 6);
        if ((*str & 0xc0) != 0x80) return 2;
        c += (*str++ & 0x3f);
        *out_char = c;
        return 2;
    }
    if ((*str & 0xf0) == 0xe0)
    {
        *out_char = 0xFFFD; // will be invalid but not end of string
        if (in_text_end && in_text_end - (const char*)str < 3) return 1;
        if (*str == 0xe0 && (str[1] < 0xa0 || str[1] > 0xbf)) return 3;
        if (*str == 0xed && str[1] > 0x9f) return 3; // str[1] < 0x80 is checked below
        c = (unsigned int)((*str++ & 0x0f) << 12);
        if ((*str & 0xc0) != 0x80) return 3;
        c += (unsigned int)((*str++ & 0x3f) << 6);
        if ((*str & 0xc0) != 0x80) return 3;
        c += (*str++ & 0x3f);
        *out_char = c;
        return 3;
    }
    if ((*str & 0xf8) == 0xf0)
    {
        *out_char = 0xFFFD; // will be invalid but not end of string
        if (in_text_end && in_text_end - (const char*)str < 4) return 1;
        if (*str > 0xf4) return 4;
        if (*str == 0xf0 && (str[1] < 0x90 || str[1] > 0xbf)) return 4;
        if (*str == 0xf4 && str[1] > 0x8f) return 4; // str[1] < 0x80 is checked below
        c = (unsigned int)((*str++ & 0x07) << 18);
        if ((*str & 0xc0) != 0x80) return 4;
        c += (unsigned int)((*str++ & 0x3f) << 12);
        if ((*str & 0xc0) != 0x80) return 4;
        c += (unsigned int)((*str++ & 0x3f) << 6);
        if ((*str & 0xc0) != 0x80) return 4;
        c += (*str++ & 0x3f);
        // utf-8 encodings of values used in surrogate pairs are invalid
        if ((c & 0xFFFFF800) == 0xD800) return 4;
        *out_char = c;
        return 4;
    }
    *out_char = 0;
    return 0;
}

int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_text_remaining)
{
    ImWchar* buf_out = buf;
    ImWchar* buf_end = buf + buf_size;
    while (buf_out < buf_end-1 && (!in_text_end || in_text < in_text_end) && *in_text)
    {
        unsigned int c;
        in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
        if (c == 0)
            break;
        if (c < 0x10000)    // FIXME: Losing characters that don't fit in 2 bytes
            *buf_out++ = (ImWchar)c;
    }
    *buf_out = 0;
    if (in_text_remaining)
        *in_text_remaining = in_text;
    return (int)(buf_out - buf);
}

int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end)
{
    int char_count = 0;
    while ((!in_text_end || in_text < in_text_end) && *in_text)
    {
        unsigned int c;
        in_text += ImTextCharFromUtf8(&c, in_text, in_text_end);
        if (c == 0)
            break;
        if (c < 0x10000)
            char_count++;
    }
    return char_count;
}

// Based on stb_to_utf8() from github.com/nothings/stb/
static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c)
{
    if (c < 0x80)
    {
        buf[0] = (char)c;
        return 1;
    }
    if (c < 0x800)
    {
        if (buf_size < 2) return 0;
        buf[0] = (char)(0xc0 + (c >> 6));
        buf[1] = (char)(0x80 + (c & 0x3f));
        return 2;
    }
    if (c >= 0xdc00 && c < 0xe000)
    {
        return 0;
    }
    if (c >= 0xd800 && c < 0xdc00)
    {
        if (buf_size < 4) return 0;
        buf[0] = (char)(0xf0 + (c >> 18));
        buf[1] = (char)(0x80 + ((c >> 12) & 0x3f));
        buf[2] = (char)(0x80 + ((c >> 6) & 0x3f));
        buf[3] = (char)(0x80 + ((c ) & 0x3f));
        return 4;
    }
    //else if (c < 0x10000)
    {
        if (buf_size < 3) return 0;
        buf[0] = (char)(0xe0 + (c >> 12));
        buf[1] = (char)(0x80 + ((c>> 6) & 0x3f));
        buf[2] = (char)(0x80 + ((c ) & 0x3f));
        return 3;
    }
}

static inline int ImTextCountUtf8BytesFromChar(unsigned int c)
{
    if (c < 0x80) return 1;
    if (c < 0x800) return 2;
    if (c >= 0xdc00 && c < 0xe000) return 0;
    if (c >= 0xd800 && c < 0xdc00) return 4;
    return 3;
}

int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end)
{
    char* buf_out = buf;
    const char* buf_end = buf + buf_size;
    while (buf_out < buf_end-1 && (!in_text_end || in_text < in_text_end) && *in_text)
    {
        unsigned int c = (unsigned int)(*in_text++);
        if (c < 0x80)
            *buf_out++ = (char)c;
        else
            buf_out += ImTextCharToUtf8(buf_out, (int)(buf_end-buf_out-1), c);
    }
    *buf_out = 0;
    return (int)(buf_out - buf);
}

int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* in_text_end)
{
    int bytes_count = 0;
    while ((!in_text_end || in_text < in_text_end) && *in_text)
    {
        unsigned int c = (unsigned int)(*in_text++);
        if (c < 0x80)
            bytes_count++;
        else
            bytes_count += ImTextCountUtf8BytesFromChar(c);
    }
    return bytes_count;
}

ImVec4 ImGui::ColorConvertU32ToFloat4(ImU32 in)
{
    float s = 1.0f/255.0f;
    return ImVec4(
        ((in >> IM_COL32_R_SHIFT) & 0xFF) * s,
        ((in >> IM_COL32_G_SHIFT) & 0xFF) * s,
        ((in >> IM_COL32_B_SHIFT) & 0xFF) * s,
        ((in >> IM_COL32_A_SHIFT) & 0xFF) * s);
}

ImU32 ImGui::ColorConvertFloat4ToU32(const ImVec4& in)
{
    ImU32 out;
    out  = ((ImU32)IM_F32_TO_INT8_SAT(in.x)) << IM_COL32_R_SHIFT;
    out |= ((ImU32)IM_F32_TO_INT8_SAT(in.y)) << IM_COL32_G_SHIFT;
    out |= ((ImU32)IM_F32_TO_INT8_SAT(in.z)) << IM_COL32_B_SHIFT;
    out |= ((ImU32)IM_F32_TO_INT8_SAT(in.w)) << IM_COL32_A_SHIFT;
    return out;
}

ImU32 ImGui::GetColorU32(ImGuiCol idx, float alpha_mul)  
{ 
    ImGuiStyle& style = GImGui->Style;
    ImVec4 c = style.Colors[idx]; 
    c.w *= style.Alpha * alpha_mul; 
    return ColorConvertFloat4ToU32(c); 
}

ImU32 ImGui::GetColorU32(const ImVec4& col)
{ 
    ImGuiStyle& style = GImGui->Style;
    ImVec4 c = col; 
    c.w *= style.Alpha; 
    return ColorConvertFloat4ToU32(c); 
}

const ImVec4& ImGui::GetStyleColorVec4(ImGuiCol idx)
{ 
    ImGuiStyle& style = GImGui->Style;
    return style.Colors[idx];
}

ImU32 ImGui::GetColorU32(ImU32 col)
{ 
    float style_alpha = GImGui->Style.Alpha;
    if (style_alpha >= 1.0f)
        return col;
    int a = (col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT;
    a = (int)(a * style_alpha); // We don't need to clamp 0..255 because Style.Alpha is in 0..1 range.
    return (col & ~IM_COL32_A_MASK) | (a << IM_COL32_A_SHIFT);
}

// Convert rgb floats ([0-1],[0-1],[0-1]) to hsv floats ([0-1],[0-1],[0-1]), from Foley & van Dam p592
// Optimized http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv
void ImGui::ColorConvertRGBtoHSV(float r, float g, float b, float& out_h, float& out_s, float& out_v)
{
    float K = 0.f;
    if (g < b)
    {
        const float tmp = g; g = b; b = tmp;
        K = -1.f;
    }
    if (r < g)
    {
        const float tmp = r; r = g; g = tmp;
        K = -2.f / 6.f - K;
    }

    const float chroma = r - (g < b ? g : b);
    out_h = fabsf(K + (g - b) / (6.f * chroma + 1e-20f));
    out_s = chroma / (r + 1e-20f);
    out_v = r;
}

// Convert hsv floats ([0-1],[0-1],[0-1]) to rgb floats ([0-1],[0-1],[0-1]), from Foley & van Dam p593
// also http://en.wikipedia.org/wiki/HSL_and_HSV
void ImGui::ColorConvertHSVtoRGB(float h, float s, float v, float& out_r, float& out_g, float& out_b)
{
    if (s == 0.0f)
    {
        // gray
        out_r = out_g = out_b = v;
        return;
    }

    h = fmodf(h, 1.0f) / (60.0f/360.0f);
    int   i = (int)h;
    float f = h - (float)i;
    float p = v * (1.0f - s);
    float q = v * (1.0f - s * f);
    float t = v * (1.0f - s * (1.0f - f));

    switch (i)
    {
    case 0: out_r = v; out_g = t; out_b = p; break;
    case 1: out_r = q; out_g = v; out_b = p; break;
    case 2: out_r = p; out_g = v; out_b = t; break;
    case 3: out_r = p; out_g = q; out_b = v; break;
    case 4: out_r = t; out_g = p; out_b = v; break;
    case 5: default: out_r = v; out_g = p; out_b = q; break;
    }
}

FILE* ImFileOpen(const char* filename, const char* mode)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
    // We need a fopen() wrapper because MSVC/Windows fopen doesn't handle UTF-8 filenames. Converting both strings from UTF-8 to wchar format (using a single allocation, because we can)
    const int filename_wsize = ImTextCountCharsFromUtf8(filename, NULL) + 1;
    const int mode_wsize = ImTextCountCharsFromUtf8(mode, NULL) + 1;
    ImVector<ImWchar> buf;
    buf.resize(filename_wsize + mode_wsize);
    ImTextStrFromUtf8(&buf[0], filename_wsize, filename, NULL);
    ImTextStrFromUtf8(&buf[filename_wsize], mode_wsize, mode, NULL);
    return _wfopen((wchar_t*)&buf[0], (wchar_t*)&buf[filename_wsize]);
#else
    return fopen(filename, mode);
#endif
}

// Load file content into memory
// Memory allocated with ImGui::MemAlloc(), must be freed by user using ImGui::MemFree()
void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, int* out_file_size, int padding_bytes)
{
    IM_ASSERT(filename && file_open_mode);
    if (out_file_size)
        *out_file_size = 0;

    FILE* f;
    if ((f = ImFileOpen(filename, file_open_mode)) == NULL)
        return NULL;

    long file_size_signed;
    if (fseek(f, 0, SEEK_END) || (file_size_signed = ftell(f)) == -1 || fseek(f, 0, SEEK_SET))
    {
        fclose(f);
        return NULL;
    }

    int file_size = (int)file_size_signed;
    void* file_data = ImGui::MemAlloc(file_size + padding_bytes);
    if (file_data == NULL)
    {
        fclose(f);
        return NULL;
    }
    if (fread(file_data, 1, (size_t)file_size, f) != (size_t)file_size)
    {
        fclose(f);
        ImGui::MemFree(file_data);
        return NULL;
    }
    if (padding_bytes > 0)
        memset((void *)(((char*)file_data) + file_size), 0, padding_bytes);

    fclose(f);
    if (out_file_size)
        *out_file_size = file_size;

    return file_data;
}

//-----------------------------------------------------------------------------
// ImGuiStorage
//-----------------------------------------------------------------------------

// Helper: Key->value storage
void ImGuiStorage::Clear()
{
    Data.clear();
}

// std::lower_bound but without the bullshit
static ImVector<ImGuiStorage::Pair>::iterator LowerBound(ImVector<ImGuiStorage::Pair>& data, ImGuiID key)
{
    ImVector<ImGuiStorage::Pair>::iterator first = data.begin();
    ImVector<ImGuiStorage::Pair>::iterator last = data.end();
    int count = (int)(last - first);
    while (count > 0)
    {
        int count2 = count / 2;
        ImVector<ImGuiStorage::Pair>::iterator mid = first + count2;
        if (mid->key < key)
        {
            first = ++mid;
            count -= count2 + 1;
        }
        else
        {
            count = count2;
        }
    }
    return first;
}

int ImGuiStorage::GetInt(ImGuiID key, int default_val) const
{
    ImVector<Pair>::iterator it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
    if (it == Data.end() || it->key != key)
        return default_val;
    return it->val_i;
}

bool ImGuiStorage::GetBool(ImGuiID key, bool default_val) const
{
    return GetInt(key, default_val ? 1 : 0) != 0;
}

float ImGuiStorage::GetFloat(ImGuiID key, float default_val) const
{
    ImVector<Pair>::iterator it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
    if (it == Data.end() || it->key != key)
        return default_val;
    return it->val_f;
}

void* ImGuiStorage::GetVoidPtr(ImGuiID key) const
{
    ImVector<Pair>::iterator it = LowerBound(const_cast<ImVector<ImGuiStorage::Pair>&>(Data), key);
    if (it == Data.end() || it->key != key)
        return NULL;
    return it->val_p;
}

// References are only valid until a new value is added to the storage. Calling a Set***() function or a Get***Ref() function invalidates the pointer.
int* ImGuiStorage::GetIntRef(ImGuiID key, int default_val)
{
    ImVector<Pair>::iterator it = LowerBound(Data, key);
    if (it == Data.end() || it->key != key)
        it = Data.insert(it, Pair(key, default_val));
    return &it->val_i;
}

bool* ImGuiStorage::GetBoolRef(ImGuiID key, bool default_val)
{
    return (bool*)GetIntRef(key, default_val ? 1 : 0);
}

float* ImGuiStorage::GetFloatRef(ImGuiID key, float default_val)
{
    ImVector<Pair>::iterator it = LowerBound(Data, key);
    if (it == Data.end() || it->key != key)
        it = Data.insert(it, Pair(key, default_val));
    return &it->val_f;
}

void** ImGuiStorage::GetVoidPtrRef(ImGuiID key, void* default_val)
{
    ImVector<Pair>::iterator it = LowerBound(Data, key);
    if (it == Data.end() || it->key != key)
        it = Data.insert(it, Pair(key, default_val));
    return &it->val_p;
}

// FIXME-OPT: Need a way to reuse the result of lower_bound when doing GetInt()/SetInt() - not too bad because it only happens on explicit interaction (maximum one a frame)
void ImGuiStorage::SetInt(ImGuiID key, int val)
{
    ImVector<Pair>::iterator it = LowerBound(Data, key);
    if (it == Data.end() || it->key != key)
    {
        Data.insert(it, Pair(key, val));
        return;
    }
    it->val_i = val;
}

void ImGuiStorage::SetBool(ImGuiID key, bool val)
{
    SetInt(key, val ? 1 : 0);
}

void ImGuiStorage::SetFloat(ImGuiID key, float val)
{
    ImVector<Pair>::iterator it = LowerBound(Data, key);
    if (it == Data.end() || it->key != key)
    {
        Data.insert(it, Pair(key, val));
        return;
    }
    it->val_f = val;
}

void ImGuiStorage::SetVoidPtr(ImGuiID key, void* val)
{
    ImVector<Pair>::iterator it = LowerBound(Data, key);
    if (it == Data.end() || it->key != key)
    {
        Data.insert(it, Pair(key, val));
        return;
    }
    it->val_p = val;
}

void ImGuiStorage::SetAllInt(int v)
{
    for (int i = 0; i < Data.Size; i++)
        Data[i].val_i = v;
}

//-----------------------------------------------------------------------------
// ImGuiTextFilter
//-----------------------------------------------------------------------------

// Helper: Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]"
ImGuiTextFilter::ImGuiTextFilter(const char* default_filter)
{
    if (default_filter)
    {
        ImStrncpy(InputBuf, default_filter, IM_ARRAYSIZE(InputBuf));
        Build();
    }
    else
    {
        InputBuf[0] = 0;
        CountGrep = 0;
    }
}

bool ImGuiTextFilter::Draw(const char* label, float width)
{
    if (width != 0.0f)
        ImGui::PushItemWidth(width);
    bool value_changed = ImGui::InputText(label, InputBuf, IM_ARRAYSIZE(InputBuf));
    if (width != 0.0f)
        ImGui::PopItemWidth();
    if (value_changed)
        Build();
    return value_changed;
}

void ImGuiTextFilter::TextRange::split(char separator, ImVector<TextRange>& out)
{
    out.resize(0);
    const char* wb = b;
    const char* we = wb;
    while (we < e)
    {
        if (*we == separator)
        {
            out.push_back(TextRange(wb, we));
            wb = we + 1;
        }
        we++;
    }
    if (wb != we)
        out.push_back(TextRange(wb, we));
}

void ImGuiTextFilter::Build()
{
    Filters.resize(0);
    TextRange input_range(InputBuf, InputBuf+strlen(InputBuf));
    input_range.split(',', Filters);

    CountGrep = 0;
    for (int i = 0; i != Filters.Size; i++)
    {
        Filters[i].trim_blanks();
        if (Filters[i].empty())
            continue;
        if (Filters[i].front() != '-')
            CountGrep += 1;
    }
}

bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const
{
    if (Filters.empty())
        return true;

    if (text == NULL)
        text = "";

    for (int i = 0; i != Filters.Size; i++)
    {
        const TextRange& f = Filters[i];
        if (f.empty())
            continue;
        if (f.front() == '-')
        {
            // Subtract
            if (ImStristr(text, text_end, f.begin()+1, f.end()) != NULL)
                return false;
        }
        else
        {
            // Grep
            if (ImStristr(text, text_end, f.begin(), f.end()) != NULL)
                return true;
        }
    }

    // Implicit * grep
    if (CountGrep == 0)
        return true;

    return false;
}

//-----------------------------------------------------------------------------
// ImGuiTextBuffer
//-----------------------------------------------------------------------------

// On some platform vsnprintf() takes va_list by reference and modifies it.
// va_copy is the 'correct' way to copy a va_list but Visual Studio prior to 2013 doesn't have it.
#ifndef va_copy
#define va_copy(dest, src) (dest = src)
#endif

// Helper: Text buffer for logging/accumulating text
void ImGuiTextBuffer::appendv(const char* fmt, va_list args)
{
    va_list args_copy;
    va_copy(args_copy, args);

    int len = vsnprintf(NULL, 0, fmt, args);         // FIXME-OPT: could do a first pass write attempt, likely successful on first pass.
    if (len <= 0)
        return;

    const int write_off = Buf.Size;
    const int needed_sz = write_off + len;
    if (write_off + len >= Buf.Capacity)
    {
        int double_capacity = Buf.Capacity * 2;
        Buf.reserve(needed_sz > double_capacity ? needed_sz : double_capacity);
    }

    Buf.resize(needed_sz);
    ImFormatStringV(&Buf[write_off] - 1, len+1, fmt, args_copy);
}

void ImGuiTextBuffer::append(const char* fmt, ...)
{
    va_list args;
    va_start(args, fmt);
    appendv(fmt, args);
    va_end(args);
}

//-----------------------------------------------------------------------------
// ImGuiSimpleColumns
//-----------------------------------------------------------------------------

ImGuiSimpleColumns::ImGuiSimpleColumns()
{
    Count = 0;
    Spacing = Width = NextWidth = 0.0f;
    memset(Pos, 0, sizeof(Pos));
    memset(NextWidths, 0, sizeof(NextWidths));
}

void ImGuiSimpleColumns::Update(int count, float spacing, bool clear)
{
    IM_ASSERT(Count <= IM_ARRAYSIZE(Pos));
    Count = count;
    Width = NextWidth = 0.0f;
    Spacing = spacing;
    if (clear) memset(NextWidths, 0, sizeof(NextWidths));
    for (int i = 0; i < Count; i++)
    {
        if (i > 0 && NextWidths[i] > 0.0f)
            Width += Spacing;
        Pos[i] = (float)(int)Width;
        Width += NextWidths[i];
        NextWidths[i] = 0.0f;
    }
}

float ImGuiSimpleColumns::DeclColumns(float w0, float w1, float w2) // not using va_arg because they promote float to double
{
    NextWidth = 0.0f;
    NextWidths[0] = ImMax(NextWidths[0], w0);
    NextWidths[1] = ImMax(NextWidths[1], w1);
    NextWidths[2] = ImMax(NextWidths[2], w2);
    for (int i = 0; i < 3; i++)
        NextWidth += NextWidths[i] + ((i > 0 && NextWidths[i] > 0.0f) ? Spacing : 0.0f);
    return ImMax(Width, NextWidth);
}

float ImGuiSimpleColumns::CalcExtraSpace(float avail_w)
{
    return ImMax(0.0f, avail_w - Width);
}

//-----------------------------------------------------------------------------
// ImGuiListClipper
//-----------------------------------------------------------------------------

static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height)
{
    // Set cursor position and a few other things so that SetScrollHere() and Columns() can work when seeking cursor. 
    // FIXME: It is problematic that we have to do that here, because custom/equivalent end-user code would stumble on the same issue. Consider moving within SetCursorXXX functions?
    ImGui::SetCursorPosY(pos_y);
    ImGuiWindow* window = ImGui::GetCurrentWindow();
    window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height;      // Setting those fields so that SetScrollHere() can properly function after the end of our clipper usage.
    window->DC.PrevLineHeight = (line_height - GImGui->Style.ItemSpacing.y);    // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list.
    if (window->DC.ColumnsCount > 1)
        window->DC.ColumnsCellMinY = window->DC.CursorPos.y;                    // Setting this so that cell Y position are set properly
}

// Use case A: Begin() called from constructor with items_height<0, then called again from Sync() in StepNo 1
// Use case B: Begin() called from constructor with items_height>0
// FIXME-LEGACY: Ideally we should remove the Begin/End functions but they are part of the legacy API we still support. This is why some of the code in Step() calling Begin() and reassign some fields, spaghetti style.
void ImGuiListClipper::Begin(int count, float items_height)
{
    StartPosY = ImGui::GetCursorPosY();
    ItemsHeight = items_height;
    ItemsCount = count;
    StepNo = 0;
    DisplayEnd = DisplayStart = -1;
    if (ItemsHeight > 0.0f)
    {
        ImGui::CalcListClipping(ItemsCount, ItemsHeight, &DisplayStart, &DisplayEnd); // calculate how many to clip/display
        if (DisplayStart > 0)
            SetCursorPosYAndSetupDummyPrevLine(StartPosY + DisplayStart * ItemsHeight, ItemsHeight); // advance cursor
        StepNo = 2;
    }
}

void ImGuiListClipper::End()
{
    if (ItemsCount < 0)
        return;
    // In theory here we should assert that ImGui::GetCursorPosY() == StartPosY + DisplayEnd * ItemsHeight, but it feels saner to just seek at the end and not assert/crash the user.
    if (ItemsCount < INT_MAX)
        SetCursorPosYAndSetupDummyPrevLine(StartPosY + ItemsCount * ItemsHeight, ItemsHeight); // advance cursor
    ItemsCount = -1;
    StepNo = 3;
}

bool ImGuiListClipper::Step()
{
    if (ItemsCount == 0 || ImGui::GetCurrentWindowRead()->SkipItems)
    {
        ItemsCount = -1; 
        return false; 
    }
    if (StepNo == 0) // Step 0: the clipper let you process the first element, regardless of it being visible or not, so we can measure the element height.
    {
        DisplayStart = 0;
        DisplayEnd = 1;
        StartPosY = ImGui::GetCursorPosY();
        StepNo = 1;
        return true;
    }
    if (StepNo == 1) // Step 1: the clipper infer height from first element, calculate the actual range of elements to display, and position the cursor before the first element.
    {
        if (ItemsCount == 1) { ItemsCount = -1; return false; }
        float items_height = ImGui::GetCursorPosY() - StartPosY;
        IM_ASSERT(items_height > 0.0f);   // If this triggers, it means Item 0 hasn't moved the cursor vertically
        Begin(ItemsCount-1, items_height);
        DisplayStart++;
        DisplayEnd++;
        StepNo = 3;
        return true;
    }
    if (StepNo == 2) // Step 2: dummy step only required if an explicit items_height was passed to constructor or Begin() and user still call Step(). Does nothing and switch to Step 3.
    {
        IM_ASSERT(DisplayStart >= 0 && DisplayEnd >= 0);
        StepNo = 3;
        return true;
    }
    if (StepNo == 3) // Step 3: the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd), advance the cursor to the end of the list and then returns 'false' to end the loop.
        End();
    return false;
}

//-----------------------------------------------------------------------------
// ImGuiWindow
//-----------------------------------------------------------------------------

ImGuiWindow::ImGuiWindow(const char* name)
{
    Name = ImStrdup(name);
    ID = ImHash(name, 0);
    IDStack.push_back(ID);
    MoveId = GetID("#MOVE");

    Flags = 0;
    OrderWithinParent = 0;
    PosFloat = Pos = ImVec2(0.0f, 0.0f);
    Size = SizeFull = ImVec2(0.0f, 0.0f);
    SizeContents = SizeContentsExplicit = ImVec2(0.0f, 0.0f);
    WindowPadding = ImVec2(0.0f, 0.0f);
    Scroll = ImVec2(0.0f, 0.0f);
    ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
    ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f);
    ScrollbarX = ScrollbarY = false;
    ScrollbarSizes = ImVec2(0.0f, 0.0f);
    BorderSize = 0.0f;
    Active = WasActive = false;
    Accessed = false;
    Collapsed = false;
    SkipItems = false;
    BeginCount = 0;
    PopupId = 0;
    AutoFitFramesX = AutoFitFramesY = -1;
    AutoFitOnlyGrows = false;
    AutoFitChildAxises = 0x00;
    AutoPosLastDirection = -1;
    HiddenFrames = 0;
    SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing;
    SetWindowPosCenterWanted = false;

    LastFrameActive = -1;
    ItemWidthDefault = 0.0f;
    FontWindowScale = 1.0f;

    DrawList = (ImDrawList*)ImGui::MemAlloc(sizeof(ImDrawList));
    IM_PLACEMENT_NEW(DrawList) ImDrawList();
    DrawList->_OwnerName = Name;
    RootWindow = NULL;
    RootNonPopupWindow = NULL;
    ParentWindow = NULL;

    FocusIdxAllCounter = FocusIdxTabCounter = -1;
    FocusIdxAllRequestCurrent = FocusIdxTabRequestCurrent = INT_MAX;
    FocusIdxAllRequestNext = FocusIdxTabRequestNext = INT_MAX;
}

ImGuiWindow::~ImGuiWindow()
{
    DrawList->~ImDrawList();
    ImGui::MemFree(DrawList);
    DrawList = NULL;
    ImGui::MemFree(Name);
    Name = NULL;
}

ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end)
{
    ImGuiID seed = IDStack.back();
    ImGuiID id = ImHash(str, str_end ? (int)(str_end - str) : 0, seed);
    ImGui::KeepAliveID(id);
    return id;
}

ImGuiID ImGuiWindow::GetID(const void* ptr)
{
    ImGuiID seed = IDStack.back();
    ImGuiID id = ImHash(&ptr, sizeof(void*), seed);
    ImGui::KeepAliveID(id);
    return id;
}

ImGuiID ImGuiWindow::GetIDNoKeepAlive(const char* str, const char* str_end)
{
    ImGuiID seed = IDStack.back();
    return ImHash(str, str_end ? (int)(str_end - str) : 0, seed);
}

//-----------------------------------------------------------------------------
// Internal API exposed in imgui_internal.h
//-----------------------------------------------------------------------------

static void SetCurrentWindow(ImGuiWindow* window)
{
    ImGuiContext& g = *GImGui;
    g.CurrentWindow = window;
    if (window)
        g.FontSize = window->CalcFontSize();
}

ImGuiWindow* ImGui::GetParentWindow()
{
    ImGuiContext& g = *GImGui;
    IM_ASSERT(g.CurrentWindowStack.Size >= 2);
    return g.CurrentWindowStack[(unsigned int)g.CurrentWindowStack.Size - 2];
}

void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
{
    ImGuiContext& g = *GImGui;
    g.ActiveId = id;
    g.ActiveIdAllowOverlap = false;
    g.ActiveIdIsJustActivated = true;
    if (id)
        g.ActiveIdIsAlive = true;
    g.ActiveIdWindow = window;
}

void ImGui::ClearActiveID()
{
    SetActiveID(0, NULL);
}

void ImGui::SetHoveredID(ImGuiID id)
{
    ImGuiContext& g = *GImGui;
    g.HoveredId = id;
    g.HoveredIdAllowOverlap = false;
}

void ImGui::KeepAliveID(ImGuiID id)
{
    ImGuiContext& g = *GImGui;
    if (g.ActiveId == id)
        g.ActiveIdIsAlive = true;
}

// Advance cursor given item size for layout.
void ImGui::ItemSize(const ImVec2& size, float text_offset_y)
{
    ImGuiWindow* window = GetCurrentWindow();
    if (window->SkipItems)
        return;

    // Always align ourselves on pixel boundaries
    ImGuiContext& g = *GImGui;
    const float line_height = ImMax(window->DC.CurrentLineHeight, size.y);
    const float text_base_offset = ImMax(window->DC.CurrentLineTextBaseOffset, text_offset_y);
    window->DC.CursorPosPrevLine = ImVec2(window->DC.CursorPos.x + size.x, window->DC.CursorPos.y);
    window->DC.CursorPos = ImVec2((float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX), (float)(int)(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y));
    window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x);
    window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y);

    //window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, IM_COL32(255,0,0,255), 4); // Debug

    window->DC.PrevLineHeight = line_height;
    window->DC.PrevLineTextBaseOffset = text_base_offset;
    window->DC.CurrentLineHeight = window->DC.CurrentLineTextBaseOffset = 0.0f;
}

void ImGui::ItemSize(const ImRect& bb, float text_offset_y)
{
    ItemSize(bb.GetSize(), text_offset_y);
}

// Declare item bounding box for clipping and interaction.
// Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface
// declares their minimum size requirement to ItemSize() and then use a larger region for drawing/interaction, which is passed to ItemAdd().
bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id)
{
    ImGuiWindow* window = GetCurrentWindow();
    window->DC.LastItemId = id ? *id : 0;
    window->DC.LastItemRect = bb;
    window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRect = false;
    if (IsClippedEx(bb, id, false))
        return false;

    // This is a sensible default, but widgets are free to override it after calling ItemAdd()
    ImGuiContext& g = *GImGui;
    if (IsMouseHoveringRect(bb.Min, bb.Max))
    {
        // Matching the behavior of IsHovered() but allow if ActiveId==window->MoveID (we clicked on the window background)
        // So that clicking on items with no active id such as Text() still returns true with IsItemHovered()
        window->DC.LastItemHoveredRect = true;
        if (g.HoveredRootWindow == window->RootWindow)
            if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdAllowOverlap || (g.ActiveId == window->MoveId))
                if (IsWindowContentHoverable(window))
                    window->DC.LastItemHoveredAndUsable = true;
    }

    return true;
}

bool ImGui::IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when_logged)
{
    ImGuiContext& g = *GImGui;
    ImGuiWindow* window = GetCurrentWindowRead();
    if (!bb.Overlaps(window->ClipRect))
        if (!id || *id != GImGui->ActiveId)
            if (clip_even_when_logged || !g.LogEnabled)
                return true;
    return false;
}

// NB: This is an internal helper. The user-facing IsItemHovered() is using data emitted from ItemAdd(), with a slightly different logic.
bool ImGui::IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs)
{
    ImGuiContext& g = *GImGui;
    if (g.HoveredId == 0 || g.HoveredId == id || g.HoveredIdAllowOverlap)
    {
        ImGuiWindow* window = GetCurrentWindowRead();
        if (g.HoveredWindow == window || (flatten_childs && g.HoveredRootWindow == window->RootWindow))
            if ((g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdAllowOverlap) && IsMouseHoveringRect(bb.Min, bb.Max))
                if (IsWindowContentHoverable(g.HoveredRootWindow))
                    return true;
    }
    return false;
}

bool ImGui::FocusableItemRegister(ImGuiWindow* window, bool is_active, bool tab_stop)
{
    ImGuiContext& g = *GImGui;

    const bool allow_keyboard_focus = window->DC.AllowKeyboardFocus;
    window->FocusIdxAllCounter++;
    if (allow_keyboard_focus)
        window->FocusIdxTabCounter++;

    // Process keyboard input at this point: TAB, Shift-TAB switch focus
    // We can always TAB out of a widget that doesn't allow tabbing in.
    if (tab_stop && window->FocusIdxAllRequestNext == INT_MAX && window->FocusIdxTabRequestNext == INT_MAX && is_active && IsKeyPressedMap(ImGuiKey_Tab))
    {
        // Modulo on index will be applied at the end of frame once we've got the total counter of items.
        window->FocusIdxTabRequestNext = window->FocusIdxTabCounter + (g.IO.KeyShift ? (allow_keyboard_focus ? -1 : 0) : +1);
    }

    if (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent)
        return true;

    if (allow_keyboard_focus)
        if (window->FocusIdxTabCounter == window->FocusIdxTabRequestCurrent)
            return true;

    return false;
}

void ImGui::FocusableItemUnregister(ImGuiWindow* window)
{
    window->FocusIdxAllCounter--;
    window->FocusIdxTabCounter--;
}

ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_x, float default_y)
{
    ImGuiContext& g = *GImGui;
    ImVec2 content_max;
    if (size.x < 0.0f || size.y < 0.0f)
        content_max = g.CurrentWindow->Pos + GetContentRegionMax();
    if (size.x <= 0.0f)
        size.x = (size.x == 0.0f) ? default_x : ImMax(content_max.x - g.CurrentWindow->DC.CursorPos.x, 4.0f) + size.x;
    if (size.y <= 0.0f)
        size.y = (size.y == 0.0f) ? default_y : ImMax(content_max.y - g.CurrentWindow->DC.CursorPos.y, 4.0f) + size.y;
    return size;
}

float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x)
{
    if (wrap_pos_x < 0.0f)
        return 0.0f;

    ImGuiWindow* window = GetCurrentWindowRead();
    if (wrap_pos_x == 0.0f)
        wrap_pos_x = GetContentRegionMax().x + window->Pos.x;
    else if (wrap_pos_x > 0.0f)
        wrap_pos_x += window->Pos.x - window->Scroll.x; // wrap_pos_x is provided is window local space

    return ImMax(wrap_pos_x - pos.x, 1.0f);
}

//-----------------------------------------------------------------------------

void* ImGui::MemAlloc(size_t sz)
{
    GImGui->IO.MetricsAllocs++;
    return GImGui->IO.MemAllocFn(sz);
}

void ImGui::MemFree(void* ptr)
{
    if (ptr) GImGui->IO.MetricsAllocs--;
    return GImGui->IO.MemFreeFn(ptr);
}

const char* ImGui::GetClipboardText()
{
    return GImGui->IO.GetClipboardTextFn ? GImGui->IO.GetClipboardTextFn(GImGui->IO.ClipboardUserData) : "";
}

void ImGui::SetClipboardText(const char* text)
{
    if (GImGui->IO.SetClipboardTextFn)
        GImGui->IO.SetClipboardTextFn(GImGui->IO.ClipboardUserData, text);
}

const char* ImGui::GetVersion()
{
    return IMGUI_VERSION;
}

// Internal state access - if you want to share ImGui state between modules (e.g. DLL) or allocate it yourself
// Note that we still point to some static data and members (such as GFontAtlas), so the state instance you end up using will point to the static data within its module
ImGuiContext* ImGui::GetCurrentContext()
{
    return GImGui;
}

void ImGui::SetCurrentContext(ImGuiContext* ctx)
{
#ifdef IMGUI_SET_CURRENT_CONTEXT_FUNC
    IMGUI_SET_CURRENT_CONTEXT_FUNC(ctx); // For custom thread-based hackery you may want to have control over this.
#else
    GImGui = ctx;
#endif
}

ImGuiContext* ImGui::CreateContext(void* (*malloc_fn)(size_t), void (*free_fn)(void*))
{
    if (!malloc_fn) malloc_fn = malloc;
    ImGuiContext* ctx = (ImGuiContext*)malloc_fn(sizeof(ImGuiContext));
    IM_PLACEMENT_NEW(ctx) ImGuiContext();
    ctx->IO.MemAllocFn = malloc_fn;
    ctx->IO.MemFreeFn = free_fn ? free_fn : free;
    return ctx;
}

void ImGui::DestroyContext(ImGuiContext* ctx)
{
    void (*free_fn)(void*) = ctx->IO.MemFreeFn;
    ctx->~ImGuiContext();
    free_fn(ctx);
    if (GImGui == ctx)
        SetCurrentContext(NULL);
}

ImGuiIO& ImGui::GetIO()
{
    return GImGui->IO;
}

ImGuiStyle& ImGui::GetStyle()
{
    return GImGui->Style;
}

// Same value as passed to your RenderDrawListsFn() function. valid after Render() and until the next call to NewFrame()
ImDrawData* ImGui::GetDrawData()
{
    return GImGui->RenderDrawData.Valid ? &GImGui->RenderDrawData : NULL;
}

float ImGui::GetTime()
{
    return GImGui->Time;
}

int ImGui::GetFrameCount()
{
    return GImGui->FrameCount;
}

void ImGui::NewFrame()
{
    ImGuiContext& g = *GImGui;

    // Check user data
    IM_ASSERT(g.IO.DeltaTime >= 0.0f);               // Need a positive DeltaTime (zero is tolerated but will cause some timing issues)
    IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f);
    IM_ASSERT(g.IO.Fonts->Fonts.Size > 0);           // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
    IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded());     // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
    IM_ASSERT(g.Style.CurveTessellationTol > 0.0f);  // Invalid style setting
    IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f);  // Invalid style setting. Alpha cannot be negative (allows us to avoid a few clamps in color computations)

    if (!g.Initialized)
    {
        // Initialize on first frame
        g.LogClipboard = (ImGuiTextBuffer*)ImGui::MemAlloc(sizeof(ImGuiTextBuffer));
        IM_PLACEMENT_NEW(g.LogClipboard) ImGuiTextBuffer();

        IM_ASSERT(g.Settings.empty());
        LoadIniSettingsFromDisk(g.IO.IniFilename);
        g.Initialized = true;
    }

    SetCurrentFont(GetDefaultFont());
    IM_ASSERT(g.Font->IsLoaded());

    g.Time += g.IO.DeltaTime;
    g.FrameCount += 1;
    g.TooltipOverrideCount = 0;
    g.OverlayDrawList.Clear();
    g.OverlayDrawList.PushTextureID(g.IO.Fonts->TexID);
    g.OverlayDrawList.PushClipRectFullScreen();

    // Mark rendering data as invalid to prevent user who may have a handle on it to use it
    g.RenderDrawData.Valid = false;
    g.RenderDrawData.CmdLists = NULL;
    g.RenderDrawData.CmdListsCount = g.RenderDrawData.TotalVtxCount = g.RenderDrawData.TotalIdxCount = 0;


    // Update mouse input state
    if (g.IO.MousePos.x < 0 && g.IO.MousePos.y < 0)
        g.IO.MousePos = ImVec2(-9999.0f, -9999.0f);
    if ((g.IO.MousePos.x < 0 && g.IO.MousePos.y < 0) || (g.IO.MousePosPrev.x < 0 && g.IO.MousePosPrev.y < 0))   // if mouse just appeared or disappeared (negative coordinate) we cancel out movement in MouseDelta
        g.IO.MouseDelta = ImVec2(0.0f, 0.0f);
    else
        g.IO.MouseDelta = g.IO.MousePos - g.IO.MousePosPrev;
    g.IO.MousePosPrev = g.IO.MousePos;
    for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++)
    {
        g.IO.MouseClicked[i] = g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] < 0.0f;
        g.IO.MouseReleased[i] = !g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] >= 0.0f;
        g.IO.MouseDownDurationPrev[i] = g.IO.MouseDownDuration[i];
        g.IO.MouseDownDuration[i] = g.IO.MouseDown[i] ? (g.IO.MouseDownDuration[i] < 0.0f ? 0.0f : g.IO.MouseDownDuration[i] + g.IO.DeltaTime) : -1.0f;
        g.IO.MouseDoubleClicked[i] = false;
        if (g.IO.MouseClicked[i])
        {
            if (g.Time - g.IO.MouseClickedTime[i] < g.IO.MouseDoubleClickTime)
            {
                if (ImLengthSqr(g.IO.MousePos - g.IO.MouseClickedPos[i]) < g.IO.MouseDoubleClickMaxDist * g.IO.MouseDoubleClickMaxDist)
                    g.IO.MouseDoubleClicked[i] = true;
                g.IO.MouseClickedTime[i] = -FLT_MAX;    // so the third click isn't turned into a double-click
            }
            else
            {
                g.IO.MouseClickedTime[i] = g.Time;
            }
            g.IO.MouseClickedPos[i] = g.IO.MousePos;
            g.IO.MouseDragMaxDistanceSqr[i] = 0.0f;
        }
        else if (g.IO.MouseDown[i])
        {
            g.IO.MouseDragMaxDistanceSqr[i] = ImMax(g.IO.MouseDragMaxDistanceSqr[i], ImLengthSqr(g.IO.MousePos - g.IO.MouseClickedPos[i]));
        }
    }
    memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration));
    for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++)
        g.IO.KeysDownDuration[i] = g.IO.KeysDown[i] ? (g.IO.KeysDownDuration[i] < 0.0f ? 0.0f : g.IO.KeysDownDuration[i] + g.IO.DeltaTime) : -1.0f;

    // Calculate frame-rate for the user, as a purely luxurious feature
    g.FramerateSecPerFrameAccum += g.IO.DeltaTime - g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx];
    g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx] = g.IO.DeltaTime;
    g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame);
    g.IO.Framerate = 1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame));

    // Clear reference to active widget if the widget isn't alive anymore
    g.HoveredIdPreviousFrame = g.HoveredId;
    g.HoveredId = 0;
    g.HoveredIdAllowOverlap = false;
    if (!g.ActiveIdIsAlive && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0)
        ClearActiveID();
    g.ActiveIdPreviousFrame = g.ActiveId;
    g.ActiveIdIsAlive = false;
    g.ActiveIdIsJustActivated = false;

    // Handle user moving window (at the beginning of the frame to avoid input lag or sheering). Only valid for root windows.
    if (g.MovedWindowMoveId && g.MovedWindowMoveId == g.ActiveId)
    {
        KeepAliveID(g.MovedWindowMoveId);
        IM_ASSERT(g.MovedWindow && g.MovedWindow->RootWindow);
        IM_ASSERT(g.MovedWindow->RootWindow->MoveId == g.MovedWindowMoveId);
        if (g.IO.MouseDown[0])
        {
            if (!(g.MovedWindow->Flags & ImGuiWindowFlags_NoMove))
            {
                g.MovedWindow->PosFloat += g.IO.MouseDelta;
                if (!(g.MovedWindow->Flags & ImGuiWindowFlags_NoSavedSettings) && (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f))
                    MarkIniSettingsDirty(g.MovedWindow);
            }
            FocusWindow(g.MovedWindow);
        }
        else
        {
            ClearActiveID();
            g.MovedWindow = NULL;
            g.MovedWindowMoveId = 0;
        }
    }
    else
    {
        g.MovedWindow = NULL;
        g.MovedWindowMoveId = 0;
    }

    // Delay saving settings so we don't spam disk too much
    if (g.SettingsDirtyTimer > 0.0f)
    {
        g.SettingsDirtyTimer -= g.IO.DeltaTime;
        if (g.SettingsDirtyTimer <= 0.0f)
            SaveIniSettingsToDisk(g.IO.IniFilename);
    }

    // Find the window we are hovering. Child windows can extend beyond the limit of their parent so we need to derive HoveredRootWindow from HoveredWindow
    g.HoveredWindow = g.MovedWindow ? g.MovedWindow : FindHoveredWindow(g.IO.MousePos, false);
    if (g.HoveredWindow && (g.HoveredWindow->Flags & ImGuiWindowFlags_ChildWindow))
        g.HoveredRootWindow = g.HoveredWindow->RootWindow;
    else
        g.HoveredRootWindow = g.MovedWindow ? g.MovedWindow->RootWindow : FindHoveredWindow(g.IO.MousePos, true);

    if (ImGuiWindow* modal_window = GetFrontMostModalRootWindow())
    {
        g.ModalWindowDarkeningRatio = ImMin(g.ModalWindowDarkeningRatio + g.IO.DeltaTime * 6.0f, 1.0f);
        ImGuiWindow* window = g.HoveredRootWindow;
        while (window && window != modal_window)
            window = window->ParentWindow;
        if (!window)
            g.HoveredRootWindow = g.HoveredWindow = NULL;
    }
    else
    {
        g.ModalWindowDarkeningRatio = 0.0f;
    }

    // Are we using inputs? Tell user so they can capture/discard the inputs away from the rest of their application.
    // When clicking outside of a window we assume the click is owned by the application and won't request capture. We need to track click ownership.
    int mouse_earliest_button_down = -1;
    bool mouse_any_down = false;
    for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++)
    {
        if (g.IO.MouseClicked[i])
            g.IO.MouseDownOwned[i] = (g.HoveredWindow != NULL) || (!g.OpenPopupStack.empty());
        mouse_any_down |= g.IO.MouseDown[i];
        if (g.IO.MouseDown[i])
            if (mouse_earliest_button_down == -1 || g.IO.MouseClickedTime[mouse_earliest_button_down] > g.IO.MouseClickedTime[i])
                mouse_earliest_button_down = i;
    }
    bool mouse_avail_to_imgui = (mouse_earliest_button_down == -1) || g.IO.MouseDownOwned[mouse_earliest_button_down];
    if (g.CaptureMouseNextFrame != -1)
        g.IO.WantCaptureMouse = (g.CaptureMouseNextFrame != 0);
    else
        g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (g.ActiveId != 0) || (!g.OpenPopupStack.empty());
    g.IO.WantCaptureKeyboard = (g.CaptureKeyboardNextFrame != -1) ? (g.CaptureKeyboardNextFrame != 0) : (g.ActiveId != 0);
    g.IO.WantTextInput = (g.ActiveId != 0 && g.InputTextState.Id == g.ActiveId);
    g.MouseCursor = ImGuiMouseCursor_Arrow;
    g.CaptureMouseNextFrame = g.CaptureKeyboardNextFrame = -1;
    g.OsImePosRequest = ImVec2(1.0f, 1.0f); // OS Input Method Editor showing on top-left of our window by default

    // If mouse was first clicked outside of ImGui bounds we also cancel out hovering.
    if (!mouse_avail_to_imgui)
        g.HoveredWindow = g.HoveredRootWindow = NULL;

    // Scale & Scrolling
    if (g.HoveredWindow && g.IO.MouseWheel != 0.0f && !g.HoveredWindow->Collapsed)
    {
        ImGuiWindow* window = g.HoveredWindow;
        if (g.IO.KeyCtrl && g.IO.FontAllowUserScaling)
        {
            // Zoom / Scale window
            const float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f);
            const float scale = new_font_scale / window->FontWindowScale;
            window->FontWindowScale = new_font_scale;

            const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size;
            window->Pos += offset;
            window->PosFloat += offset;
            window->Size *= scale;
            window->SizeFull *= scale;
        }
        else if (!g.IO.KeyCtrl && !(window->Flags & ImGuiWindowFlags_NoScrollWithMouse))
        {
            // Scroll
            const int scroll_lines = (window->Flags & ImGuiWindowFlags_ComboBox) ? 3 : 5;
            SetWindowScrollY(window, window->Scroll.y - g.IO.MouseWheel * window->CalcFontSize() * scroll_lines);
        }
    }

    // Pressing TAB activate widget focus
    // NB: Don't discard FocusedWindow if it isn't active, so that a window that go on/off programatically won't lose its keyboard focus.
    if (g.ActiveId == 0 && g.NavWindow != NULL && g.NavWindow->Active && IsKeyPressedMap(ImGuiKey_Tab, false))
        g.NavWindow->FocusIdxTabRequestNext = 0;

    // Mark all windows as not visible
    for (int i = 0; i != g.Windows.Size; i++)
    {
        ImGuiWindow* window = g.Windows[i];
        window->WasActive = window->Active;
        window->Active = false;
        window->Accessed = false;
    }

    // Closing the focused window restore focus to the first active root window in descending z-order
    if (g.NavWindow && !g.NavWindow->WasActive)
        for (int i = g.Windows.Size-1; i >= 0; i--)
            if (g.Windows[i]->WasActive && !(g.Windows[i]->Flags & ImGuiWindowFlags_ChildWindow))
            {
                FocusWindow(g.Windows[i]);
                break;
            }

    // No window should be open at the beginning of the frame.
    // But in order to allow the user to call NewFrame() multiple times without calling Render(), we are doing an explicit clear.
    g.CurrentWindowStack.resize(0);
    g.CurrentPopupStack.resize(0);
    CloseInactivePopups();

    // Create implicit window - we will only render it if the user has added something to it.
    ImGui::SetNextWindowSize(ImVec2(400,400), ImGuiCond_FirstUseEver);
    ImGui::Begin("Debug");
}

// NB: behavior of ImGui after Shutdown() is not tested/guaranteed at the moment. This function is merely here to free heap allocations.
void ImGui::Shutdown()
{
    ImGuiContext& g = *GImGui;

    // The fonts atlas can be used prior to calling NewFrame(), so we clear it even if g.Initialized is FALSE (which would happen if we never called NewFrame)
    if (g.IO.Fonts) // Testing for NULL to allow user to NULLify in case of running Shutdown() on multiple contexts. Bit hacky.
        g.IO.Fonts->Clear();

    // Cleanup of other data are conditional on actually having used ImGui.
    if (!g.Initialized)
        return;

    SaveIniSettingsToDisk(g.IO.IniFilename);

    for (int i = 0; i < g.Windows.Size; i++)
    {
        g.Windows[i]->~ImGuiWindow();
        ImGui::MemFree(g.Windows[i]);
    }
    g.Windows.clear();
    g.WindowsSortBuffer.clear();
    g.CurrentWindow = NULL;
    g.CurrentWindowStack.clear();
    g.NavWindow = NULL;
    g.HoveredWindow = NULL;
    g.HoveredRootWindow = NULL;
    g.ActiveIdWindow = NULL;
    g.MovedWindow = NULL;
    for (int i = 0; i < g.Settings.Size; i++)
        ImGui::MemFree(g.Settings[i].Name);
    g.Settings.clear();
    g.ColorModifiers.clear();
    g.StyleModifiers.clear();
    g.FontStack.clear();
    g.OpenPopupStack.clear();
    g.CurrentPopupStack.clear();
    g.SetNextWindowSizeConstraintCallback = NULL;
    g.SetNextWindowSizeConstraintCallbackUserData = NULL;
    for (int i = 0; i < IM_ARRAYSIZE(g.RenderDrawLists); i++)
        g.RenderDrawLists[i].clear();
    g.OverlayDrawList.ClearFreeMemory();
    g.PrivateClipboard.clear();
    g.InputTextState.Text.clear();
    g.InputTextState.InitialText.clear();
    g.InputTextState.TempTextBuffer.clear();

    if (g.LogFile && g.LogFile != stdout)
    {
        fclose(g.LogFile);
        g.LogFile = NULL;
    }
    if (g.LogClipboard)
    {
        g.LogClipboard->~ImGuiTextBuffer();
        ImGui::MemFree(g.LogClipboard);
    }

    g.Initialized = false;
}

static ImGuiIniData* FindWindowSettings(const char* name)
{
    ImGuiContext& g = *GImGui;
    ImGuiID id = ImHash(name, 0);
    for (int i = 0; i != g.Settings.Size; i++)
    {
        ImGuiIniData* ini = &g.Settings[i];
        if (ini->Id == id)
            return ini;
    }
    return NULL;
}

static ImGuiIniData* AddWindowSettings(const char* name)
{
    GImGui->Settings.resize(GImGui->Settings.Size + 1);
    ImGuiIniData* ini = &GImGui->Settings.back();
    ini->Name = ImStrdup(name);
    ini->Id = ImHash(name, 0);
    ini->Collapsed = false;
    ini->Pos = ImVec2(FLT_MAX,FLT_MAX);
    ini->Size = ImVec2(0,0);
    return ini;
}

// Zero-tolerance, poor-man .ini parsing
// FIXME: Write something less rubbish
static void LoadIniSettingsFromDisk(const char* ini_filename)
{
    ImGuiContext& g = *GImGui;
    if (!ini_filename)
        return;

    int file_size;
    char* file_data = (char*)ImFileLoadToMemory(ini_filename, "rb", &file_size, 1);
    if (!file_data)
        return;

    ImGuiIniData* settings = NULL;
    const char* buf_end = file_data + file_size;
    for (const char* line_start = file_data; line_start < buf_end; )
    {
        const char* line_end = line_start;
        while (line_end < buf_end && *line_end != '\n' && *line_end != '\r')
            line_end++;

        if (line_start[0] == '[' && line_end > line_start && line_end[-1] == ']')
        {
            char name[64];
            ImFormatString(name, IM_ARRAYSIZE(name), "%.*s", (int)(line_end-line_start-2), line_start+1);
            settings = FindWindowSettings(name);
            if (!settings)
                settings = AddWindowSettings(name);
        }
        else if (settings)
        {
            float x, y;
            int i;
            if (sscanf(line_start, "Pos=%f,%f", &x, &y) == 2)
                settings->Pos = ImVec2(x, y);
            else if (sscanf(line_start, "Size=%f,%f", &x, &y) == 2)
                settings->Size = ImMax(ImVec2(x, y), g.Style.WindowMinSize);
            else if (sscanf(line_start, "Collapsed=%d", &i) == 1)
                settings->Collapsed = (i != 0);
        }

        line_start = line_end+1;
    }

    ImGui::MemFree(file_data);
}

static void SaveIniSettingsToDisk(const char* ini_filename)
{
    ImGuiContext& g = *GImGui;
    g.SettingsDirtyTimer = 0.0f;
    if (!ini_filename)
        return;

    // Gather data from windows that were active during this session
    for (int i = 0; i != g.Windows.Size; i++)
    {
        ImGuiWindow* window = g.Windows[i];
        if (window->Flags & ImGuiWindowFlags_NoSavedSettings)
            continue;
        ImGuiIniData* settings = FindWindowSettings(window->Name);
        if (!settings)  // This will only return NULL in the rare instance where the window was first created with ImGuiWindowFlags_NoSavedSettings then had the flag disabled later on. We don't bind settings in this case (bug #1000).
            continue;
        settings->Pos = window->Pos;
        settings->Size = window->SizeFull;
        settings->Collapsed = window->Collapsed;
    }

    // Write .ini file
    // If a window wasn't opened in this session we preserve its settings
    FILE* f = ImFileOpen(ini_filename, "wt");
    if (!f)
        return;
    for (int i = 0; i != g.Settings.Size; i++)
    {
        const ImGuiIniData* settings = &g.Settings[i];
        if (settings->Pos.x == FLT_MAX)
            continue;
        const char* name = settings->Name;
        if (const char* p = strstr(name, "###"))  // Skip to the "###" marker if any. We don't skip past to match the behavior of GetID()
            name = p;
        fprintf(f, "[%s]\n", name);
        fprintf(f, "Pos=%d,%d\n", (int)settings->Pos.x, (int)settings->Pos.y);
        fprintf(f, "Size=%d,%d\n", (int)settings->Size.x, (int)settings->Size.y);
        fprintf(f, "Collapsed=%d\n", settings->Collapsed);
        fprintf(f, "\n");
    }

    fclose(f);
}

static void MarkIniSettingsDirty(ImGuiWindow* window)
{
    ImGuiContext& g = *GImGui;
    if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings))
        if (g.SettingsDirtyTimer <= 0.0f)
            g.SettingsDirtyTimer = g.IO.IniSavingRate;
}

// FIXME: Add a more explicit sort order in the window structure.
static int ChildWindowComparer(const void* lhs, const void* rhs)
{
    const ImGuiWindow* a = *(const ImGuiWindow**)lhs;
    const ImGuiWindow* b = *(const ImGuiWindow**)rhs;
    if (int d = (a->Flags & ImGuiWindowFlags_Popup) - (b->Flags & ImGuiWindowFlags_Popup))
        return d;
    if (int d = (a->Flags & ImGuiWindowFlags_Tooltip) - (b->Flags & ImGuiWindowFlags_Tooltip))
        return d;
    if (int d = (a->Flags & ImGuiWindowFlags_ComboBox) - (b->Flags & ImGuiWindowFlags_ComboBox))
        return d;
    return (a->OrderWithinParent - b->OrderWithinParent);
}

static void AddWindowToSortedBuffer(ImVector<ImGuiWindow*>& out_sorted_windows, ImGuiWindow* window)
{
    out_sorted_windows.push_back(window);
    if (window->Active)
    {
        int count = window->DC.ChildWindows.Size;
        if (count > 1)
            qsort(window->DC.ChildWindows.begin(), (size_t)count, sizeof(ImGuiWindow*), ChildWindowComparer);
        for (int i = 0; i < count; i++)
        {
            ImGuiWindow* child = window->DC.ChildWindows[i];
            if (child->Active)
                AddWindowToSortedBuffer(out_sorted_windows, child);
        }
    }
}

static void AddDrawListToRenderList(ImVector<ImDrawList*>& out_render_list, ImDrawList* draw_list)
{
    if (draw_list->CmdBuffer.empty())
        return;

    // Remove trailing command if unused
    ImDrawCmd& last_cmd = draw_list->CmdBuffer.back();
    if (last_cmd.ElemCount == 0 && last_cmd.UserCallback == NULL)
    {
        draw_list->CmdBuffer.pop_back();
        if (draw_list->CmdBuffer.empty())
            return;
    }

    // Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc. May trigger for you if you are using PrimXXX functions incorrectly.
    IM_ASSERT(draw_list->VtxBuffer.Size == 0 || draw_list->_VtxWritePtr == draw_list->VtxBuffer.Data + draw_list->VtxBuffer.Size);
    IM_ASSERT(draw_list->IdxBuffer.Size == 0 || draw_list->_IdxWritePtr == draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size);
    IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size);

    // Check that draw_list doesn't use more vertices than indexable in a single draw call (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per window)
    // If this assert triggers because you are drawing lots of stuff manually, you can:
    // A) Add '#define ImDrawIdx unsigned int' in imconfig.h to set the index size to 4 bytes. You'll need to handle the 4-bytes indices to your renderer.
    //    For example, the OpenGL example code detect index size at compile-time by doing:
    //    'glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);'
    //    Your own engine or render API may use different parameters or function calls to specify index sizes. 2 and 4 bytes indices are generally supported by most API.
    // B) If for some reason you cannot use 4 bytes indices or don't want to, a workaround is to call BeginChild()/EndChild() before reaching the 64K limit to split your draw commands in multiple draw lists.
    IM_ASSERT(((ImU64)draw_list->_VtxCurrentIdx >> (sizeof(ImDrawIdx)*8)) == 0);  // Too many vertices in same ImDrawList. See comment above.
    
    out_render_list.push_back(draw_list);
    GImGui->IO.MetricsRenderVertices += draw_list->VtxBuffer.Size;
    GImGui->IO.MetricsRenderIndices += draw_list->IdxBuffer.Size;
}

static void AddWindowToRenderList(ImVector<ImDrawList*>& out_render_list, ImGuiWindow* window)
{
    AddDrawListToRenderList(out_render_list, window->DrawList);
    for (int i = 0; i < window->DC.ChildWindows.Size; i++)
    {
        ImGuiWindow* child = window->DC.ChildWindows[i];
        if (!child->Active) // clipped children may have been marked not active
            continue;
        if ((child->Flags & ImGuiWindowFlags_Popup) && child->HiddenFrames > 0)
            continue;
        AddWindowToRenderList(out_render_list, child);
    }
}

// When using this function it is sane to ensure that float are perfectly rounded to integer values, to that e.g. (int)(max.x-min.x) in user's render produce correct result.
void ImGui::PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect)
{
    ImGuiWindow* window = GetCurrentWindow();
    window->DrawList->PushClipRect(clip_rect_min, clip_rect_max, intersect_with_current_clip_rect);
    window->ClipRect = window->DrawList->_ClipRectStack.back();
}

void ImGui::PopClipRect()
{
    ImGuiWindow* window = GetCurrentWindow();
    window->DrawList->PopClipRect();
    window->ClipRect = window->DrawList->_ClipRectStack.back();
}

// This is normally called by Render(). You may want to call it directly if you want to avoid calling Render() but the gain will be very minimal.
void ImGui::EndFrame()
{
    ImGuiContext& g = *GImGui;
    IM_ASSERT(g.Initialized);                       // Forgot to call ImGui::NewFrame()
    IM_ASSERT(g.FrameCountEnded != g.FrameCount);   // ImGui::EndFrame() called multiple times, or forgot to call ImGui::NewFrame() again

    // Notify OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME)
    if (g.IO.ImeSetInputScreenPosFn && ImLengthSqr(g.OsImePosRequest - g.OsImePosSet) > 0.0001f)
    {
        g.IO.ImeSetInputScreenPosFn((int)g.OsImePosRequest.x, (int)g.OsImePosRequest.y);
        g.OsImePosSet = g.OsImePosRequest;
    }

    // Hide implicit "Debug" window if it hasn't been used
    IM_ASSERT(g.CurrentWindowStack.Size == 1);    // Mismatched Begin()/End() calls
    if (g.CurrentWindow && !g.CurrentWindow->Accessed)
        g.CurrentWindow->Active = false;
    ImGui::End();

    // Click to focus window and start moving (after we're done with all our widgets)
    if (g.ActiveId == 0 && g.HoveredId == 0 && g.IO.MouseClicked[0])
    {
        if (!(g.NavWindow && !g.NavWindow->WasActive && g.NavWindow->Active)) // Unless we just made a popup appear
        {
            if (g.HoveredRootWindow != NULL)
            {
                FocusWindow(g.HoveredWindow);
                if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove))
                {
                    g.MovedWindow = g.HoveredWindow;
                    g.MovedWindowMoveId = g.HoveredRootWindow->MoveId;
                    SetActiveID(g.MovedWindowMoveId, g.HoveredRootWindow);
                }
            }
            else if (g.NavWindow != NULL && GetFrontMostModalRootWindow() == NULL)
            {
                // Clicking on void disable focus
                FocusWindow(NULL);
            }
        }
    }

    // Sort the window list so that all child windows are after their parent
    // We cannot do that on FocusWindow() because childs may not exist yet
    g.WindowsSortBuffer.resize(0);
    g.WindowsSortBuffer.reserve(g.Windows.Size);
    for (int i = 0; i != g.Windows.Size; i++)
    {
        ImGuiWindow* window = g.Windows[i];
        if (window->Active && (window->Flags & ImGuiWindowFlags_ChildWindow))       // if a child is active its parent will add it
            continue;
        AddWindowToSortedBuffer(g.WindowsSortBuffer, window);
    }

    IM_ASSERT(g.Windows.Size == g.WindowsSortBuffer.Size);  // we done something wrong
    g.Windows.swap(g.WindowsSortBuffer);

    // Clear Input data for next frame
    g.IO.MouseWheel = 0.0f;
    memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters));

    g.FrameCountEnded = g.FrameCount;
}

void ImGui::Render()
{
    ImGuiContext& g = *GImGui;
    IM_ASSERT(g.Initialized);   // Forgot to call ImGui::NewFrame()

    if (g.FrameCountEnded != g.FrameCount)
        ImGui::EndFrame();
    g.FrameCountRendered = g.FrameCount;

    // Skip render altogether if alpha is 0.0
    // Note that vertex buffers have been created and are wasted, so it is best practice that you don't create windows in the first place, or consistently respond to Begin() returning false.
    if (g.Style.Alpha > 0.0f)
    {
        // Gather windows to render
        g.IO.MetricsRenderVertices = g.IO.MetricsRenderIndices = g.IO.MetricsActiveWindows = 0;
        for (int i = 0; i < IM_ARRAYSIZE(g.RenderDrawLists); i++)
            g.RenderDrawLists[i].resize(0);
        for (int i = 0; i != g.Windows.Size; i++)
        {
            ImGuiWindow* window = g.Windows[i];
            if (window->Active && window->HiddenFrames <= 0 && (window->Flags & (ImGuiWindowFlags_ChildWindow)) == 0)
            {
                // FIXME: Generalize this with a proper layering system so e.g. user can draw in specific layers, below text, ..
                g.IO.MetricsActiveWindows++;
                if (window->Flags & ImGuiWindowFlags_Popup)
                    AddWindowToRenderList(g.RenderDrawLists[1], window);
                else if (window->Flags & ImGuiWindowFlags_Tooltip)
                    AddWindowToRenderList(g.RenderDrawLists[2], window);
                else
                    AddWindowToRenderList(g.RenderDrawLists[0], window);
            }
        }

        // Flatten layers
        int n = g.RenderDrawLists[0].Size;
        int flattened_size = n;
        for (int i = 1; i < IM_ARRAYSIZE(g.RenderDrawLists); i++)
            flattened_size += g.RenderDrawLists[i].Size;
        g.RenderDrawLists[0].resize(flattened_size);
        for (int i = 1; i < IM_ARRAYSIZE(g.RenderDrawLists); i++)
        {
            ImVector<ImDrawList*>& layer = g.RenderDrawLists[i];
            if (layer.empty())
                continue;
            memcpy(&g.RenderDrawLists[0][n], &layer[0], layer.Size * sizeof(ImDrawList*));
            n += layer.Size;
        }

        // Draw software mouse cursor if requested
        if (g.IO.MouseDrawCursor)
        {
            const ImGuiMouseCursorData& cursor_data = g.MouseCursorData[g.MouseCursor];
            const ImVec2 pos = g.IO.MousePos - cursor_data.HotOffset;
            const ImVec2 size = cursor_data.Size;
            const ImTextureID tex_id = g.IO.Fonts->TexID;
            g.OverlayDrawList.PushTextureID(tex_id);
            g.OverlayDrawList.AddImage(tex_id, pos+ImVec2(1,0), pos+ImVec2(1,0) + size, cursor_data.TexUvMin[1], cursor_data.TexUvMax[1], IM_COL32(0,0,0,48));        // Shadow
            g.OverlayDrawList.AddImage(tex_id, pos+ImVec2(2,0), pos+ImVec2(2,0) + size, cursor_data.TexUvMin[1], cursor_data.TexUvMax[1], IM_COL32(0,0,0,48));        // Shadow
            g.OverlayDrawList.AddImage(tex_id, pos,             pos + size,             cursor_data.TexUvMin[1], cursor_data.TexUvMax[1], IM_COL32(0,0,0,255));       // Black border
            g.OverlayDrawList.AddImage(tex_id, pos,             pos + size,             cursor_data.TexUvMin[0], cursor_data.TexUvMax[0], IM_COL32(255,255,255,255)); // White fill
            g.OverlayDrawList.PopTextureID();
        }
        if (!g.OverlayDrawList.VtxBuffer.empty())
            AddDrawListToRenderList(g.RenderDrawLists[0], &g.OverlayDrawList);

        // Setup draw data
        g.RenderDrawData.Valid = true;
        g.RenderDrawData.CmdLists = (g.RenderDrawLists[0].Size > 0) ? &g.RenderDrawLists[0][0] : NULL;
        g.RenderDrawData.CmdListsCount = g.RenderDrawLists[0].Size;
        g.RenderDrawData.TotalVtxCount = g.IO.MetricsRenderVertices;
        g.RenderDrawData.TotalIdxCount = g.IO.MetricsRenderIndices;

        // Render. If user hasn't set a callback then they may retrieve the draw data via GetDrawData()
        if (g.RenderDrawData.CmdListsCount > 0 && g.IO.RenderDrawListsFn != NULL)
            g.IO.RenderDrawListsFn(&g.RenderDrawData);
    }
}

const char* ImGui::FindRenderedTextEnd(const char* text, const char* text_end)
{
    const char* text_display_end = text;
    if (!text_end)
        text_end = (const char*)-1;

    while (text_display_end < text_end && *text_display_end != '\0' && (text_display_end[0] != '#' || text_display_end[1] != '#'))
        text_display_end++;
    return text_display_end;
}

// Pass text data straight to log (without being displayed)
void ImGui::LogText(const char* fmt, ...)
{
    ImGuiContext& g = *GImGui;
    if (!g.LogEnabled)
        return;

    va_list args;
    va_start(args, fmt);
    if (g.LogFile)
    {
        vfprintf(g.LogFile, fmt, args);
    }
    else
    {
        g.LogClipboard->appendv(fmt, args);
    }
    va_end(args);
}

// Internal version that takes a position to decide on newline placement and pad items according to their depth.
// We split text into individual lines to add current tree level padding
static void LogRenderedText(const ImVec2& ref_pos, const char* text, const char* text_end)
{
    ImGuiContext& g = *GImGui;
    ImGuiWindow* window = ImGui::GetCurrentWindowRead();

    if (!text_end)
        text_end = ImGui::FindRenderedTextEnd(text, text_end);

    const bool log_new_line = ref_pos.y > window->DC.LogLinePosY+1;
    window->DC.LogLinePosY = ref_pos.y;

    const char* text_remaining = text;
    if (g.LogStartDepth > window->DC.TreeDepth)  // Re-adjust padding if we have popped out of our starting depth
        g.LogStartDepth = window->DC.TreeDepth;
    const int tree_depth = (window->DC.TreeDepth - g.LogStartDepth);
    for (;;)
    {
        // Split the string. Each new line (after a '\n') is followed by spacing corresponding to the current depth of our log entry.
        const char* line_end = text_remaining;
        while (line_end < text_end)
            if (*line_end == '\n')
                break;
            else
                line_end++;
        if (line_end >= text_end)
            line_end = NULL;

        const bool is_first_line = (text == text_remaining);
        bool is_last_line = false;
        if (line_end == NULL)
        {
            is_last_line = true;
            line_end = text_end;
        }
        if (line_end != NULL && !(is_last_line && (line_end - text_remaining)==0))
        {
            const int char_count = (int)(line_end - text_remaining);
            if (log_new_line || !is_first_line)
                ImGui::LogText(IM_NEWLINE "%*s%.*s", tree_depth*4, "", char_count, text_remaining);
            else
                ImGui::LogText(" %.*s", char_count, text_remaining);
        }

        if (is_last_line)
            break;
        text_remaining = line_end + 1;
    }
}

// Internal ImGui functions to render text
// RenderText***() functions calls ImDrawList::AddText() calls ImBitmapFont::RenderText()
void ImGui::RenderText(ImVec2 pos, const char* text, const char* text_end, bool hide_text_after_hash)
{
    ImGuiContext& g = *GImGui;
    ImGuiWindow* window = GetCurrentWindow();

    // Hide anything after a '##' string
    const char* text_display_end;
    if (hide_text_after_hash)
    {
        text_display_end = FindRenderedTextEnd(text, text_end);
    }
    else
    {
        if (!text_end)
            text_end = text + strlen(text); // FIXME-OPT
        text_display_end = text_end;
    }

    const int text_len = (int)(text_display_end - text);
    if (text_len > 0)
    {
        window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end);
        if (g.LogEnabled)
            LogRenderedText(pos, text, text_display_end);
    }
}

void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width)
{
    ImGuiContext& g = *GImGui;
    ImGuiWindow* window = GetCurrentWindow();

    if (!text_end)
        text_end = text + strlen(text); // FIXME-OPT

    const int text_len = (int)(text_end - text);
    if (text_len > 0)
    {
        window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_end, wrap_width);
        if (g.LogEnabled)
            LogRenderedText(pos, text, text_end);
    }
}

// Default clip_rect uses (pos_min,pos_max)
// Handle clipping on CPU immediately (vs typically let the GPU clip the triangles that are overlapping the clipping rectangle edges)
void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect)
{
    // Hide anything after a '##' string
    const char* text_display_end = FindRenderedTextEnd(text, text_end);
    const int text_len = (int)(text_display_end - text);
    if (text_len == 0)
        return;

    ImGuiContext& g = *GImGui;
    ImGuiWindow* window = GetCurrentWindow();

    // Perform CPU side clipping for single clipped element to avoid using scissor state
    ImVec2 pos = pos_min;
    const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_display_end, false, 0.0f);

    const ImVec2* clip_min = clip_rect ? &clip_rect->Min : &pos_min;
    const ImVec2* clip_max = clip_rect ? &clip_rect->Max : &pos_max;
    bool need_clipping = (pos.x + text_size.x >= clip_max->x) || (pos.y + text_size.y >= clip_max->y);
    if (clip_rect) // If we had no explicit clipping rectangle then pos==clip_min
        need_clipping |= (pos.x < clip_min->x) || (pos.y < clip_min->y);

    // Align whole block. We should defer that to the better rendering function when we'll have support for individual line alignment.
    if (align.x > 0.0f) pos.x = ImMax(pos.x, pos.x + (pos_max.x - pos.x - text_size.x) * align.x);
    if (align.y > 0.0f) pos.y = ImMax(pos.y, pos.y + (pos_max.y - pos.y - text_size.y) * align.y);

    // Render
    if (need_clipping)
    {
        ImVec4 fine_clip_rect(clip_min->x, clip_min->y, clip_max->x, clip_max->y);
        window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, &fine_clip_rect);
    }
    else
    {
        window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, NULL);
    }
    if (g.LogEnabled)
        LogRenderedText(pos, text, text_display_end);
}

// Render a rectangle shaped with optional rounding and borders
void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border, float rounding)
{
    ImGuiWindow* window = GetCurrentWindow();

    window->DrawList->AddRectFilled(p_min, p_max, fill_col, rounding);
    if (border && (window->Flags & ImGuiWindowFlags_ShowBorders))
    {
        window->DrawList->AddRect(p_min+ImVec2(1,1), p_max+ImVec2(1,1), GetColorU32(ImGuiCol_BorderShadow), rounding);
        window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding);
    }
}

void ImGui::RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding)
{
    ImGuiWindow* window = GetCurrentWindow();
    if (window->Flags & ImGuiWindowFlags_ShowBorders)
    {
        window->DrawList->AddRect(p_min+ImVec2(1,1), p_max+ImVec2(1,1), GetColorU32(ImGuiCol_BorderShadow), rounding);
        window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding);
    }
}

// Render a triangle to denote expanded/collapsed state
void ImGui::RenderCollapseTriangle(ImVec2 p_min, bool is_open, float scale)
{
    ImGuiContext& g = *GImGui;
    ImGuiWindow* window = GetCurrentWindow();

    const float h = g.FontSize * 1.00f;
    const float r = h * 0.40f * scale;
    ImVec2 center = p_min + ImVec2(h*0.50f, h*0.50f*scale);

    ImVec2 a, b, c;
    if (is_open)
    {
        center.y -= r*0.25f;
        a = center + ImVec2(0,1)*r;
        b = center + ImVec2(-0.866f,-0.5f)*r;
        c = center + ImVec2(0.866f,-0.5f)*r;
    }
    else
    {
        a = center + ImVec2(1,0)*r;
        b = center + ImVec2(-0.500f,0.866f)*r;
        c = center + ImVec2(-0.500f,-0.866f)*r;
    }

    window->DrawList->AddTriangleFilled(a, b, c, GetColorU32(ImGuiCol_Text));
}

void ImGui::RenderBullet(ImVec2 pos)
{
    ImGuiWindow* window = GetCurrentWindow();
    window->DrawList->AddCircleFilled(pos, GImGui->FontSize*0.20f, GetColorU32(ImGuiCol_Text), 8);
}

void ImGui::RenderCheckMark(ImVec2 pos, ImU32 col)
{
    ImGuiContext& g = *GImGui;
    ImGuiWindow* window = GetCurrentWindow();
    float start_x = (float)(int)(g.FontSize * 0.307f + 0.5f);
    float rem_third = (float)(int)((g.FontSize - start_x) / 3.0f);
    float bx = pos.x + 0.5f + start_x + rem_third;
    float by = pos.y - 1.0f + (float)(int)(g.Font->Ascent * (g.FontSize / g.Font->FontSize) + 0.5f) + (float)(int)(g.Font->DisplayOffset.y);
    window->DrawList->PathLineTo(ImVec2(bx - rem_third, by - rem_third));
    window->DrawList->PathLineTo(ImVec2(bx, by));
    window->DrawList->PathLineTo(ImVec2(bx + rem_third*2, by - rem_third*2));
    window->DrawList->PathStroke(col, false);
}

// Calculate text size. Text can be multi-line. Optionally ignore text after a ## marker.
// CalcTextSize("") should return ImVec2(0.0f, GImGui->FontSize)
ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_text_after_double_hash, float wrap_width)
{
    ImGuiContext& g = *GImGui;

    const char* text_display_end;
    if (hide_text_after_double_hash)
        text_display_end = FindRenderedTextEnd(text, text_end);      // Hide anything after a '##' string
    else
        text_display_end = text_end;

    ImFont* font = g.Font;
    const float font_size = g.FontSize;
    if (text == text_display_end)
        return ImVec2(0.0f, font_size);
    ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL);

    // Cancel out character spacing for the last character of a line (it is baked into glyph->XAdvance field)
    const float font_scale = font_size / font->FontSize;
    const float character_spacing_x = 1.0f * font_scale;
    if (text_size.x > 0.0f)
        text_size.x -= character_spacing_x;
    text_size.x = (float)(int)(text_size.x + 0.95f);

    return text_size;
}

// Helper to calculate coarse clipping of large list of evenly sized items.
// NB: Prefer using the ImGuiListClipper higher-level helper if you can! Read comments and instructions there on how those use this sort of pattern.
// NB: 'items_count' is only used to clamp the result, if you don't know your count you can use INT_MAX
void ImGui::CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end)
{
    ImGuiContext& g = *GImGui;
    ImGuiWindow* window = GetCurrentWindowRead();
    if (g.LogEnabled)
    {
        // If logging is active, do not perform any clipping
        *out_items_display_start = 0;
        *out_items_display_end = items_count;
        return;
    }
    if (window->SkipItems)
    {
        *out_items_display_start = *out_items_display_end = 0;
        return;
    }

    const ImVec2 pos = window->DC.CursorPos;
    int start = (int)((window->ClipRect.Min.y - pos.y) / items_height);
    int end = (int)((window->ClipRect.Max.y - pos.y) / items_height);
    start = ImClamp(start, 0, items_count);
    end = ImClamp(end + 1, start, items_count);
    *out_items_display_start = start;
    *out_items_display_end = end;
}

// Find window given position, search front-to-back
// FIXME: Note that we have a lag here because WindowRectClipped is updated in Begin() so windows moved by user via SetWindowPos() and not SetNextWindowPos() will have that rectangle lagging by a frame at the time FindHoveredWindow() is called, aka before the next Begin(). Moving window thankfully isn't affected.
static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs)
{
    ImGuiContext& g = *GImGui;
    for (int i = g.Windows.Size-1; i >= 0; i--)
    {
        ImGuiWindow* window = g.Windows[i];
        if (!window->Active)
            continue;
        if (window->Flags & ImGuiWindowFlags_NoInputs)
            continue;
        if (excluding_childs && (window->Flags & ImGuiWindowFlags_ChildWindow) != 0)
            continue;

        // Using the clipped AABB so a child window will typically be clipped by its parent.
        ImRect bb(window->WindowRectClipped.Min - g.Style.TouchExtraPadding, window->WindowRectClipped.Max + g.Style.TouchExtraPadding);
        if (bb.Contains(pos))
            return window;
    }
    return NULL;
}

// Test if mouse cursor is hovering given rectangle
// NB- Rectangle is clipped by our current clip setting
// NB- Expand the rectangle to be generous on imprecise inputs systems (g.Style.TouchExtraPadding)
bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip)
{
    ImGuiContext& g = *GImGui;
    ImGuiWindow* window = GetCurrentWindowRead();

    // Clip
    ImRect rect_clipped(r_min, r_max);
    if (clip)
        rect_clipped.ClipWith(window->ClipRect);

    // Expand for touch input
    const ImRect rect_for_touch(rect_clipped.Min - g.Style.TouchExtraPadding, rect_clipped.Max + g.Style.TouchExtraPadding);
    return rect_for_touch.Contains(g.IO.MousePos);
}

bool ImGui::IsAnyWindowHovered()
{
    ImGuiContext& g = *GImGui;
    return g.HoveredWindow != NULL;
}

static bool IsKeyPressedMap(ImGuiKey key, bool repeat)
{
    const int key_index = GImGui->IO.KeyMap[key];
    return ImGui::IsKeyPressed(key_index, repeat);
}

int ImGui::GetKeyIndex(ImGuiKey imgui_key)
{
    IM_ASSERT(imgui_key >= 0 && imgui_key < ImGuiKey_COUNT);
    return GImGui->IO.KeyMap[imgui_key];
}

// Note that imgui doesn't know the semantic of each entry of io.KeyDown[]. Use your own indices/enums according to how your backend/engine stored them into KeyDown[]!
bool ImGui::IsKeyDown(int user_key_index)
{
    if (user_key_index < 0) return false;
    IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(GImGui->IO.KeysDown));
    return GImGui->IO.KeysDown[user_key_index];
}

bool ImGui::IsKeyPressed(int user_key_index, bool repeat)
{
    ImGuiContext& g = *GImGui;
    if (user_key_index < 0) return false;
    IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown));
    const float t = g.IO.KeysDownDuration[user_key_index];
    if (t == 0.0f)
        return true;

    if (repeat && t > g.IO.KeyRepeatDelay)
    {
        float delay = g.IO.KeyRepeatDelay, rate = g.IO.KeyRepeatRate;
        if ((fmodf(t - delay, rate) > rate*0.5f) != (fmodf(t - delay - g.IO.DeltaTime, rate) > rate*0.5f))
            return true;
    }
    return false;
}

bool ImGui::IsKeyReleased(int user_key_index)
{
    ImGuiContext& g = *GImGui;
    if (user_key_index < 0) return false;
    IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown));
    if (g.IO.KeysDownDurationPrev[user_key_index] >= 0.0f && !g.IO.KeysDown[user_key_index])
        return true;
    return false;
}

bool ImGui::IsMouseDown(int button)
{
    ImGuiContext& g = *GImGui;
    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
    return g.IO.MouseDown[button];
}

bool ImGui::IsMouseClicked(int button, bool repeat)
{
    ImGuiContext& g = *GImGui;
    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
    const float t = g.IO.MouseDownDuration[button];
    if (t == 0.0f)
        return true;

    if (repeat && t > g.IO.KeyRepeatDelay)
    {
        float delay = g.IO.KeyRepeatDelay, rate = g.IO.KeyRepeatRate;
        if ((fmodf(t - delay, rate) > rate*0.5f) != (fmodf(t - delay - g.IO.DeltaTime, rate) > rate*0.5f))
            return true;
    }

    return false;
}

bool ImGui::IsMouseReleased(int button)
{
    ImGuiContext& g = *GImGui;
    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
    return g.IO.MouseReleased[button];
}

bool ImGui::IsMouseDoubleClicked(int button)
{
    ImGuiContext& g = *GImGui;
    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
    return g.IO.MouseDoubleClicked[button];
}

bool ImGui::IsMouseDragging(int button, float lock_threshold)
{
    ImGuiContext& g = *GImGui;
    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
    if (!g.IO.MouseDown[button])
        return false;
    if (lock_threshold < 0.0f)
        lock_threshold = g.IO.MouseDragThreshold;
    return g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold;
}

ImVec2 ImGui::GetMousePos()
{
    return GImGui->IO.MousePos;
}

// NB: prefer to call right after BeginPopup(). At the time Selectable/MenuItem is activated, the popup is already closed!
ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup()
{
    ImGuiContext& g = *GImGui;
    if (g.CurrentPopupStack.Size > 0)
        return g.OpenPopupStack[g.CurrentPopupStack.Size-1].MousePosOnOpen;
    return g.IO.MousePos;
}

ImVec2 ImGui::GetMouseDragDelta(int button, float lock_threshold)
{
    ImGuiContext& g = *GImGui;
    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
    if (lock_threshold < 0.0f)
        lock_threshold = g.IO.MouseDragThreshold;
    if (g.IO.MouseDown[button])
        if (g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold)
            return g.IO.MousePos - g.IO.MouseClickedPos[button];     // Assume we can only get active with left-mouse button (at the moment).
    return ImVec2(0.0f, 0.0f);
}

void ImGui::ResetMouseDragDelta(int button)
{
    ImGuiContext& g = *GImGui;
    IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown));
    // NB: We don't need to reset g.IO.MouseDragMaxDistanceSqr
    g.IO.MouseClickedPos[button] = g.IO.MousePos;
}

ImGuiMouseCursor ImGui::GetMouseCursor()
{
    return GImGui->MouseCursor;
}

void ImGui::SetMouseCursor(ImGuiMouseCursor cursor_type)
{
    GImGui->MouseCursor = cursor_type;
}

void ImGui::CaptureKeyboardFromApp(bool capture)
{
    GImGui->CaptureKeyboardNextFrame = capture ? 1 : 0;
}

void ImGui::CaptureMouseFromApp(bool capture)
{
    GImGui->CaptureMouseNextFrame = capture ? 1 : 0;
}

bool ImGui::IsItemHovered()
{
    ImGuiWindow* window = GetCurrentWindowRead();
    return window->DC.LastItemHoveredAndUsable;
}

bool ImGui::IsItemRectHovered()
{
    ImGuiWindow* window = GetCurrentWindowRead();
    return window->DC.LastItemHoveredRect;
}

bool ImGui::IsItemActive()
{
    ImGuiContext& g = *GImGui;
    if (g.ActiveId)
    {
        ImGuiWindow* window = GetCurrentWindowRead();
        return g.ActiveId == window->DC.LastItemId;
    }
    return false;
}

bool ImGui::IsItemClicked(int mouse_button)
{
    return IsMouseClicked(mouse_button) && IsItemHovered();
}

bool ImGui::IsAnyItemHovered()
{
    return GImGui->HoveredId != 0 || GImGui->HoveredIdPreviousFrame != 0;
}

bool ImGui::IsAnyItemActive()
{
    return GImGui->ActiveId != 0;
}

bool ImGui::IsItemVisible()
{
    ImGuiWindow* window = GetCurrentWindowRead();
    return window->ClipRect.Overlaps(window->DC.LastItemRect);
}

// Allow last item to be overlapped by a subsequent item. Both may be activated during the same frame before the later one takes priority.
void ImGui::SetItemAllowOverlap()
{
    ImGuiContext& g = *GImGui;
    if (g.HoveredId == g.CurrentWindow->DC.LastItemId)
        g.HoveredIdAllowOverlap = true;
    if (g.ActiveId == g.CurrentWindow->DC.LastItemId)
        g.ActiveIdAllowOverlap = true;
}

ImVec2 ImGui::GetItemRectMin()
{
    ImGuiWindow* window = GetCurrentWindowRead();
    return window->DC.LastItemRect.Min;
}

ImVec2 ImGui::GetItemRectMax()
{
    ImGuiWindow* window = GetCurrentWindowRead();
    return window->DC.LastItemRect.Max;
}

ImVec2 ImGui::GetItemRectSize()
{
    ImGuiWindow* window = GetCurrentWindowRead();
    return window->DC.LastItemRect.GetSize();
}

ImVec2 ImGui::CalcItemRectClosestPoint(const ImVec2& pos, bool on_edge, float outward)
{
    ImGuiWindow* window = GetCurrentWindowRead();
    ImRect rect = window->DC.LastItemRect;
    rect.Expand(outward);
    return rect.GetClosestPoint(pos, on_edge);
}

static ImRect GetVisibleRect()
{
    ImGuiContext& g = *GImGui;
    if (g.IO.DisplayVisibleMin.x != g.IO.DisplayVisibleMax.x && g.IO.DisplayVisibleMin.y != g.IO.DisplayVisibleMax.y)
        return ImRect(g.IO.DisplayVisibleMin, g.IO.DisplayVisibleMax);
    return ImRect(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y);
}

// Not exposed publicly as BeginTooltip() because bool parameters are evil. Let's see if other needs arise first.
static void BeginTooltipEx(bool override_previous_tooltip)
{
    ImGuiContext& g = *GImGui;
    char window_name[16];
    ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip%02d", g.TooltipOverrideCount);
    if (override_previous_tooltip)
        if (ImGuiWindow* window = ImGui::FindWindowByName(window_name))
            if (window->Active)
            {
                // Hide previous tooltips. We can't easily "reset" the content of a window so we create a new one.
                window->HiddenFrames = 1;
                ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip%02d", ++g.TooltipOverrideCount);
            }
    ImGui::Begin(window_name, NULL, ImGuiWindowFlags_Tooltip|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize);
}

void ImGui::SetTooltipV(const char* fmt, va_list args)
{
    BeginTooltipEx(true);
    TextV(fmt, args);
    EndTooltip();
}

void ImGui::SetTooltip(const char* fmt, ...)
{
    va_list args;
    va_start(args, fmt);
    SetTooltipV(fmt, args);
    va_end(args);
}

void ImGui::BeginTooltip()
{
    BeginTooltipEx(false);
}

void ImGui::EndTooltip()
{
    IM_ASSERT(GetCurrentWindowRead()->Flags & ImGuiWindowFlags_Tooltip);   // Mismatched BeginTooltip()/EndTooltip() calls
    ImGui::End();
}

// Mark popup as open (toggle toward open state).
// Popups are closed when user click outside, or activate a pressable item, or CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block.
// Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level).
// One open popup per level of the popup hierarchy (NB: when assigning we reset the Window member of ImGuiPopupRef to NULL)
void ImGui::OpenPopupEx(ImGuiID id, bool reopen_existing)
{
    ImGuiContext& g = *GImGui;
    ImGuiWindow* window = g.CurrentWindow;
    int current_stack_size = g.CurrentPopupStack.Size;
    ImGuiPopupRef popup_ref = ImGuiPopupRef(id, window, window->GetID("##menus"), g.IO.MousePos); // Tagged as new ref because constructor sets Window to NULL (we are passing the ParentWindow info here)
    if (g.OpenPopupStack.Size < current_stack_size + 1)
        g.OpenPopupStack.push_back(popup_ref);
    else if (reopen_existing || g.OpenPopupStack[current_stack_size].PopupId != id)
    {
        g.OpenPopupStack.resize(current_stack_size+1);
        g.OpenPopupStack[current_stack_size] = popup_ref;
    }
}

void ImGui::OpenPopup(const char* str_id)
{
    ImGuiContext& g = *GImGui;
    OpenPopupEx(g.CurrentWindow->GetID(str_id), false);
}

static void CloseInactivePopups()
{
    ImGuiContext& g = *GImGui;
    if (g.OpenPopupStack.empty())
        return;

    // When popups are stacked, clicking on a lower level popups puts focus back to it and close popups above it.
    // Don't close our own child popup windows
    int n = 0;
    if (g.NavWindow)
    {
        for (n = 0; n < g.OpenPopupStack.Size; n++)
        {
            ImGuiPopupRef& popup = g.OpenPopupStack[n];
            if (!popup.Window)
                continue;
            IM_ASSERT((popup.Window->Flags & ImGuiWindowFlags_Popup) != 0);
            if (popup.Window->Flags & ImGuiWindowFlags_ChildWindow)
                continue;

            bool has_focus = false;
            for (int m = n; m < g.OpenPopupStack.Size && !has_focus; m++)
                has_focus = (g.OpenPopupStack[m].Window && g.OpenPopupStack[m].Window->RootWindow == g.NavWindow->RootWindow);
            if (!has_focus)
                break;
        }
    }
    if (n < g.OpenPopupStack.Size)   // This test is not required but it allows to set a useful breakpoint on the line below
        g.OpenPopupStack.resize(n);
}

static ImGuiWindow* GetFrontMostModalRootWindow()
{
    ImGuiContext& g = *GImGui;
    for (int n = g.OpenPopupStack.Size-1; n >= 0; n--)
        if (ImGuiWindow* front_most_popup = g.OpenPopupStack.Data[n].Window)
            if (front_most_popup->Flags & ImGuiWindowFlags_Modal)
                return front_most_popup;
    return NULL;
}

static void ClosePopupToLevel(int remaining)
{
    ImGuiContext& g = *GImGui;
    if (remaining > 0)
        ImGui::FocusWindow(g.OpenPopupStack[remaining-1].Window);
    else
        ImGui::FocusWindow(g.OpenPopupStack[0].ParentWindow);
    g.OpenPopupStack.resize(remaining);
}

static void ClosePopup(ImGuiID id)
{
    if (!ImGui::IsPopupOpen(id))
        return;
    ImGuiContext& g = *GImGui;
    ClosePopupToLevel(g.OpenPopupStack.Size - 1);
}

// Close the popup we have begin-ed into.
void ImGui::CloseCurrentPopup()
{
    ImGuiContext& g = *GImGui;
    int popup_idx = g.CurrentPopupStack.Size - 1;
    if (popup_idx < 0 || popup_idx >= g.OpenPopupStack.Size || g.CurrentPopupStack[popup_idx].PopupId != g.OpenPopupStack[popup_idx].PopupId)
        return;
    while (popup_idx > 0 && g.OpenPopupStack[popup_idx].Window && (g.OpenPopupStack[popup_idx].Window->Flags & ImGuiWindowFlags_ChildMenu))
        popup_idx--;
    ClosePopupToLevel(popup_idx);
}

static inline void ClearSetNextWindowData()
{
    // FIXME-OPT
    ImGuiContext& g = *GImGui;
    g.SetNextWindowPosCond = g.SetNextWindowSizeCond = g.SetNextWindowContentSizeCond = g.SetNextWindowCollapsedCond = 0;
    g.SetNextWindowSizeConstraint = g.SetNextWindowFocus = false;
}

static bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags)
{
    ImGuiContext& g = *GImGui;
    ImGuiWindow* window = g.CurrentWindow;
    if (!ImGui::IsPopupOpen(id))
    {
        ClearSetNextWindowData(); // We behave like Begin() and need to consume those values
        return false;
    }

    ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
    ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize;

    char name[20];
    if (flags & ImGuiWindowFlags_ChildMenu)
        ImFormatString(name, IM_ARRAYSIZE(name), "##menu_%d", g.CurrentPopupStack.Size);    // Recycle windows based on depth
    else
        ImFormatString(name, IM_ARRAYSIZE(name), "##popup_%08x", id); // Not recycling, so we can close/open during the same frame

    bool is_open = ImGui::Begin(name, NULL, flags);
    if (!(window->Flags & ImGuiWindowFlags_ShowBorders))
        g.CurrentWindow->Flags &= ~ImGuiWindowFlags_ShowBorders;
    if (!is_open) // NB: is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
        ImGui::EndPopup();

    return is_open;
}

bool ImGui::BeginPopup(const char* str_id)
{
    ImGuiContext& g = *GImGui;
    if (g.OpenPopupStack.Size <= g.CurrentPopupStack.Size) // Early out for performance
    {
        ClearSetNextWindowData(); // We behave like Begin() and need to consume those values
        return false;
    }
    return BeginPopupEx(g.CurrentWindow->GetID(str_id), ImGuiWindowFlags_ShowBorders);
}

bool ImGui::IsPopupOpen(ImGuiID id)
{
    ImGuiContext& g = *GImGui;
    return g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].PopupId == id;
}

bool ImGui::IsPopupOpen(const char* str_id)
{
    ImGuiContext& g = *GImGui;
    return g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].PopupId == g.CurrentWindow->GetID(str_id);
}

bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags extra_flags)
{
    ImGuiContext& g = *GImGui;
    ImGuiWindow* window = g.CurrentWindow;
    const ImGuiID id = window->GetID(name);
    if (!IsPopupOpen(id))
    {
        ClearSetNextWindowData(); // We behave like Begin() and need to consume those values
        return false;
    }

    ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_Modal|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoSavedSettings;
    bool is_open = ImGui::Begin(name, p_open, flags);
    if (!is_open || (p_open && !*p_open)) // NB: is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
    {
        ImGui::
Download .txt
gitextract_vt6hakd8/

├── .gitignore
├── CMakeLists.txt
├── FindSDL2_mixer.cmake
├── Findjsoncpp.cmake
├── Findrange-v3.cmake
├── Findrxcpp.cmake
├── LICENSE
├── LICENSE_OFL.txt
├── README.md
├── future.cpp
├── imgui/
│   ├── LICENSE.txt
│   ├── imconfig.h
│   ├── imgui.cpp
│   ├── imgui.h
│   ├── imgui_demo.cpp
│   ├── imgui_draw.cpp
│   ├── imgui_impl_sdl_gl3.cpp
│   ├── imgui_impl_sdl_gl3.h
│   ├── imgui_internal.h
│   ├── stb_rect_pack.h
│   ├── stb_textedit.h
│   └── stb_truetype.h
├── imgui.ini
├── main.cpp
├── model.h
├── rxcurl.h
├── rximgui.h
├── seahawkandeagles.json
├── shared.cmake
├── tweets.h
├── tweetsample.json
├── tweetsample.txt
└── util.h
Download .txt
SYMBOL INDEX (612 symbols across 17 files)

FILE: future.cpp
  type Split (line 34) | enum class Split {
  function string (line 54) | inline string tweettext(const json& tweet) {
  function string (line 67) | inline string tolower(string s) {
  function splitwords (line 72) | inline vector<string> splitwords(const string& text) {
  type It (line 115) | struct It
    type Cursor (line 118) | struct Cursor : public enable_shared_from_this<Cursor>
      method set_value (line 126) | void set_value(T v) {
    method It (line 141) | It() : end(true) {}
    method It (line 142) | explicit It(shared_ptr<Cursor> v) : end(false), v(v) {
    method It (line 145) | explicit It(nullptr_t) : end(false), v(make_shared<Cursor>()) {
    method T (line 159) | T& operator*() {
  function each (line 176) | inline future<void> each(future<It<T>> next, It<T> end, function<void(It...
  function fncCallback (line 196) | size_t fncCallback(char* ptr, size_t size, size_t nmemb, It<string>::Cur...
  class Proc (line 205) | class Proc
  function main (line 286) | int main(int /*argc*/, const char *argv[])

FILE: imgui/imgui.cpp
  function ImVec2 (line 826) | ImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2...
  function ImTriangleContainsPoint (line 840) | bool ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, const ImV...
  function ImTriangleBarycentricCoords (line 848) | void ImTriangleBarycentricCoords(const ImVec2& a, const ImVec2& b, const...
  function ImVec2 (line 859) | ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const Im...
  function ImStricmp (line 875) | int ImStricmp(const char* str1, const char* str2)
  function ImStrnicmp (line 882) | int ImStrnicmp(const char* str1, const char* str2, int count)
  function ImStrncpy (line 889) | void ImStrncpy(char* dst, const char* src, int count)
  function ImStrlenW (line 903) | int ImStrlenW(const ImWchar* str)
  function ImWchar (line 910) | const ImWchar* ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf...
  function ImFormatString (line 941) | int ImFormatString(char* buf, int buf_size, const char* fmt, ...)
  function ImFormatStringV (line 954) | int ImFormatStringV(char* buf, int buf_size, const char* fmt, va_list args)
  function ImU32 (line 966) | ImU32 ImHash(const void* data, int data_size, ImU32 seed)
  function ImTextCharFromUtf8 (line 1015) | int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, cons...
  function ImTextStrFromUtf8 (line 1073) | int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, c...
  function ImTextCountCharsFromUtf8 (line 1092) | int ImTextCountCharsFromUtf8(const char* in_text, const char* in_text_end)
  function ImTextCharToUtf8 (line 1108) | static inline int ImTextCharToUtf8(char* buf, int buf_size, unsigned int c)
  function ImTextCountUtf8BytesFromChar (line 1145) | static inline int ImTextCountUtf8BytesFromChar(unsigned int c)
  function ImTextStrToUtf8 (line 1154) | int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, con...
  function ImTextCountUtf8BytesFromStr (line 1170) | int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, const ImWchar* i...
  function ImVec4 (line 1184) | ImVec4 ImGui::ColorConvertU32ToFloat4(ImU32 in)
  function ImU32 (line 1194) | ImU32 ImGui::ColorConvertFloat4ToU32(const ImVec4& in)
  function ImU32 (line 1204) | ImU32 ImGui::GetColorU32(ImGuiCol idx, float alpha_mul)
  function ImU32 (line 1212) | ImU32 ImGui::GetColorU32(const ImVec4& col)
  function ImVec4 (line 1220) | const ImVec4& ImGui::GetStyleColorVec4(ImGuiCol idx)
  function ImU32 (line 1226) | ImU32 ImGui::GetColorU32(ImU32 col)
  function FILE (line 1287) | FILE* ImFileOpen(const char* filename, const char* mode)
  function LowerBound (line 1356) | static ImVector<ImGuiStorage::Pair>::iterator LowerBound(ImVector<ImGuiS...
  function SetCursorPosYAndSetupDummyPrevLine (line 1671) | static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_h...
  function ImGuiID (line 1812) | ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end)
  function ImGuiID (line 1820) | ImGuiID ImGuiWindow::GetID(const void* ptr)
  function ImGuiID (line 1828) | ImGuiID ImGuiWindow::GetIDNoKeepAlive(const char* str, const char* str_end)
  function SetCurrentWindow (line 1838) | static void SetCurrentWindow(ImGuiWindow* window)
  function ImGuiWindow (line 1846) | ImGuiWindow* ImGui::GetParentWindow()
  function ImVec2 (line 1998) | ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_x, float default_y)
  function ImGuiContext (line 2057) | ImGuiContext* ImGui::GetCurrentContext()
  function ImGuiContext (line 2071) | ImGuiContext* ImGui::CreateContext(void* (*malloc_fn)(size_t), void (*fr...
  function ImGuiIO (line 2090) | ImGuiIO& ImGui::GetIO()
  function ImGuiStyle (line 2095) | ImGuiStyle& ImGui::GetStyle()
  function ImDrawData (line 2101) | ImDrawData* ImGui::GetDrawData()
  function ImGuiIniData (line 2416) | static ImGuiIniData* FindWindowSettings(const char* name)
  function ImGuiIniData (line 2429) | static ImGuiIniData* AddWindowSettings(const char* name)
  function LoadIniSettingsFromDisk (line 2443) | static void LoadIniSettingsFromDisk(const char* ini_filename)
  function SaveIniSettingsToDisk (line 2488) | static void SaveIniSettingsToDisk(const char* ini_filename)
  function MarkIniSettingsDirty (line 2532) | static void MarkIniSettingsDirty(ImGuiWindow* window)
  function ChildWindowComparer (line 2541) | static int ChildWindowComparer(const void* lhs, const void* rhs)
  function AddWindowToSortedBuffer (line 2554) | static void AddWindowToSortedBuffer(ImVector<ImGuiWindow*>& out_sorted_w...
  function AddDrawListToRenderList (line 2571) | static void AddDrawListToRenderList(ImVector<ImDrawList*>& out_render_li...
  function AddWindowToRenderList (line 2604) | static void AddWindowToRenderList(ImVector<ImDrawList*>& out_render_list...
  function LogRenderedText (line 2809) | static void LogRenderedText(const ImVec2& ref_pos, const char* text, con...
  function ImVec2 (line 3018) | ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool ...
  function ImGuiWindow (line 3075) | static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs)
  function IsKeyPressedMap (line 3120) | static bool IsKeyPressedMap(ImGuiKey key, bool repeat)
  function ImVec2 (line 3218) | ImVec2 ImGui::GetMousePos()
  function ImVec2 (line 3224) | ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup()
  function ImVec2 (line 3232) | ImVec2 ImGui::GetMouseDragDelta(int button, float lock_threshold)
  function ImGuiMouseCursor (line 3252) | ImGuiMouseCursor ImGui::GetMouseCursor()
  function ImVec2 (line 3326) | ImVec2 ImGui::GetItemRectMin()
  function ImVec2 (line 3332) | ImVec2 ImGui::GetItemRectMax()
  function ImVec2 (line 3338) | ImVec2 ImGui::GetItemRectSize()
  function ImVec2 (line 3344) | ImVec2 ImGui::CalcItemRectClosestPoint(const ImVec2& pos, bool on_edge, ...
  function ImRect (line 3352) | static ImRect GetVisibleRect()
  function BeginTooltipEx (line 3361) | static void BeginTooltipEx(bool override_previous_tooltip)
  function CloseInactivePopups (line 3428) | static void CloseInactivePopups()
  function ImGuiWindow (line 3459) | static ImGuiWindow* GetFrontMostModalRootWindow()
  function ClosePopupToLevel (line 3469) | static void ClosePopupToLevel(int remaining)
  function ClosePopup (line 3479) | static void ClosePopup(ImGuiID id)
  function ClearSetNextWindowData (line 3499) | static inline void ClearSetNextWindowData()
  function BeginPopupEx (line 3507) | static bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags)
  function BeginChildEx (line 3626) | static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& siz...
  function CheckStacksSize (line 3714) | static void CheckStacksSize(ImGuiWindow* window, bool write)
  function ImVec2 (line 3728) | static ImVec2 FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec...
  function ImGuiWindow (line 3756) | ImGuiWindow* ImGui::FindWindowByName(const char* name)
  function ImGuiWindow (line 3767) | static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGui...
  function ApplySizeFullWithConstraint (line 3833) | static void ApplySizeFullWithConstraint(ImGuiWindow* window, ImVec2 new_...
  function Scrollbar (line 4458) | static void Scrollbar(ImGuiWindow* window, bool horizontal)
  function PushMultiItemsWidths (line 4599) | static void PushMultiItemsWidths(int components, float w_full)
  function ImFont (line 4634) | static ImFont* GetDefaultFont()
  function SetCurrentFont (line 4640) | static void SetCurrentFont(ImFont* font)
  type ImGuiStyleVarInfo (line 4744) | struct ImGuiStyleVarInfo
  function ImGuiStyleVarInfo (line 4767) | static const ImGuiStyleVarInfo* GetStyleVarInfo(ImGuiStyleVar idx)
  function ImVec2 (line 4915) | ImVec2 ImGui::GetWindowPos()
  function SetWindowScrollY (line 4922) | static void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y)
  function SetWindowPos (line 4929) | static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCo...
  function ImVec2 (line 4957) | ImVec2 ImGui::GetWindowSize()
  function SetWindowSize (line 4963) | static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGui...
  function SetWindowCollapsed (line 5005) | static void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGu...
  function ImVec2 (line 5109) | ImVec2 ImGui::GetContentRegionMax()
  function ImVec2 (line 5118) | ImVec2 ImGui::GetContentRegionAvail()
  function ImVec2 (line 5130) | ImVec2 ImGui::GetWindowContentRegionMin()
  function ImVec2 (line 5136) | ImVec2 ImGui::GetWindowContentRegionMax()
  function ImDrawList (line 5166) | ImDrawList* ImGui::GetWindowDrawList()
  function ImFont (line 5172) | ImFont* ImGui::GetFont()
  function ImVec2 (line 5182) | ImVec2 ImGui::GetFontTexUvWhitePixel()
  function ImVec2 (line 5197) | ImVec2 ImGui::GetCursorPos()
  function ImVec2 (line 5236) | ImVec2 ImGui::GetCursorStartPos()
  function ImVec2 (line 5242) | ImVec2 ImGui::GetCursorScreenPos()
  function ImGuiStorage (line 5324) | ImGuiStorage* ImGui::GetStateStorage()
  function IsWindowContentHoverable (line 5548) | static inline bool IsWindowContentHoverable(ImGuiWindow* window)
  function ImGuiID (line 6234) | ImGuiID ImGui::GetID(const char* str_id)
  function ImGuiID (line 6239) | ImGuiID ImGui::GetID(const char* str_id_begin, const char* str_id_end)
  function ImGuiID (line 6244) | ImGuiID ImGui::GetID(const void* ptr_id)
  function DataTypeFormatString (line 6304) | static inline void DataTypeFormatString(ImGuiDataType data_type, void* d...
  function DataTypeFormatString (line 6312) | static inline void DataTypeFormatString(ImGuiDataType data_type, void* d...
  function DataTypeApplyOp (line 6330) | static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* value...
  function DataTypeApplyOpFromText (line 6349) | static bool DataTypeApplyOpFromText(const char* buf, const char* initial...
  function GetMinimumStepAtDecimalPrecision (line 6463) | static float GetMinimumStepAtDecimalPrecision(int decimal_precision)
  function SliderBehaviorCalcRatioFromValue (line 6485) | static inline float SliderBehaviorCalcRatioFromValue(float v, float v_mi...
  type ImGuiPlotArrayGetterData (line 7241) | struct ImGuiPlotArrayGetterData
    method ImGuiPlotArrayGetterData (line 7246) | ImGuiPlotArrayGetterData(const float* values, int stride) { Values = v...
  function Plot_ArrayGetter (line 7249) | static float Plot_ArrayGetter(void* data, int idx)
  function InputTextCalcTextLenAndLineCount (line 7444) | static int InputTextCalcTextLenAndLineCount(const char* text_begin, cons...
  function ImVec2 (line 7458) | static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const Im...
  type ImGuiStb (line 7503) | namespace ImGuiStb
    function STB_TEXTEDIT_STRINGLEN (line 7506) | static int     STB_TEXTEDIT_STRINGLEN(const STB_TEXTEDIT_STRING* obj) ...
    function ImWchar (line 7507) | static ImWchar STB_TEXTEDIT_GETCHAR(const STB_TEXTEDIT_STRING* obj, in...
    function STB_TEXTEDIT_GETWIDTH (line 7508) | static float   STB_TEXTEDIT_GETWIDTH(STB_TEXTEDIT_STRING* obj, int lin...
    function STB_TEXTEDIT_KEYTOTEXT (line 7509) | static int     STB_TEXTEDIT_KEYTOTEXT(int key)                        ...
    function STB_TEXTEDIT_LAYOUTROW (line 7511) | static void    STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, STB_TEXTEDIT_...
    function is_separator (line 7524) | static bool is_separator(unsigned int c)                              ...
    function is_word_boundary_from_right (line 7525) | static int  is_word_boundary_from_right(STB_TEXTEDIT_STRING* obj, int ...
    function STB_TEXTEDIT_MOVEWORDLEFT_IMPL (line 7526) | static int  STB_TEXTEDIT_MOVEWORDLEFT_IMPL(STB_TEXTEDIT_STRING* obj, i...
    function is_word_boundary_from_left (line 7528) | static int  is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int i...
    function STB_TEXTEDIT_MOVEWORDRIGHT_IMPL (line 7529) | static int  STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, ...
    function STB_TEXTEDIT_MOVEWORDRIGHT_IMPL (line 7531) | static int  STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, ...
    function STB_TEXTEDIT_DELETECHARS (line 7536) | static void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING* obj, int pos...
    function STB_TEXTEDIT_INSERTCHARS (line 7551) | static bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int pos...
  function InputTextFilterCharacter (line 7643) | static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTex...
  function Items_ArrayGetter (line 8442) | static bool Items_ArrayGetter(void* data, int idx, const char** out_text)
  function Items_SingleStringGetter (line 8450) | static bool Items_SingleStringGetter(void* data, int idx, const char** o...
  function ColorSquareSize (line 9022) | static inline float ColorSquareSize()
  function ImU32 (line 9028) | static inline ImU32 ImAlphaBlendColor(ImU32 col_a, ImU32 col_b)
  function ColorEditOptionsPopup (line 9144) | static void ColorEditOptionsPopup(ImGuiColorEditFlags flags)
  function ColorPickerOptionsPopup (line 9168) | static void ColorPickerOptionsPopup(ImGuiColorEditFlags flags, float* re...
  function RenderArrow (line 9398) | static void RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_s...
  function RenderArrowsForVerticalBar (line 9410) | static void RenderArrowsForVerticalBar(ImDrawList* draw_list, ImVec2 pos...
  function PaintVertsLinearGradientKeepAlpha (line 9418) | static void PaintVertsLinearGradientKeepAlpha(ImDrawVert* vert_start, Im...
  function OffsetNormToPixels (line 9936) | static float OffsetNormToPixels(ImGuiWindow* window, float offset_norm)
  function PixelsToOffsetNorm (line 9941) | static float PixelsToOffsetNorm(ImGuiWindow* window, float offset)
  function GetDraggedColumnOffset (line 9946) | static float GetDraggedColumnOffset(int column_index)
  function SetClipboardTextFn_DefaultImpl (line 10288) | static void SetClipboardTextFn_DefaultImpl(void*, const char* text)
  function SetClipboardTextFn_DefaultImpl (line 10314) | static void SetClipboardTextFn_DefaultImpl(void*, const char* text)
  function ImeSetInputScreenPosFn_DefaultImpl (line 10334) | static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y)
  function ImeSetInputScreenPosFn_DefaultImpl (line 10350) | static void ImeSetInputScreenPosFn_DefaultImpl(int, int) {}
  type Funcs (line 10370) | struct Funcs
    method NodeDrawList (line 10372) | static void NodeDrawList(ImDrawList* draw_list, const char* label)
    method NodeWindows (line 10430) | static void NodeWindows(ImVector<ImGuiWindow*>& windows, const char* l...
    method NodeWindow (line 10439) | static void NodeWindow(ImGuiWindow* window, const char* label)

FILE: imgui/imgui.h
  type ImDrawChannel (line 45) | struct ImDrawChannel
  type ImDrawCmd (line 46) | struct ImDrawCmd
  type ImDrawData (line 47) | struct ImDrawData
  type ImDrawList (line 48) | struct ImDrawList
  type ImDrawVert (line 49) | struct ImDrawVert
  type ImFont (line 50) | struct ImFont
  type ImFontAtlas (line 51) | struct ImFontAtlas
  type ImFontConfig (line 52) | struct ImFontConfig
  type ImColor (line 53) | struct ImColor
  type ImGuiIO (line 54) | struct ImGuiIO
  type ImGuiOnceUponAFrame (line 55) | struct ImGuiOnceUponAFrame
  type ImGuiStorage (line 56) | struct ImGuiStorage
  type ImGuiStyle (line 57) | struct ImGuiStyle
  type ImGuiTextFilter (line 58) | struct ImGuiTextFilter
  type ImGuiTextBuffer (line 59) | struct ImGuiTextBuffer
  type ImGuiTextEditCallbackData (line 60) | struct ImGuiTextEditCallbackData
  type ImGuiSizeConstraintCallbackData (line 61) | struct ImGuiSizeConstraintCallbackData
  type ImGuiListClipper (line 62) | struct ImGuiListClipper
  type ImGuiContext (line 63) | struct ImGuiContext
  type ImU32 (line 66) | typedef unsigned int ImU32;
  type ImGuiID (line 67) | typedef unsigned int ImGuiID;
  type ImWchar (line 68) | typedef unsigned short ImWchar;
  type ImGuiCol (line 70) | typedef int ImGuiCol;
  type ImGuiStyleVar (line 71) | typedef int ImGuiStyleVar;
  type ImGuiKey (line 72) | typedef int ImGuiKey;
  type ImGuiColorEditFlags (line 73) | typedef int ImGuiColorEditFlags;
  type ImGuiMouseCursor (line 74) | typedef int ImGuiMouseCursor;
  type ImGuiWindowFlags (line 75) | typedef int ImGuiWindowFlags;
  type ImGuiCond (line 76) | typedef int ImGuiCond;
  type ImGuiColumnsFlags (line 77) | typedef int ImGuiColumnsFlags;
  type ImGuiInputTextFlags (line 78) | typedef int ImGuiInputTextFlags;
  type ImGuiSelectableFlags (line 79) | typedef int ImGuiSelectableFlags;
  type ImGuiTreeNodeFlags (line 80) | typedef int ImGuiTreeNodeFlags;
  type ImU64 (line 84) | typedef unsigned __int64 ImU64;
  type ImU64 (line 86) | typedef unsigned long long ImU64;
  function ImVec2 (line 93) | struct ImVec2
  function ImVec4 (line 103) | struct ImVec4
  function namespace (line 115) | namespace ImGui
  type ImGuiWindowFlags_ (line 497) | enum ImGuiWindowFlags_
  type ImGuiInputTextFlags_ (line 527) | enum ImGuiInputTextFlags_
  type ImGuiTreeNodeFlags_ (line 551) | enum ImGuiTreeNodeFlags_
  type ImGuiSelectableFlags_ (line 569) | enum ImGuiSelectableFlags_
  type ImGuiKey_ (line 578) | enum ImGuiKey_
  type ImGuiCol_ (line 603) | enum ImGuiCol_
  type ImGuiStyleVar_ (line 659) | enum ImGuiStyleVar_
  type ImGuiColorEditFlags_ (line 678) | enum ImGuiColorEditFlags_
  type ImGuiMouseCursor_ (line 708) | enum ImGuiMouseCursor_
  type ImGuiCond_ (line 723) | enum ImGuiCond_
  type ImGuiStyle (line 736) | struct ImGuiStyle
  type ImGuiIO (line 768) | struct ImGuiIO
  type T (line 891) | typedef T                   value_type;
  type value_type (line 892) | typedef value_type*         iterator;
  type value_type (line 893) | typedef const value_type*   const_iterator;
  function value_type (line 902) | inline value_type&          operator[](int i)               { IM_ASSERT(...
  function value_type (line 903) | inline const value_type&    operator[](int i) const         { IM_ASSERT(...
  function clear (line 905) | inline void                 clear()                         { if (Data) ...
  function iterator (line 906) | inline iterator             begin()                         { return Dat...
  function iterator (line 908) | inline iterator             end()                           { return Dat...
  function value_type (line 910) | inline value_type&          front()                         { IM_ASSERT(...
  function value_type (line 911) | inline const value_type&    front() const                   { IM_ASSERT(...
  function value_type (line 913) | inline const value_type&    back() const                    { IM_ASSERT(...
  function _grow_capacity (line 916) | inline int                  _grow_capacity(int size) const  { int new_ca...
  function resize (line 918) | inline void                 resize(int new_size)            { if (new_si...
  function reserve (line 919) | inline void                 reserve(int new_capacity)
  function push_back (line 930) | inline void                 push_back(const value_type& v)  { if (Size =...
  function pop_back (line 931) | inline void                 pop_back()                      { IM_ASSERT(...
  function iterator (line 933) | inline iterator             erase(const_iterator it)        { IM_ASSERT(...
  function iterator (line 934) | inline iterator             insert(const_iterator it, const value_type& ...
  type ImGuiOnceUponAFrame (line 942) | struct ImGuiOnceUponAFrame
  type ImGuiTextFilter (line 955) | struct ImGuiTextFilter
  function is_blank (line 968) | static bool is_blank(char c) { return c == ' ' || c == '\t'; }
  function trim_blanks (line 969) | void trim_blanks() { while (b < e && is_blank(*b)) b++; while (e > b && ...
  function Clear (line 979) | void                Clear() { InputBuf[0] = 0; Build(); }
  type ImGuiTextBuffer (line 987) | struct ImGuiTextBuffer
  function empty (line 996) | bool                empty() { return Buf.Size <= 1; }
  function clear (line 997) | void                clear() { Buf.clear(); Buf.push_back(0); }
  function Pair (line 1011) | struct ImGuiStorage
  type ImGuiTextEditCallbackData (line 1050) | struct ImGuiTextEditCallbackData
  type ImGuiSizeConstraintCallbackData (line 1079) | struct ImGuiSizeConstraintCallbackData
  type ImColor (line 1110) | struct ImColor
  function operator (line 1119) | inline operator ImU32() const                                   { return...
  function ImGuiListClipper (line 1140) | struct ImGuiListClipper
  type ImDrawIdx (line 1182) | typedef unsigned short ImDrawIdx;
  type ImDrawVert (line 1187) | struct ImDrawVert
  type ImDrawChannel (line 1203) | struct ImDrawChannel
  function ImDrawList (line 1216) | struct ImDrawList
  function ImVec2 (line 1242) | inline ImVec2   GetClipRectMin() const { const ImVec4& cr = _ClipRectSta...
  function PathClear (line 1265) | inline    void  PathClear()                                             ...
  function PathLineTo (line 1266) | inline    void  PathLineTo(const ImVec2& pos)                           ...
  function PathLineToMergeDuplicate (line 1267) | inline    void  PathLineToMergeDuplicate(const ImVec2& pos)             ...
  function PathFillConvex (line 1268) | inline    void  PathFillConvex(ImU32 col)                               ...
  function PrimWriteVtx (line 1294) | inline    void  PrimWriteVtx(const ImVec2& pos, const ImVec2& uv, ImU32 ...
  function PrimWriteIdx (line 1295) | inline    void  PrimWriteIdx(ImDrawIdx idx)                             ...
  function PrimVtx (line 1296) | inline    void  PrimVtx(const ImVec2& pos, const ImVec2& uv, ImU32 col) ...
  type ImDrawData (line 1302) | struct ImDrawData
  type ImFontConfig (line 1316) | struct ImFontConfig
  type ImFontAtlas (line 1345) | struct ImFontAtlas
  function GetBit (line 1379) | struct GlyphRangesBuilder
  function SetBit (line 1384) | void           SetBit(int n)        { UsedChars[n >> 3] |= 1 << (n & 7); }
  function AddChar (line 1385) | void           AddChar(ImWchar c)   { SetBit(c); }
  type CustomRect (line 1404) | struct CustomRect
  type ImFont (line 1423) | struct ImFont

FILE: imgui/imgui_demo.cpp
  function ShowHelpMarker (line 88) | static void ShowHelpMarker(const char* desc)
  type TextFilters (line 641) | struct TextFilters { static int FilterImGuiLetters(ImGuiTextEditCallback...
    method FilterImGuiLetters (line 641) | static int FilterImGuiLetters(ImGuiTextEditCallbackData* data) { if (d...
  type Funcs (line 704) | struct Funcs
    method Sin (line 706) | static float Sin(void*, int i) { return sinf(i * 0.1f); }
    method Saw (line 707) | static float Saw(void*, int i) { return (i & 1) ? 1.0f : -1.0f; }
  function ShowExampleAppMainMenuBar (line 1982) | static void ShowExampleAppMainMenuBar()
  function ShowExampleMenuFile (line 2005) | static void ShowExampleMenuFile()
  function ShowExampleAppAutoResize (line 2063) | static void ShowExampleAppAutoResize(bool* p_open)
  function ShowExampleAppConstrainedResize (line 2080) | static void ShowExampleAppConstrainedResize(bool* p_open)
  function ShowExampleAppFixedOverlay (line 2118) | static void ShowExampleAppFixedOverlay(bool* p_open)
  function ShowExampleAppManipulatingWindowTitle (line 2134) | static void ShowExampleAppManipulatingWindowTitle(bool*)
  function ShowExampleAppCustomRendering (line 2160) | static void ShowExampleAppCustomRendering(bool* p_open)
  function Draw (line 2261) | struct ExampleAppConsole
  function ExecCommand (line 2401) | void    ExecCommand(const char* command_line)
  function TextEditCallbackStub (line 2438) | static int TextEditCallbackStub(ImGuiTextEditCallbackData* data) // In C...
  function TextEditCallback (line 2444) | int     TextEditCallback(ImGuiTextEditCallbackData* data)
  function ShowExampleAppConsole (line 2544) | static void ShowExampleAppConsole(bool* p_open)
  function Draw (line 2554) | struct ExampleAppLog
  function ShowExampleAppLog (line 2615) | static void ShowExampleAppLog(bool* p_open)
  function ShowExampleAppLayout (line 2633) | static void ShowExampleAppLayout(bool* p_open)
  function ShowExampleAppPropertyEditor (line 2679) | static void ShowExampleAppPropertyEditor(bool* p_open)
  function ShowExampleAppLongText (line 2752) | static void ShowExampleAppLongText(bool* p_open)

FILE: imgui/imgui_draw.cpp
  function PathBezierToCasteljau (line 725) | static void PathBezierToCasteljau(ImVector<ImVec2>* path, float x1, floa...
  function ImFont (line 1197) | ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg)
  function Decode85Byte (line 1234) | static unsigned int Decode85Byte(char c)                                ...
  function Decode85 (line 1235) | static void         Decode85(const unsigned char* src, unsigned char* dst)
  function ImFont (line 1247) | ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template)
  function ImFont (line 1263) | ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size...
  function ImFont (line 1284) | ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* ttf_data, int ttf_size, ...
  function ImFont (line 1296) | ImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* compress...
  function ImFont (line 1308) | ImFont* ImFontAtlas::AddFontFromMemoryCompressedBase85TTF(const char* co...
  function ImFontAtlasBuildWithStbTruetype (line 1343) | bool    ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
  function ImFontAtlasBuildRegisterDefaultCustomRects (line 1541) | void ImFontAtlasBuildRegisterDefaultCustomRects(ImFontAtlas* atlas)
  function ImFontAtlasBuildSetupFont (line 1548) | void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontC...
  function ImFontAtlasBuildPackCustomRects (line 1564) | void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* pack_cont...
  function ImFontAtlasBuildRenderDefaultTexData (line 1588) | void ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas* atlas)
  function ImWchar (line 1639) | const ImWchar*   ImFontAtlas::GetGlyphRangesDefault()
  function ImWchar (line 1649) | const ImWchar*  ImFontAtlas::GetGlyphRangesKorean()
  function ImWchar (line 1661) | const ImWchar*  ImFontAtlas::GetGlyphRangesChinese()
  function ImWchar (line 1675) | const ImWchar*  ImFontAtlas::GetGlyphRangesJapanese()
  function ImWchar (line 1737) | const ImWchar*  ImFontAtlas::GetGlyphRangesCyrillic()
  function ImWchar (line 1750) | const ImWchar*  ImFontAtlas::GetGlyphRangesThai()
  function ImVec2 (line 2024) | ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_wid...
  function stb_decompress_length (line 2312) | static unsigned int stb_decompress_length(unsigned char *input)
  function stb__match (line 2319) | static void stb__match(unsigned char *data, unsigned int length)
  function stb__lit (line 2328) | static void stb__lit(unsigned char *data, unsigned int length)
  function stb_adler32 (line 2358) | static unsigned int stb_adler32(unsigned int adler32, unsigned char *buf...
  function stb_decompress (line 2389) | static unsigned int stb_decompress(unsigned char *output, unsigned char ...

FILE: imgui/imgui_impl_sdl_gl3.cpp
  function ImGui_ImplSdlGL3_RenderDrawLists (line 30) | void ImGui_ImplSdlGL3_RenderDrawLists(ImDrawData* draw_data)
  function ImGui_ImplSdlGL3_SetClipboardText (line 133) | static void ImGui_ImplSdlGL3_SetClipboardText(void*, const char* text)
  function ImGui_ImplSdlGL3_ProcessEvent (line 138) | bool ImGui_ImplSdlGL3_ProcessEvent(SDL_Event* event)
  function ImGui_ImplSdlGL3_CreateFontsTexture (line 178) | void ImGui_ImplSdlGL3_CreateFontsTexture()
  function ImGui_ImplSdlGL3_CreateDeviceObjects (line 203) | bool ImGui_ImplSdlGL3_CreateDeviceObjects()
  function ImGui_ImplSdlGL3_InvalidateDeviceObjects (line 280) | void    ImGui_ImplSdlGL3_InvalidateDeviceObjects()
  function ImGui_ImplSdlGL3_Init (line 306) | bool    ImGui_ImplSdlGL3_Init(SDL_Window* window)
  function ImGui_ImplSdlGL3_Shutdown (line 346) | void ImGui_ImplSdlGL3_Shutdown()
  function ImGui_ImplSdlGL3_NewFrame (line 352) | void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window)

FILE: imgui/imgui_impl_sdl_gl3.h
  type SDL_Window (line 9) | struct SDL_Window
  type SDL_Event (line 10) | typedef union SDL_Event SDL_Event;

FILE: imgui/imgui_internal.h
  type ImRect (line 35) | struct ImRect
  type ImGuiColMod (line 36) | struct ImGuiColMod
  type ImGuiStyleMod (line 37) | struct ImGuiStyleMod
  type ImGuiGroupData (line 38) | struct ImGuiGroupData
  type ImGuiSimpleColumns (line 39) | struct ImGuiSimpleColumns
  type ImGuiDrawContext (line 40) | struct ImGuiDrawContext
  type ImGuiTextEditState (line 41) | struct ImGuiTextEditState
  type ImGuiIniData (line 42) | struct ImGuiIniData
  type ImGuiMouseCursorData (line 43) | struct ImGuiMouseCursorData
  type ImGuiPopupRef (line 44) | struct ImGuiPopupRef
  type ImGuiWindow (line 45) | struct ImGuiWindow
  type ImGuiLayoutType (line 47) | typedef int ImGuiLayoutType;
  type ImGuiButtonFlags (line 48) | typedef int ImGuiButtonFlags;
  type ImGuiTreeNodeFlags (line 49) | typedef int ImGuiTreeNodeFlags;
  type ImGuiSliderFlags (line 50) | typedef int ImGuiSliderFlags;
  function namespace (line 56) | namespace ImGuiStb
  function ImCharIsSpace (line 95) | static inline bool      ImCharIsSpace(int c)            { return c == ' ...
  function ImIsPowerOfTwo (line 96) | static inline bool      ImIsPowerOfTwo(int v)           { return v != 0 ...
  function ImUpperPowerOfTwo (line 97) | static inline int       ImUpperPowerOfTwo(int v)        { v--; v |= v >>...
  function ImMin (line 131) | static inline int    ImMin(int lhs, int rhs)                            ...
  function ImMax (line 132) | static inline int    ImMax(int lhs, int rhs)                            ...
  function ImMin (line 133) | static inline float  ImMin(float lhs, float rhs)                        ...
  function ImMax (line 134) | static inline float  ImMax(float lhs, float rhs)                        ...
  function ImVec2 (line 135) | static inline ImVec2 ImMin(const ImVec2& lhs, const ImVec2& rhs)        ...
  function ImVec2 (line 136) | static inline ImVec2 ImMax(const ImVec2& lhs, const ImVec2& rhs)        ...
  function ImClamp (line 137) | static inline int    ImClamp(int v, int mn, int mx)                     ...
  function ImClamp (line 138) | static inline float  ImClamp(float v, float mn, float mx)               ...
  function ImVec2 (line 139) | static inline ImVec2 ImClamp(const ImVec2& f, const ImVec2& mn, ImVec2 m...
  function ImSaturate (line 140) | static inline float  ImSaturate(float f)                                ...
  function ImLerp (line 141) | static inline int    ImLerp(int a, int b, float t)                      ...
  function ImLerp (line 142) | static inline float  ImLerp(float a, float b, float t)                  ...
  function ImVec2 (line 143) | static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, float t)  ...
  function ImVec2 (line 144) | static inline ImVec2 ImLerp(const ImVec2& a, const ImVec2& b, const ImVe...
  function ImLengthSqr (line 145) | static inline float  ImLengthSqr(const ImVec2& lhs)                     ...
  function ImLengthSqr (line 146) | static inline float  ImLengthSqr(const ImVec4& lhs)                     ...
  function ImInvLength (line 147) | static inline float  ImInvLength(const ImVec2& lhs, float fail_value)   ...
  function ImFloor (line 148) | static inline float  ImFloor(float f)                                   ...
  function ImVec2 (line 149) | static inline ImVec2 ImFloor(const ImVec2& v)                           ...
  function ImDot (line 150) | static inline float  ImDot(const ImVec2& a, const ImVec2& b)            ...
  function ImVec2 (line 151) | static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a)...
  type ImPlacementNewDummy (line 156) | struct ImPlacementNewDummy {}
  function delete (line 158) | inline void operator delete(void*, ImPlacementNewDummy, void*) {}
  type ImGuiButtonFlags_ (line 166) | enum ImGuiButtonFlags_
  type ImGuiSliderFlags_ (line 181) | enum ImGuiSliderFlags_
  type ImGuiColumnsFlags_ (line 186) | enum ImGuiColumnsFlags_
  type ImGuiSelectableFlagsPrivate_ (line 195) | enum ImGuiSelectableFlagsPrivate_
  type ImGuiLayoutType_ (line 205) | enum ImGuiLayoutType_
  type ImGuiPlotType (line 211) | enum ImGuiPlotType
  type ImGuiDataType (line 217) | enum ImGuiDataType
  type ImGuiDir (line 224) | enum ImGuiDir
  type ImGuiCorner (line 233) | enum ImGuiCorner
  function ImRect (line 244) | struct IMGUI_API ImRect
  function Contains (line 262) | bool        Contains(const ImVec2& p) const { return p.x >= Min.x     &&...
  function Contains (line 263) | bool        Contains(const ImRect& r) const { return r.Min.x >= Min.x &&...
  function Overlaps (line 264) | bool        Overlaps(const ImRect& r) const { return r.Min.y < Max.y  &&...
  function Add (line 265) | void        Add(const ImVec2& rhs)          { if (Min.x > rhs.x)     Min...
  function Add (line 266) | void        Add(const ImRect& rhs)          { if (Min.x > rhs.Min.x) Min...
  function Expand (line 267) | void        Expand(const float amount)      { Min.x -= amount;   Min.y -...
  function Expand (line 268) | void        Expand(const ImVec2& amount)    { Min.x -= amount.x; Min.y -...
  function Translate (line 269) | void        Translate(const ImVec2& v)      { Min.x += v.x; Min.y += v.y...
  function ClipWith (line 270) | void        ClipWith(const ImRect& clip)    { if (Min.x < clip.Min.x) Mi...
  function Floor (line 271) | void        Floor()                         { Min.x = (float)(int)Min.x;...
  function ImVec2 (line 272) | ImVec2      GetClosestPoint(ImVec2 p, bool on_edge) const
  type ImGuiColMod (line 285) | struct ImGuiColMod
  function ImGuiStyleMod (line 292) | struct ImGuiStyleMod
  type ImGuiGroupData (line 302) | struct ImGuiGroupData
  type ImGuiColumnData (line 316) | struct ImGuiColumnData
  function ImGuiSimpleColumns (line 324) | struct IMGUI_API ImGuiSimpleColumns
  function ImGuiTextEditState (line 338) | struct IMGUI_API ImGuiTextEditState
  type ImGuiIniData (line 362) | struct ImGuiIniData
  type ImGuiMouseCursorData (line 372) | struct ImGuiMouseCursorData
  type ImGuiPopupRef (line 382) | struct ImGuiPopupRef
  function ImGuiDrawContext (line 567) | struct IMGUI_API ImGuiDrawContext
  function ImGuiWindow (line 651) | struct IMGUI_API ImGuiWindow
  function namespace (line 732) | namespace ImGui

FILE: imgui/stb_rect_pack.h
  type stbrp_context (line 70) | typedef struct stbrp_context stbrp_context;
  type stbrp_node (line 71) | typedef struct stbrp_node    stbrp_node;
  type stbrp_rect (line 72) | typedef struct stbrp_rect    stbrp_rect;
  type stbrp_coord (line 75) | typedef int            stbrp_coord;
  type stbrp_coord (line 77) | typedef unsigned short stbrp_coord;
  type stbrp_rect (line 102) | struct stbrp_rect
  type stbrp_node (line 162) | struct stbrp_node
  type stbrp_context (line 168) | struct stbrp_context
  function STBRP_DEF (line 214) | STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
  function STBRP_DEF (line 226) | STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int ...
  function STBRP_DEF (line 246) | STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int ...
  function stbrp__skyline_find_min_y (line 279) | static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first...
  type stbrp__findresult (line 329) | typedef struct
  function stbrp__findresult (line 335) | static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, ...
  function stbrp__findresult (line 430) | static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *co...
  function rect_height_compare (line 512) | static int rect_height_compare(const void *a, const void *b)
  function rect_width_compare (line 523) | static int rect_width_compare(const void *a, const void *b)
  function rect_original_order (line 534) | static int rect_original_order(const void *a, const void *b)
  function STBRP_DEF (line 547) | STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rect...

FILE: imgui/stb_textedit.h
  type StbUndoRecord (line 296) | typedef struct
  type StbUndoState (line 305) | typedef struct
  type STB_TexteditState (line 314) | typedef struct
  type StbTexteditRow (line 357) | typedef struct
  function stb_text_locate_coord (line 391) | static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, floa...
  function stb_textedit_click (line 451) | static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditSta...
  function stb_textedit_drag (line 460) | static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditStat...
  type StbFindState (line 480) | typedef struct
  function stb_textedit_find_charpos (line 490) | static void stb_textedit_find_charpos(StbFindState *find, STB_TEXTEDIT_S...
  function stb_textedit_clamp (line 550) | static void stb_textedit_clamp(STB_TEXTEDIT_STRING *str, STB_TexteditSta...
  function stb_textedit_delete (line 564) | static void stb_textedit_delete(STB_TEXTEDIT_STRING *str, STB_TexteditSt...
  function stb_textedit_delete_selection (line 572) | static void stb_textedit_delete_selection(STB_TEXTEDIT_STRING *str, STB_...
  function stb_textedit_sortselection (line 588) | static void stb_textedit_sortselection(STB_TexteditState *state)
  function stb_textedit_move_to_first (line 598) | static void stb_textedit_move_to_first(STB_TexteditState *state)
  function stb_textedit_move_to_last (line 609) | static void stb_textedit_move_to_last(STB_TEXTEDIT_STRING *str, STB_Text...
  function is_word_boundary (line 621) | static int is_word_boundary( STB_TEXTEDIT_STRING *str, int idx )
  function stb_textedit_move_to_word_previous (line 627) | static int stb_textedit_move_to_word_previous( STB_TEXTEDIT_STRING *str,...
  function stb_textedit_move_to_word_next (line 642) | static int stb_textedit_move_to_word_next( STB_TEXTEDIT_STRING *str, int...
  function stb_textedit_prep_selection_at_cursor (line 660) | static void stb_textedit_prep_selection_at_cursor(STB_TexteditState *state)
  function stb_textedit_cut (line 669) | static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState ...
  function stb_textedit_paste (line 680) | static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditStat...
  function stb_textedit_key (line 700) | static void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState...
  function stb_textedit_flush_redo (line 1063) | static void stb_textedit_flush_redo(StbUndoState *state)
  function stb_textedit_discard_undo (line 1070) | static void stb_textedit_discard_undo(StbUndoState *state)
  function stb_textedit_discard_redo (line 1092) | static void stb_textedit_discard_redo(StbUndoState *state)
  function StbUndoRecord (line 1112) | static StbUndoRecord *stb_text_create_undo_record(StbUndoState *state, i...
  function STB_TEXTEDIT_CHARTYPE (line 1136) | static STB_TEXTEDIT_CHARTYPE *stb_text_createundo(StbUndoState *state, i...
  function stb_text_undo (line 1156) | static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *s...
  function stb_text_redo (line 1224) | static void stb_text_redo(STB_TEXTEDIT_STRING *str, STB_TexteditState *s...
  function stb_text_makeundo_insert (line 1275) | static void stb_text_makeundo_insert(STB_TexteditState *state, int where...
  function stb_text_makeundo_delete (line 1280) | static void stb_text_makeundo_delete(STB_TEXTEDIT_STRING *str, STB_Texte...
  function stb_text_makeundo_replace (line 1290) | static void stb_text_makeundo_replace(STB_TEXTEDIT_STRING *str, STB_Text...
  function stb_textedit_clear_state (line 1301) | static void stb_textedit_clear_state(STB_TexteditState *state, int is_si...
  function stb_textedit_initialize_state (line 1318) | static void stb_textedit_initialize_state(STB_TexteditState *state, int ...

FILE: imgui/stb_truetype.h
  function my_stbtt_initfont (line 250) | void my_stbtt_initfont(void)
  function my_stbtt_print (line 262) | void my_stbtt_print(float x, float y, char *text)
  function main (line 295) | int main(int argc, char **argv)
  function main (line 336) | int main(int arg, char **argv)
  type stbtt_uint8 (line 388) | typedef unsigned char   stbtt_uint8;
  type stbtt_int8 (line 389) | typedef signed   char   stbtt_int8;
  type stbtt_uint16 (line 390) | typedef unsigned short  stbtt_uint16;
  type stbtt_int16 (line 391) | typedef signed   short  stbtt_int16;
  type stbtt_uint32 (line 392) | typedef unsigned int    stbtt_uint32;
  type stbtt_int32 (line 393) | typedef signed   int    stbtt_int32;
  type stbtt__buf (line 461) | typedef struct
  type stbtt_bakedchar (line 475) | typedef struct
  type stbtt_aligned_quad (line 491) | typedef struct
  type stbtt_packedchar (line 521) | typedef struct
  type stbtt_pack_context (line 528) | typedef struct stbtt_pack_context stbtt_pack_context;
  type stbtt_fontinfo (line 529) | typedef struct stbtt_fontinfo stbtt_fontinfo;
  type stbrp_rect (line 531) | typedef struct stbrp_rect stbrp_rect;
  type stbtt_pack_range (line 565) | typedef struct
  type stbtt_pack_context (line 618) | struct stbtt_pack_context {
  type stbtt_fontinfo (line 652) | struct stbtt_fontinfo
  type stbtt_vertex (line 755) | typedef struct
  type stbtt__bitmap (line 833) | typedef struct
  function stbtt_uint8 (line 984) | static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b)
  function stbtt_uint8 (line 991) | static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b)
  function stbtt__buf_seek (line 998) | static void stbtt__buf_seek(stbtt__buf *b, int o)
  function stbtt__buf_skip (line 1004) | static void stbtt__buf_skip(stbtt__buf *b, int o)
  function stbtt_uint32 (line 1009) | static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n)
  function stbtt__buf (line 1019) | static stbtt__buf stbtt__new_buf(const void *p, size_t size)
  function stbtt__buf (line 1032) | static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s)
  function stbtt__buf (line 1041) | static stbtt__buf stbtt__cff_get_index(stbtt__buf *b)
  function stbtt_uint32 (line 1055) | static stbtt_uint32 stbtt__cff_int(stbtt__buf *b)
  function stbtt__cff_skip_operand (line 1067) | static void stbtt__cff_skip_operand(stbtt__buf *b) {
  function stbtt__buf (line 1082) | static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key)
  function stbtt__dict_get_ints (line 1097) | static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, s...
  function stbtt__cff_index_count (line 1105) | static int stbtt__cff_index_count(stbtt__buf *b)
  function stbtt__buf (line 1111) | static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i)
  function stbtt_uint16 (line 1137) | static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; }
  function stbtt_int16 (line 1138) | static stbtt_int16 ttSHORT(stbtt_uint8 *p)   { return p[0]*256 + p[1]; }
  function stbtt_uint32 (line 1139) | static stbtt_uint32 ttULONG(stbtt_uint8 *p)  { return (p[0]<<24) + (p[1]...
  function stbtt_int32 (line 1140) | static stbtt_int32 ttLONG(stbtt_uint8 *p)    { return (p[0]<<24) + (p[1]...
  function stbtt__isfont (line 1145) | static int stbtt__isfont(stbtt_uint8 *font)
  function stbtt_uint32 (line 1157) | static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fo...
  function stbtt_GetFontOffsetForIndex_internal (line 1170) | static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_coll...
  function stbtt_GetNumberOfFonts_internal (line 1189) | static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection)
  function stbtt__buf (line 1205) | static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict)
  function stbtt_InitFont_internal (line 1218) | static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *...
  function STBTT_DEF (line 1328) | STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unico...
  function STBTT_DEF (line 1421) | STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int un...
  function stbtt_setvertex (line 1426) | static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int...
  function stbtt__GetGlyfOffset (line 1435) | static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_in...
  function STBTT_DEF (line 1457) | STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_in...
  function STBTT_DEF (line 1473) | STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int code...
  function STBTT_DEF (line 1478) | STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_i...
  function stbtt__close_shape (line 1490) | static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, ...
  function stbtt__GetGlyphShapeTT (line 1506) | static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_...
  type stbtt__csctx (line 1732) | typedef struct
  function stbtt__track_vertex (line 1746) | static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_in...
  function stbtt__csctx_v (line 1755) | static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int3...
  function stbtt__csctx_close_shape (line 1771) | static void stbtt__csctx_close_shape(stbtt__csctx *ctx)
  function stbtt__csctx_rmove_to (line 1777) | static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy)
  function stbtt__csctx_rline_to (line 1785) | static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy)
  function stbtt__csctx_rccurve_to (line 1792) | static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float ...
  function stbtt__buf (line 1803) | static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n)
  function stbtt__buf (line 1817) | static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info,...
  function stbtt__run_charstring (line 1845) | static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_i...
  function stbtt__GetGlyphShapeT2 (line 2104) | static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_...
  function stbtt__GetGlyphInfoT2 (line 2121) | static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_i...
  function STBTT_DEF (line 2134) | STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_...
  function STBTT_DEF (line 2142) | STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int gl...
  function STBTT_DEF (line 2154) | STBTT_DEF int  stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int...
  function STBTT_DEF (line 2184) | STBTT_DEF int  stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info,...
  function STBTT_DEF (line 2191) | STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, in...
  function STBTT_DEF (line 2196) | STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *as...
  function STBTT_DEF (line 2203) | STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int ...
  function STBTT_DEF (line 2211) | STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, fl...
  function STBTT_DEF (line 2217) | STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *in...
  function STBTT_DEF (line 2223) | STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
  function STBTT_DEF (line 2233) | STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *fon...
  function STBTT_DEF (line 2251) | STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int g...
  function STBTT_DEF (line 2256) | STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo ...
  function STBTT_DEF (line 2261) | STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, i...
  type stbtt__hheap_chunk (line 2270) | typedef struct stbtt__hheap_chunk
  type stbtt__hheap (line 2275) | typedef struct stbtt__hheap
  function stbtt__hheap_free (line 2303) | static void stbtt__hheap_free(stbtt__hheap *hh, void *p)
  function stbtt__hheap_cleanup (line 2309) | static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata)
  type stbtt__edge (line 2319) | typedef struct stbtt__edge {
  type stbtt__active_edge (line 2325) | typedef struct stbtt__active_edge
  function stbtt__active_edge (line 2347) | static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__ed...
  function stbtt__active_edge (line 2369) | static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__ed...
  function stbtt__fill_active_edges (line 2394) | static void stbtt__fill_active_edges(unsigned char *scanline, int len, s...
  function stbtt__rasterize_sorted_edges (line 2436) | static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__...
  function stbtt__handle_clipped_edge (line 2540) | static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__ac...
  function stbtt__fill_active_edges_new (line 2577) | static void stbtt__fill_active_edges_new(float *scanline, float *scanlin...
  function stbtt__rasterize_sorted_edges (line 2740) | static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__...
  function stbtt__sort_edges_ins_sort (line 2836) | static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n)
  function stbtt__sort_edges_quicksort (line 2854) | static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n)
  function stbtt__sort_edges (line 2916) | static void stbtt__sort_edges(stbtt__edge *p, int n)
  type stbtt__point (line 2922) | typedef struct
  function stbtt__rasterize (line 2927) | static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, i...
  function stbtt__add_point (line 2984) | static void stbtt__add_point(stbtt__point *points, int n, float x, float y)
  function stbtt__tesselate_curve (line 2992) | static int stbtt__tesselate_curve(stbtt__point *points, int *num_points,...
  function stbtt__tesselate_cubic (line 3012) | static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points...
  function stbtt__point (line 3055) | static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num...
  function STBTT_DEF (line 3132) | STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_...
  function STBTT_DEF (line 3144) | STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata)
  function STBTT_DEF (line 3194) | STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info,...
  function STBTT_DEF (line 3213) | STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigne...
  function STBTT_DEF (line 3223) | STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *i...
  function STBTT_DEF (line 3233) | STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, uns...
  function stbtt_BakeFontBitmap_internal (line 3244) | static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset...
  function STBTT_DEF (line 3290) | STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int...
  type stbrp_coord (line 3318) | typedef int stbrp_coord;
  type stbrp_context (line 3331) | typedef struct
  type stbrp_node (line 3337) | typedef struct
  type stbrp_rect (line 3342) | struct stbrp_rect
  function stbrp_init_target (line 3348) | static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_...
  function stbrp_pack_rects (line 3359) | static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int ...
  function STBTT_DEF (line 3388) | STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pi...
  function STBTT_DEF (line 3419) | STBTT_DEF void stbtt_PackEnd  (stbtt_pack_context *spc)
  function STBTT_DEF (line 3425) | STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsign...
  function stbtt__h_prefilter (line 3437) | static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int ...
  function stbtt__v_prefilter (line 3499) | static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int ...
  function stbtt__oversample_shift (line 3561) | static float stbtt__oversample_shift(int oversample)
  function STBTT_DEF (line 3574) | STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, c...
  function STBTT_DEF (line 3603) | STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *sp...
  function STBTT_DEF (line 3685) | STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, st...
  function STBTT_DEF (line 3690) | STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned cha...
  function STBTT_DEF (line 3726) | STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char...
  function STBTT_DEF (line 3738) | STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, i...
  function stbtt_int32 (line 3772) | static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint...
  function stbtt_CompareUTF8toUTF16_bigendian_internal (line 3811) | static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len...
  function STBTT_DEF (line 3818) | STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font...
  function stbtt__matchpair (line 3839) | static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint...
  function stbtt__matches (line 3886) | static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_ui...
  function stbtt_FindMatchingFont_internal (line 3915) | static int stbtt_FindMatchingFont_internal(unsigned char *font_collectio...
  function STBTT_DEF (line 3931) | STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset,
  function STBTT_DEF (line 3938) | STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int...
  function STBTT_DEF (line 3943) | STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data)
  function STBTT_DEF (line 3948) | STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *...
  function STBTT_DEF (line 3953) | STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, cons...
  function STBTT_DEF (line 3958) | STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len...

FILE: main.cpp
  function updategroups (line 70) | inline void updategroups(Model& model, milliseconds timestamp, milliseco...
  function main (line 115) | int main(int argc, const char *argv[])

FILE: model.h
  function namespace (line 3) | namespace model {
  type WordCount (line 154) | struct WordCount
  type ViewModel (line 170) | struct ViewModel
  function else (line 211) | else if (scope == scope_all_positive) {
  function function (line 360) | inline function<observable<ViewModel>(observable<ViewModel>)> reportandr...

FILE: rxcurl.h
  function namespace (line 3) | namespace rxcurl {
  type http_request (line 51) | struct http_request
  type curl_slist (line 100) | struct curl_slist
  function runtime_error (line 103) | struct http_exception : runtime_error
  type http_body (line 117) | struct http_body
  function httpStatus (line 122) | struct http_response
  type rxcurl (line 147) | struct rxcurl
  function rxcurl (line 272) | rxcurl create_rxcurl() {

FILE: rximgui.h
  function namespace (line 3) | namespace rximgui {

FILE: tweets.h
  function namespace (line 3) | namespace tweets {
  function errorcodeclass (line 103) | enum class errorcodeclass {

FILE: util.h
  function namespace (line 3) | namespace util {
Condensed preview — 33 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,219K chars).
[
  {
    "path": ".gitignore",
    "chars": 134,
    "preview": "CMakeCache.txt\nCMakeFiles\nCMakeScripts\nMakefile\ncmake_install.cmake\ninstall_manifest.txt\nCTestTestfile.cmake\nunix/*\nbuil"
  },
  {
    "path": "CMakeLists.txt",
    "chars": 5025,
    "preview": "cmake_minimum_required(VERSION 3.2 FATAL_ERROR)\n\nget_filename_component(SAMPLE_PROJECT \"${CMAKE_CURRENT_SOURCE_DIR}\" NAM"
  },
  {
    "path": "FindSDL2_mixer.cmake",
    "chars": 1359,
    "preview": "# https://raw.githubusercontent.com/ksterker/adonthell/master/config/FindSDL2_mixer.cmake\n#\n# this module look for SDL2_"
  },
  {
    "path": "Findjsoncpp.cmake",
    "chars": 1584,
    "preview": "# Copyright Gonzalo Brito Gadeschi 2015\n# Copyright Kirk Shoop 2017\n# Distributed under the Boost Software License, Vers"
  },
  {
    "path": "Findrange-v3.cmake",
    "chars": 1600,
    "preview": "# Copyright Gonzalo Brito Gadeschi 2015\n# Distributed under the Boost Software License, Version 1.0.\n# (See accompanying"
  },
  {
    "path": "Findrxcpp.cmake",
    "chars": 1575,
    "preview": "# Copyright Gonzalo Brito Gadeschi 2015\n# Copyright Kirk Shoop 2016\n# Distributed under the Boost Software License, Vers"
  },
  {
    "path": "LICENSE",
    "chars": 1067,
    "preview": "MIT License\n\nCopyright (c) 2016 Kirk Shoop\n\nPermission is hereby granted, free of charge, to any person obtaining a copy"
  },
  {
    "path": "LICENSE_OFL.txt",
    "chars": 4301,
    "preview": "This Font Software is licensed under the SIL Open Font License,\nVersion 1.1.\n\nThis license is copied below, and is also "
  },
  {
    "path": "README.md",
    "chars": 1300,
    "preview": "# twitter\n\n### rxcpp example of live twitter analysis\n\n[![president-elect](https://img.youtube.com/vi/QFcy-jQpvBg/0.jpg)"
  },
  {
    "path": "future.cpp",
    "chars": 15733,
    "preview": "/*\n * Getting timelines by Twitter Streaming API\n * from: https://gist.github.com/komasaru/9c78a278f6916548f146\n */\n#inc"
  },
  {
    "path": "imgui/LICENSE.txt",
    "chars": 1106,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2014-2015 Omar Cornut and ImGui contributors\n\nPermission is hereby granted, free of"
  },
  {
    "path": "imgui/imconfig.h",
    "chars": 2764,
    "preview": "//-----------------------------------------------------------------------------\n// USER IMPLEMENTATION\n// This file cont"
  },
  {
    "path": "imgui/imgui.cpp",
    "chars": 470261,
    "preview": "// dear imgui, v1.51\n// (main code and documentation)\n\n// See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code.\n/"
  },
  {
    "path": "imgui/imgui.h",
    "chars": 134989,
    "preview": "// dear imgui, v1.51\n// (headers)\n\n// See imgui.cpp file for documentation.\n// See ImGui::ShowTestWindow() in imgui_demo"
  },
  {
    "path": "imgui/imgui_demo.cpp",
    "chars": 138485,
    "preview": "// dear imgui, v1.51\n// (demo code)\n\n// Message to the person tempted to delete this file when integrating ImGui into th"
  },
  {
    "path": "imgui/imgui_draw.cpp",
    "chars": 114716,
    "preview": "// dear imgui, v1.51\n// (drawing and font code)\n\n// Contains implementation for\n// - ImDrawList\n// - ImDrawData\n// - ImF"
  },
  {
    "path": "imgui/imgui_impl_sdl_gl3.cpp",
    "chars": 17126,
    "preview": "// ImGui SDL2 binding with OpenGL3\n// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifie"
  },
  {
    "path": "imgui/imgui_impl_sdl_gl3.h",
    "chars": 1090,
    "preview": "// ImGui SDL2 binding with OpenGL3\n// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifie"
  },
  {
    "path": "imgui/imgui_internal.h",
    "chars": 50969,
    "preview": "// dear imgui, v1.51\n// (internals)\n\n// You may use this file to debug, understand or extend ImGui features but we don't"
  },
  {
    "path": "imgui/stb_rect_pack.h",
    "chars": 17384,
    "preview": "// stb_rect_pack.h - v0.10 - public domain - rectangle packing\n// Sean Barrett 2014\n//\n// Useful for e.g. packing rectan"
  },
  {
    "path": "imgui/stb_textedit.h",
    "chars": 49161,
    "preview": "// [ImGui] this is a slightly modified version of stb_truetype.h 1.9. Those changes would need to be pushed into nothing"
  },
  {
    "path": "imgui/stb_truetype.h",
    "chars": 152430,
    "preview": "// stb_truetype.h - v1.14 - public domain\n// authored from 2009-2016 by Sean Barrett / RAD Game Tools\n//\n//   This libra"
  },
  {
    "path": "imgui.ini",
    "chars": 519,
    "preview": "[Debug]\nPos=60,60\nSize=400,400\nCollapsed=0\n\n[Live Analysis]\nPos=16,66\nSize=542,396\nCollapsed=0\n\n[Recent Tweets]\nPos=994,"
  },
  {
    "path": "main.cpp",
    "chars": 74038,
    "preview": "/*\n * Getting timelines by Twitter Streaming API\n */\n#include <iostream>\n#include <stdio.h>\n#include <stdlib.h>\n#include"
  },
  {
    "path": "model.h",
    "chars": 16315,
    "preview": "#pragma once\n\nnamespace model {\n\ninline string tweettext(const json& tweet) {\n    if (!!tweet.count(\"extended_tweet\")) {"
  },
  {
    "path": "rxcurl.h",
    "chars": 9509,
    "preview": "#pragma once\n\nnamespace rxcurl {\n\nstruct rxcurl_state\n{\n    ~rxcurl_state(){\n        if (!!curlm) {\n            worker.a"
  },
  {
    "path": "rximgui.h",
    "chars": 485,
    "preview": "#pragma once\n\nnamespace rximgui {\n\ninline float  Clamp(float v, float mn, float mx)                       { return (v < "
  },
  {
    "path": "shared.cmake",
    "chars": 1148,
    "preview": "FIND_PACKAGE(Threads)\n\n# define some compiler settings\n\nMESSAGE( STATUS \"CMAKE_CXX_COMPILER_ID: \" ${CMAKE_CXX_COMPILER_I"
  },
  {
    "path": "tweets.h",
    "chars": 11241,
    "preview": "#pragma once\n\nnamespace tweets {\n\ninline milliseconds timestamp_ms(const Tweet& tw) {\n    auto& tweet = tw.data->tweet;\n"
  },
  {
    "path": "tweetsample.txt",
    "chars": 789824,
    "preview": "{\"created_at\":\"Sat Oct 29 23:00:47 +0000 2016\",\"id\":792501464090411008,\"id_str\":\"792501464090411008\",\"text\":\"00:00h - pa"
  },
  {
    "path": "util.h",
    "chars": 1454,
    "preview": "#pragma once\n\nnamespace util {\n\nconst float fltmax = numeric_limits<float>::max();\n\ninline string tolower(string s) {\n  "
  }
]

// ... and 2 more files (download for full content)

About this extraction

This page contains the full source code of the kirkshoop/twitter GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 33 files (106.3 MB), approximately 591.2k tokens, and a symbol index with 612 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!