├── .gitignore ├── .gitmodules ├── COPYING ├── ChangeLog ├── INSTALL ├── Makefile.am ├── README ├── THANKS ├── autogen.sh ├── cmd ├── logstalgia └── logstalgia.cmd ├── configure.ac ├── data ├── ball.tga ├── example.log ├── fonts │ ├── FreeMonoBold.ttf │ ├── FreeSerif.ttf │ └── README ├── glow.tga └── logstalgia.1 ├── dev ├── .gitignore ├── bin │ ├── build_tar.pl │ └── build_win64.pl └── nsis │ ├── disclaimer.txt │ ├── welcome.bmp │ └── welcome.xcf ├── logstalgia.pro ├── m4 ├── ax_boost_base.m4 ├── ax_boost_filesystem.m4 ├── ax_boost_system.m4 ├── ax_check_gl.m4 ├── ax_check_glu.m4 ├── ax_check_glut.m4 ├── ax_pthread.m4 ├── ax_restore_flags_with_prefix.m4 ├── ax_save_flags_with_prefix.m4 └── pkg.m4 └── src ├── .gitignore ├── configwatcher.cpp ├── configwatcher.h ├── custom.cpp ├── custom.h ├── logentry.cpp ├── logentry.h ├── logstalgia.cpp ├── logstalgia.h ├── main.cpp ├── ncsa.cpp ├── ncsa.h ├── paddle.cpp ├── paddle.h ├── requestball.cpp ├── requestball.h ├── settings.cpp ├── settings.h ├── slider.cpp ├── slider.h ├── summarizer.cpp ├── summarizer.h ├── tests.cpp ├── tests.h ├── textarea.cpp └── textarea.h /.gitignore: -------------------------------------------------------------------------------- 1 | aclocal.m4 2 | /logstalgia 3 | /dev/win64 4 | logstalgia.exe 5 | logstalgia.pro.user 6 | autom4te.cache 7 | debug.log 8 | Makefile 9 | Makefile.in 10 | *.dll 11 | logs 12 | configure 13 | config.log 14 | config.status 15 | /build-aux 16 | *.swp 17 | *.d 18 | .objs 19 | .deps 20 | .dirstamp 21 | logstalgia-*.png 22 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/core"] 2 | path = src/core 3 | url = https://github.com/acaudwell/Core.git 4 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 1.1.4: 2 | * Added experimental support for Wayland (beroset). 3 | * Updated autoconf macros. 4 | * Fixed INSTALL instructions regarding GLM. 5 | 6 | 1.1.3: 7 | * Added --high-dpi option. 8 | * Support rendering at native resolution on Retina / Ultra HD displays. 9 | * Change regular expression library to PCRE2. 10 | * Added Boost Filesystem build requirement. 11 | 12 | 1.1.2: 13 | * Fixed compatibility with GLM 0.9.9.0. 14 | 15 | 1.1.0: 16 | * Fixed rendering of FreeMonoBold with FreeType2 2.8 by disabling hinting. 17 | * Updated fonts. 18 | 19 | 1.0.9: 20 | * Fixed compilation issues on FreeBSD (ehaupt) and OpenBSD (gonzalo-). 21 | * Fixed config change not being detected in some cases. 22 | 23 | 1.0.8: 24 | * Performance improvements. 25 | * Changed unsuccessful response code direction to match ball. 26 | * Added --screen option. 27 | * Added --window-position XxY option. 28 | * Added --frameless option. 29 | * Added --title option (mclang). 30 | * Added --detect-changes option to automatically reload config file. 31 | * Added --display-fields FIELDS to set fields shown mousing over a request. 32 | * Can now specify path separators, max path depth and min abbreviation depth. 33 | * Reload config (F5). 34 | * Save config (Ctrl+S) with updated display settings. 35 | * Fixed queued log entries not being deleted when seeking using the timeline. 36 | * Made --hide-url-prefix apply to https URLs (rudisimo). 37 | * Counter no longer overflows at 100000000. 38 | * Now requires SDL 2 to build (deprecated SDL 1.2 support removed). 39 | 40 | 1.0.7: 41 | * Added window frame toggle (F11). 42 | * Fixed crash loading large log files on Windows. 43 | * Fixed crash when taking a screenshot with an odd resolution. 44 | * Handle exception when user defined regular expression is invalid. 45 | * Fixed --hide-url-prefix not working (jettero). 46 | 47 | 1.0.6: 48 | * Display invalid requests as having the path '???'. 49 | * Updated the boost autoconf macro. 50 | 51 | 1.0.5: 52 | * Performance improvements. 53 | * Multi-monitor support using SDL 2.0. 54 | * SDL 1.2 support is deprecated. 55 | * Can now specify the attribute to match the group regex (-g) against. 56 | * When using --sync, now catches back up after resuming from pause. 57 | * Added --pitch-speed option (control how fast balls travel). 58 | * Made default group matches case-insensitive (Sebastian Krzyszkowiak). 59 | * Display tokens in multi-paddle modes (Sebastian Krzyszkowiak). 60 | * Added window resizing and a full-screen toggle (alt-enter). 61 | * Take screenshots (F12). 62 | * Summarizer component content is now sorted. 63 | * IPv6 addresses now anonymized by default as well (last 64 bits). 64 | * New dependencies on libpng, GLEW. 65 | * Now requires GLM and Boost header-only libraries to build. 66 | 67 | 1.0.4: 68 | * Changed type of log entry timestamp to time_t. 69 | * Stopped directly linking PNG/JPG libraries. 70 | 71 | 1.0.3: 72 | * Added automatic skipping of empty periods (--disable-auto-skip to turn off). 73 | * Updated docs to reflect support for NCSA log formats, not just 'Apache'. 74 | * Support log entry dates with a valid numeric month in place of MMM. 75 | 76 | 1.0.2: 77 | * Performance improvements. 78 | * Stopped frame-rate being a bottle neck for the number of requests shown. 79 | * Improved STDIN input reliability on windows. 80 | * Handle log entry timezone offsets. 81 | * Added --paddle-position option (to allow more space for URLs). 82 | * Added --font-size option. 83 | 84 | 1.0.1: 85 | * Made STDIN non-blocking on Windows using PeekNamedPipe (thanks Rui Lopes). 86 | * Added --hide-url-prefix option to remove protocol and hostname from requests. 87 | * Removed arbitrary 1024 maximum length limit for log entries. 88 | * Fixed custom log format not working when optional fields are omitted. 89 | 90 | 1.0.0: 91 | * Every 60 minutes fade static text out and back in over a period of a minute. 92 | 93 | 0.9.9: 94 | * Support for more common Apache access log formats. 95 | * Added --paddle-mode (vhost,pid,single) which spawns separate paddles. 96 | * Fixed PPM exporter producing blank images on some video cards. 97 | 98 | 0.9.8: 99 | * Added --background option to control the background colour. 100 | * Filter hostnames from URLs before displaying them. 101 | * Fixed command line option documentation. 102 | 103 | 0.9.7: 104 | * Added --sync option (start from the next entry received on STDIN). 105 | 106 | 0.9.6: 107 | * Defer to homepage for video recording instructions. 108 | 109 | 0.9.5: 110 | * Adjust time scale with <> keys. 111 | 112 | 0.9.4: 113 | * Fixed STDIN stopping working after the first lot of records. 114 | 115 | 0.9.3: 116 | * Added seekbar for log files (not available from STDIN). 117 | * Added glow on impact with paddle (turn off using --disable-glow). 118 | * PPM output for videos using --output-ppm-stream option. 119 | * Custom log file format support. 120 | * Changed font library to FTGL. 121 | * --stop-position and --start-position options. 122 | * Open a file selector if no log file supplied (on Windows). 123 | 124 | 0.9.2: 125 | * Fixed issue with resource.h. 126 | * Makefile patch for OPTFLAGS from terjeros. 127 | * Fixed apache.log hostname parsing issue. 128 | 129 | 0.9.1: 130 | * Added example.log. 131 | 132 | 0.9.0c: 133 | * Changed Makefile to use configure libs. 134 | 135 | 0.9.0b: 136 | * Incorporated manual page fixes from Francois Marier. 137 | * Fixed bug in URL summarizer that caused it to leave out some URLs 138 | when pressed for space. 139 | 140 | 0.9.0a: 141 | * Fixed manual description of -x flag. 142 | 143 | 0.9.0: 144 | * First release. 145 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | This file is to help you configure, build and install Logstalgia on your system. 2 | 3 | Contents 4 | ======== 5 | 6 | 1. Dependencies 7 | 2. Building 8 | 3. Configure Options 9 | 10 | 1. Dependencies 11 | =============== 12 | 13 | Logstalgia requires the following libraries to compile (package names may vary): 14 | 15 | SDL 2.0 (libsdl2-dev) 16 | SDL Image 2.0 (libsdl2-image-dev) 17 | PCRE2 (libpcre2-dev) 18 | Freetype 2 (libfreetype6-dev) 19 | GLEW (libglew-dev) 20 | GLM >= 0.9.3 (libglm-dev) 21 | Boost Filesystem >= 1.46 (libboost-filesystem-dev) 22 | PNG >= 1.2 (libpng12-dev) 23 | 24 | 2. Building 25 | =========== 26 | 27 | Logstalgia requires a GNU compatible C++ compiler that supports c++0x features such as 'auto' and the new 'for' loop syntax. 28 | 29 | GCC 4.6+ or Clang recommended. 30 | 31 | If you got the source directly from the Logstalgia.git repository, you will 32 | first need to run autogen.sh which will generate the configure script and 33 | initialize and update the submodules. 34 | 35 | ./autogen.sh 36 | 37 | Building on Linux/Mac OS: 38 | 39 | ./configure 40 | make 41 | make install 42 | 43 | Building on Windows: 44 | 45 | On Windows compile logstalgia.pro with Qt Creator. 46 | 47 | A pre-built version for Windows is normally available from the homepage. 48 | 49 | Logstalgia expects SDL to have been built with the NO_STDIO_REDIRECT flag. 50 | 51 | 3. Configure Options 52 | ==================== 53 | 54 | By default Logstalgia will install some GNU FreeFont TTF Fonts on your system. 55 | 56 | If you already have these fonts installed, you can configure Logstalgia to use 57 | these instead: 58 | 59 | ./configure --enable-ttf-font-dir=/path/to/freefont/ 60 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | ACLOCAL_AMFLAGS = -I m4 2 | 3 | bin_PROGRAMS = logstalgia 4 | 5 | logstalgia_CXXFLAGS = -std=gnu++0x -Wall -Wno-sign-compare -Wno-reorder -Wno-unused-but-set-variable -Wno-unused-variable 6 | 7 | logstalgia_SOURCES = \ 8 | src/core/conffile.cpp \ 9 | src/core/display.cpp \ 10 | src/core/frustum.cpp \ 11 | src/core/fxfont.cpp \ 12 | src/core/logger.cpp \ 13 | src/core/ppm.cpp \ 14 | src/core/png_writer.cpp \ 15 | src/core/plane.cpp \ 16 | src/core/quadtree.cpp \ 17 | src/core/regex.cpp \ 18 | src/core/resource.cpp \ 19 | src/core/sdlapp.cpp \ 20 | src/core/seeklog.cpp \ 21 | src/core/settings.cpp \ 22 | src/core/shader.cpp \ 23 | src/core/shader_common.cpp \ 24 | src/core/stringhash.cpp \ 25 | src/core/texture.cpp \ 26 | src/core/timezone.cpp \ 27 | src/core/vbo.cpp \ 28 | src/core/vectors.cpp \ 29 | src/configwatcher.cpp \ 30 | src/ncsa.cpp \ 31 | src/custom.cpp \ 32 | src/logentry.cpp \ 33 | src/logstalgia.cpp \ 34 | src/main.cpp \ 35 | src/paddle.cpp \ 36 | src/requestball.cpp \ 37 | src/settings.cpp \ 38 | src/slider.cpp \ 39 | src/summarizer.cpp \ 40 | src/textarea.cpp \ 41 | src/tests.cpp 42 | 43 | AM_CPPFLAGS = -DSDLAPP_RESOURCE_DIR=\"$(pkgdatadir)\" 44 | 45 | dist_pkgdata_DATA = data/ball.tga data/example.log data/glow.tga 46 | 47 | install-data-hook: 48 | mkdir -p -m 755 ${DESTDIR}/$(mandir)/man1 49 | $(SED) 's|SDLAPP_RESOURCE_DIR|$(pkgdatadir)|g' data/logstalgia.1 | gzip -f9 > $(DESTDIR)$(mandir)/man1/logstalgia.1.gz 50 | 51 | uninstall-hook: 52 | -rm -f $(DESTDIR)$(mandir)/man1/logstalgia.1.gz 53 | 54 | if FONTDIR 55 | AM_CPPFLAGS += -DSDLAPP_FONT_DIR=\"$(sdlappfontdir)\" 56 | else 57 | fontsdir = $(pkgdatadir)/fonts 58 | dist_fonts_DATA = data/fonts/README data/fonts/FreeMonoBold.ttf data/fonts/FreeSerif.ttf 59 | endif 60 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | 2 | Logstalgia 3 | 4 | a website access log visualisation tool 5 | 6 | Copyright (C) 2008 Andrew Caudwell 7 | 8 | http://logstalgia.io 9 | 10 | Contents 11 | ======== 12 | 13 | 1. Description 14 | 2. Requirements 15 | 3. Using Logstalgia 16 | 4. Copyright 17 | 18 | 1. Description 19 | ============== 20 | 21 | Logstalgia is a visualization tool that replays or streams web server access 22 | logs as a retro arcade game simulation. 23 | 24 | 2. Requirements 25 | =============== 26 | 27 | Logstalgia's display is rendered using OpenGL and requires a 3D accelerated 28 | video card to run. 29 | 30 | Logstalgia supports several standardized access.log formats used by web servers 31 | such as Apache and Nginx (see 'Supported Log Formats' below). 32 | 33 | As Logstalgia is designed to playback logs in real time you will need a log from 34 | a fairly busy webserver to achieve interesting results (eg 100s of requests 35 | each minute). 36 | 37 | 3. Using Logstalgia 38 | =================== 39 | 40 | logstalgia [options] logfile 41 | 42 | options: 43 | 44 | -f Fullscreen. 45 | 46 | -WxH Set the window size. If -f is also supplied, will attempt to set the 47 | video mode to this also. Add ! to make the window non-resizable. 48 | 49 | --screen SCREEN 50 | Set the number of the screen to display on. 51 | 52 | --high-dpi 53 | Request a high DPI display when creating the window. 54 | 55 | On some platforms such as MacOS, the window resolution is specified in points instead of pixels. 56 | The --high-dpi flag may be required to access some higher resolutions. 57 | 58 | E.g. requesting a high DPI 800x600 window may produce a window that is 1600x1200 pixels. 59 | 60 | --window-position XxY 61 | Initial window position on your desktop which may be made up of 62 | multiple monitors. 63 | 64 | This will override the screen setting so don't specify both. 65 | 66 | --frameless 67 | Frameless window. 68 | 69 | --title TITLE 70 | Set a title. 71 | 72 | -b, --background FFFFFF 73 | Background colour in hex. 74 | 75 | -x, --full-hostnames 76 | Show full request ip/hostname. 77 | 78 | -s, --simulation-speed 79 | Simulation speed. Defaults to 1 (1 second-per-second). 80 | 81 | -p, --pitch-speed 82 | Speed balls travel across the screen (defaults to 0.15). 83 | 84 | -u, --update-rate 85 | Page Summary update speed. Defaults to 5 (5 seconds). 86 | 87 | -g name,(HOST|URI|CODE)=regex[,SEP=chars][,MAX=n][,ABBR=n],percent[,colour] 88 | 89 | Creates a new named summarizer group for requests for which a 90 | specified attribute (HOST, URI or response CODE) matches a 91 | regular expression. Percent specifies a vertical percentage of 92 | screen to use. 93 | 94 | SEP=chars can specify a list of separator characters (e.g. /) 95 | to split on. The default separator is /. 96 | 97 | MAX=n specifies the max depth into the path to be displayed. 98 | (e.g. MAX=1 would show only root directory names of paths). By 99 | default there is 0 (no limit). 100 | 101 | ABBR=n specifies the minimum depth at which to allow partially 102 | abbreviated strings. The default is 0 (allow). -1 to disallow. 103 | 104 | A colour may optionally be supplied in hexadecimal format 105 | (eg FF0000 for red) which will be applied to all labels 106 | and request balls matched to the group. 107 | 108 | Examples: 109 | 110 | -g "HTML,URI=html?$,30" 111 | -g "Lan,HOST=^192,30" 112 | -g "Success,CODE=^[23],30" 113 | 114 | If no groups are specified, the default groups are Images 115 | (image files), CSS (.css files) and Scripts (.js files). 116 | 117 | If there is enough space remaining a catch-all group 'Misc' 118 | will appear as the last group. 119 | 120 | --address-separators CHARS 121 | List of address separator characters. Defaults to '.:'. 122 | 123 | --address-max-depth DEPTH 124 | Maximum depth to display in address summarizer. 0 for no maximum. 125 | 126 | --address-abbr-depth DEPTH 127 | Minimum abbreviation depth of address summarizer. 128 | 0 to always allow abbreviations, -1 to never abbreviate. 129 | 130 | --path-separators CHARS 131 | Default list of path separator characters. Defaults to /. 132 | 133 | --path-max-depth DEPTH 134 | Default maximum path depth shown in the summarizer. 135 | 0 for no maximum. 136 | 137 | --path-abbr-depth DEPTH 138 | Default minimum path abbreviation depth. 139 | 0 to always allow abbreviations, -1 to never abbreviate. 140 | 141 | --paddle-mode MODE 142 | Paddle mode (pid, vhost, single). 143 | 144 | vhost - separate paddle for each virtual host in the log file. 145 | 146 | pid - separate paddle for each process id in the log file. 147 | 148 | single - single paddle (the default). 149 | 150 | --paddle-position POSITION 151 | Paddle position as a fraction of the view width (0.25 - 0.75). 152 | 153 | --display-fields REQUEST_FIELDS 154 | List of one or more request fields that are shown when the user 155 | hovers the mouse over an individual request: 156 | 157 | path - the path of the resource requested 158 | hostname - hostname or IP address 159 | response_size - size of the response in bytes 160 | response_code - response code 161 | method - method 162 | protocol - protocol 163 | timestamp - timestamp of request 164 | referrer - referrer of the request 165 | user_agent - user agent 166 | vhost - virtual host name 167 | log_entry - full log entry 168 | pid - the pid of the instance that handled the request 169 | 170 | Separate multiple fields with commas (eg 'path,hostname') 171 | 172 | --sync Read from STDIN, ignoring entries before the current time. 173 | 174 | --from, --to "YYYY-MM-DD hh:mm:ss +tz" 175 | Show entries from a specific time period. 176 | 177 | If a time zone offset isn't specified the local time zone is used. 178 | 179 | Example accepted formats: 180 | 181 | "2012-06-30" 182 | "2012-06-30 12:00" 183 | "2012-06-30 12:00:00 +12" 184 | 185 | --start-position POSITION 186 | Begin at some position in the log file (between 0.0 and 1.0). 187 | 188 | --stop-position POSITION 189 | Stop at some position. 190 | 191 | --no-bounce 192 | No bouncing. 193 | 194 | --hide-response-code 195 | Hide response code. 196 | 197 | --hide-paddle 198 | Hide paddle. 199 | 200 | --hide-paddle-tokens 201 | Hide paddle tokens shown in multi-paddle modes. 202 | 203 | --hide-url-prefix 204 | Hide URL protocol and hostname prefix of requests. 205 | 206 | --disable-auto-skip 207 | Disable automatic skipping of empty time periods. 208 | 209 | --disable-progress 210 | Disable the progress bar. 211 | 212 | --disable-glow 213 | Disable the glow effect. 214 | 215 | --font-size SIZE 216 | Font size (10 - 40). 217 | 218 | --glow-duration 219 | Duration of the glow (between 0.0 and 1.0). 220 | 221 | --glow-multiplier 222 | Adjust the amount of glow. 223 | 224 | --glow-intensity 225 | Intensity of the glow. 226 | 227 | -o, --output-ppm-stream FILE 228 | Write frames as PPM to a file ('-' for STDOUT). 229 | 230 | -r, --output-framerate FPS 231 | Framerate of output (used with --output-ppm-stream). 232 | 233 | --load-config CONFIG_FILE 234 | Load a config file. 235 | 236 | --save-config CONFIG_FILE 237 | Save a config file with the current options. 238 | 239 | --detect-changes 240 | Automatically reload config file when it is modified. 241 | 242 | logfile 243 | The path to the access log file to read or '-' if you wish to 244 | supply log entries via STDIN. 245 | 246 | Examples: 247 | 248 | Watch an example access.log file using the default settings: 249 | 250 | logstalgia data/example.log 251 | 252 | Watch the live access.log, starting from the most recent batch of entries 253 | in the log (requires tail). Note than '-' at the end is required for logstalgia 254 | to know it needs to read from STDIN: 255 | 256 | tail -f /var/log/apache2/access.log | logstalgia - 257 | 258 | To follow the log in real time, use the --sync option. This will start reading 259 | from the next entry received on STDIN: 260 | 261 | tail -f /var/log/apache2/access.log | logstalgia --sync 262 | 263 | Watch a remote access.log via ssh: 264 | 265 | ssh user@example.com tail -f /var/log/apache2/access.log | logstalgia --sync 266 | 267 | Supported Log Formats: 268 | 269 | Logstalgia supports the following standardized log formats used by web servers like Apache and Nginx: 270 | 271 | NCSA Common Log Format (CLF) 272 | "%h %l %u %t \"%r\" %>s %b" 273 | 274 | NCSA Common Log Format with Virtual Host 275 | "%v %h %l %u %t \"%r\" %>s %b" 276 | 277 | NCSA extended/combined log format 278 | "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" 279 | 280 | NCSA extended/combined log format with Virtual Host 281 | "%v %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" 282 | 283 | The process id (%P), or some other identifier, may be included as an additional 284 | field at the end of the entry. This can be used with '--paddle-mode pid' where 285 | a separate paddle will be created for each unique value in this field. 286 | 287 | 288 | Custom Log Format: 289 | 290 | Logstalgia now supports a pipe ('|') delimited custom log file format: 291 | 292 | timestamp - unix timestamp of the request date. 293 | hostname - hostname of the request 294 | path - path requested 295 | response_code - the response code from the webserver (eg 200) 296 | response_size - the size of the response in bytes 297 | 298 | The following are optional: 299 | success - 1 or 0 to indicate if successful 300 | response_colour - response colour in hexidecial (#FFFFFF) format 301 | referrer url - the referrer url 302 | user agent - the user agent 303 | virtual host - the virtual host (to use with --paddle-mode vhost) 304 | pid - process id or some other identifier (--paddle-mode pid) 305 | 306 | If success or response_colour are not provided, they will be derived from the 307 | response_code using the normal HTTP conventions (code < 400 = success). 308 | 309 | 310 | Recording Videos: 311 | 312 | See the guide on the homepage for examples of recording videos with Logstalgia: 313 | 314 | https://github.com/acaudwell/Logstalgia/wiki/Videos 315 | 316 | Interface: 317 | 318 | The time shown in the top left of the screen is set initially from the first log 319 | entry read and is incremented according to the simulation speed (-s). 320 | 321 | The counter in the bottom right hand corner shows the number of requests 322 | displayed since the start of the current session. 323 | 324 | Pressing space at any time will pause/unpause the simulation. While paused you 325 | may use the mouse to inspect the detail of individual requests. 326 | 327 | You can click on summarizer group entries on the left and right side of the 328 | screen to filter to requests matching that entry. Click on the filter 329 | description to remove the filter. 330 | 331 | Interactive keyboard commands: 332 | 333 | (C) Displays Logstalgia logo 334 | (N) Jump forward in time to next log entry 335 | (+-) Adjust simulation speed 336 | (<>) Adjust pitch speed 337 | (F5) Reload config 338 | (F6) Load config (Windows only) 339 | (F11) Window frame toggle 340 | (F12) Screenshot 341 | (Alt+Enter) Fullscreen toggle 342 | (Ctrl+S) Save config 343 | (Home/End) Adjust address summarizer maximum depth 344 | (Page Up/Down) Adjust group summarizer maximum depth 345 | (Ctrl+Home/End) Adjust address summarizer abbreviation depth 346 | (Ctrl+Page Up/Down) Adjust group summarizer abbreviation depth 347 | (ESC) Quit 348 | 349 | 350 | 4. Copyright 351 | ============ 352 | 353 | Logstalgia - web server access log visualization 354 | Copyright (C) 2008 Andrew Caudwell 355 | 356 | This program is free software: you can redistribute it and/or modify 357 | it under the terms of the GNU General Public License as published by 358 | the Free Software Foundation, either version 3 of the License, or 359 | (at your option) any later version. 360 | 361 | This program is distributed in the hope that it will be useful, 362 | but WITHOUT ANY WARRANTY; without even the implied warranty of 363 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 364 | GNU General Public License for more details. 365 | 366 | You should have received a copy of the GNU General Public License 367 | along with this program. If not, see . 368 | -------------------------------------------------------------------------------- /THANKS: -------------------------------------------------------------------------------- 1 | Many thanks to Francois Marier for anwering my many packaging and licensing 2 | questions and for sponsoring my program into Debian. 3 | 4 | Cheers to everyone at Catalyst IT for their support and encouragement. 5 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | if (autoreconf -f -i) ; then 3 | echo "autoreconf ran successfully." 4 | echo "Initializing submodules..." 5 | if (git submodule init) ; then 6 | echo "Updating submodules..." 7 | if (git submodule update --init --recursive) ; then 8 | echo "Run './configure && make' to continue." 9 | else 10 | echo "Error: could not update submodules!" 11 | fi 12 | else 13 | echo "Error: could not initialize submodules (hint: delete the src/core directory if it exists and try again)" 14 | fi 15 | else 16 | echo "Running autoreconf failed, please make sure you have autoconf installed." 17 | fi 18 | -------------------------------------------------------------------------------- /cmd/logstalgia: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | LOGSTALGIA_CMD_DIR=`dirname "$0"` 3 | "$LOGSTALGIA_CMD_DIR/../logstalgia.exe" "$@" 4 | -------------------------------------------------------------------------------- /cmd/logstalgia.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | "%~dp0\..\logstalgia.exe" %* 3 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ(2.61) 5 | 6 | AC_INIT(Logstalgia, 1.1.4, [acaudwell@gmail.com]) 7 | AC_CONFIG_AUX_DIR([build-aux]) 8 | AC_CONFIG_SRCDIR([src/main.cpp]) 9 | 10 | AM_INIT_AUTOMAKE([dist-bzip2 foreign subdir-objects]) 11 | 12 | AC_CANONICAL_HOST 13 | 14 | # Checks for programs. 15 | AC_PROG_SED 16 | AC_PROG_CXX 17 | AC_LANG(C++) 18 | 19 | #Disable X11 on Macs unless required 20 | AS_IF([test "$with_x" != yes], [ 21 | case "$host_os" in 22 | darwin*) 23 | with_x="no" 24 | ;; 25 | esac 26 | ], []) 27 | 28 | #GL 29 | AX_CHECK_GL 30 | AX_CHECK_GLU 31 | CXXFLAGS="$CXXFLAGS $GL_CFLAGS $GLU_CFLAGS" 32 | CPPFLAGS="$CPPFLAGS $GL_CFLAGS $GLU_CFLAGS" 33 | LIBS="$LIBS $GL_LIBS $GLU_LIBS" 34 | 35 | PKG_CHECK_MODULES([FT2], [freetype2 >= 9.0.3]) 36 | PKG_CHECK_MODULES([PCRE2], [libpcre2-8]) 37 | PKG_CHECK_MODULES([GLEW], [glew]) 38 | PKG_CHECK_MODULES([SDL2], [sdl2 SDL2_image]) 39 | PKG_CHECK_MODULES([PNG], [libpng >= 1.2]) 40 | 41 | CPPFLAGS="${CPPFLAGS} ${FT2_CFLAGS} ${PCRE2_CFLAGS} ${GLEW_CFLAGS} ${SDL2_CFLAGS} ${PNG_CFLAGS}" 42 | LIBS="${LIBS} ${FT2_LIBS} ${PCRE2_LIBS} ${GLEW_LIBS} ${SDL2_LIBS} ${PNG_LIBS}" 43 | 44 | AC_CHECK_FUNCS([IMG_LoadPNG_RW], , AC_MSG_ERROR([SDL2_image with PNG support required. Please see INSTALL])) 45 | AC_CHECK_FUNCS([IMG_LoadJPG_RW], , AC_MSG_ERROR([SDL2_image with JPEG support required. Please see INSTALL])) 46 | 47 | #BOOST 48 | AX_BOOST_BASE([1.46], , AC_MSG_ERROR(Boost Filesystem >= 1.46 is required. Please see INSTALL)) 49 | AX_BOOST_SYSTEM 50 | AX_BOOST_FILESYSTEM 51 | 52 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" 53 | LIBS="$LIBS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB" 54 | 55 | #GLM 56 | AC_CHECK_HEADER([glm/glm.hpp],, AC_MSG_ERROR(GLM headers are required. Please see INSTALL)) 57 | 58 | #see if ttf-font-dir option is enabled 59 | AC_ARG_ENABLE(ttf-font-dir,[AS_HELP_STRING([--enable-ttf-font-dir=DIR],[directory containing GNU FreeFont TTF fonts])],[sdlappfontdir="$enableval"],[sdlappfontdir=""]) 60 | AM_CONDITIONAL([FONTDIR], [test "x$sdlappfontdir" != "x"]) 61 | AC_SUBST(sdlappfontdir) 62 | 63 | AC_CONFIG_FILES([Makefile]) 64 | AC_OUTPUT 65 | -------------------------------------------------------------------------------- /data/ball.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acaudwell/Logstalgia/8853a406febe10854a973b598712b0e69076d0d7/data/ball.tga -------------------------------------------------------------------------------- /data/fonts/FreeMonoBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acaudwell/Logstalgia/8853a406febe10854a973b598712b0e69076d0d7/data/fonts/FreeMonoBold.ttf -------------------------------------------------------------------------------- /data/fonts/FreeSerif.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acaudwell/Logstalgia/8853a406febe10854a973b598712b0e69076d0d7/data/fonts/FreeSerif.ttf -------------------------------------------------------------------------------- /data/fonts/README: -------------------------------------------------------------------------------- 1 | -*-text-*- 2 | GNU FreeFont 3 | 4 | The GNU FreeFont project aims to provide a useful set of free scalable 5 | (i.e., OpenType) fonts covering as much as possible of the ISO 10646/Unicode 6 | UCS (Universal Character Set). 7 | 8 | Statement of Purpose 9 | -------------------- 10 | 11 | The practical reason for putting glyphs together in a single font face is 12 | to conveniently mix symbols and characters from different writing systems, 13 | without having to switch fonts. 14 | 15 | Coverage 16 | -------- 17 | 18 | FreeFont covers the following character ranges 19 | * Latin, Cyrillic, and Arabic, with supplements for many languages 20 | * Greek, Hebrew, Armenian, Georgian, Thaana, Syriac 21 | * Devanagari, Bengali, Gujarati, Gurmukhi, Sinhala, Tamil, Malayalam 22 | * Thai, Tai Le, Kayah Li, Hanunóo, Buginese 23 | * Cherokee, Unified Canadian Aboriginal Syllabics 24 | * Ethiopian, Tifnagh, Vai, Osmanya, Coptic 25 | * Glagolitic, Gothic, Runic, Ugaritic, Old Persian, Phoenician, Old Italic 26 | * Braille, International Phonetic Alphabet 27 | * currency symbols, general punctuation and diacritical marks, dingbats 28 | * mathematical symbols, including much of the TeX repertoire of symbols 29 | * technical symbols: APL, OCR, arrows, 30 | * geometrical shapes, box drawing 31 | * musical symbols, gaming symbols, miscellaneous symbols 32 | etc. 33 | For more detail see 34 | 35 | Editing 36 | ------- 37 | 38 | The free outline font editor, George Williams' FontForge 39 | is used for editing the fonts. 40 | 41 | Design Issues 42 | ------------- 43 | 44 | Which font shapes should be made? Historical style terms like Renaissance 45 | or Baroque letterforms cannot be applied beyond Latin/Cyrillic/Greek 46 | scripts to any greater extent than Kufi or Nashki can be applied beyond 47 | Arabic script; "italic" is strictly meaningful only for Latin letters, 48 | although many scripts such as Cyrillic have a history with "cursive" and 49 | many others with "oblique" faces. 50 | 51 | However, most modern writing systems have typographic formulations for 52 | contrasting uniform and modulated character stroke widths, and since the 53 | advent of the typewriter, most have developed a typographic style with 54 | uniform-width characters. 55 | 56 | Accordingly, the FreeFont family has one monospaced - FreeMono - and two 57 | proportional faces (one with uniform stroke - FreeSans - and one with 58 | modulated stroke - FreeSerif). 59 | 60 | The point of having characters from different writing systems in one font 61 | is that mixed text should look good, and so each FreeFont face contains 62 | characters of similar style and weight. 63 | 64 | Licensing 65 | --------- 66 | 67 | Free UCS scalable fonts is free software; you can redistribute it and/or 68 | modify it under the terms of the GNU General Public License as published 69 | by the Free Software Foundation; either version 3 of the License, or 70 | (at your option) any later version. 71 | 72 | The fonts are distributed in the hope that they will be useful, but 73 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 74 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 75 | for more details. 76 | 77 | You should have received a copy of the GNU General Public License along 78 | with this program; if not, write to the Free Software Foundation, Inc., 79 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 80 | 81 | As a special exception, if you create a document which uses this font, and 82 | embed this font or unaltered portions of this font into the document, this 83 | font does not by itself cause the resulting document to be covered by the 84 | GNU General Public License. This exception does not however invalidate any 85 | other reasons why the document might be covered by the GNU General Public 86 | License. If you modify this font, you may extend this exception to your 87 | version of the font, but you are not obligated to do so. If you do not 88 | wish to do so, delete this exception statement from your version. 89 | 90 | Files and their suffixes 91 | ------------------------ 92 | 93 | The files with .sfd (Spline Font Database) are in FontForge's native format. 94 | They may be used to modify the fonts. 95 | 96 | TrueType fonts are the files with the .ttf (TrueType Font) suffix. These 97 | are ready to use in Linux/Unix, on Apple Mac OS, and on Microsoft Windows 98 | systems. 99 | 100 | OpenType fonts (with suffix .otf) are preferred for use on Linux/Unix, 101 | but *not* for recent Microsoft Windows systems. 102 | See the INSTALL file for more information. 103 | 104 | Web Open Font Format files (with suffix .woff) are for use in Web sites. 105 | See the webfont_guidelines.txt for further information. 106 | 107 | Further information 108 | ------------------- 109 | 110 | Home page of GNU FreeFont: 111 | http://www.gnu.org/software/freefont/ 112 | 113 | More information is at the main project page of Free UCS scalable fonts: 114 | http://savannah.gnu.org/projects/freefont/ 115 | 116 | To report problems with GNU FreeFont, it is best to obtain a Savannah 117 | account and post reports using that account on 118 | https://savannah.gnu.org/bugs/ 119 | 120 | Public discussions about GNU FreeFont may be posted to the mailing list 121 | freefont-bugs@gnu.org 122 | 123 | -------------------------------------------------------------------------- 124 | Original author: Primoz Peterlin 125 | Current administrator: Steve White 126 | 127 | $Id: README,v 1.10 2011-06-12 07:14:12 Stevan_White Exp $ 128 | -------------------------------------------------------------------------------- /data/glow.tga: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acaudwell/Logstalgia/8853a406febe10854a973b598712b0e69076d0d7/data/glow.tga -------------------------------------------------------------------------------- /data/logstalgia.1: -------------------------------------------------------------------------------- 1 | .TH Logstalgia 1 2 | .SH NAME 3 | Logstalgia - a web server access log visualization tool 4 | .SH SYNOPSIS 5 | \fIlogstalgia\fR 6 | [options] logfile 7 | .SH DESCRIPTION 8 | \fIlogstalgia\fR 9 | is a visualization tool that replays or streams web server access logs as a retro arcade game simulation. 10 | .SH REQUIREMENTS 11 | \fIlogstalgia\fR's display is rendered using OpenGL and requires a 3D accelerated video card to run. 12 | 13 | Logstalgia supports several standardized access.log formats used by web servers such as Apache and Nginx (see 'SUPPORTED LOG FORMATS' below). 14 | 15 | As \fIlogstalgia\fR is designed to playback logs in real time you will need a log from a fairly busy webserver to achieve interesting results (eg 100s of requests each minute). 16 | .SH OPTIONS 17 | .TP 18 | \fB\-f\fR 19 | Fullscreen. 20 | .TP 21 | \fB\-WIDTHxHEIGHT\fR 22 | Set the window size. If \-f is also supplied, will attempt to set the video mode to this also. Add ! to make the window non-resizable. 23 | .TP 24 | \fB\-\-screen SCREEN\fR 25 | Set the number of the screen to display on. 26 | .TP 27 | \fB\-\-high\-dpi\fR 28 | Request a high DPI display when creating the window. 29 | 30 | On some platforms such as MacOS, the window resolution is specified in points instead of pixels. 31 | The \-\-high-dpi flag may be required to access some higher resolutions. 32 | 33 | E.g. requesting a high DPI 800x600 window may produce a window that is 1600x1200 pixels. 34 | .TP 35 | \fB\-\-window\-position XxY\fR 36 | Initial window position on your desktop which may be made up of multiple monitors. 37 | 38 | This will override the screen setting so don't specify both. 39 | .TP 40 | \fB\-\-frameless\fR 41 | Frameless window. 42 | .TP 43 | \fB\-\-title TITLE\fR 44 | Set a title. 45 | .TP 46 | \fB\-b, \-\-background\fR 47 | Background colour in hex. 48 | .TP 49 | \fB\-x \-\-full\-hostnames\fR 50 | Show full request ip/hostname. 51 | .TP 52 | \fB\-s, \-\-simulation-speed\fR 53 | Simulation speed. Defaults to 1 (1 second-per-second). 54 | .TP 55 | \fB\-p, \-\-pitch-speed\fR 56 | Speed balls travel across the screen (defaults to 0.15). 57 | .TP 58 | \fB\-u, \-\-update\-rate\fR 59 | Page Summary update speed. Defaults to 5 (5 seconds). 60 | .TP 61 | \fB\-g name,(HOST|URI|CODE)=regex[,SEP=chars][,MAX=n][,ABBR=n],percent[,colour]\fR 62 | Creates a new named summarizer group for requests for which a specified attribute (HOST, URI or response CODE) matches a regular expression. Percent specifies a vertical percentage of screen to use. 63 | 64 | SEP=chars can specify a list of separator characters (e.g. /) to split on. The default separator is /. 65 | 66 | MAX=n specifies the max depth into the path to be displayed. (e.g. MAX=1 would show only root directory names of paths). By default there is 0 (no limit). 67 | 68 | ABBR=n specifies the minimum depth at which to allow partially abbreviated strings. The default is 0 (allow). -1 to disallow. 69 | 70 | A colour may optionally be supplied in hexadecimal format (eg FF0000 for red) which will be applied to all labels and request balls matched to the group. 71 | 72 | Examples: 73 | 74 | \-g "HTML,URI=html?$,30" 75 | \-g "Lan,HOST=^192,30" 76 | \-g "Success,CODE=^[23],30" 77 | 78 | If no groups are specified, the default groups are Images (image files), CSS (.css files) and Scripts (.js files). 79 | 80 | If there is enough space remaining a catch-all group 'Misc' will appear as the last group. 81 | .TP 82 | \fB\-\-address\-separators CHARS\fR 83 | List of address separator characters. Defaults to '.:'. 84 | .TP 85 | \fB\-\-address\-max\-depth DEPTH\fR 86 | Maximum depth to display in address summarizer. 0 for no maximum. 87 | .TP 88 | \fB\-\-address\-abbr\-depth DEPTH\fR 89 | Minimum abbreviation depth of address summarizer. 0 to always allow abbreviations, -1 to never abbreviate. 90 | .TP 91 | \fB\-\-path\-separators CHARS\fR 92 | Default list of path separator characters. Defaults to /. 93 | .TP 94 | \fB\-\-path\-max\-depth DEPTH\fR 95 | Default maximum path depth shown in the summarizer. 0 for no maximum. 96 | .TP 97 | \fB\-\-path\-abbr\-depth DEPTH\fR 98 | Default minimum path abbreviation depth. 0 to always allow abbreviations, -1 to never abbreviate. 99 | .TP 100 | \fB\-\-paddle\-mode MODE\fR 101 | Paddle mode (pid, vhost, single). 102 | 103 | \fBvhost\fR \- separate paddle for each virtual host in the log file. 104 | 105 | \fBpid\fR \- separate paddle for each process id in the log file. 106 | 107 | \fBsingle\fR \- single paddle (the default). 108 | .TP 109 | \fB\-\-paddle\-position POSITION\fR 110 | Paddle position as a fraction of the view width (0.25 - 0.75). 111 | .TP 112 | \fB\-\-display\-fields REQUEST_FIELDS\fR 113 | List of one or more request fields that are shown when the user hovers the mouse over an individual request: 114 | 115 | path \- the path of the resource requested 116 | hostname \- hostname or IP address 117 | response_size \- size of the response in bytes 118 | response_code \- response code 119 | method \- method 120 | protocol \- protocol 121 | timestamp \- timestamp of request 122 | referrer \- referrer URL of the request 123 | user_agent \- user agent 124 | vhost \- virtual host name 125 | log_entry \- full log entry 126 | pid \- the pid of the instance that handled the request 127 | 128 | Separate multiple fields with commas (eg "path,hostname") 129 | .TP 130 | \fB\-\-sync\fR 131 | Read from STDIN, ignoring entries before the current time. 132 | .TP 133 | \fB\-\-from, \-\-to "YYYY\-MM\-DD hh:mm:ss +tz"\fR 134 | Show entries from a specific time period. 135 | 136 | If a time zone offset isn't specified the local time zone is used. 137 | 138 | Example accepted formats: 139 | 140 | "2012-06-30" 141 | "2012-06-30 12:00" 142 | "2012-06-30 12:00:00 +12" 143 | .TP 144 | \fB\-\-start\-position POSITION\fR 145 | Begin at some position in the log file (between 0.0 and 1.0). 146 | .TP 147 | \fB\-\-stop\-position POSITION\fR 148 | Stop at some position. 149 | .TP 150 | \fB\-\-no\-bounce\fR 151 | No bouncing. 152 | .TP 153 | \fB\-\-hide\-response\-code\fR 154 | Hide response code. 155 | .TP 156 | \fB\-\-hide\-paddle\fR 157 | Hide paddle. 158 | .TP 159 | \fB\-\-hide\-paddle\-tokens\fR 160 | Hide paddle tokens shown in multi-paddle modes. 161 | .TP 162 | \fB\-\-hide\-url\-prefix\fR 163 | Hide URL protocol and hostname prefix of requests. 164 | .TP 165 | \fB\-\-disable\-auto\-skip\fR 166 | Disable automatic skipping of empty time periods. 167 | .TP 168 | \fB\-\-disable\-progress\fR 169 | Disable the progress bar. 170 | .TP 171 | \fB\-\-disable\-glow\fR 172 | Disable the glow effect. 173 | .TP 174 | \fB\-\-font\-size SIZE\fR 175 | Font size. 176 | .TP 177 | \fB\-\-glow\-duration\fR 178 | Duration of the glow (between 0.0 and 1.0). 179 | .TP 180 | \fB\-\-glow\-multiplier\fR 181 | Adjust the amount of glow. 182 | .TP 183 | \fB\-\-glow\-intensity\fR 184 | Intensity of the glow. 185 | .TP 186 | \fB\-o, -\-output\-ppm\-stream FILE\fR 187 | Write frames as PPM to a file ('\-' for STDOUT). 188 | .TP 189 | \fB\-r, -\-output\-framerate FPS\fR 190 | Framerate of output (used with \-\-output\-ppm\-stream). 191 | .TP 192 | \fB\-\-load\-config CONFIG_FILE\fR 193 | Load a config file. 194 | .TP 195 | \fB\-\-save\-config CONFIG_FILE\fR 196 | Save a config file with the current options. 197 | .TP 198 | \fB\-\-detect\-changes\fR 199 | Automatically reload config file when it is modified. 200 | .TP 201 | \fBlogfile\fR 202 | The path to the access log file to read or '\-' if you wish to supply log entries via STDIN. 203 | 204 | .SH EXAMPLES 205 | 206 | Watch an example access.log using the default settings: 207 | 208 | .ti 10 209 | \fIlogstalgia\fR SDLAPP_RESOURCE_DIR/example.log 210 | 211 | Watch the live access.log, starting from the most recent batch of entries in the log (requires tail). Note than '\-' at the end is required for 212 | \fIlogstalgia\fR 213 | to know it needs to read from STDIN: 214 | 215 | .ti 10 216 | tail \-f /var/log/apache2/access.log | \fIlogstalgia\fR \- 217 | 218 | To follow the log in real time, use the \-\-sync option. This will start reading from the next entry received on STDIN: 219 | 220 | .ti 10 221 | tail \-f /var/log/apache2/access.log | \fIlogstalgia\fR \-\-sync 222 | 223 | Watch a remote access.log via ssh: 224 | 225 | .ti 10 226 | ssh user@example.com tail \-f /var/log/apache2/access.log | \fIlogstalgia\fR \-\-sync 227 | 228 | .SH SUPPORTED LOG FORMATS 229 | 230 | Logstalgia supports the following standardized log formats used by web servers like Apache and Nginx: 231 | 232 | .ti 10 233 | NCSA Common Log Format (CLF) 234 | .ti 10 235 | "%h %l %u %t \\"%r\\" %\>s %b" 236 | 237 | .ti 10 238 | NCSA Common Log Format with Virtual Host 239 | .ti 10 240 | "%v %h %l %u %t \\"%r\\" %\>s %b" 241 | 242 | .ti 10 243 | NCSA extended/combined log format 244 | .ti 10 245 | "%h %l %u %t \\"%r\\" %\>s %b \\"%{Referer}i\\" \\"%{User-agent}i\\"" 246 | 247 | .ti 10 248 | NCSA extended/combined log format with Virtual Host 249 | .ti 10 250 | "%v %h %l %u %t \\"%r\\" %\>s %b \\"%{Referer}i\\" \\"%{User-agent}i\\"" 251 | 252 | The process id (%P), or some other identifier, may be included as an additional field at the end of the entry. This can be used with '\-\-paddle\-mode pid' where a separate paddle will be created for each unique value in this field. 253 | 254 | .SH CUSTOM LOG FORMAT 255 | 256 | Logstalgia now supports a pipe ('|') delimited custom log file format: 257 | 258 | .ti 10 259 | timestamp - unix timestamp of the request date. 260 | .ti 10 261 | hostname - hostname of the request 262 | .ti 10 263 | path - path requested 264 | .ti 10 265 | response_code - the response code from the webserver (eg 200) 266 | .ti 10 267 | response_size - the size of the response in bytes 268 | 269 | The following are optional: 270 | 271 | .ti 10 272 | success - 1 or 0 to indicate if successful 273 | .ti 10 274 | response_colour - response colour in hexidecial (#FFFFFF) format 275 | .ti 10 276 | referrer url - the referrer url 277 | .ti 10 278 | user agent - the user agent 279 | .ti 10 280 | virtual host - the virtual host (to use with \-\-paddle-mode vhost) 281 | .ti 10 282 | pid - process id or some other identifier (\-\-paddle-mode pid) 283 | 284 | If success or response_colour are not provided, they will be derived from the response_code using the normal HTTP conventions (code < 400 = success). 285 | 286 | .SH RECORDING VIDEOS 287 | 288 | See the guide on the homepage for examples of recording videos with Logstalgia: 289 | 290 | .ti 10 291 | https://github.com/acaudwell/Logstalgia/wiki/Videos 292 | 293 | .SH INTERFACE 294 | The time shown in the top left of the screen is set initially from the first log entry read and is incremented according to the simulation speed (\-s). 295 | 296 | The counter in the bottom right hand corner shows the number of requests displayed since the start of the current session. 297 | 298 | Pressing space at any time will pause/unpause the simulation. While paused you may use the mouse to inspect the detail of individual requests. 299 | 300 | You can click on summarizer group entries on the left and right side of the screen to filter to requests matching that entry. Click on the filter description to remove the filter. 301 | 302 | Interactive keyboard commands: 303 | .sp 304 | .ti 10 305 | (q) Debug Information 306 | .ti 10 307 | (c) Displays Logstalgia logo 308 | .ti 10 309 | (n) Jump forward in time to next log entry. 310 | .ti 10 311 | (+-) Adjust simulation speed. 312 | .ti 10 313 | (<>) Adjust pitch speed. 314 | .ti 10 315 | (F5) Reload config 316 | .ti 10 317 | (F11) Window frame toggle 318 | .ti 10 319 | (F12) Screenshot 320 | .ti 10 321 | (Alt+Enter) Fullscreen toggle 322 | .ti 10 323 | (Ctrl+S) Save config 324 | .ti 10 325 | (Home/End) Adjust address summarizer maximum depth 326 | .ti 10 327 | (Page Up/Down) Adjust group summarizer maximum depth 328 | .ti 10 329 | (Ctrl+Home/End) Adjust address summarizer abbreviation depth 330 | .ti 10 331 | (Ctrl+Page Up/Down) Adjust group summarizer abbreviation depth 332 | .ti 10 333 | (ESC) Quit 334 | 335 | .SH AUTHOR 336 | .nf 337 | Written by Andrew Caudwell 338 | 339 | Project Homepage: http://logstalgia.io 340 | .SH COPYRIGHT 341 | .nf 342 | Copyright (C) 2008 Andrew Caudwell (acaudwell@gmail.com) 343 | 344 | This program is free software; you can redistribute it and/or 345 | modify it under the terms of the GNU General Public License 346 | as published by the Free Software Foundation; either version 347 | 3 of the License, or (at your option) any later version. 348 | 349 | This program is distributed in the hope that it will be useful, 350 | but WITHOUT ANY WARRANTY; without even the implied warranty of 351 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 352 | GNU General Public License for more details. 353 | 354 | You should have received a copy of the GNU General Public License 355 | along with this program. If not, see . 356 | .fi 357 | .SH ACKNOWLEDGEMENTS 358 | .nf 359 | Catalyst IT (catalyst.net.nz) 360 | 361 | For supporting the development and promotion of Logstalgia! 362 | .fi 363 | -------------------------------------------------------------------------------- /dev/.gitignore: -------------------------------------------------------------------------------- 1 | builds/ 2 | -------------------------------------------------------------------------------- /dev/bin/build_tar.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | #copy stuff we want to go into the source tar ball 3 | 4 | use strict; 5 | use warnings; 6 | 7 | 8 | use FindBin; 9 | use File::Path; 10 | use File::Copy; 11 | use Date::Format; 12 | use Getopt::Long qw(GetOptions); 13 | use Cwd; 14 | 15 | my $APP_NAME = 'logstalgia'; 16 | 17 | sub app_version { 18 | my $version = `cat $FindBin::Bin/../../src/settings.h | grep LOGSTALGIA_VERSION`; 19 | $version =~ /"([^"]+)"/ or die("could not determine version\n"); 20 | $version = $1; 21 | return $version; 22 | } 23 | 24 | my $VERSION = app_version(); 25 | 26 | my @exclusions = ( 27 | qr{^/autogen\.sh$}, 28 | qr{^/cmd/}, 29 | qr{^/config.status$}, 30 | qr{^/config.log$}, 31 | qr{^/logstalgia$}, 32 | qr{^/dev/}, 33 | qr{^/logs/}, 34 | qr{/\.}, 35 | qr{Makefile$}, 36 | qr{\.o$}, 37 | qr{^/todo.txt$}, 38 | qr{^/build-stamp$}, 39 | qr{^/autom4te}, 40 | qr{^/src/core/README$}, 41 | qr{^/src/core/ui/}, 42 | ); 43 | 44 | my @inclusions = ( 45 | qr{^/logstalgia\.pro$}, 46 | qr{^/ChangeLog$}, 47 | qr{^/THANKS$}, 48 | qr{^/COPYING$}, 49 | qr{^/INSTALL$}, 50 | qr{^/README$}, 51 | qr{/Makefile\.in$}, 52 | qr{/Makefile\.am$}, 53 | qr{^/aclocal\.m4$}, 54 | qr{^/m4/.+\.m4$}, 55 | qr{^/configure(?:\.ac)?$}, 56 | qr{^/src/.+\.(?:cpp|h|cc|hh)$}, 57 | qr{^/data/.+\.(?:png|tga|ttf|1)$}, 58 | qr{^/data/fonts/README$}, 59 | qr{^/data/example\.log$}, 60 | qr{^/build-aux/(?:compile|config.(?:guess|sub)|depcomp|install-sh|missing)$}, 61 | ); 62 | 63 | my $tmp_path = "/var/tmp/$APP_NAME-$VERSION"; 64 | 65 | system("rm -r $tmp_path") if -d $tmp_path; 66 | mkpath($tmp_path) or die("failed to make temp folder $tmp_path"); 67 | 68 | chdir("$FindBin::Bin/../../"); 69 | 70 | my @files = `find .`; 71 | 72 | #check configure.ac has been updated 73 | unless(`cat configure.ac` =~ /AC_INIT\(Logstalgia, $VERSION,/) { 74 | die("configure.ac does not mention current version number\n"); 75 | } 76 | 77 | #check ChangeLog has been updated 78 | unless(`cat ChangeLog` =~ /^$VERSION:/) { 79 | die("ChangeLog does not mention current version number\n"); 80 | } 81 | 82 | #if Makefile exists, do distclean 83 | if(-e 'Makefile') { 84 | if(system("make distclean") != 0) { 85 | die("make distclean failed: $!\n"); 86 | } 87 | } 88 | 89 | #reconfigure 90 | if(system("autoreconf -f -i -v") != 0) { 91 | die("autoreconf failed: $!\n"); 92 | } 93 | 94 | foreach my $file (@files) { 95 | $file =~ s/[\r\n]+//; 96 | $file =~ s/^\.//; 97 | 98 | (my $relfile = $file) =~ s{^/}{}; 99 | (my $dir = $file) =~ s{[^/]+$}{/}; 100 | 101 | next if $file =~ /^\s*$/; 102 | next if -d $relfile; 103 | 104 | next if grep { $file =~ $_ } @exclusions; 105 | 106 | unless(grep { $file =~ $_ } @inclusions) { 107 | warn "nothing known about $file\n"; 108 | next; 109 | } 110 | 111 | mkpath("$tmp_path/$dir"); 112 | if(system("cp", "$relfile", "$tmp_path/$relfile") != 0) { 113 | die("error copying $file to $tmp_path/$relfile: $? $!\n"); 114 | } 115 | } 116 | 117 | my $current_dir = cwd; 118 | chdir("/var/tmp/"); 119 | 120 | my $archive = "$APP_NAME-$VERSION.tar.gz"; 121 | 122 | if(system("tar -czf $archive $APP_NAME-$VERSION") !=0) { 123 | die("failed to make archive $archive"); 124 | } 125 | 126 | unlink("$FindBin::Bin/../builds/$archive"); 127 | 128 | my $builds_dir = "$FindBin::Bin/../builds/"; 129 | 130 | system('mkdir', '-p', $builds_dir); 131 | 132 | unlink("$builds_dir/$archive") if -e "$builds_dir/$archive"; 133 | 134 | move("$archive", $builds_dir); 135 | system("rm -r $tmp_path"); 136 | 137 | print "Built $archive\n"; 138 | -------------------------------------------------------------------------------- /dev/bin/build_win64.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # windows archive + installer generator 3 | 4 | use strict; 5 | use warnings; 6 | use FindBin; 7 | use File::Copy; 8 | 9 | my $base_dir = "$FindBin::Bin/../.."; 10 | my $build_dir = "$base_dir/../build-logstalgia-Desktop_Qt_MinGW_64bit-Release/release"; 11 | my $binaries_dir = "$base_dir/dev/win64"; 12 | 13 | my $builds_output_dir = "$base_dir/dev/builds"; 14 | 15 | sub logstalgia_version { 16 | my $version = `cat $base_dir/src/settings.h | grep LOGSTALGIA_VERSION`; 17 | $version =~ /"([^"]+)"/ or die("could not determine version\n"); 18 | $version = $1; 19 | return $version; 20 | } 21 | 22 | sub doit { 23 | my $cmd = shift; 24 | 25 | if(system($cmd) != 0) { 26 | die("command '$cmd' failed: $!"); 27 | } 28 | } 29 | 30 | sub dosify { 31 | my($src, $dest) = @_; 32 | 33 | my $content = `cat $src`; 34 | $content =~ s/\r?\n/\r\n/g; 35 | 36 | open OUTPUT, ">$dest" or die("$!"); 37 | print OUTPUT $content; 38 | close OUTPUT; 39 | } 40 | 41 | sub update_binaries { 42 | copy("$build_dir/logstalgia.exe", "$binaries_dir/logstalgia.exe") or die("failed to copy $build_dir/logstalgia.exe: $!\n"); 43 | 44 | chdir($binaries_dir) or die("failed to change directory to $binaries_dir\n"); 45 | 46 | for my $existing_dll (glob("*.dll")) { 47 | unlink($existing_dll) or die("failed to remove existing dll $existing_dll: $!\n"); 48 | } 49 | 50 | my @dlls = `cygcheck ./logstalgia.exe | grep msys`; 51 | 52 | for my $dll (@dlls) { 53 | $dll =~ s/^\s+//g; 54 | $dll =~ s/[\r\n]//g; 55 | my($name) = $dll =~ m{\\([^\\]+\.dll)$}; 56 | 57 | warn "adding $name\n"; 58 | 59 | copy($dll, "$binaries_dir/$name") or die "failed to copy $name: $!\n"; 60 | } 61 | } 62 | 63 | my $nsis_script = q[ 64 | !define MULTIUSER_MUI 65 | !define MULTIUSER_EXECUTIONLEVEL Highest 66 | !define MULTIUSER_INSTALLMODE_COMMANDLINE 67 | !define MULTIUSER_USE_PROGRAMFILES64 68 | !define MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY "Software\Logstalgia" 69 | !define MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY "Software\Logstalgia" 70 | !define MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME "Install_Mode" 71 | !define MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME "Install_Dir" 72 | !define MULTIUSER_INSTALLMODE_INSTDIR "Logstalgia" 73 | 74 | !include "x64.nsh" 75 | !include "MultiUser.nsh" 76 | !include "MUI2.nsh" 77 | !include "LogicLib.nsh" 78 | !include "SafeEnvVarUpdate.nsh" 79 | 80 | Name "Logstalgia LOGSTALGIA_VERSION" 81 | 82 | OutFile "LOGSTALGIA_INSTALLER" 83 | 84 | !define MUI_WELCOMEFINISHPAGE_BITMAP "..\..\nsis\welcome.bmp" 85 | !define MUI_UNWELCOMEFINISHPAGE_BITMAP "..\..\nsis\welcome.bmp" 86 | 87 | !define MUI_COMPONENTSPAGE_NODESC 88 | 89 | !insertmacro MULTIUSER_PAGE_INSTALLMODE 90 | !insertmacro MUI_PAGE_WELCOME 91 | !define MUI_PAGE_HEADER_TEXT "Legal Disclaimer" 92 | !insertmacro MUI_PAGE_LICENSE "..\..\nsis\disclaimer.txt" 93 | !insertmacro MUI_PAGE_COMPONENTS 94 | !insertmacro MUI_PAGE_DIRECTORY 95 | !insertmacro MUI_PAGE_INSTFILES 96 | !insertmacro MUI_PAGE_FINISH 97 | 98 | !insertmacro MUI_LANGUAGE "English" 99 | 100 | Function .onInit 101 | ${IfNot} ${RunningX64} 102 | MessageBox MB_OK "This installer requires 64-bit Windows" 103 | Quit 104 | ${EndIf} 105 | !insertmacro MULTIUSER_INIT 106 | ReadRegStr $R0 SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\Logstalgia" "UninstallString" 107 | StrCmp $R0 "" done 108 | MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION \ 109 | "Logstalgia appears to already be installed. $\n$\nClick OK to remove the previous version and continue the installation." \ 110 | IDOK uninst 111 | Abort 112 | 113 | uninst: 114 | ClearErrors 115 | ExecWait $R0 116 | 117 | done: 118 | 119 | FunctionEnd 120 | 121 | Function un.onInit 122 | !insertmacro MULTIUSER_UNINIT 123 | FunctionEnd 124 | 125 | Section "Logstalgia" SecLogstalgia 126 | SectionIn RO 127 | 128 | LOGSTALGIA_INSTALL_LIST 129 | 130 | writeUninstaller $INSTDIR\uninstall.exe 131 | 132 | WriteRegStr SHCTX "Software\Logstalgia" ${MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME} "$INSTDIR" 133 | WriteRegStr SHCTX "Software\Logstalgia" ${MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME} "$MultiUser.InstallMode" 134 | 135 | WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\Logstalgia" "DisplayName" "Logstalgia" 136 | WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\Logstalgia" "DisplayVersion" "LOGSTALGIA_VERSION" 137 | WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\Logstalgia" "UninstallString" '"$INSTDIR\uninstall.exe"' 138 | WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\Logstalgia" "QuietUninstallString" '"$INSTDIR\uninstall.exe" /S' 139 | WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\Logstalgia" "NoModify" 1 140 | WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\Logstalgia" "NoRepair" 1 141 | 142 | SectionEnd 143 | 144 | Section "Add to PATH" SecAddtoPath 145 | 146 | ${If} $MultiUser.InstallMode == "AllUsers" 147 | ${EnvVarUpdate} $0 "PATH" "A" "HKLM" "$INSTDIR\cmd" 148 | ${ElseIf} $MultiUser.InstallMode == "CurrentUser" 149 | ${EnvVarUpdate} $0 "PATH" "A" "HKCU" "$INSTDIR\cmd" 150 | ${EndIf} 151 | 152 | SectionEnd 153 | 154 | Section "Uninstall" 155 | 156 | ${If} $MultiUser.InstallMode == "AllUsers" 157 | ${un.EnvVarUpdate} $0 "PATH" "R" "HKLM" "$INSTDIR\cmd" 158 | ${ElseIf} $MultiUser.InstallMode == "CurrentUser" 159 | ${un.EnvVarUpdate} $0 "PATH" "R" "HKCU" "$INSTDIR\cmd" 160 | ${EndIf} 161 | 162 | DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\Logstalgia" 163 | DeleteRegKey SHCTX "Software\Logstalgia" 164 | 165 | LOGSTALGIA_UNINSTALL_LIST 166 | LOGSTALGIA_UNINSTALL_DIRS 167 | 168 | Delete $INSTDIR\uninstall.exe 169 | RMDir "$INSTDIR" 170 | SectionEnd 171 | ]; 172 | 173 | my @logstalgia_files = qw( 174 | data/example.log 175 | data/ball.tga 176 | data/glow.tga 177 | data/fonts/FreeMonoBold.ttf 178 | data/fonts/FreeSerif.ttf 179 | cmd/logstalgia.cmd 180 | cmd/logstalgia 181 | ); 182 | 183 | my @logstalgia_txts = qw( 184 | README 185 | ChangeLog 186 | data/fonts/README 187 | COPYING 188 | THANKS 189 | ); 190 | 191 | my @bin_files = qw( 192 | logstalgia.exe 193 | glew32.dll 194 | libbz2-1.dll 195 | libfreetype-6.dll 196 | libgcc_s_seh-1.dll 197 | libglib-2.0-0.dll 198 | libgraphite2.dll 199 | libharfbuzz-0.dll 200 | libiconv-2.dll 201 | libintl-8.dll 202 | libjpeg-8.dll 203 | liblzma-5.dll 204 | libpcre-1.dll 205 | libpng16-16.dll 206 | libstdc++-6.dll 207 | libtiff-5.dll 208 | libwebp-7.dll 209 | libwinpthread-1.dll 210 | SDL2.dll 211 | SDL2_image.dll 212 | zlib1.dll 213 | ); 214 | 215 | my @logstalgia_dirs = qw( 216 | data 217 | data/fonts 218 | cmd 219 | ); 220 | 221 | mkdir($binaries_dir) unless -d $binaries_dir; 222 | mkdir($builds_output_dir) unless -d $builds_output_dir; 223 | 224 | my $tmp_dir = "$builds_output_dir/logstalgia-build.$$"; 225 | 226 | doit("rm $tmp_dir") if -d $tmp_dir; 227 | mkdir($tmp_dir); 228 | 229 | # create directories 230 | foreach my $dir (@logstalgia_dirs) { 231 | mkdir("$tmp_dir/$dir"); 232 | } 233 | 234 | my @logstalgia_bundle; 235 | 236 | update_binaries(); 237 | 238 | chdir("$base_dir") or die("chdir to $base_dir failed"); 239 | 240 | # copy binaries 241 | foreach my $file (@bin_files) { 242 | doit("cp $binaries_dir/$file $tmp_dir/$file"); 243 | push @logstalgia_bundle, $file; 244 | } 245 | 246 | # copy general files 247 | foreach my $file (@logstalgia_files) { 248 | doit("cp $file $tmp_dir/$file"); 249 | push @logstalgia_bundle, $file; 250 | } 251 | 252 | # convert text files 253 | foreach my $file (@logstalgia_txts) { 254 | dosify("$file", "$tmp_dir/$file.txt"); 255 | push @logstalgia_bundle, "$file.txt"; 256 | } 257 | 258 | my $version = logstalgia_version(); 259 | 260 | my $installer_name = "logstalgia-${version}.win64-setup.exe"; 261 | my $archive_name = "logstalgia-${version}.win64.zip"; 262 | 263 | my $install_list = ''; 264 | 265 | foreach my $dir ('', @logstalgia_dirs) { 266 | 267 | my @dir_files = map { my $f = $_; $f =~ s{/}{\\}g; $f; } 268 | grep { my $d = /^(.+)\// ? $1 : ''; $d eq $dir } 269 | @logstalgia_bundle; 270 | 271 | (my $output_dir = $dir) =~ s{/}{\\}g; 272 | 273 | $install_list .= "\n" . ' SetOutPath "$INSTDIR' . ( $dir ? "\\$output_dir" : "" ) . "\"\n\n"; 274 | 275 | foreach my $file (@dir_files) { 276 | $install_list .= ' File '.$file."\n"; 277 | } 278 | } 279 | 280 | my $uninstall_list = join("\n", map { my $f = $_; $f =~ s{/}{\\}g; ' Delete $INSTDIR\\'.$f } @logstalgia_bundle); 281 | my $uninstall_dirs = join("\n", map { my $d = $_; $d =~ s{/}{\\}g; ' RMDir $INSTDIR\\'.$d } reverse @logstalgia_dirs); 282 | 283 | $nsis_script =~ s/LOGSTALGIA_VERSION/$version/g; 284 | $nsis_script =~ s/LOGSTALGIA_INSTALLER/$installer_name/g; 285 | $nsis_script =~ s/LOGSTALGIA_INSTALL_LIST/$install_list/; 286 | $nsis_script =~ s/LOGSTALGIA_UNINSTALL_LIST/$uninstall_list/; 287 | $nsis_script =~ s/LOGSTALGIA_UNINSTALL_DIRS/$uninstall_dirs/; 288 | $nsis_script =~ s/\n/\r\n/g; 289 | 290 | chdir($tmp_dir) or die("failed to change directory to '$tmp_dir'\n"); 291 | 292 | # remove existing copies of the version installer if they exist 293 | 294 | unlink("../$installer_name") if -e "../$installer_name"; 295 | unlink("../$archive_name") if -e "../$archive_name"; 296 | 297 | my $output_file = "logstalgia.nsi"; 298 | 299 | open my $NSIS_HANDLE, ">$output_file" or die("failed to open $output_file: $!"); 300 | print $NSIS_HANDLE $nsis_script; 301 | close $NSIS_HANDLE; 302 | 303 | # generate installer 304 | 305 | # assert we have the long string build of NSIS 306 | doit("makensis -HDRINFO | grep -q NSIS_MAX_STRLEN=8192"); 307 | 308 | doit("makensis $output_file"); 309 | 310 | doit("rm $output_file"); 311 | doit("mv $installer_name .."); 312 | 313 | # also create zip archive 314 | 315 | doit("zip -r $archive_name *"); 316 | doit("mv $archive_name .."); 317 | 318 | chdir("$tmp_dir/.."); 319 | doit("rm -rf $tmp_dir"); 320 | -------------------------------------------------------------------------------- /dev/nsis/disclaimer.txt: -------------------------------------------------------------------------------- 1 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 3 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 4 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 5 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 6 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 7 | DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /dev/nsis/welcome.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acaudwell/Logstalgia/8853a406febe10854a973b598712b0e69076d0d7/dev/nsis/welcome.bmp -------------------------------------------------------------------------------- /dev/nsis/welcome.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acaudwell/Logstalgia/8853a406febe10854a973b598712b0e69076d0d7/dev/nsis/welcome.xcf -------------------------------------------------------------------------------- /logstalgia.pro: -------------------------------------------------------------------------------- 1 | # Note: this project file only supports building on Windows with Mingw-w64 2 | # See the INSTALL file for building instructions 3 | 4 | TEMPLATE = app 5 | CONFIG += console 6 | CONFIG -= app_bundle 7 | CONFIG -= qt 8 | DEFINES -= UNICODE 9 | 10 | CONFIG += c++11 11 | CONFIG += object_parallel_to_source 12 | 13 | gcc { 14 | QMAKE_CXXFLAGS_WARN_ON = -Wall -Wno-unused-variable -Wno-sign-compare -Wno-unused-parameter -Wno-reorder 15 | QMAKE_CXXFLAGS_DEBUG += -DASSERTS_ENABLED 16 | } 17 | 18 | mingw { 19 | QMAKE_CXXFLAGS += -Dmain=SDL_main 20 | QMAKE_LFLAGS += -mconsole 21 | 22 | INCLUDEPATH += C:\msys64\mingw64\include\SDL2 23 | INCLUDEPATH += C:\msys64\mingw64\include\freetype2 24 | 25 | LIBS += -lmingw32 -lSDL2main -lSDL2.dll 26 | LIBS += -lSDL2_image.dll -lfreetype.dll -lpcre.dll -lpng.dll -lglew32.dll -lopengl32 -lglu32 27 | LIBS += -static-libgcc -static-libstdc++ 28 | LIBS += -lcomdlg32 29 | } 30 | 31 | linux { 32 | INCLUDEPATH += /usr/include/GL \ 33 | /usr/include/SDL2 \ 34 | /usr/include/libpng12 \ 35 | /usr/include/freetype2 \ 36 | /usr/include 37 | 38 | LIBS += -lGL -lGLU -lfreetype -lpcre -lGLEW -lGLU -lGL -lSDL2_image -lSDL2 -lpng12 39 | } 40 | 41 | VPATH += ./src 42 | 43 | SOURCES += custom.cpp \ 44 | logentry.cpp \ 45 | logstalgia.cpp \ 46 | main.cpp \ 47 | ncsa.cpp \ 48 | paddle.cpp \ 49 | requestball.cpp \ 50 | settings.cpp \ 51 | slider.cpp \ 52 | summarizer.cpp \ 53 | textarea.cpp \ 54 | src/tests.cpp \ 55 | configwatcher.cpp \ 56 | core/conffile.cpp \ 57 | core/display.cpp \ 58 | core/frustum.cpp \ 59 | core/fxfont.cpp \ 60 | core/logger.cpp \ 61 | core/plane.cpp \ 62 | core/png_writer.cpp \ 63 | core/ppm.cpp \ 64 | core/quadtree.cpp \ 65 | core/regex.cpp \ 66 | core/resource.cpp \ 67 | core/sdlapp.cpp \ 68 | core/seeklog.cpp \ 69 | core/settings.cpp \ 70 | core/shader.cpp \ 71 | core/shader_common.cpp \ 72 | core/stringhash.cpp \ 73 | core/texture.cpp \ 74 | core/timezone.cpp \ 75 | core/vbo.cpp \ 76 | core/vectors.cpp 77 | 78 | HEADERS += custom.h \ 79 | logentry.h \ 80 | logstalgia.h \ 81 | ncsa.h \ 82 | paddle.h \ 83 | requestball.h \ 84 | settings.h \ 85 | slider.h \ 86 | summarizer.h \ 87 | textarea.h \ 88 | configwatcher.h \ 89 | src/tests.h \ 90 | core/bounds.h \ 91 | core/conffile.h \ 92 | core/display.h \ 93 | core/frustum.h \ 94 | core/fxfont.h \ 95 | core/gl.h \ 96 | core/logger.h \ 97 | core/pi.h \ 98 | core/plane.h \ 99 | core/png_writer.h \ 100 | core/ppm.h \ 101 | core/quadtree.h \ 102 | core/regex.h \ 103 | core/resource.h \ 104 | core/sdlapp.h \ 105 | core/seeklog.h \ 106 | core/settings.h \ 107 | core/shader.h \ 108 | core/shader_common.h \ 109 | core/stringhash.h \ 110 | core/texture.h \ 111 | core/timezone.h \ 112 | core/vbo.h \ 113 | core/vectors.h \ 114 | core/settings.h 115 | -------------------------------------------------------------------------------- /m4/ax_boost_filesystem.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_boost_filesystem.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_BOOST_FILESYSTEM 8 | # 9 | # DESCRIPTION 10 | # 11 | # Test for Filesystem library from the Boost C++ libraries. The macro 12 | # requires a preceding call to AX_BOOST_BASE. Further documentation is 13 | # available at . 14 | # 15 | # This macro calls: 16 | # 17 | # AC_SUBST(BOOST_FILESYSTEM_LIB) 18 | # 19 | # And sets: 20 | # 21 | # HAVE_BOOST_FILESYSTEM 22 | # 23 | # LICENSE 24 | # 25 | # Copyright (c) 2009 Thomas Porschberg 26 | # Copyright (c) 2009 Michael Tindal 27 | # Copyright (c) 2009 Roman Rybalko 28 | # 29 | # Copying and distribution of this file, with or without modification, are 30 | # permitted in any medium without royalty provided the copyright notice 31 | # and this notice are preserved. This file is offered as-is, without any 32 | # warranty. 33 | 34 | #serial 28 35 | 36 | AC_DEFUN([AX_BOOST_FILESYSTEM], 37 | [ 38 | AC_ARG_WITH([boost-filesystem], 39 | AS_HELP_STRING([--with-boost-filesystem@<:@=special-lib@:>@], 40 | [use the Filesystem library from boost - it is possible to specify a certain library for the linker 41 | e.g. --with-boost-filesystem=boost_filesystem-gcc-mt ]), 42 | [ 43 | if test "$withval" = "no"; then 44 | want_boost="no" 45 | elif test "$withval" = "yes"; then 46 | want_boost="yes" 47 | ax_boost_user_filesystem_lib="" 48 | else 49 | want_boost="yes" 50 | ax_boost_user_filesystem_lib="$withval" 51 | fi 52 | ], 53 | [want_boost="yes"] 54 | ) 55 | 56 | if test "x$want_boost" = "xyes"; then 57 | AC_REQUIRE([AC_PROG_CC]) 58 | CPPFLAGS_SAVED="$CPPFLAGS" 59 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" 60 | export CPPFLAGS 61 | 62 | LDFLAGS_SAVED="$LDFLAGS" 63 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" 64 | export LDFLAGS 65 | 66 | LIBS_SAVED=$LIBS 67 | LIBS="$LIBS $BOOST_SYSTEM_LIB" 68 | export LIBS 69 | 70 | AC_CACHE_CHECK(whether the Boost::Filesystem library is available, 71 | ax_cv_boost_filesystem, 72 | [AC_LANG_PUSH([C++]) 73 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], 74 | [[using namespace boost::filesystem; 75 | path my_path( "foo/bar/data.txt" ); 76 | return 0;]])], 77 | ax_cv_boost_filesystem=yes, ax_cv_boost_filesystem=no) 78 | AC_LANG_POP([C++]) 79 | ]) 80 | if test "x$ax_cv_boost_filesystem" = "xyes"; then 81 | AC_DEFINE(HAVE_BOOST_FILESYSTEM,,[define if the Boost::Filesystem library is available]) 82 | BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'` 83 | if test "x$ax_boost_user_filesystem_lib" = "x"; then 84 | for libextension in `ls -r $BOOSTLIBDIR/libboost_filesystem* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\..*,,'` ; do 85 | ax_lib=${libextension} 86 | AC_CHECK_LIB($ax_lib, exit, 87 | [BOOST_FILESYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_FILESYSTEM_LIB) link_filesystem="yes"; break], 88 | [link_filesystem="no"]) 89 | done 90 | if test "x$link_filesystem" != "xyes"; then 91 | for libextension in `ls -r $BOOSTLIBDIR/boost_filesystem* 2>/dev/null | sed 's,.*/,,' | sed -e 's,\..*,,'` ; do 92 | ax_lib=${libextension} 93 | AC_CHECK_LIB($ax_lib, exit, 94 | [BOOST_FILESYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_FILESYSTEM_LIB) link_filesystem="yes"; break], 95 | [link_filesystem="no"]) 96 | done 97 | fi 98 | else 99 | for ax_lib in $ax_boost_user_filesystem_lib boost_filesystem-$ax_boost_user_filesystem_lib; do 100 | AC_CHECK_LIB($ax_lib, exit, 101 | [BOOST_FILESYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_FILESYSTEM_LIB) link_filesystem="yes"; break], 102 | [link_filesystem="no"]) 103 | done 104 | 105 | fi 106 | if test "x$ax_lib" = "x"; then 107 | AC_MSG_ERROR(Could not find a version of the Boost::Filesystem library!) 108 | fi 109 | if test "x$link_filesystem" != "xyes"; then 110 | AC_MSG_ERROR(Could not link against $ax_lib !) 111 | fi 112 | fi 113 | 114 | CPPFLAGS="$CPPFLAGS_SAVED" 115 | LDFLAGS="$LDFLAGS_SAVED" 116 | LIBS="$LIBS_SAVED" 117 | fi 118 | ]) 119 | -------------------------------------------------------------------------------- /m4/ax_boost_system.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_boost_system.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_BOOST_SYSTEM 8 | # 9 | # DESCRIPTION 10 | # 11 | # Test for System library from the Boost C++ libraries. The macro requires 12 | # a preceding call to AX_BOOST_BASE. Further documentation is available at 13 | # . 14 | # 15 | # This macro calls: 16 | # 17 | # AC_SUBST(BOOST_SYSTEM_LIB) 18 | # 19 | # And sets: 20 | # 21 | # HAVE_BOOST_SYSTEM 22 | # 23 | # LICENSE 24 | # 25 | # Copyright (c) 2008 Thomas Porschberg 26 | # Copyright (c) 2008 Michael Tindal 27 | # Copyright (c) 2008 Daniel Casimiro 28 | # 29 | # Copying and distribution of this file, with or without modification, are 30 | # permitted in any medium without royalty provided the copyright notice 31 | # and this notice are preserved. This file is offered as-is, without any 32 | # warranty. 33 | 34 | #serial 20 35 | 36 | AC_DEFUN([AX_BOOST_SYSTEM], 37 | [ 38 | AC_ARG_WITH([boost-system], 39 | AS_HELP_STRING([--with-boost-system@<:@=special-lib@:>@], 40 | [use the System library from boost - it is possible to specify a certain library for the linker 41 | e.g. --with-boost-system=boost_system-gcc-mt ]), 42 | [ 43 | if test "$withval" = "no"; then 44 | want_boost="no" 45 | elif test "$withval" = "yes"; then 46 | want_boost="yes" 47 | ax_boost_user_system_lib="" 48 | else 49 | want_boost="yes" 50 | ax_boost_user_system_lib="$withval" 51 | fi 52 | ], 53 | [want_boost="yes"] 54 | ) 55 | 56 | if test "x$want_boost" = "xyes"; then 57 | AC_REQUIRE([AC_PROG_CC]) 58 | AC_REQUIRE([AC_CANONICAL_BUILD]) 59 | CPPFLAGS_SAVED="$CPPFLAGS" 60 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" 61 | export CPPFLAGS 62 | 63 | LDFLAGS_SAVED="$LDFLAGS" 64 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" 65 | export LDFLAGS 66 | 67 | AC_CACHE_CHECK(whether the Boost::System library is available, 68 | ax_cv_boost_system, 69 | [AC_LANG_PUSH([C++]) 70 | CXXFLAGS_SAVE=$CXXFLAGS 71 | CXXFLAGS= 72 | 73 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], 74 | [[boost::system::error_category *a = 0;]])], 75 | ax_cv_boost_system=yes, ax_cv_boost_system=no) 76 | CXXFLAGS=$CXXFLAGS_SAVE 77 | AC_LANG_POP([C++]) 78 | ]) 79 | if test "x$ax_cv_boost_system" = "xyes"; then 80 | AC_SUBST(BOOST_CPPFLAGS) 81 | 82 | AC_DEFINE(HAVE_BOOST_SYSTEM,,[define if the Boost::System library is available]) 83 | BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'` 84 | 85 | LDFLAGS_SAVE=$LDFLAGS 86 | if test "x$ax_boost_user_system_lib" = "x"; then 87 | for libextension in `ls -r $BOOSTLIBDIR/libboost_system* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\..*,,'` ; do 88 | ax_lib=${libextension} 89 | AC_CHECK_LIB($ax_lib, exit, 90 | [BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break], 91 | [link_system="no"]) 92 | done 93 | if test "x$link_system" != "xyes"; then 94 | for libextension in `ls -r $BOOSTLIBDIR/boost_system* 2>/dev/null | sed 's,.*/,,' | sed -e 's,\..*,,'` ; do 95 | ax_lib=${libextension} 96 | AC_CHECK_LIB($ax_lib, exit, 97 | [BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break], 98 | [link_system="no"]) 99 | done 100 | fi 101 | 102 | else 103 | for ax_lib in $ax_boost_user_system_lib boost_system-$ax_boost_user_system_lib; do 104 | AC_CHECK_LIB($ax_lib, exit, 105 | [BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break], 106 | [link_system="no"]) 107 | done 108 | 109 | fi 110 | if test "x$ax_lib" = "x"; then 111 | AC_MSG_ERROR(Could not find a version of the Boost::System library!) 112 | fi 113 | if test "x$link_system" = "xno"; then 114 | AC_MSG_ERROR(Could not link against $ax_lib !) 115 | fi 116 | fi 117 | 118 | CPPFLAGS="$CPPFLAGS_SAVED" 119 | LDFLAGS="$LDFLAGS_SAVED" 120 | fi 121 | ]) 122 | -------------------------------------------------------------------------------- /m4/ax_check_gl.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_check_gl.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_GL([ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Checks for an OpenGL implementation. If a valid OpenGL implementation is 12 | # found, this macro would set C preprocessor symbol HAVE_GL to 1. 13 | # 14 | # If either a valid OpenGL header or library was not found, by default the 15 | # configuration would exits on error. This behavior can be overwritten by 16 | # providing a custom "ACTION-IF-NOT-FOUND" hook. 17 | # 18 | # If the header, library was found, and been tested for compiling and 19 | # linking the configuration would export the required compiler flags to 20 | # "GL_CFLAGS" and "GL_LIBS". These two variables can also be overwritten 21 | # by user from the command line if they want to link against the library 22 | # they specified instead of having the configuration script to detect the 23 | # flags automatically. Note that having "GL_CFLAGS" or "GL_LIBS" set 24 | # doesn't mean it can compile or link with the flags, since it could be 25 | # overwritten by user. However the "HAVE_GL" symbol and "ACTION-IF-FOUND" 26 | # hook is always guaranteed to reflect a valid OpenGL implementation. 27 | # 28 | # If user didn't specify the "ACTION-IF-FOUND" hook, the configuration 29 | # would prepend "GL_CFLAGS" and "GL_LIBS" to "CFLAGS" and "LIBS", like 30 | # many other autoconf macros do. 31 | # 32 | # OpenGL is one of the libraries that has different header names on 33 | # different platforms. This macro does the header detection, and will 34 | # export the following symbol: "HAVE_GL_GL_H" for having "GL/gl.h" or 35 | # "HAVE_OPENGL_GL_H" for having "OpenGL/gl.h". To write a portable OpenGL 36 | # code, you should include OpenGL header like so: 37 | # 38 | # #if defined(HAVE_WINDOWS_H) && defined(_WIN32) 39 | # # include 40 | # #endif 41 | # #ifdef HAVE_GL_GL_H 42 | # # include 43 | # #elif defined(HAVE_OPENGL_GL_H) 44 | # # include 45 | # #else 46 | # # error no gl.h 47 | # #endif 48 | # 49 | # On the OSX platform, there's two possible OpenGL implementation. One is 50 | # the OpenGL that ships with OSX, the other comes with X11/XQuartz 51 | # (http://www.xquartz.org). To use the xquartz variant, user can use the 52 | # option --with-xquartz-gl[=path to xquartz root]. By default the 53 | # configuration will check "/opt/X11", which is the default X11 install 54 | # location on OSX. 55 | # 56 | # LICENSE 57 | # 58 | # Copyright (c) 2009 Braden McDaniel 59 | # Copyright (c) 2012 Bastien Roucaries 60 | # Copyright (c) 2016 Felix Chern 61 | # 62 | # This program is free software; you can redistribute it and/or modify it 63 | # under the terms of the GNU General Public License as published by the 64 | # Free Software Foundation; either version 2 of the License, or (at your 65 | # option) any later version. 66 | # 67 | # This program is distributed in the hope that it will be useful, but 68 | # WITHOUT ANY WARRANTY; without even the implied warranty of 69 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 70 | # Public License for more details. 71 | # 72 | # You should have received a copy of the GNU General Public License along 73 | # with this program. If not, see . 74 | # 75 | # As a special exception, the respective Autoconf Macro's copyright owner 76 | # gives unlimited permission to copy, distribute and modify the configure 77 | # scripts that are the output of Autoconf when processing the Macro. You 78 | # need not follow the terms of the GNU General Public License when using 79 | # or distributing such scripts, even though portions of the text of the 80 | # Macro appear in them. The GNU General Public License (GPL) does govern 81 | # all other use of the material that constitutes the Autoconf Macro. 82 | # 83 | # This special exception to the GPL applies to versions of the Autoconf 84 | # Macro released by the Autoconf Archive. When you make and distribute a 85 | # modified version of the Autoconf Macro, you may extend this special 86 | # exception to the GPL to apply to your modified version as well. 87 | 88 | #serial 22 89 | 90 | # example gl program 91 | m4_define([_AX_CHECK_GL_PROGRAM], 92 | [AC_LANG_PROGRAM([[ 93 | # if defined(HAVE_WINDOWS_H) && defined(_WIN32) 94 | # include 95 | # endif 96 | # ifdef HAVE_GL_GL_H 97 | # include 98 | # elif defined(HAVE_OPENGL_GL_H) 99 | # include 100 | # else 101 | # error no gl.h 102 | # endif 103 | ]],[[glBegin(0)]])]) 104 | 105 | dnl Default include : add windows.h 106 | dnl see http://www.opengl.org/wiki/Platform_specifics:_Windows 107 | dnl (acceded 20120801) 108 | AC_DEFUN([_AX_CHECK_GL_INCLUDES_DEFAULT],dnl 109 | [ 110 | AC_INCLUDES_DEFAULT 111 | [ 112 | # if defined(HAVE_WINDOWS_H) && defined(_WIN32) 113 | # include 114 | # endif 115 | ] 116 | ]) 117 | 118 | 119 | # _AX_CHECK_GL_SAVE_FLAGS(LIST-OF-FLAGS) 120 | # Use this macro before you modify the flags. 121 | # Restore the flags by _AX_CHECK_GL_RESTORE_FLAGS 122 | # 123 | # Example: _AX_CHECK_GL_SAVE_FLAGS([[CFLAGS],[LIBS]]) expands to 124 | # gl_saved_flag_cflags=$CFLAGS 125 | # gl_saved_flag_libs=$LIBS 126 | # CFLAGS="$GL_CFLAGS $CFLAGS" 127 | # LIBS="$GL_LIBS $LIBS" 128 | AC_DEFUN([_AX_CHECK_GL_SAVE_FLAGS], [ 129 | AX_SAVE_FLAGS_WITH_PREFIX([GL],[$1]) 130 | AC_LANG_PUSH([C]) 131 | ]) 132 | 133 | # _AX_CHECK_GL_RESTORE_FLAGS(LIST-OF-FLAGS) 134 | # Use this marcro to restore the flags you saved using 135 | # _AX_CHECK_GL_SAVE_FLAGS 136 | # 137 | # Example: _AX_CHECK_GL_RESTORE_FLAGS([[CFLAGS],[LIBS]]) expands to 138 | # CFLAGS="$gl_saved_flag_cflags" 139 | # LIBS="$gl_saved_flag_libs" 140 | AC_DEFUN([_AX_CHECK_GL_RESTORE_FLAGS], [ 141 | AX_RESTORE_FLAGS_WITH_PREFIX([GL],[$1]) 142 | AC_LANG_POP([C]) 143 | ]) 144 | 145 | # Check if the program compiles 146 | AC_DEFUN([_AX_CHECK_GL_COMPILE], 147 | [dnl 148 | _AX_CHECK_GL_SAVE_FLAGS([CFLAGS]) 149 | AC_COMPILE_IFELSE([_AX_CHECK_GL_PROGRAM], 150 | [ax_check_gl_compile_opengl="yes"], 151 | [ax_check_gl_compile_opengl="no"]) 152 | _AX_CHECK_GL_RESTORE_FLAGS([CFLAGS]) 153 | ]) 154 | 155 | # Compile the example program (cache) 156 | AC_DEFUN([_AX_CHECK_GL_COMPILE_CV], 157 | [dnl 158 | AC_CACHE_CHECK([for compiling a minimal OpenGL program],[ax_cv_check_gl_compile_opengl], 159 | [_AX_CHECK_GL_COMPILE() 160 | ax_cv_check_gl_compile_opengl="${ax_check_gl_compile_opengl}"]) 161 | ax_check_gl_compile_opengl="${ax_cv_check_gl_compile_opengl}" 162 | ]) 163 | 164 | # Link the example program 165 | AC_DEFUN([_AX_CHECK_GL_LINK], 166 | [dnl 167 | _AX_CHECK_GL_SAVE_FLAGS([[CFLAGS],[LIBS],[LDFLAGS]]) 168 | AC_LINK_IFELSE([_AX_CHECK_GL_PROGRAM], 169 | [ax_check_gl_link_opengl="yes"], 170 | [ax_check_gl_link_opengl="no"]) 171 | _AX_CHECK_GL_RESTORE_FLAGS([[CFLAGS],[LIBS],[LDFLAGS]]) 172 | ]) 173 | 174 | # Link the example program (cache) 175 | AC_DEFUN([_AX_CHECK_GL_LINK_CV], 176 | [dnl 177 | AC_CACHE_CHECK([for linking a minimal OpenGL program],[ax_cv_check_gl_link_opengl], 178 | [_AX_CHECK_GL_LINK() 179 | ax_cv_check_gl_link_opengl="${ax_check_gl_link_opengl}"]) 180 | ax_check_gl_link_opengl="${ax_cv_check_gl_link_opengl}" 181 | ]) 182 | 183 | 184 | # _AX_CHECK_GL_MANUAL_LIBS_GENERIC(LIBRARIES-TO-SEARCH) 185 | # Searches library provided in $1, and output the flag 186 | # $ax_check_gl_lib_opengl 187 | AC_DEFUN([_AX_CHECK_GL_MANUAL_LIBS_GENERIC], [ 188 | AS_IF([test -n "$GL_LIBS"],[], [ 189 | ax_check_gl_manual_libs_generic_extra_libs="$1" 190 | AS_IF([test "X$ax_check_gl_manual_libs_generic_extra_libs" = "X"], 191 | [AC_MSG_ERROR([AX_CHECK_GL_MANUAL_LIBS_GENERIC argument must no be empty])]) 192 | 193 | _AX_CHECK_GL_SAVE_FLAGS([CFLAGS]) 194 | AC_SEARCH_LIBS([glBegin],[$ax_check_gl_manual_libs_generic_extra_libs], [ 195 | ax_check_gl_lib_opengl="yes" 196 | break 197 | ]) 198 | AS_IF([test "X$ax_check_gl_lib_opengl"="Xyes"], 199 | [GL_LIBS="${ac_cv_search_glBegin}"]) 200 | _AX_CHECK_GL_RESTORE_FLAGS([CFLAGS]) 201 | ]) 202 | ]) 203 | 204 | # _WITH_XQUARTZ_GL 205 | # ---------------- 206 | # Provides an option in command line to specify the XQuartz installation 207 | # path on OSX, so that user can link to it instead of using the default 208 | # OSX OpenGL framework. (Mac OSX only) 209 | AC_DEFUN_ONCE([_WITH_XQUARTZ_GL],[ 210 | AC_ARG_WITH([xquartz-gl], 211 | [AS_HELP_STRING([--with-xquartz-gl@<:@=DIR@:>@], 212 | [On Mac OSX, use opengl provided by X11/XQuartz instead of the built-in framework. 213 | If enabled, the default location is @<:@DIR=/opt/X11@:>@. 214 | This option is default to false.])], 215 | [AS_IF([test "X$with_xquartz_gl"="Xyes"], 216 | [with_xquartz_gl="/opt/X11"])], 217 | [with_xquartz_gl=no]) 218 | AS_IF([test "X$with_xquartz_gl" != "Xno"], 219 | [AC_MSG_CHECKING([OSX X11 path]) 220 | AS_IF([test -e "$with_xquartz_gl"], 221 | [AC_MSG_RESULT(["$with_xquartz_gl"]) 222 | CFLAGS="-I$with_xquartz_gl/include $CFLAGS" 223 | LIBS="-L$with_xquartz_gl/lib $LIBS" 224 | ], 225 | [with_xquartz_gl=no 226 | AC_MSG_RESULT([no]) 227 | AC_MSG_WARN([--with-xquartz-gl was given, but test for X11 failed. Fallback to system framework]) 228 | ]) 229 | ]) 230 | ]) 231 | 232 | # OSX specific setup for OpenGL check 233 | AC_DEFUN([_AX_CHECK_DARWIN_GL], [ 234 | AC_REQUIRE([_WITH_XQUARTZ_GL]) 235 | AS_IF([test "x$with_xquartz_gl" != "xno"], 236 | [GL_LIBS="${GL_LIBS:--lGL}"], 237 | [GL_LIBS="${GL_LIBS:--framework OpenGL}"]) 238 | ]) 239 | 240 | 241 | # AX_CHECK_GL_LIB([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) 242 | # --------------------------------------------------------- 243 | # Checks OpenGL headers and library and provides hooks for success and failures. 244 | # When $1 is not set, this macro would modify CFLAGS and LIBS environment variables. 245 | # However, user can override this behavior by providing their own hooks. 246 | # The CFLAGS and LIBS flags required by OpenGL is always exported in 247 | # GL_CFLAGS and GL_LIBS environment variable. 248 | # 249 | # In other words, the default behavior of AX_CHECK_GL_LIB() is equivalent to 250 | # AX_CHECK_GL_LIB( 251 | # [CFLAGS="$GL_CFLAGS $CFLAGS" 252 | # LIBS="$GL_LIBS $LIBS"] 253 | # ) 254 | AC_DEFUN([AX_CHECK_GL], 255 | [AC_REQUIRE([AC_CANONICAL_HOST]) 256 | AC_REQUIRE([PKG_PROG_PKG_CONFIG]) 257 | AC_ARG_VAR([GL_CFLAGS],[C compiler flags for GL, overriding configure script defaults]) 258 | AC_ARG_VAR([GL_LIBS],[Linker flags for GL, overriding configure script defaults]) 259 | 260 | dnl --with-gl or not can be implemented outside of check-gl 261 | AS_CASE([${host}], 262 | [*-darwin*],[_AX_CHECK_DARWIN_GL], 263 | dnl some windows may support X11 opengl, and should be able to linked 264 | dnl by -lGL. However I have no machine to test it. 265 | [*-cygwin*|*-mingw*],[ 266 | _AX_CHECK_GL_MANUAL_LIBS_GENERIC([opengl32 GL gl]) 267 | AC_CHECK_HEADERS([windows.h]) 268 | ], 269 | [PKG_PROG_PKG_CONFIG 270 | PKG_CHECK_MODULES([GL],[gl], 271 | [], 272 | [_AX_CHECK_GL_MANUAL_LIBS_GENERIC([GL gl])]) 273 | ]) dnl host specific checks 274 | 275 | dnl this was cache 276 | _AX_CHECK_GL_SAVE_FLAGS([CFLAGS]) 277 | AC_CHECK_HEADERS([GL/gl.h OpenGL/gl.h], 278 | [ax_check_gl_have_headers="yes";break]) 279 | _AX_CHECK_GL_RESTORE_FLAGS([CFLAGS]) 280 | 281 | AS_IF([test "X$ax_check_gl_have_headers" = "Xyes"], 282 | [_AX_CHECK_GL_COMPILE_CV()], 283 | [no_gl=yes]) 284 | AS_IF([test "X$ax_check_gl_compile_opengl" = "Xyes"], 285 | [_AX_CHECK_GL_LINK_CV()], 286 | [no_gl=yes]) 287 | AS_IF([test "X$no_gl" = "X"], 288 | [AC_DEFINE([HAVE_GL], [1], [Defined if a valid OpenGL implementation is found.]) 289 | m4_ifval([$1], 290 | [$1], 291 | [CFLAGS="$GL_CFLAGS $CFLAGS" 292 | LIBS="$GL_LIBS $LIBS"]) 293 | ], 294 | [m4_ifval([$2], 295 | [$2], 296 | [AC_MSG_ERROR([Could not find a valid OpenGL implementation])]) 297 | ]) 298 | ]) 299 | -------------------------------------------------------------------------------- /m4/ax_check_glu.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_check_glu.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_GLU([ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Checks for GLUT. If a valid GLU implementation is found, the configure 12 | # script would export the C preprocessor symbol "HAVE_GLU=1". 13 | # 14 | # If either a valid GLU header or library was not found, by default the 15 | # configure script would exit on error. This behavior can be overwritten 16 | # by providing a custom "ACTION-IF-NOT-FOUND" hook. 17 | # 18 | # If the header, library was found, and been tested for compiling and 19 | # linking the configuration would export the required compiler flags to 20 | # "GLU_CFLAGS" and "GLU_LIBS" environment variables. These two variables 21 | # can also be overwritten by defining the environment variables before 22 | # executing the configure program. If it was predefined, configure would 23 | # not try to overwrite it, but it would still perform the compile and link 24 | # test. Only when the tests succeeded does the configure script to export 25 | # "HAVE_GLU=1" and to run "ACTION-IF-FOUND" hook. 26 | # 27 | # If user didn't specify the "ACTION-IF-FOUND" hook, the configuration 28 | # would prepend "GLU_CFLAGS" and "GLU_LIBS" to "CFLAGS" and "LIBS", like 29 | # many other autoconf macros do. 30 | # 31 | # If the header "GL/glu.h" is found, "HAVE_GL_GLU_H" is defined. If the 32 | # header "OpenGL/glu.h" is found, HAVE_OPENGL_GLU_H is defined. 33 | # 34 | # You should use something like this in your headers: 35 | # 36 | # # if defined(HAVE_WINDOWS_H) && defined(_WIN32) 37 | # # include 38 | # # endif 39 | # # if defined(HAVE_GL_GLU_H) 40 | # # include 41 | # # elif defined(HAVE_OPENGL_GLU_H) 42 | # # include 43 | # # else 44 | # # error no glu.h 45 | # # endif 46 | # 47 | # On the OSX platform, you can use the option --with-xquartz-gl to use 48 | # X11/Xquartz GLU implementation instead of the system built in GLU 49 | # framework. 50 | # 51 | # Some implementations (in particular, some versions of Mac OS X) are 52 | # known to treat the GLU tesselator callback function type as "GLvoid 53 | # (*)(...)" rather than the standard "GLvoid (*)()". If the former 54 | # condition is detected, this macro defines "HAVE_VARARGS_GLU_TESSCB". 55 | # 56 | # LICENSE 57 | # 58 | # Copyright (c) 2009 Braden McDaniel 59 | # Copyright (c) 2013 Bastien Roucaries 60 | # Copyright (c) 2016 Felix Chern 61 | # 62 | # This program is free software; you can redistribute it and/or modify it 63 | # under the terms of the GNU General Public License as published by the 64 | # Free Software Foundation; either version 2 of the License, or (at your 65 | # option) any later version. 66 | # 67 | # This program is distributed in the hope that it will be useful, but 68 | # WITHOUT ANY WARRANTY; without even the implied warranty of 69 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 70 | # Public License for more details. 71 | # 72 | # You should have received a copy of the GNU General Public License along 73 | # with this program. If not, see . 74 | # 75 | # As a special exception, the respective Autoconf Macro's copyright owner 76 | # gives unlimited permission to copy, distribute and modify the configure 77 | # scripts that are the output of Autoconf when processing the Macro. You 78 | # need not follow the terms of the GNU General Public License when using 79 | # or distributing such scripts, even though portions of the text of the 80 | # Macro appear in them. The GNU General Public License (GPL) does govern 81 | # all other use of the material that constitutes the Autoconf Macro. 82 | # 83 | # This special exception to the GPL applies to versions of the Autoconf 84 | # Macro released by the Autoconf Archive. When you make and distribute a 85 | # modified version of the Autoconf Macro, you may extend this special 86 | # exception to the GPL to apply to your modified version as well. 87 | 88 | #serial 23 89 | 90 | # example program 91 | m4_define([_AX_CHECK_GLU_PROGRAM], 92 | [AC_LANG_PROGRAM([[ 93 | # if defined(HAVE_WINDOWS_H) && defined(_WIN32) 94 | # include 95 | # endif 96 | # ifdef HAVE_GL_GLU_H 97 | # include 98 | # elif defined(HAVE_OPENGL_GLU_H) 99 | # include 100 | # else 101 | # error no glu.h 102 | # endif 103 | ]],[[gluBeginCurve(0)]])]) 104 | 105 | 106 | dnl Default include : add windows.h 107 | dnl see http://www.opengl.org/wiki/Platform_specifics:_Windows 108 | dnl (acceded 20120801) 109 | AC_DEFUN([_AX_CHECK_GLU_INCLUDES_DEFAULT],dnl 110 | [ 111 | AC_INCLUDES_DEFAULT 112 | [ 113 | # if defined(HAVE_WINDOWS_H) && defined(_WIN32) 114 | # include 115 | # endif 116 | ] 117 | ]) 118 | 119 | # check tesselation callback function signature. 120 | m4_define([_AX_CHECK_GLU_VARARGS_TESSVB_PROGRAM], 121 | [AC_LANG_PROGRAM([[ 122 | # if defined(HAVE_WINDOWS_H) && defined(_WIN32) 123 | # include 124 | # endif 125 | # ifdef HAVE_GL_GLU_H 126 | # include 127 | # elif defined(HAVE_OPENGL_GLU_H) 128 | # include 129 | # else 130 | # error no glu.h 131 | # endif 132 | ]], 133 | [[GLvoid (*func)(...); gluTessCallback(0, 0, func)]]) 134 | ]) 135 | 136 | 137 | # _AX_CHECK_GLU_SAVE_FLAGS(LIST-OF-FLAGS,[LANG]) 138 | # ---------------------------------------------- 139 | # Save the flags to shell variables. 140 | # Example: _AX_CHECK_GLU_SAVE_FLAGS([[CFLAGS],[LIBS]]) expands to 141 | # AC_LANG_PUSH([C]) 142 | # glu_saved_flag_cflags=$CFLAGS 143 | # glu_saved_flag_libs=$LIBS 144 | # CFLAGS="$GLU_CFLAGS $CFLAGS" 145 | # LIBS="$GLU_LIBS $LIBS" 146 | # 147 | # Can optionally support other LANG by specifying $2 148 | AC_DEFUN([_AX_CHECK_GLU_SAVE_FLAGS], [ 149 | m4_ifval([$2], 150 | [AC_LANG_PUSH([$2])], 151 | [AC_LANG_PUSH([C])]) 152 | AX_SAVE_FLAGS_WITH_PREFIX([GLU],[$1]) dnl defined in ax_check_gl 153 | ]) 154 | 155 | # _AX_CHECK_GLU_RESTORE_FLAGS(LIST-OF-FLAGS) 156 | # Use this marcro to restore the flags you saved using 157 | # _AX_CHECK_GLU_SAVE_FLAGS 158 | # 159 | # Example: _AX_CHECK_GLU_RESTORE_FLAGS([[CFLAGS],[LIBS]]) expands to 160 | # CFLAGS="$glu_saved_flag_cflags" 161 | # LIBS="$glu_saved_flag_libs" 162 | # AC_LANG_POP([C]) 163 | AC_DEFUN([_AX_CHECK_GLU_RESTORE_FLAGS], [ 164 | AX_RESTORE_FLAGS_WITH_PREFIX([GLU],[$1]) dnl defined in ax_check_gl 165 | m4_ifval([$2], 166 | [AC_LANG_POP([$2])], 167 | [AC_LANG_POP([C])]) 168 | ]) 169 | 170 | 171 | # Search headers and export $ax_check_glu_have_headers 172 | AC_DEFUN([_AX_CHECK_GLU_HEADERS], [ 173 | _AX_CHECK_GLU_SAVE_FLAGS([CFLAGS]) 174 | AC_CHECK_HEADERS([$1], 175 | [ax_check_glu_have_headers="yes";], 176 | [], 177 | [_AX_CHECK_GLU_INCLUDES_DEFAULT()]) 178 | _AX_CHECK_GLU_RESTORE_FLAGS([CFLAGS]) 179 | ]) 180 | 181 | 182 | # _AX_CHECK_GLU_SEARCH_LIBS(LIBS) 183 | # ------------------------------- 184 | # Search for a valid GLU lib from $1 and set 185 | # GLU_LIBS respectively 186 | AC_DEFUN([_AX_CHECK_GLU_SEARCH_LIBS], [ 187 | _AX_CHECK_GLU_SAVE_FLAGS([[CFLAGS],[LIBS]]) 188 | AC_SEARCH_LIBS([gluBeginCurve],[$1], 189 | [GLU_LIBS="${GLU_LIBS:-$ac_cv_search_gluBeginCurve}"]) 190 | _AX_CHECK_GLU_RESTORE_FLAGS([[CFLAGS],[LIBS]]) 191 | ]) 192 | 193 | # OSX specific GLU checks 194 | AC_DEFUN([_AX_CHECK_DARWIN_GLU], [ 195 | AC_REQUIRE([_WITH_XQUARTZ_GL]) 196 | AS_IF([test "x$with_xquartz_gl" != "xno"], 197 | [GLU_LIBS="${GLU_LIBS:--lGLU}"], 198 | [GLU_LIBS="${GLU_LIBS:--framework OpenGL}"]) 199 | ]) 200 | 201 | # AX_CHECK_GLU([ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND]) 202 | # ----------------------------------------------------- 203 | # Checks GLU and provides hooks for success and failures 204 | AC_DEFUN([AX_CHECK_GLU],[ 205 | AC_REQUIRE([AC_CANONICAL_HOST]) 206 | AC_REQUIRE([_WITH_XQUARTZ_GL]) 207 | AC_REQUIRE([PKG_PROG_PKG_CONFIG]) 208 | AC_ARG_VAR([GLU_CFLAGS],[C compiler flags for GLU, overriding system check]) 209 | AC_ARG_VAR([GLU_LIBS],[Linker flags for GLU, overriding system check]) 210 | 211 | dnl Setup GLU_CFLAGS and GLU_LIBS 212 | AS_CASE([${host}], 213 | [*-darwin*],[_AX_CHECK_DARWIN_GLU], 214 | [*-cygwin*],[_AX_CHECK_GLU_SEARCH_LIBS([GLU glu MesaGLU glu32]) 215 | AC_CHECK_HEADERS([windows.h])], 216 | # try first native 217 | [*-mingw*],[_AX_CHECK_GLU_SEARCH_LIBS([glu32 GLU glu MesaGLU]) 218 | AC_CHECK_HEADERS([windows.h])], 219 | [PKG_PROG_PKG_CONFIG 220 | PKG_CHECK_MODULES([GLU],[glu], 221 | [], 222 | [_AX_CHECK_GLU_SEARCH_LIBS([GLU glu MesaGLU])]) 223 | ]) 224 | 225 | AS_CASE([$host], 226 | [*-darwin*], 227 | [AS_IF([test "X$with_xquartz_gl" = "Xno"], 228 | [_AX_CHECK_GLU_HEADERS([OpenGL/glu.h])], 229 | [_AX_CHECK_GLU_HEADERS([GL/glu.h])] 230 | )], 231 | [_AX_CHECK_GLU_HEADERS([GL/glu.h])]) 232 | 233 | dnl compile test 234 | AS_IF([test "X$ax_check_glu_have_headers" = "Xyes"], 235 | [AC_CACHE_CHECK([for compiling a minimal OpenGL Utility (GLU) program], 236 | [ax_cv_check_glu_compile], 237 | [_AX_CHECK_GLU_SAVE_FLAGS([CFLAGS]) 238 | AC_COMPILE_IFELSE([_AX_CHECK_GLU_PROGRAM], 239 | [ax_cv_check_glu_compile="yes"], 240 | [ax_cv_check_glu_compile="no"]) 241 | _AX_CHECK_GLU_RESTORE_FLAGS([CFLAGS])]) 242 | ]) 243 | 244 | dnl link test 245 | AS_IF([test "X$ax_cv_check_glu_compile" = "Xyes"], 246 | [AC_CACHE_CHECK([for linking a minimal GLU program], 247 | [ax_cv_check_glu_link], 248 | [_AX_CHECK_GLU_SAVE_FLAGS([[CFLAGS],[LIBS]]) 249 | AC_LINK_IFELSE([_AX_CHECK_GLU_PROGRAM], 250 | [ax_cv_check_glu_link="yes"], 251 | [ax_cv_check_glu_link="no"]) 252 | _AX_CHECK_GLU_RESTORE_FLAGS([[CFLAGS],[LIBS]])]) 253 | ]) 254 | 255 | # 256 | # Some versions of Mac OS X include a broken interpretation of the GLU 257 | # tesselation callback function signature. 258 | AS_IF([test "X$ax_cv_check_glu_link" = "Xyes"], 259 | [AC_CACHE_CHECK([if GLU varargs tesselator is using non-standard form], 260 | [ax_cv_varargs_glu_tesscb], 261 | [_AX_CHECK_GLU_SAVE_FLAGS([CFLAGS],[C++]) 262 | AC_COMPILE_IFELSE([_AX_CHECK_GLU_VARARGS_TESSVB_PROGRAM], 263 | [ax_cv_varargs_glu_tesscb="yes"], 264 | [ax_cv_varargs_glu_tesscb="no"]) 265 | _AX_CHECK_GLU_RESTORE_FLAGS([CFLAGS],[C++])]) 266 | AS_IF([test "X$ax_cv_varargs_glu_tesscb" = "yes"], 267 | [AC_DEFINE([HAVE_VARARGS_GLU_TESSCB], [1], 268 | [Use nonstandard varargs form for the GLU tesselator callback])]) 269 | ]) 270 | 271 | dnl hook 272 | AS_IF([test "X$ax_cv_check_glu_link" = "Xyes"], 273 | [AC_DEFINE([HAVE_GLU],[1],[Defined if a valid GLU implementation is found.]) 274 | m4_ifval([$1], 275 | [$1], 276 | [CFLAGS="$GLU_CFLAGS $CFLAGS" 277 | LIBS="$GLU_LIBS $LIBS"])], 278 | [m4_ifval([$2], 279 | [$2], 280 | [AC_MSG_ERROR([Could not find a valid GLU implementation])]) 281 | ]) 282 | ]) 283 | -------------------------------------------------------------------------------- /m4/ax_check_glut.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_check_glut.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_GLUT([ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Checks for GLUT. If a valid GLUT implementation is found, the configure 12 | # script would export the C preprocessor symbol "HAVE_GLUT=1". 13 | # 14 | # If either a valid GLUT header or library was not found, by default the 15 | # configure script would exit on error. This behavior can be overwritten 16 | # by providing a custom "ACTION-IF-NOT-FOUND" hook. 17 | # 18 | # If the header, library was found, and been tested for compiling and 19 | # linking the configuration would export the required compiler flags to 20 | # "GLUT_CFLAGS" and "GLUT_LIBS" environment variables. These two variables 21 | # can also be overwritten by defining the environment variables before 22 | # executing the configure program. If it was predefined, configure would 23 | # not try to overwrite it, but it would still perform the compile and link 24 | # test. Only when the tests succeeded does the configure script to export 25 | # "HAVE_GLUT=1" and to run "ACTION-IF-FOUND" hook. 26 | # 27 | # If user didn't specify the "ACTION-IF-FOUND" hook, the configuration 28 | # would prepend "GLUT_CFLAGS" and "GLUT_LIBS" to "CFLAGS" and "LIBS", like 29 | # many other autoconf macros do. 30 | # 31 | # If the header "GL/glut.h" is found, "HAVE_GL_GLUT_H" is defined. If the 32 | # header "GLUT/glut.h" is found, HAVE_GLUT_GLUT_H is defined. 33 | # 34 | # You should use something like this in your headers: 35 | # 36 | # # if HAVE_WINDOWS_H && defined(_WIN32) 37 | # # include 38 | # # endif 39 | # # if defined(HAVE_GL_GLUT_H) 40 | # # include 41 | # # elif defined(HAVE_GLUT_GLUT_H) 42 | # # include 43 | # # else 44 | # # error no glut.h 45 | # # endif 46 | # 47 | # On the OSX platform, you can use the option --with-xquartz-gl to use 48 | # X11/Xquartz GLUT implementation instead of the system built in GLUT 49 | # framework. 50 | # 51 | # LICENSE 52 | # 53 | # Copyright (c) 2009 Braden McDaniel 54 | # Copyright (c) 2013 Bastien Roucaries 55 | # Copyright (c) 2016 Felix Chern 56 | # 57 | # This program is free software; you can redistribute it and/or modify it 58 | # under the terms of the GNU General Public License as published by the 59 | # Free Software Foundation; either version 2 of the License, or (at your 60 | # option) any later version. 61 | # 62 | # This program is distributed in the hope that it will be useful, but 63 | # WITHOUT ANY WARRANTY; without even the implied warranty of 64 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 65 | # Public License for more details. 66 | # 67 | # You should have received a copy of the GNU General Public License along 68 | # with this program. If not, see . 69 | # 70 | # As a special exception, the respective Autoconf Macro's copyright owner 71 | # gives unlimited permission to copy, distribute and modify the configure 72 | # scripts that are the output of Autoconf when processing the Macro. You 73 | # need not follow the terms of the GNU General Public License when using 74 | # or distributing such scripts, even though portions of the text of the 75 | # Macro appear in them. The GNU General Public License (GPL) does govern 76 | # all other use of the material that constitutes the Autoconf Macro. 77 | # 78 | # This special exception to the GPL applies to versions of the Autoconf 79 | # Macro released by the Autoconf Archive. When you make and distribute a 80 | # modified version of the Autoconf Macro, you may extend this special 81 | # exception to the GPL to apply to your modified version as well. 82 | 83 | #serial 17 84 | 85 | AC_DEFUN([_AX_CHECK_GLUT_SAVE_FLAGS], [ 86 | AX_SAVE_FLAGS_WITH_PREFIX([GLUT],[$1]) dnl defined in ax_check_gl 87 | AC_LANG_PUSH([C]) 88 | ]) 89 | 90 | AC_DEFUN([_AX_CHECK_GLUT_RESTORE_FLAGS], [ 91 | AX_RESTORE_FLAGS_WITH_PREFIX([GLUT],[$1]) dnl defined in ax_check_gl 92 | AC_LANG_POP([C]) 93 | ]) 94 | 95 | dnl Default include : add windows.h 96 | dnl see http://www.opengl.org/wiki/Platform_specifics:_Windows 97 | dnl (acceded 20120801) 98 | AC_DEFUN([_AX_CHECK_GLUT_INCLUDES_DEFAULT],dnl 99 | [ 100 | AC_INCLUDES_DEFAULT 101 | [ 102 | # if defined(HAVE_WINDOWS_H) && defined(_WIN32) 103 | # include 104 | # endif 105 | ] 106 | ]) 107 | 108 | m4_define([_AX_CHECK_GLUT_PROGRAM], 109 | [AC_LANG_PROGRAM([[ 110 | # if HAVE_WINDOWS_H && defined(_WIN32) 111 | # include 112 | # endif 113 | # ifdef HAVE_GL_GLUT_H 114 | # include 115 | # elif defined(HAVE_GLUT_GLUT_H) 116 | # include 117 | # else 118 | # error no glut.h 119 | # endif]], 120 | [[glutMainLoop()]])]) 121 | 122 | 123 | # _AX_CHECK_GLUT_MANUAL_LIBS_GENERIC(LIST-OF-LIBS) 124 | # ------------------------------------------------ 125 | # Searches libraries provided in $1, and export variable 126 | # $ax_check_glut_lib_glut 127 | AC_DEFUN([_AX_CHECK_GLUT_MANUAL_LIBS_GENERIC], 128 | [ 129 | _AX_CHECK_GLUT_SAVE_FLAGS([[CFLAGS],[LIBS]]) 130 | AC_SEARCH_LIBS([glutMainLoop],[$1], 131 | [GLUT_LIBS="${GLUT_LIBS:-$ac_cv_search_glutMainLoop}"]) 132 | _AX_CHECK_GLUT_RESTORE_FLAGS([[CFLAGS],[LIBS]]) 133 | ]) 134 | 135 | # Wrapper macro to check GLUT header 136 | AC_DEFUN([_AX_CHECK_GLUT_HEADER],[ 137 | _AX_CHECK_GLUT_SAVE_FLAGS([CFLAGS]) 138 | AC_CHECK_HEADERS([$1], 139 | [ax_check_glut_have_headers=yes]) 140 | _AX_CHECK_GLUT_RESTORE_FLAGS([CFLAGS]) 141 | ]) 142 | 143 | 144 | # AX_CHECK_GLUT_LIB([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) 145 | # --------------------------------------------------------- 146 | # Checks GLUT headers and library and provides hooks for success and failures. 147 | AC_DEFUN([AX_CHECK_GLUT], 148 | [AC_REQUIRE([AC_CANONICAL_HOST]) 149 | AC_REQUIRE([_WITH_XQUARTZ_GL]) 150 | AC_ARG_VAR([GLUT_CFLAGS],[C compiler flags for GLUT, overriding configure script defaults]) 151 | AC_ARG_VAR([GLUT_LIBS],[Linker flags for GLUT, overriding configure script defaults]) 152 | 153 | AS_CASE([${host}], 154 | [*-darwin*],[AS_IF([test "x$with_xquartz_gl" != "xno"], 155 | [GLUT_LIBS="${GLUT_LIBS:--lGLUT}"], 156 | [GLUT_LIBS="${GLUT_LIBS:--framework GLUT}"])], 157 | [*-cygwin*|*-mingw*],[ 158 | _AX_CHECK_GLUT_MANUAL_LIBS_GENERIC([glut32 glut]) 159 | AC_CHECK_HEADERS([windows.h]) 160 | ], 161 | [_AX_CHECK_GLUT_MANUAL_LIBS_GENERIC([glut]) 162 | ]) dnl host specific checks 163 | 164 | dnl checks header 165 | AS_CASE([${host}], 166 | [*-darwin*],[AS_IF([test "x$with_xquartz_gl" = "xno"], 167 | [_AX_CHECK_GLUT_HEADER([GLUT/glut.h])], 168 | [_AX_CHECK_GLUT_HEADER([GL/glut.h])] 169 | )], 170 | [_AX_CHECK_GLUT_HEADER([GL/glut.h])]) 171 | 172 | dnl compile 173 | AS_IF([test "X$ax_check_glut_have_headers" = "Xyes"], 174 | [AC_CACHE_CHECK([for compiling a minimal GLUT program], 175 | [ax_cv_check_glut_compile], 176 | [_AX_CHECK_GLUT_SAVE_FLAGS([CFLAGS]) 177 | AC_COMPILE_IFELSE([_AX_CHECK_GLUT_PROGRAM], 178 | [ax_cv_check_glut_compile="yes"], 179 | [ax_cv_check_glut_compile="no"]) 180 | _AX_CHECK_GLUT_RESTORE_FLAGS([CFLAGS]) 181 | ]) 182 | ]) 183 | 184 | dnl link 185 | AS_IF([test "X$ax_cv_check_glut_compile" = "Xyes"], 186 | [AC_CACHE_CHECK([for linking a minimal GLUT program], 187 | [ax_cv_check_glut_link], 188 | [_AX_CHECK_GLUT_SAVE_FLAGS([[CFLAGS],[LIBS]]) 189 | AC_LINK_IFELSE([_AX_CHECK_GLUT_PROGRAM], 190 | [ax_cv_check_glut_link="yes"], 191 | [ax_cv_check_glut_link="no"]) 192 | _AX_CHECK_GLUT_RESTORE_FLAGS([[CFLAGS],[LIBS]]) 193 | ]) 194 | ]) 195 | 196 | dnl hook 197 | AS_IF([test "X$ax_cv_check_glut_link" = "Xyes"], 198 | [AC_DEFINE([HAVE_GLUT], [1], [Defined if a valid GLUT implementation is found]) 199 | m4_ifval([$1], 200 | [$1], 201 | [CFLAGS="$GLUT_CFLAGS $CFLAGS" 202 | LIBS="$GLUT_LIBS $LIBS"]) 203 | ], 204 | [m4_ifval([$2], 205 | [$2], 206 | [AC_MSG_ERROR([Could not find a valid GLUT implementation])] 207 | ) 208 | ]) 209 | 210 | ]) 211 | -------------------------------------------------------------------------------- /m4/ax_pthread.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.nongnu.org/autoconf-archive/ax_pthread.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # This macro figures out how to build C programs using POSIX threads. It 12 | # sets the PTHREAD_LIBS output variable to the threads library and linker 13 | # flags, and the PTHREAD_CFLAGS output variable to any special C compiler 14 | # flags that are needed. (The user can also force certain compiler 15 | # flags/libs to be tested by setting these environment variables.) 16 | # 17 | # Also sets PTHREAD_CC to any special C compiler that is needed for 18 | # multi-threaded programs (defaults to the value of CC otherwise). (This 19 | # is necessary on AIX to use the special cc_r compiler alias.) 20 | # 21 | # NOTE: You are assumed to not only compile your program with these flags, 22 | # but also link it with them as well. e.g. you should link with 23 | # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS 24 | # 25 | # If you are only building threads programs, you may wish to use these 26 | # variables in your default LIBS, CFLAGS, and CC: 27 | # 28 | # LIBS="$PTHREAD_LIBS $LIBS" 29 | # CFLAGS="$CFLAGS $PTHREAD_CFLAGS" 30 | # CC="$PTHREAD_CC" 31 | # 32 | # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant 33 | # has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name 34 | # (e.g. PTHREAD_CREATE_UNDETACHED on AIX). 35 | # 36 | # ACTION-IF-FOUND is a list of shell commands to run if a threads library 37 | # is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it 38 | # is not found. If ACTION-IF-FOUND is not specified, the default action 39 | # will define HAVE_PTHREAD. 40 | # 41 | # Please let the authors know if this macro fails on any platform, or if 42 | # you have any other suggestions or comments. This macro was based on work 43 | # by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help 44 | # from M. Frigo), as well as ac_pthread and hb_pthread macros posted by 45 | # Alejandro Forero Cuervo to the autoconf macro repository. We are also 46 | # grateful for the helpful feedback of numerous users. 47 | # 48 | # LICENSE 49 | # 50 | # Copyright (c) 2008 Steven G. Johnson 51 | # 52 | # This program is free software: you can redistribute it and/or modify it 53 | # under the terms of the GNU General Public License as published by the 54 | # Free Software Foundation, either version 3 of the License, or (at your 55 | # option) any later version. 56 | # 57 | # This program is distributed in the hope that it will be useful, but 58 | # WITHOUT ANY WARRANTY; without even the implied warranty of 59 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 60 | # Public License for more details. 61 | # 62 | # You should have received a copy of the GNU General Public License along 63 | # with this program. If not, see . 64 | # 65 | # As a special exception, the respective Autoconf Macro's copyright owner 66 | # gives unlimited permission to copy, distribute and modify the configure 67 | # scripts that are the output of Autoconf when processing the Macro. You 68 | # need not follow the terms of the GNU General Public License when using 69 | # or distributing such scripts, even though portions of the text of the 70 | # Macro appear in them. The GNU General Public License (GPL) does govern 71 | # all other use of the material that constitutes the Autoconf Macro. 72 | # 73 | # This special exception to the GPL applies to versions of the Autoconf 74 | # Macro released by the Autoconf Archive. When you make and distribute a 75 | # modified version of the Autoconf Macro, you may extend this special 76 | # exception to the GPL to apply to your modified version as well. 77 | 78 | AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) 79 | AC_DEFUN([AX_PTHREAD], [ 80 | AC_REQUIRE([AC_CANONICAL_HOST]) 81 | AC_LANG_SAVE 82 | AC_LANG_C 83 | ax_pthread_ok=no 84 | 85 | # We used to check for pthread.h first, but this fails if pthread.h 86 | # requires special compiler flags (e.g. on True64 or Sequent). 87 | # It gets checked for in the link test anyway. 88 | 89 | # First of all, check if the user has set any of the PTHREAD_LIBS, 90 | # etcetera environment variables, and if threads linking works using 91 | # them: 92 | if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then 93 | save_CFLAGS="$CFLAGS" 94 | CFLAGS="$CFLAGS $PTHREAD_CFLAGS" 95 | save_LIBS="$LIBS" 96 | LIBS="$PTHREAD_LIBS $LIBS" 97 | AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) 98 | AC_TRY_LINK_FUNC(pthread_join, ax_pthread_ok=yes) 99 | AC_MSG_RESULT($ax_pthread_ok) 100 | if test x"$ax_pthread_ok" = xno; then 101 | PTHREAD_LIBS="" 102 | PTHREAD_CFLAGS="" 103 | fi 104 | LIBS="$save_LIBS" 105 | CFLAGS="$save_CFLAGS" 106 | fi 107 | 108 | # We must check for the threads library under a number of different 109 | # names; the ordering is very important because some systems 110 | # (e.g. DEC) have both -lpthread and -lpthreads, where one of the 111 | # libraries is broken (non-POSIX). 112 | 113 | # Create a list of thread flags to try. Items starting with a "-" are 114 | # C compiler flags, and other items are library names, except for "none" 115 | # which indicates that we try without any flags at all, and "pthread-config" 116 | # which is a program returning the flags for the Pth emulation library. 117 | 118 | ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" 119 | 120 | # The ordering *is* (sometimes) important. Some notes on the 121 | # individual items follow: 122 | 123 | # pthreads: AIX (must check this before -lpthread) 124 | # none: in case threads are in libc; should be tried before -Kthread and 125 | # other compiler flags to prevent continual compiler warnings 126 | # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) 127 | # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) 128 | # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) 129 | # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) 130 | # -pthreads: Solaris/gcc 131 | # -mthreads: Mingw32/gcc, Lynx/gcc 132 | # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it 133 | # doesn't hurt to check since this sometimes defines pthreads too; 134 | # also defines -D_REENTRANT) 135 | # ... -mt is also the pthreads flag for HP/aCC 136 | # pthread: Linux, etcetera 137 | # --thread-safe: KAI C++ 138 | # pthread-config: use pthread-config program (for GNU Pth library) 139 | 140 | case "${host_cpu}-${host_os}" in 141 | *solaris*) 142 | 143 | # On Solaris (at least, for some versions), libc contains stubbed 144 | # (non-functional) versions of the pthreads routines, so link-based 145 | # tests will erroneously succeed. (We need to link with -pthreads/-mt/ 146 | # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather 147 | # a function called by this macro, so we could check for that, but 148 | # who knows whether they'll stub that too in a future libc.) So, 149 | # we'll just look for -pthreads and -lpthread first: 150 | 151 | ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags" 152 | ;; 153 | esac 154 | 155 | if test x"$ax_pthread_ok" = xno; then 156 | for flag in $ax_pthread_flags; do 157 | 158 | case $flag in 159 | none) 160 | AC_MSG_CHECKING([whether pthreads work without any flags]) 161 | ;; 162 | 163 | -*) 164 | AC_MSG_CHECKING([whether pthreads work with $flag]) 165 | PTHREAD_CFLAGS="$flag" 166 | ;; 167 | 168 | pthread-config) 169 | AC_CHECK_PROG(ax_pthread_config, pthread-config, yes, no) 170 | if test x"$ax_pthread_config" = xno; then continue; fi 171 | PTHREAD_CFLAGS="`pthread-config --cflags`" 172 | PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" 173 | ;; 174 | 175 | *) 176 | AC_MSG_CHECKING([for the pthreads library -l$flag]) 177 | PTHREAD_LIBS="-l$flag" 178 | ;; 179 | esac 180 | 181 | save_LIBS="$LIBS" 182 | save_CFLAGS="$CFLAGS" 183 | LIBS="$PTHREAD_LIBS $LIBS" 184 | CFLAGS="$CFLAGS $PTHREAD_CFLAGS" 185 | 186 | # Check for various functions. We must include pthread.h, 187 | # since some functions may be macros. (On the Sequent, we 188 | # need a special flag -Kthread to make this header compile.) 189 | # We check for pthread_join because it is in -lpthread on IRIX 190 | # while pthread_create is in libc. We check for pthread_attr_init 191 | # due to DEC craziness with -lpthreads. We check for 192 | # pthread_cleanup_push because it is one of the few pthread 193 | # functions on Solaris that doesn't have a non-functional libc stub. 194 | # We try pthread_create on general principles. 195 | AC_TRY_LINK([#include 196 | static void routine(void* a) {a=0;} 197 | static void* start_routine(void* a) {return a;}], 198 | [pthread_t th; pthread_attr_t attr; 199 | pthread_join(th, 0); 200 | pthread_attr_init(&attr); 201 | pthread_cleanup_push(routine, 0); 202 | pthread_create(&th,0,start_routine,0); 203 | pthread_cleanup_pop(0); ], 204 | [ax_pthread_ok=yes]) 205 | 206 | LIBS="$save_LIBS" 207 | CFLAGS="$save_CFLAGS" 208 | 209 | AC_MSG_RESULT($ax_pthread_ok) 210 | if test "x$ax_pthread_ok" = xyes; then 211 | break; 212 | fi 213 | 214 | PTHREAD_LIBS="" 215 | PTHREAD_CFLAGS="" 216 | done 217 | fi 218 | 219 | # Various other checks: 220 | if test "x$ax_pthread_ok" = xyes; then 221 | save_LIBS="$LIBS" 222 | LIBS="$PTHREAD_LIBS $LIBS" 223 | save_CFLAGS="$CFLAGS" 224 | CFLAGS="$CFLAGS $PTHREAD_CFLAGS" 225 | 226 | # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. 227 | AC_MSG_CHECKING([for joinable pthread attribute]) 228 | attr_name=unknown 229 | for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do 230 | AC_TRY_LINK([#include ], [int attr=$attr; return attr;], 231 | [attr_name=$attr; break]) 232 | done 233 | AC_MSG_RESULT($attr_name) 234 | if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then 235 | AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name, 236 | [Define to necessary symbol if this constant 237 | uses a non-standard name on your system.]) 238 | fi 239 | 240 | AC_MSG_CHECKING([if more special flags are required for pthreads]) 241 | flag=no 242 | case "${host_cpu}-${host_os}" in 243 | *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; 244 | *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; 245 | esac 246 | AC_MSG_RESULT(${flag}) 247 | if test "x$flag" != xno; then 248 | PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" 249 | fi 250 | 251 | LIBS="$save_LIBS" 252 | CFLAGS="$save_CFLAGS" 253 | 254 | # More AIX lossage: must compile with xlc_r or cc_r 255 | if test x"$GCC" != xyes; then 256 | AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC}) 257 | else 258 | PTHREAD_CC=$CC 259 | fi 260 | else 261 | PTHREAD_CC="$CC" 262 | fi 263 | 264 | AC_SUBST(PTHREAD_LIBS) 265 | AC_SUBST(PTHREAD_CFLAGS) 266 | AC_SUBST(PTHREAD_CC) 267 | 268 | # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: 269 | if test x"$ax_pthread_ok" = xyes; then 270 | ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) 271 | : 272 | else 273 | ax_pthread_ok=no 274 | $2 275 | fi 276 | AC_LANG_RESTORE 277 | ])dnl AX_PTHREAD 278 | -------------------------------------------------------------------------------- /m4/ax_restore_flags_with_prefix.m4: -------------------------------------------------------------------------------- 1 | # ================================================================================= 2 | # https://www.gnu.org/software/autoconf-archive/ax_restore_flags_with_prefix.html 3 | # ================================================================================= 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_RESTORE_FLAGS_WITH_PREFIX(PREFIX, LIST-OF-FLAGS) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Restore the flags saved by AX_SAVE_FLAGS_WITH_PREFIX. 12 | # 13 | # Expansion example: AX_RESTORE_FLAGS_WITH_PREFIX([GL], [[CFLAGS],[LIBS]]) 14 | # expands to 15 | # 16 | # CFLAGS="$gl_saved_flag_cflags" 17 | # LIBS="$gl_saved_flag_libs" 18 | # 19 | # One common use case is to define a package specific wrapper macro around 20 | # this one, and also restore other variables if needed. For example: 21 | # 22 | # AC_DEFUN([_AX_CHECK_GL_RESTORE_FLAGS], [ 23 | # AX_RESTORE_FLAGS_WITH_PREFIX([GL],[$1]) 24 | # AC_LANG_POP([C]) 25 | # ]) 26 | # 27 | # # Restores CFLAGS, LIBS and language state 28 | # _AX_CHECK_GL_RESTORE_FLAGS([[CFLAGS],[LIBS]]) 29 | # 30 | # LICENSE 31 | # 32 | # Copyright (c) 2016 Felix Chern 33 | # 34 | # This program is free software; you can redistribute it and/or modify it 35 | # under the terms of the GNU General Public License as published by the 36 | # Free Software Foundation; either version 2 of the License, or (at your 37 | # option) any later version. 38 | # 39 | # This program is distributed in the hope that it will be useful, but 40 | # WITHOUT ANY WARRANTY; without even the implied warranty of 41 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 42 | # Public License for more details. 43 | # 44 | # You should have received a copy of the GNU General Public License along 45 | # with this program. If not, see . 46 | # 47 | # As a special exception, the respective Autoconf Macro's copyright owner 48 | # gives unlimited permission to copy, distribute and modify the configure 49 | # scripts that are the output of Autoconf when processing the Macro. You 50 | # need not follow the terms of the GNU General Public License when using 51 | # or distributing such scripts, even though portions of the text of the 52 | # Macro appear in them. The GNU General Public License (GPL) does govern 53 | # all other use of the material that constitutes the Autoconf Macro. 54 | # 55 | # This special exception to the GPL applies to versions of the Autoconf 56 | # Macro released by the Autoconf Archive. When you make and distribute a 57 | # modified version of the Autoconf Macro, you may extend this special 58 | # exception to the GPL to apply to your modified version as well. 59 | 60 | #serial 3 61 | 62 | AC_DEFUN([AX_RESTORE_FLAGS_WITH_PREFIX],[ 63 | m4_ifval([$2], [ 64 | m4_car($2)="$_ax_[]m4_tolower($1)_saved_flag_[]m4_tolower(m4_car($2))" 65 | $0($1, m4_cdr($2))]) 66 | ]) 67 | -------------------------------------------------------------------------------- /m4/ax_save_flags_with_prefix.m4: -------------------------------------------------------------------------------- 1 | # ============================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_save_flags_with_prefix.html 3 | # ============================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_SAVE_FLAGS_WITH_PREFIX(PREFIX, LIST-OF-FLAGS) 8 | # 9 | # DESCRIPTION 10 | # 11 | # For each flag in LIST-OF-FLAGS, it expands to lower-cased shell variable 12 | # with the prefix holding the flag original value. The saved variables 13 | # can be restored by AX_RESTORE_FLAGS_WITH_PREFIX 14 | # 15 | # As an example: AX_SAVE_FLAGS_WITH_PREFIX([GL], [[CFLAGS],[LIBS]]) 16 | # expands to 17 | # 18 | # gl_saved_flag_cflags="$CFLAGS" 19 | # gl_saved_flag_libs="$LIBS" 20 | # CFLAGS="$GL_CFLAGS $CFLAGS" 21 | # LIBS="$GL_LIBS $LIBS" 22 | # 23 | # One common use case is to define a package specific wrapper macro around 24 | # this one, and also setup other variables if needed. For example: 25 | # 26 | # AC_DEFUN([_AX_CHECK_GL_SAVE_FLAGS], [ 27 | # AX_SAVE_FLAGS_WITH_PREFIX([GL],[$1]) 28 | # AC_LANG_PUSH([C]) 29 | # ]) 30 | # 31 | # # pushes GL_CFLAGS and GL_LIBS to CFLAGS and LIBS 32 | # # also set the current language to test to C 33 | # _AX_CHECK_GL_SAVE_FLAGS([[CFLAGS],[LIBS]]) 34 | # 35 | # LICENSE 36 | # 37 | # Copyright (c) 2016 Felix Chern 38 | # 39 | # This program is free software; you can redistribute it and/or modify it 40 | # under the terms of the GNU General Public License as published by the 41 | # Free Software Foundation; either version 2 of the License, or (at your 42 | # option) any later version. 43 | # 44 | # This program is distributed in the hope that it will be useful, but 45 | # WITHOUT ANY WARRANTY; without even the implied warranty of 46 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 47 | # Public License for more details. 48 | # 49 | # You should have received a copy of the GNU General Public License along 50 | # with this program. If not, see . 51 | # 52 | # As a special exception, the respective Autoconf Macro's copyright owner 53 | # gives unlimited permission to copy, distribute and modify the configure 54 | # scripts that are the output of Autoconf when processing the Macro. You 55 | # need not follow the terms of the GNU General Public License when using 56 | # or distributing such scripts, even though portions of the text of the 57 | # Macro appear in them. The GNU General Public License (GPL) does govern 58 | # all other use of the material that constitutes the Autoconf Macro. 59 | # 60 | # This special exception to the GPL applies to versions of the Autoconf 61 | # Macro released by the Autoconf Archive. When you make and distribute a 62 | # modified version of the Autoconf Macro, you may extend this special 63 | # exception to the GPL to apply to your modified version as well. 64 | 65 | #serial 3 66 | 67 | AC_DEFUN([AX_SAVE_FLAGS_WITH_PREFIX],[ 68 | m4_ifval([$2], [ 69 | _ax_[]m4_tolower($1)_saved_flag_[]m4_tolower(m4_car($2))="$m4_car($2)" 70 | m4_car($2)="$$1_[]m4_car($2) $m4_car($2)" 71 | $0($1, m4_cdr($2)) 72 | ])]) 73 | -------------------------------------------------------------------------------- /m4/pkg.m4: -------------------------------------------------------------------------------- 1 | # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- 2 | # 3 | # Copyright © 2004 Scott James Remnant . 4 | # 5 | # This program is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, but 11 | # WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | # General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, write to the Free Software 17 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 | # 19 | # As a special exception to the GNU General Public License, if you 20 | # distribute this file as part of a program that contains a 21 | # configuration script generated by Autoconf, you may include it under 22 | # the same distribution terms that you use for the rest of that program. 23 | 24 | # PKG_PROG_PKG_CONFIG([MIN-VERSION]) 25 | # ---------------------------------- 26 | AC_DEFUN([PKG_PROG_PKG_CONFIG], 27 | [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) 28 | m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) 29 | AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl 30 | if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then 31 | AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) 32 | fi 33 | if test -n "$PKG_CONFIG"; then 34 | _pkg_min_version=m4_default([$1], [0.9.0]) 35 | AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) 36 | if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then 37 | AC_MSG_RESULT([yes]) 38 | else 39 | AC_MSG_RESULT([no]) 40 | PKG_CONFIG="" 41 | fi 42 | 43 | fi[]dnl 44 | ])# PKG_PROG_PKG_CONFIG 45 | 46 | # PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) 47 | # 48 | # Check to see whether a particular set of modules exists. Similar 49 | # to PKG_CHECK_MODULES(), but does not set variables or print errors. 50 | # 51 | # 52 | # Similar to PKG_CHECK_MODULES, make sure that the first instance of 53 | # this or PKG_CHECK_MODULES is called, or make sure to call 54 | # PKG_CHECK_EXISTS manually 55 | # -------------------------------------------------------------- 56 | AC_DEFUN([PKG_CHECK_EXISTS], 57 | [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl 58 | if test -n "$PKG_CONFIG" && \ 59 | AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then 60 | m4_ifval([$2], [$2], [:]) 61 | m4_ifvaln([$3], [else 62 | $3])dnl 63 | fi]) 64 | 65 | 66 | # _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) 67 | # --------------------------------------------- 68 | m4_define([_PKG_CONFIG], 69 | [if test -n "$PKG_CONFIG"; then 70 | if test -n "$$1"; then 71 | pkg_cv_[]$1="$$1" 72 | else 73 | PKG_CHECK_EXISTS([$3], 74 | [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], 75 | [pkg_failed=yes]) 76 | fi 77 | else 78 | pkg_failed=untried 79 | fi[]dnl 80 | ])# _PKG_CONFIG 81 | 82 | # _PKG_SHORT_ERRORS_SUPPORTED 83 | # ----------------------------- 84 | AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], 85 | [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) 86 | if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then 87 | _pkg_short_errors_supported=yes 88 | else 89 | _pkg_short_errors_supported=no 90 | fi[]dnl 91 | ])# _PKG_SHORT_ERRORS_SUPPORTED 92 | 93 | 94 | # PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], 95 | # [ACTION-IF-NOT-FOUND]) 96 | # 97 | # 98 | # Note that if there is a possibility the first call to 99 | # PKG_CHECK_MODULES might not happen, you should be sure to include an 100 | # explicit call to PKG_PROG_PKG_CONFIG in your configure.ac 101 | # 102 | # 103 | # -------------------------------------------------------------- 104 | AC_DEFUN([PKG_CHECK_MODULES], 105 | [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl 106 | AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl 107 | AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl 108 | 109 | pkg_failed=no 110 | AC_MSG_CHECKING([for $1]) 111 | 112 | _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) 113 | _PKG_CONFIG([$1][_LIBS], [libs], [$2]) 114 | 115 | m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS 116 | and $1[]_LIBS to avoid the need to call pkg-config. 117 | See the pkg-config man page for more details.]) 118 | 119 | if test $pkg_failed = yes; then 120 | _PKG_SHORT_ERRORS_SUPPORTED 121 | if test $_pkg_short_errors_supported = yes; then 122 | $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"` 123 | else 124 | $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` 125 | fi 126 | # Put the nasty error message in config.log where it belongs 127 | echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD 128 | 129 | ifelse([$4], , [AC_MSG_ERROR(dnl 130 | [Package requirements ($2) were not met: 131 | 132 | $$1_PKG_ERRORS 133 | 134 | Consider adjusting the PKG_CONFIG_PATH environment variable if you 135 | installed software in a non-standard prefix. 136 | 137 | _PKG_TEXT 138 | ])], 139 | [AC_MSG_RESULT([no]) 140 | $4]) 141 | elif test $pkg_failed = untried; then 142 | ifelse([$4], , [AC_MSG_FAILURE(dnl 143 | [The pkg-config script could not be found or is too old. Make sure it 144 | is in your PATH or set the PKG_CONFIG environment variable to the full 145 | path to pkg-config. 146 | 147 | _PKG_TEXT 148 | 149 | To get pkg-config, see .])], 150 | [$4]) 151 | else 152 | $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS 153 | $1[]_LIBS=$pkg_cv_[]$1[]_LIBS 154 | AC_MSG_RESULT([yes]) 155 | ifelse([$3], , :, [$3]) 156 | fi[]dnl 157 | ])# PKG_CHECK_MODULES 158 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | -------------------------------------------------------------------------------- /src/configwatcher.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2017 Andrew Caudwell (acaudwell@gmail.com) 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | as published by the Free Software Foundation; either version 7 | 3 of the License, or (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include "configwatcher.h" 19 | 20 | #include "core/logger.h" 21 | #include "core/sdlapp.h" 22 | 23 | #include 24 | #include 25 | 26 | ConfigWatcher::ConfigWatcher() 27 | : changed(false), last_mtime(0), elapsed(0.0f) { 28 | } 29 | 30 | ConfigWatcher::~ConfigWatcher() { 31 | } 32 | 33 | void ConfigWatcher::setConfig(const std::string &config_file) { 34 | this->config_file = config_file; 35 | elapsed = 0.0f; 36 | changed = false; 37 | 38 | struct stat st; 39 | int rc = stat(config_file.c_str(), &st); 40 | 41 | if(rc == 0) { 42 | last_mtime = st.st_mtime; 43 | } else { 44 | last_mtime = time(0); 45 | } 46 | } 47 | 48 | void ConfigWatcher::logic(float dt) { 49 | 50 | elapsed += dt; 51 | 52 | if(elapsed >= 1.0f) { 53 | elapsed = 0.0f; 54 | 55 | if(!changed) { 56 | struct stat st; 57 | int rc = stat(config_file.c_str(), &st); 58 | 59 | if(rc == 0) { 60 | time_t mtime = st.st_mtime; 61 | 62 | if(mtime > this->last_mtime) { 63 | this->last_mtime = mtime; 64 | changed = true; 65 | } 66 | } 67 | } 68 | } 69 | } 70 | 71 | bool ConfigWatcher::changeDetected() { 72 | bool has_changed = changed; 73 | changed = false; 74 | return has_changed; 75 | } 76 | -------------------------------------------------------------------------------- /src/configwatcher.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2017 Andrew Caudwell (acaudwell@gmail.com) 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | as published by the Free Software Foundation; either version 7 | 3 of the License, or (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef CONFIG_WATCHER_H 19 | #define CONFIG_WATCHER_H 20 | 21 | #include 22 | #include 23 | 24 | class ConfigWatcher { 25 | protected: 26 | std::string config_file; 27 | bool changed; 28 | time_t last_mtime; 29 | float elapsed; 30 | public: 31 | ConfigWatcher(); 32 | virtual ~ConfigWatcher(); 33 | 34 | void setConfig(const std::string& config_file); 35 | 36 | void logic(float dt); 37 | 38 | bool changeDetected(); 39 | }; 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/custom.cpp: -------------------------------------------------------------------------------- 1 | #include "custom.h" 2 | 3 | #include "core/regex.h" 4 | #include "settings.h" 5 | 6 | //timestamp 7 | //hostname 8 | //path 9 | //response_code 10 | //response_size 11 | //success (1|0) 12 | //response_colour 13 | //referrer 14 | //user_agent 15 | //virtual_host 16 | //pid 17 | 18 | Regex custom_entry("^([^|]*)\\|([^|]*)\\|([^|]*)\\|([^|]*)\\|([^|]*)(?:\\|([^|]*))?(?:\\|#?([^|]*))?(?:\\|([^|]*))?(?:\\|([^|]*))?(?:\\|([^|]*))?(?:\\|([^|]*))?$"); 19 | 20 | CustomAccessLog::CustomAccessLog() { 21 | } 22 | 23 | bool CustomAccessLog::parseLine(std::string& line, LogEntry& entry) { 24 | 25 | std::vector matches; 26 | 27 | if(!custom_entry.match(line, &matches)) return false; 28 | 29 | entry.timestamp = atol(matches[0].c_str()); 30 | entry.hostname = matches[1]; 31 | entry.path = matches[2]; 32 | entry.response_code = matches[3]; 33 | entry.response_size = atol(matches[4].c_str()); 34 | 35 | if(settings.display_log_entry) { 36 | entry.log_entry = line; 37 | } 38 | 39 | //optional fields 40 | 41 | //success 1 or 0 42 | if(matches.size() > 5) { 43 | std::string success = matches[5]; 44 | 45 | if(success.empty() || (success.size()==1 && success[0] == ' ')) { 46 | entry.setSuccess(); 47 | } else { 48 | entry.successful = atoi(success.c_str())==1 ? true : false; 49 | } 50 | } else entry.setSuccess(); 51 | 52 | //response colour 53 | if(matches.size()>6) { 54 | 55 | std::string colour = matches[6]; 56 | 57 | int r, g, b; 58 | if(colour.size()>0 && 59 | sscanf(colour.c_str(), "%02x%02x%02x", &r, &g, &b) == 3) { 60 | entry.response_colour = vec3( r, g, b ); 61 | entry.response_colour /= 255.0f; 62 | } else { 63 | entry.setResponseColour(); 64 | } 65 | } else entry.setResponseColour(); 66 | 67 | //referrer 68 | if(matches.size()>7) { 69 | entry.referrer = matches[7]; 70 | } 71 | 72 | //user agent 73 | if(matches.size()>8) { 74 | entry.user_agent = matches[8]; 75 | } 76 | 77 | //vhost 78 | if(matches.size()>9) { 79 | entry.vhost = matches[9]; 80 | } 81 | 82 | //pid or some other identifier 83 | if(matches.size()>10) { 84 | entry.pid = matches[10]; 85 | } 86 | 87 | return entry.validate(); 88 | } 89 | -------------------------------------------------------------------------------- /src/custom.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2010 Andrew Caudwell (acaudwell@gmail.com) 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | as published by the Free Software Foundation; either version 7 | 3 of the License, or (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef CUSTOM_ACCESS_LOG 19 | #define CUSTOM_ACCESS_LOG 20 | 21 | #include "logentry.h" 22 | 23 | class CustomAccessLog : public AccessLog { 24 | 25 | public: 26 | CustomAccessLog(); 27 | bool parseLine(std::string& line, LogEntry& entry); 28 | }; 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /src/logentry.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2008 Andrew Caudwell (acaudwell@gmail.com) 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | as published by the Free Software Foundation; either version 7 | 3 of the License, or (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include "logentry.h" 19 | #include "settings.h" 20 | #include "core/regex.h" 21 | 22 | #include 23 | #include 24 | 25 | //AccessLog 26 | 27 | AccessLog::AccessLog() { 28 | } 29 | 30 | //LogEntry 31 | 32 | std::vector LogEntry::fields; 33 | std::vector LogEntry::default_fields; 34 | std::map LogEntry::field_titles; 35 | 36 | LogEntry::LogEntry() { 37 | timestamp = 0; 38 | response_size = 0; 39 | successful = false; 40 | response_colour = vec3(1.0, 0.0, 0.0); 41 | } 42 | 43 | Regex logentry_ipv6("(?i)^[a-f0-9:]+$"); 44 | 45 | Regex logentry_hostname_parts("([^.]+)(?:\\.([^.]+))?(?:\\.([^.]+))?(?:\\.([^.]+))?(?:\\.([^.]+))?(?:\\.([^.]+))?(?:\\.([^.]+))?(?:\\.([^.]+))?$"); 46 | 47 | std::string LogEntry::maskHostname(const std::string& hostname) { 48 | 49 | std::vector parts; 50 | 51 | // could be an ipv6 address 52 | if(logentry_ipv6.match(hostname) && hostname.find(":") != std::string::npos) { 53 | 54 | size_t c = 0; 55 | size_t last = hostname.size(); 56 | 57 | size_t colon_count = std::count(hostname.begin(), hostname.end(), ':'); 58 | size_t padding = 7 - colon_count; 59 | 60 | if(colon_count <= 7) { 61 | 62 | size_t previous = 0; 63 | 64 | while( (last = hostname.rfind(":",last-1)) != std::string::npos) { 65 | 66 | c++; 67 | 68 | if(last == (previous-1)) c += padding; 69 | 70 | if(c >= 4) { 71 | std::string output = hostname.substr(0, last); 72 | output += '-'; 73 | return output; 74 | } 75 | 76 | previous = last; 77 | } 78 | } 79 | } 80 | 81 | logentry_hostname_parts.match(hostname, &parts); 82 | 83 | size_t part_count = parts.size(); 84 | 85 | //if only 1-2 parts, or 3 parts and a 2 character suffix, pass through unchanged 86 | if( part_count <= 2 || (part_count == 3 && parts[part_count-1].size()==2)) 87 | return hostname; 88 | 89 | int num = atoi(parts[part_count-1].c_str()); 90 | 91 | std::string output; 92 | 93 | //if last element is numeric, assume it is a numbered ip address 94 | //(ie 192.168.0.1 => 192.168.0-) 95 | 96 | if(num != 0) { 97 | for(size_t i=0;i0) output += '.'; 99 | output += parts[i]; 100 | } 101 | 102 | output += '-'; 103 | return output; 104 | } 105 | 106 | //hide the first element 107 | //(ie dhcp113.web.com -> web.com 108 | for(size_t i=1;i1) output += '.'; 110 | output += parts[i]; 111 | } 112 | 113 | return output; 114 | } 115 | 116 | void LogEntry::setSuccess() { 117 | 118 | int code = atoi(response_code.c_str()); 119 | 120 | successful = (code<400) ? true : false; 121 | } 122 | 123 | void LogEntry::setResponseColour() { 124 | 125 | int code = atoi(response_code.c_str()); 126 | 127 | //set response colour 128 | if(code<200) { 129 | response_colour = vec3(0.0f, 1.0f, 0.5f); 130 | } 131 | else if(code>= 200 && code < 300) { 132 | response_colour = vec3(1.0f, 1.0f, 0.0f); 133 | } 134 | else if(code>= 300 && code < 400) { 135 | response_colour = vec3(1.0f, 0.5f, 0.0f); 136 | } 137 | else { 138 | response_colour = vec3(1.0f, 0.0f, 0.0f); 139 | } 140 | } 141 | 142 | const std::vector& LogEntry::getFields() { 143 | 144 | if(fields.empty()) { 145 | fields.push_back("pid"); 146 | fields.push_back("method"); 147 | fields.push_back("protocol"); 148 | fields.push_back("path"); 149 | fields.push_back("vhost"); 150 | fields.push_back("hostname"); 151 | fields.push_back("response_code"); 152 | fields.push_back("response_size"); 153 | fields.push_back("referrer"); 154 | fields.push_back("user_agent"); 155 | fields.push_back("timestamp"); 156 | fields.push_back("log_entry"); 157 | } 158 | 159 | return fields; 160 | } 161 | 162 | const std::vector& LogEntry::getDefaultFields() { 163 | 164 | if(default_fields.empty()) { 165 | default_fields.push_back("vhost"); 166 | default_fields.push_back("timestamp"); 167 | default_fields.push_back("hostname"); 168 | default_fields.push_back("path"); 169 | default_fields.push_back("method"); 170 | default_fields.push_back("response_code"); 171 | default_fields.push_back("response_size"); 172 | default_fields.push_back("referrer"); 173 | default_fields.push_back("user_agent"); 174 | } 175 | 176 | return default_fields; 177 | } 178 | 179 | const std::string& LogEntry::getFieldTitle(const std::string& field) { 180 | 181 | if(field_titles.empty()) { 182 | field_titles["pid"] = "PID"; 183 | field_titles["path"] = "Path"; 184 | field_titles["method"] = "Method"; 185 | field_titles["protocol"] = "Protocol"; 186 | field_titles["vhost"] = "Virtual Host"; 187 | field_titles["hostname"] = "Hostname"; 188 | field_titles["response_size"] = "Response Size"; 189 | field_titles["response_code"] = "Response Code"; 190 | field_titles["referrer"] = "Referrer"; 191 | field_titles["user_agent"] = "User Agent"; 192 | field_titles["timestamp"] = "Timestamp"; 193 | field_titles["log_entry"] = "Log Entry"; 194 | } 195 | 196 | auto it = field_titles.find(field); 197 | 198 | assert(it != field_titles.end()); 199 | 200 | return it->second; 201 | } 202 | 203 | bool LogEntry::getValue(const std::string& field, std::string& value) const { 204 | 205 | if(field == "pid") { 206 | value = pid; 207 | return true; 208 | } 209 | 210 | if(field == "path") { 211 | value = path; 212 | return true; 213 | } 214 | 215 | if(field == "method") { 216 | value = method; 217 | return true; 218 | } 219 | 220 | if(field == "protocol") { 221 | value = protocol; 222 | return true; 223 | } 224 | 225 | if(field == "hostname") { 226 | value = hostname; 227 | return true; 228 | } 229 | 230 | if(field == "vhost") { 231 | value = vhost; 232 | return true; 233 | } 234 | 235 | if(field == "response_size") { 236 | value = std::to_string(response_size); 237 | return true; 238 | } 239 | 240 | if(field == "response_code") { 241 | value = response_code; 242 | return true; 243 | } 244 | 245 | if(field == "referrer") { 246 | value = referrer; 247 | return true; 248 | } 249 | 250 | if(field == "user_agent") { 251 | value = user_agent; 252 | return true; 253 | } 254 | 255 | if(field == "timestamp") { 256 | struct tm* timeinfo = localtime ( ×tamp ); 257 | char timestamp_buff[256]; 258 | strftime(timestamp_buff, 256, "%Y-%m-%d %H:%M:%S", timeinfo); 259 | value = std::string(timestamp_buff); 260 | return true; 261 | } 262 | 263 | if(field == "log_entry") { 264 | value = log_entry; 265 | return true; 266 | } 267 | 268 | value = ""; 269 | return false; 270 | } 271 | 272 | bool LogEntry::validate() { 273 | if(pid == "-") pid = ""; 274 | if(referrer == "-") referrer = ""; 275 | 276 | if(hostname.empty()) return false; 277 | 278 | if(settings.mask_hostnames) { 279 | hostname = maskHostname(hostname); 280 | } 281 | 282 | if(path.empty()) return false; 283 | if(timestamp == 0) return false; 284 | 285 | return true; 286 | } 287 | -------------------------------------------------------------------------------- /src/logentry.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2008 Andrew Caudwell (acaudwell@gmail.com) 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | as published by the Free Software Foundation; either version 7 | 3 of the License, or (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef LOGENTRY_H 19 | #define LOGENTRY_H 20 | 21 | #include "core/vectors.h" 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | class LogEntry { 29 | 30 | private: 31 | static std::vector fields; 32 | static std::vector default_fields; 33 | static std::map field_titles; 34 | 35 | std::string maskHostname(const std::string& hostname); 36 | public: 37 | LogEntry(); 38 | bool validate(); 39 | 40 | void setSuccess(); 41 | void setResponseColour(); 42 | 43 | bool getValue(const std::string& field, std::string& value) const; 44 | 45 | std::string log_entry; 46 | 47 | time_t timestamp; 48 | 49 | std::string hostname; 50 | std::string vhost; 51 | 52 | std::string path; 53 | 54 | std::string pid; 55 | std::string method; 56 | std::string protocol; 57 | 58 | std::string response_code; 59 | long response_size; 60 | 61 | std::string referrer; 62 | std::string user_agent; 63 | 64 | vec3 response_colour; 65 | 66 | bool successful; 67 | 68 | static const std::vector& getFields(); 69 | static const std::vector& getDefaultFields(); 70 | static const std::string& getFieldTitle(const std::string& field); 71 | }; 72 | 73 | class AccessLog { 74 | 75 | public: 76 | AccessLog(); 77 | virtual ~AccessLog() {}; 78 | virtual bool parseLine(std::string& line, LogEntry& entry) = 0; 79 | 80 | }; 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /src/logstalgia.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2008 Andrew Caudwell (acaudwell@gmail.com) 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | as published by the Free Software Foundation; either version 7 | 3 of the License, or (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef LOGSTALGIA_H 19 | #define LOGSTALGIA_H 20 | 21 | #include "core/sdlapp.h" 22 | #include "core/fxfont.h" 23 | #include "core/seeklog.h" 24 | #include "core/ppm.h" 25 | 26 | #include "logentry.h" 27 | #include "paddle.h" 28 | #include "requestball.h" 29 | #include "summarizer.h" 30 | #include "textarea.h" 31 | #include "slider.h" 32 | #include "settings.h" 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | class ConfigWatcher; 41 | 42 | class Logstalgia : public SDLApp { 43 | 44 | std::map paddles; 45 | 46 | std::string logfile; 47 | 48 | std::string displaydate; 49 | std::string displaytime; 50 | 51 | bool info; 52 | bool paused; 53 | bool retarget; 54 | bool next; 55 | bool end_reached; 56 | bool take_screenshot; 57 | bool initialized; 58 | 59 | uint64_t highscore; 60 | 61 | time_t mintime; 62 | 63 | time_t starttime; 64 | time_t currtime; 65 | time_t lasttime; 66 | 67 | float screen_blank_interval; 68 | float screen_blank_period; 69 | float screen_blank_elapsed; 70 | 71 | float font_alpha; 72 | 73 | double elapsed_time; 74 | 75 | float spawn_delay; 76 | 77 | std::string message; 78 | float message_timer; 79 | 80 | int total_space; 81 | int remaining_space; 82 | int total_entries; 83 | 84 | vec4 paddle_colour; 85 | float paddle_x; 86 | 87 | TextureResource* balltex; 88 | TextureResource* glowtex; 89 | 90 | float toggle_delay; 91 | 92 | float mousehide_timeout; 93 | vec2 mousepos; 94 | 95 | FXFont fontSmall; 96 | FXFont fontMedium; 97 | FXFont fontLarge; 98 | FXFont fontBall; 99 | 100 | bool adjusting_size; 101 | SDL_Cursor* default_cursor; 102 | SDL_Cursor* resize_cursor; 103 | 104 | Summarizer* ipSummarizer; 105 | 106 | std::vector summarizers; 107 | std::map*> summarizer_types; 108 | 109 | PositionSlider slider; 110 | 111 | AccessLog* accesslog; 112 | 113 | SeekLog* seeklog; 114 | StreamLog* streamlog; 115 | 116 | std::list queued_entries; 117 | std::list balls; 118 | 119 | TextArea infowindow; 120 | 121 | float runtime; 122 | float fixed_tick_rate; 123 | int framecount; 124 | int frameskip; 125 | FrameExporter* frameExporter; 126 | 127 | ConfigWatcher* config_watcher; 128 | bool detect_changes; 129 | 130 | bool hasProgressBar(); 131 | 132 | std::string filterURLHostname(const std::string& hostname); 133 | 134 | std::string dateAtPosition(float percent); 135 | void seekTo(float percent); 136 | 137 | void filterLogLine(std::string& line); 138 | 139 | void readLog(int buffer_rows = 0); 140 | 141 | RequestBall* findNearest(Paddle* paddle, const std::string& paddle_token); 142 | void updateGroups(float dt); 143 | void drawGroups(float dt, float alpha); 144 | 145 | Summarizer* getGroupSummarizer(LogEntry* le); 146 | 147 | void addStrings(LogEntry* le); 148 | 149 | void addBall(LogEntry* le, float start_offset); 150 | void removeBall(RequestBall* ball); 151 | void addGroup(const SummarizerGroup& group); 152 | void addGroup(const std::string& group_type, const std::string& group_title, const std::string& group_regex, const std::string& separators, int max_depth, int abbrev_depth, int percent = 0, vec3 colour = vec3(0.0f, 0.0f, 0.0f)); 153 | void togglePause(); 154 | 155 | BaseLog* getLog(); 156 | 157 | void changeSummarizerMaxDepth(Summarizer* summarizer, int delta); 158 | void changeSummarizerAbbreviationDepth(Summarizer* summarizer, int delta); 159 | 160 | void changeIPSummarizerMaxDepth(int delta); 161 | void changeIPSummarizerAbbreviationDepth(int delta); 162 | 163 | void changeGroupSummarizerMaxDepth(int delta); 164 | void changeGroupSummarizerAbbreviationDepth(int delta); 165 | 166 | bool mouseOverSummarizerWidthAdjuster(const vec2& pos); 167 | 168 | void changePaddleX(float x); 169 | 170 | void saveConfig(); 171 | 172 | void loadConfig(); 173 | void loadConfig(const std::string& config_file); 174 | 175 | void reloadConfig(); 176 | 177 | void reset(); 178 | 179 | void reposition(); 180 | 181 | void initPaddles(); 182 | void initRequestBalls(); 183 | void resizeSummarizers(); 184 | 185 | void setMessage(const char* str, ...); 186 | 187 | void screenshot(); 188 | 189 | void toggleFullscreen(); 190 | 191 | void logic(float t, float dt); 192 | void draw(float t, float dt); 193 | public: 194 | Logstalgia(const std::string& logfile); 195 | ~Logstalgia(); 196 | 197 | void setFrameExporter(FrameExporter* exporter); 198 | 199 | void resize(int width, int height); 200 | void toggleWindowFrame(); 201 | 202 | //inherited methods 203 | void init(); 204 | void update(float t, float dt); 205 | void keyPress(SDL_KeyboardEvent *e); 206 | void mouseMove(SDL_MouseMotionEvent *e); 207 | void mouseClick(SDL_MouseButtonEvent *e); 208 | }; 209 | 210 | #endif 211 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2008 Andrew Caudwell (acaudwell@gmail.com) 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | as published by the Free Software Foundation; either version 7 | 3 of the License, or (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include "logstalgia.h" 19 | #include "settings.h" 20 | #include "tests.h" 21 | 22 | #ifdef _WIN32 23 | std::string win32LogSelector() { 24 | 25 | //get original directory 26 | char cwd_buff[1024]; 27 | 28 | if(getcwd(cwd_buff, 1024) != cwd_buff) { 29 | SDLAppQuit("error getting current working directory"); 30 | } 31 | 32 | OPENFILENAME ofn; 33 | 34 | char filepath[_MAX_PATH]; 35 | filepath[0] = '\0'; 36 | 37 | ZeroMemory(&ofn, sizeof(ofn)); 38 | ofn.lStructSize = sizeof(ofn); 39 | ofn.hwndOwner = 0; 40 | ofn.lpstrFile = filepath; 41 | ofn.nMaxFile = sizeof(filepath); 42 | ofn.lpstrFilter = "Website Access Log\0*.log\0*.*\0*.*\0"; 43 | ofn.nFilterIndex = 1; 44 | ofn.lpstrFileTitle = 0; 45 | ofn.nMaxFileTitle = 0; 46 | ofn.lpstrInitialDir = 0; 47 | ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; 48 | 49 | GetOpenFileName(&ofn); 50 | 51 | //change back to original directory 52 | if(chdir(cwd_buff) != 0) { 53 | SDLAppQuit("error changing directory"); 54 | } 55 | 56 | return std::string(filepath); 57 | } 58 | #endif 59 | 60 | int main(int argc, char *argv[]) { 61 | 62 | ConfFile conf; 63 | std::vector files; 64 | 65 | SDLAppInit("Logstalgia", "logstalgia"); 66 | 67 | #ifdef _WIN32 68 | SDLApp::initConsole(); 69 | #endif 70 | 71 | try { 72 | settings.parseArgs(argc, argv, conf, &files); 73 | 74 | //set log level 75 | Logger::getDefault()->setLevel(settings.log_level); 76 | 77 | #ifdef _WIN32 78 | // hide console if not needed 79 | if(settings.log_level == LOG_LEVEL_OFF && !SDLApp::existing_console) { 80 | SDLApp::showConsole(false); 81 | } 82 | #endif 83 | //load config 84 | if(!settings.load_config.empty()) { 85 | conf.clear(); 86 | conf.load(settings.load_config); 87 | 88 | //apply args to loaded conf file 89 | settings.parseArgs(argc, argv, conf); 90 | } 91 | 92 | if(!files.empty()) { 93 | std::string path = files[files.size()-1]; 94 | 95 | ConfSectionList* sectionlist = conf.getSections("logstalgia"); 96 | 97 | if(sectionlist!=0) { 98 | for(ConfSectionList::iterator sit = sectionlist->begin(); sit != sectionlist->end(); sit++) { 99 | (*sit)->setEntry("path", path); 100 | } 101 | } else { 102 | conf.setEntry("logstalgia", "path", path); 103 | } 104 | } 105 | 106 | //apply the config / see if its valid 107 | settings.importDisplaySettings(conf); 108 | settings.importLogstalgiaSettings(conf); 109 | 110 | //save config 111 | if(!settings.save_config.empty()) { 112 | conf.save(settings.save_config); 113 | exit(0); 114 | } 115 | 116 | 117 | } catch(ConfFileException& exception) { 118 | 119 | SDLAppQuit(exception.what()); 120 | } 121 | 122 | #ifdef _WIN32 123 | if(settings.path.empty()) { 124 | 125 | //open file dialog 126 | settings.path = win32LogSelector(); 127 | 128 | //TODO chdir back to original directory 129 | 130 | if(settings.path.empty()) return 0; 131 | } 132 | #endif 133 | 134 | if(settings.path.empty()) SDLAppQuit("no file supplied"); 135 | 136 | //enable vsync 137 | display.enableVsync(settings.vsync); 138 | 139 | //enable frameless 140 | display.enableFrameless(settings.frameless); 141 | 142 | // this causes corruption on some video drivers 143 | if(settings.multisample) display.multiSample(4); 144 | 145 | if(settings.resizable && settings.output_ppm_filename.empty()) { 146 | display.enableResize(true); 147 | } 148 | 149 | // Change OS High DPI display behaviour 150 | // On Windows this behaves differently, it seems safe to always enable it 151 | bool high_dpi = true; 152 | #ifndef _WIN32 153 | // Requesting High DPI on MacOS may cause the pixel resolution to be doubled. 154 | // If a resolution has been specified this may not be appropriate 155 | // E.g. if you are recording a video at a specific resolution 156 | // Can override by supplying --high-dpi option. 157 | if(/* settings.viewport_specified && */ !settings.high_dpi) { 158 | high_dpi = false; 159 | } 160 | #endif 161 | display.enableHighDPIAwareness(high_dpi); 162 | 163 | display.init("Logstalgia", settings.display_width, settings.display_height, settings.fullscreen, settings.screen); 164 | 165 | #if SDL_VERSION_ATLEAST(2,0,0) 166 | if(!display.isFullscreen() && settings.window_x >= 0 && settings.window_y >= 0) { 167 | SDL_SetWindowPosition(display.sdl_window, settings.window_x, settings.window_y); 168 | } 169 | 170 | // Don't minimize when alt-tabbing so you can fullscreen logstalgia on a second monitor 171 | SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); 172 | #endif 173 | 174 | // run unit tests 175 | if(settings.run_tests) { 176 | LogstalgiaTester tester; 177 | try { 178 | tester.runTests(); 179 | } catch(std::exception& e) { 180 | SDLAppQuit(e.what()); 181 | } 182 | display.quit(); 183 | exit(0); 184 | } 185 | 186 | //disable OpenGL 2.0 functions if not supported 187 | if(!GLEW_VERSION_2_0) settings.ffp = true; 188 | 189 | //init frame exporter 190 | FrameExporter* exporter = 0; 191 | 192 | if(!settings.output_ppm_filename.empty()) { 193 | 194 | try { 195 | 196 | exporter = new PPMExporter(settings.output_ppm_filename); 197 | 198 | } catch(PPMExporterException& exception) { 199 | 200 | char errormsg[1024]; 201 | snprintf(errormsg, 1024, "could not write to '%s'", exception.what()); 202 | 203 | SDLAppQuit(errormsg); 204 | } 205 | } 206 | 207 | if(settings.multisample) glEnable(GL_MULTISAMPLE_ARB); 208 | 209 | Logstalgia* ls = 0; 210 | 211 | try { 212 | ls = new Logstalgia(settings.path); 213 | 214 | if(exporter != 0) { 215 | ls->setFrameExporter(exporter); 216 | } 217 | 218 | ls->run(); 219 | 220 | } catch(ResourceException& exception) { 221 | 222 | char errormsg[1024]; 223 | snprintf(errormsg, 1024, "failed to load resource '%s'", exception.what()); 224 | 225 | SDLAppQuit(errormsg); 226 | 227 | } catch(SDLAppException& exception) { 228 | 229 | if(exception.showHelp()) { 230 | settings.help(); 231 | } else { 232 | SDLAppQuit(exception.what()); 233 | } 234 | 235 | } 236 | 237 | if(ls!=0) delete ls; 238 | 239 | if(exporter!=0) delete exporter; 240 | 241 | display.quit(); 242 | 243 | return 0; 244 | } 245 | -------------------------------------------------------------------------------- /src/ncsa.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2010 Andrew Caudwell (acaudwell@gmail.com) 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | as published by the Free Software Foundation; either version 7 | 3 of the License, or (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include "ncsa.h" 19 | #include "core/regex.h" 20 | #include "settings.h" 21 | 22 | #include 23 | 24 | const char* ls_ncsa_months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug" , "Sep", "Oct", "Nov", "Dec" }; 25 | Regex ls_ncsa_entry_start("^(?:([^ ]+) )?([^ ]+) +[^ ]+ +([^ ]+) +\\[(.*?)\\] +(.*)$"); 26 | Regex ls_ncsa_entry_date("(\\d+)/(\\d+|[A-Za-z]+)/(\\d+):(\\d+):(\\d+):(\\d+) ([+-])(\\d+)"); 27 | Regex ls_ncsa_entry_request("\"(?:([^ ]+) +([^ ]+) +([^ ]+)|(?:[^\"]*))\" +([^ ]+) +([^\\s+]+)(.*)"); 28 | Regex ls_ncsa_entry_agent("(?: +\"([^\"]+)\" +\"([^\"]+)\")?( .+)?"); 29 | Regex ls_ncsa_extra_field("^ +(\"[^\"]*\"|[^ ]+)"); 30 | 31 | NCSALog::NCSALog() { 32 | } 33 | 34 | //parse NCSA format access.log entry into components 35 | bool NCSALog::parseLine(std::string& line, LogEntry& entry) { 36 | 37 | std::vector matches; 38 | ls_ncsa_entry_start.match(line, &matches); 39 | 40 | if(matches.size()!=5) { 41 | return 0; 42 | } 43 | 44 | //get details 45 | entry.vhost = matches[0]; 46 | entry.hostname = matches[1]; 47 | //entry.username = matches[1]; 48 | 49 | if(settings.display_log_entry) { 50 | entry.log_entry = line; 51 | } 52 | 53 | //parse timestamp 54 | struct tm time_str; 55 | 56 | int day, month, year, hour, minute, second; 57 | 58 | std::string request_str = matches[4]; 59 | std::string datestr = matches[3]; 60 | 61 | matches.clear(); 62 | ls_ncsa_entry_date.match(datestr, &matches); 63 | 64 | if(matches.size()!=8) { 65 | return 0; 66 | } 67 | 68 | day = atoi(matches[0].c_str()); 69 | month = atoi(matches[1].c_str()); 70 | year = atoi(matches[2].c_str()); 71 | hour = atoi(matches[3].c_str()); 72 | minute = atoi(matches[4].c_str()); 73 | second = atoi(matches[5].c_str()); 74 | 75 | if(month) { 76 | month--; 77 | } else { 78 | //parse non numeric month 79 | for(int i=0;i<12;i++) { 80 | if(strcmp(matches[1].c_str(), ls_ncsa_months[i])==0) { 81 | month=i; 82 | break; 83 | } 84 | } 85 | } 86 | 87 | //could not parse month (range 0-11 as used by mktime) 88 | if(month<0 || month>11) return 0; 89 | 90 | //convert zone to utc offset 91 | int tz_hour = atoi(matches[7].substr(0,2).c_str()); 92 | int tz_min = atoi(matches[7].substr(2,2).c_str()); 93 | 94 | int tz_offset = tz_hour * 3600 + tz_min * 60; 95 | 96 | if(matches[6] == "-") { 97 | tz_offset = -tz_offset; 98 | } 99 | 100 | time_str.tm_year = year - 1900; 101 | time_str.tm_mon = month; 102 | time_str.tm_mday = day; 103 | time_str.tm_hour = hour; 104 | time_str.tm_min = minute; 105 | time_str.tm_sec = second; 106 | time_str.tm_isdst = -1; 107 | 108 | entry.timestamp = mktime(&time_str); 109 | 110 | //apply utc offset 111 | entry.timestamp -= tz_offset; 112 | 113 | matches.clear(); 114 | ls_ncsa_entry_request.match(request_str, &matches); 115 | 116 | if(matches.size() < 5) { 117 | return 0; 118 | } 119 | 120 | entry.method = matches[0]; 121 | entry.path = (!matches[1].empty()) ? matches[1] : "???"; 122 | entry.protocol = matches[2]; 123 | 124 | entry.response_code = matches[3]; 125 | entry.response_size = atol(matches[4].c_str()); 126 | 127 | if(matches.size() > 5) { 128 | std::string agentstr = matches[5]; 129 | matches.clear(); 130 | ls_ncsa_entry_agent.match(agentstr, &matches); 131 | 132 | if(matches.size()==3) { 133 | entry.referrer = matches[0]; 134 | entry.user_agent = matches[1]; 135 | 136 | std::string extra = matches[2]; 137 | 138 | // NOTE: could store extra fields and allow --paddle-mode to address then via their offset 139 | if(!extra.empty()) { 140 | 141 | std::vector extra_fields; 142 | if(ls_ncsa_extra_field.matchAll(extra, &extra_fields)) { 143 | 144 | // for(size_t i=0;i=2 && entry.pid[0] == '"' && entry.pid[entry.pid.size()-1] == '"') { 152 | entry.pid = entry.pid.substr(1, entry.pid.size()-2); 153 | } 154 | } 155 | } 156 | } 157 | } 158 | } 159 | 160 | //successful if response code less than 400 161 | int code = atoi(entry.response_code.c_str()); 162 | 163 | entry.setSuccess(); 164 | entry.setResponseColour(); 165 | 166 | return entry.validate(); 167 | } 168 | 169 | -------------------------------------------------------------------------------- /src/ncsa.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2010 Andrew Caudwell (acaudwell@gmail.com) 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | as published by the Free Software Foundation; either version 7 | 3 of the License, or (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef NCSA_ACCESS_LOG 19 | #define NCSA_ACCESS_LOG 20 | 21 | #include "logentry.h" 22 | 23 | class NCSALog : public AccessLog { 24 | 25 | public: 26 | NCSALog(); 27 | bool parseLine(std::string& line, LogEntry& entry); 28 | }; 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /src/paddle.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2008 Andrew Caudwell (acaudwell@gmail.com) 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | as published by the Free Software Foundation; either version 7 | 3 of the License, or (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include "paddle.h" 19 | #include "requestball.h" 20 | #include "settings.h" 21 | 22 | #include "core/stringhash.h" 23 | 24 | Paddle::Paddle(vec2 pos, vec4 colour, std::string token, FXFont font) { 25 | this->token = token; 26 | 27 | // TODO: fix colouring 28 | // this->token_colour = token.size() > 0 ? colourHash2(token) : vec3(0.5,0.5,0.5); 29 | this->token_colour = token.size() > 0 ? colourHash(token) : vec3(0.5,0.5,0.5); 30 | 31 | this->pos = pos; 32 | this->lastcol = colour; 33 | this->default_colour = colour; 34 | this->colour = lastcol; 35 | this->width = 10; 36 | this->height = 50; 37 | this->target = 0; 38 | 39 | font.alignTop(true); 40 | font.alignRight(true); 41 | font.dropShadow(true); 42 | 43 | this->font = font; 44 | 45 | dest_y = -1; 46 | } 47 | 48 | Paddle::~Paddle() { 49 | } 50 | 51 | void Paddle::moveTo(int y, float eta, vec4 nextcol) { 52 | this->start_y = (int) this->pos.y; 53 | this->dest_y = y; 54 | this->dest_eta = eta; 55 | this->dest_elapsed = 0.0f; 56 | this->nextcol = nextcol; 57 | 58 | //debugLog("move to %d over %.2f\n", dest_y, dest_eta); 59 | } 60 | 61 | bool Paddle::visible() { 62 | return colour.w > 0.01; 63 | } 64 | 65 | bool Paddle::moving() { 66 | return dest_y != -1; 67 | } 68 | 69 | float Paddle::getY() { 70 | return pos.y; 71 | } 72 | 73 | float Paddle::getX() { 74 | return pos.x; 75 | } 76 | 77 | void Paddle::setX(float x) { 78 | pos.x = x; 79 | } 80 | 81 | RequestBall* Paddle::getTarget() { 82 | return target; 83 | } 84 | 85 | void Paddle::setTarget(RequestBall* target) { 86 | this->target = target; 87 | 88 | if(target==0) { 89 | moveTo(display.height/2, 4, default_colour); 90 | return; 91 | } 92 | 93 | vec2 dest = target->getFinishPos(); 94 | vec4 col = (settings.paddle_mode == PADDLE_VHOST || settings.paddle_mode == PADDLE_PID) ? 95 | vec4(token_colour,1.0) : vec4(target->getColour(), 1.0f); 96 | 97 | moveTo((int)dest.y, target->arrivalTime(), col); 98 | } 99 | 100 | bool Paddle::mouseOver(TextArea& textarea, vec2& mouse) { 101 | 102 | if(!token.empty() && pos.x <= mouse.x && pos.x + width >= mouse.x && abs(pos.y - mouse.y) < height/2) { 103 | 104 | std::vector content; 105 | 106 | content.push_back( token ); 107 | 108 | textarea.setText(content); 109 | textarea.setPos(mouse); 110 | textarea.setColour(vec3(colour)); 111 | 112 | return true; 113 | } 114 | 115 | return false; 116 | } 117 | 118 | void Paddle::logic(float dt) { 119 | 120 | if(dest_y != -1) { 121 | float remaining = dest_eta - dest_elapsed; 122 | 123 | if(remaining<0.0f) { 124 | //debugLog("paddle end point reached\n"); 125 | pos.y = dest_y; 126 | dest_y = -1; 127 | target = 0; 128 | colour = nextcol; 129 | lastcol = colour; 130 | } else { 131 | float alpha = remaining/dest_eta; 132 | pos.y = start_y + ((dest_y-start_y)*(1.0f - alpha)); 133 | colour = lastcol * alpha + nextcol * (1.0f - alpha); 134 | } 135 | 136 | dest_elapsed += dt; 137 | } 138 | } 139 | 140 | void Paddle::drawToken() { 141 | font.setColour(colour); 142 | font.draw(pos.x-10, pos.y - (font.getMaxHeight()/2), token); 143 | } 144 | 145 | void Paddle::drawShadow() { 146 | 147 | vec2 spos = vec2(pos.x + 1.0f, pos.y + 1.0f); 148 | 149 | glColor4f(0.0, 0.0, 0.0, 0.7 * colour.w); 150 | glBegin(GL_QUADS); 151 | glVertex2f(spos.x,spos.y-(height/2)); 152 | glVertex2f(spos.x,spos.y+(height/2)); 153 | glVertex2f(spos.x+width,spos.y+(height/2)); 154 | glVertex2f(spos.x+width,spos.y-(height/2)); 155 | glEnd(); 156 | } 157 | 158 | void Paddle::draw() { 159 | 160 | glColor4fv(glm::value_ptr(colour)); 161 | glBegin(GL_QUADS); 162 | glVertex2f(pos.x,pos.y-(height/2)); 163 | glVertex2f(pos.x,pos.y+(height/2)); 164 | glVertex2f(pos.x+width,pos.y+(height/2)); 165 | glVertex2f(pos.x+width,pos.y-(height/2)); 166 | glEnd(); 167 | } 168 | -------------------------------------------------------------------------------- /src/paddle.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2008 Andrew Caudwell (acaudwell@gmail.com) 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | as published by the Free Software Foundation; either version 7 | 3 of the License, or (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef PADDLE_H 19 | #define PADDLE_H 20 | 21 | #include "textarea.h" 22 | #include "core/fxfont.h" 23 | #include "core/vectors.h" 24 | 25 | class RequestBall; 26 | class Paddle { 27 | 28 | protected: 29 | vec2 pos; 30 | 31 | RequestBall* target; 32 | 33 | std::string token; 34 | vec3 token_colour; 35 | 36 | vec4 default_colour; 37 | vec4 proc_colour; 38 | vec4 colour; 39 | vec4 lastcol; 40 | vec4 nextcol; 41 | 42 | int width, height; 43 | 44 | int start_y; 45 | int dest_y; 46 | float dest_eta; 47 | float dest_elapsed; 48 | 49 | FXFont font; 50 | public: 51 | Paddle(vec2 pos, vec4 colour, std::string token, FXFont font); 52 | ~Paddle(); 53 | void moveTo(int y, float eta, vec4 nextcol); 54 | bool moving(); 55 | bool visible(); 56 | 57 | void setTarget(RequestBall* target); 58 | RequestBall* getTarget(); 59 | 60 | void logic(float dt); 61 | 62 | bool mouseOver(TextArea& textarea, vec2& mouse); 63 | 64 | void drawToken(); 65 | void drawShadow(); 66 | void draw(); 67 | 68 | void setX(float x); 69 | 70 | float getX(); 71 | float getY(); 72 | }; 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /src/requestball.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2008 Andrew Caudwell (acaudwell@gmail.com) 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | as published by the Free Software Foundation; either version 7 | 3 of the License, or (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include "requestball.h" 19 | #include "settings.h" 20 | #include "textarea.h" 21 | #include "logentry.h" 22 | 23 | RequestBall::RequestBall(LogEntry* le, const vec3& colour, const vec2& pos, const vec2& dest) 24 | : le(le), pos(pos), dest(dest), colour(colour) { 25 | 26 | dir = glm::normalize(dest - pos); 27 | 28 | int bytes = le->response_size; 29 | size = log((float)bytes) + 1.0f; 30 | if(size<5.0f) size = 5.0f; 31 | 32 | has_bounced = false; 33 | no_bounce = !le->successful; 34 | 35 | distance_travelled = 0.0f; 36 | total_distance = 0.0; 37 | 38 | points.push_back(pos); 39 | addPoint(dest); 40 | 41 | float halfsize = size * 0.5f; 42 | offset = vec2(halfsize, halfsize); 43 | } 44 | 45 | RequestBall::~RequestBall() { 46 | delete le; 47 | } 48 | 49 | void RequestBall::addPoint(const vec2& p) { 50 | float line_length = glm::length(points.back() - p); 51 | total_distance += line_length; 52 | points.push_back(p); 53 | line_lengths.push_back(line_length); 54 | } 55 | 56 | void RequestBall::changeDestX(float dest_x) { 57 | if(has_bounced) return; 58 | 59 | if(dest_x <= pos.x) { 60 | bounce(); 61 | return; 62 | } 63 | 64 | float t = (dir.y / dir.x); 65 | 66 | vec2 start = points[0]; 67 | 68 | float a = t * (dest_x - start.x); 69 | float y = start.y + a; 70 | 71 | dest = vec2(dest_x, y); 72 | 73 | total_distance = 0.0f; 74 | line_lengths.clear(); 75 | 76 | points.clear(); 77 | points.push_back(start); 78 | addPoint(dest); 79 | } 80 | 81 | void RequestBall::project() { 82 | distance_travelled = 0.0f; 83 | total_distance = 0.0f; 84 | 85 | vec2 target = dest; 86 | 87 | if(!no_bounce) { 88 | dir.x = -dir.x; 89 | target.x = 0; 90 | } else { 91 | target.x = display.width; 92 | } 93 | 94 | points.clear(); 95 | line_lengths.clear(); 96 | 97 | points.push_back(pos); 98 | 99 | // tan = o / a 100 | // o = tan * a 101 | // a = o / tan 102 | 103 | float t = (dir.y / dir.x); 104 | 105 | float a = (target.x - pos.x); 106 | float y = pos.y + t * a; 107 | 108 | if(y < offset.y || y > display.height-offset.y) { 109 | 110 | // bounced off the top/bottom of screen 111 | 112 | float intersect_y = y <= offset.y ? offset.y : display.height-offset.y; 113 | 114 | float o = (intersect_y - pos.y); 115 | float x = pos.x + (o / t); 116 | 117 | vec2 intersect = vec2(x, intersect_y); 118 | 119 | addPoint(intersect); 120 | 121 | // continue from bounce to destination 122 | 123 | vec2 bounce_dir = dir; 124 | 125 | bounce_dir.y = -bounce_dir.y; 126 | 127 | t = (bounce_dir.y / bounce_dir.x); 128 | 129 | a = t * (target.x - intersect.x); 130 | y = intersect.y + a; 131 | 132 | intersect = vec2(target.x, y); 133 | 134 | addPoint(intersect); 135 | } else { 136 | vec2 intersect = vec2(target.x, y); 137 | addPoint(intersect); 138 | } 139 | } 140 | 141 | bool RequestBall::isFinished() const { 142 | return has_bounced && distance_travelled >= total_distance; 143 | } 144 | 145 | void RequestBall::bounce() { 146 | if(has_bounced) return; 147 | 148 | project(); 149 | 150 | has_bounced=true; 151 | } 152 | 153 | float RequestBall::arrivalTime() { 154 | return (total_distance-distance_travelled) / (settings.pitch_speed * (float) display.width); 155 | } 156 | 157 | float RequestBall::getProgress() const { 158 | return (distance_travelled/total_distance); 159 | } 160 | 161 | const vec2& RequestBall::getFinishPos() const { 162 | return points.back(); 163 | } 164 | 165 | bool RequestBall::hasBounced() const { 166 | return has_bounced; 167 | } 168 | 169 | const vec3& RequestBall::getColour() const { 170 | return colour; 171 | } 172 | 173 | LogEntry* RequestBall::getLogEntry() const { 174 | return le; 175 | } 176 | 177 | void RequestBall::formatRequestDetail(LogEntry* le, TextArea& textarea) { 178 | 179 | std::vector content; 180 | 181 | std::vector fields = settings.display_fields; 182 | if(fields.empty()) fields = LogEntry::getDefaultFields(); 183 | 184 | size_t longest_title = 0; 185 | for(const std::string& field : fields) { 186 | longest_title = std::max( longest_title, le->getFieldTitle(field).size() ); 187 | } 188 | 189 | for(const std::string& field : fields) { 190 | 191 | std::string title = le->getFieldTitle(field); 192 | 193 | int title_padding_length = longest_title - title.size(); 194 | 195 | if(title_padding_length > 0) { 196 | title += std::string().append(title_padding_length, ' '); 197 | } 198 | 199 | std::string value; 200 | le->getValue(field, value); 201 | 202 | std::string overflow_padding(title.size() + 1, ' '); 203 | 204 | size_t max_characters = textarea.getMaxCharacters(); 205 | 206 | size_t max_value_length = std::max(0, (int) (max_characters - overflow_padding.size())); 207 | 208 | if(!value.empty() && max_value_length > 0) { 209 | content.push_back(title + std::string(" ") + value.substr(0, max_value_length)); 210 | 211 | for(size_t i = max_value_length; i < value.length(); i += max_value_length) { 212 | content.push_back(overflow_padding + value.substr(i, max_value_length)); 213 | } 214 | } 215 | } 216 | 217 | textarea.setText(content); 218 | } 219 | 220 | bool RequestBall::mouseOver(TextArea& textarea, vec2& mouse) { 221 | 222 | //within 3 pixels 223 | vec2 from_mouse = pos - mouse; 224 | 225 | if( glm::dot(from_mouse, from_mouse) < 36.0f) { 226 | 227 | std::vector content; 228 | formatRequestDetail(le, textarea); 229 | 230 | textarea.setPos(mouse); 231 | textarea.setColour(colour); 232 | return true; 233 | } 234 | 235 | return false; 236 | } 237 | 238 | void RequestBall::animate(float dt) { 239 | distance_travelled += dt * settings.pitch_speed * (float) display.width; 240 | 241 | if(distance_travelled >= total_distance) { 242 | 243 | if(!has_bounced) { 244 | bounce(); 245 | } 246 | return; 247 | } 248 | 249 | //number of lines 250 | int nolines = points.size()-1; 251 | 252 | int pointno = 0; 253 | float len=0; 254 | 255 | while(pointno < nolines && len+line_lengths[pointno] < distance_travelled) { 256 | len += line_lengths[pointno]; 257 | pointno++; 258 | } 259 | 260 | if(pointno>=nolines) { 261 | 262 | if(!has_bounced) { 263 | bounce(); 264 | return; 265 | } 266 | 267 | return; 268 | } 269 | 270 | vec2 from = points[pointno]; 271 | vec2 to = points[pointno+1]; 272 | 273 | float linepos = (distance_travelled - len)/line_lengths[pointno]; 274 | 275 | this->pos = from + ((to-from)*linepos); 276 | } 277 | 278 | int RequestBall::logic(float dt) { 279 | float old_x = pos.x; 280 | 281 | animate(dt); 282 | 283 | //returns 1 if just became visible (for score incrementing) 284 | return (old_x<0.0f && pos.x>=0.0f); 285 | } 286 | 287 | void RequestBall::drawGlow() const { 288 | if(!has_bounced) return; 289 | 290 | float prog = getProgress(); 291 | 292 | float glow_radius = size * size * settings.glow_multiplier; 293 | 294 | float alpha = std::min(1.0f, 1.0f-(prog/settings.glow_duration)) * settings.glow_intensity; 295 | 296 | if(alpha <=0.001f) return; 297 | 298 | vec3 glow_col = colour * alpha; 299 | 300 | glColor4f(glow_col.x, glow_col.y, glow_col.z, 1.0f); 301 | 302 | glPushMatrix(); 303 | glTranslatef(pos.x, pos.y, 0.0f); 304 | 305 | glBegin(GL_QUADS); 306 | glTexCoord2f(1.0f, 1.0f); 307 | glVertex2f(glow_radius,glow_radius); 308 | glTexCoord2f(1.0f, 0.0f); 309 | glVertex2f(glow_radius,-glow_radius); 310 | glTexCoord2f(0.0f, 0.0f); 311 | glVertex2f(-glow_radius,-glow_radius); 312 | glTexCoord2f(0.0f, 1.0f); 313 | glVertex2f(-glow_radius,glow_radius); 314 | glEnd(); 315 | glPopMatrix(); 316 | } 317 | 318 | void RequestBall::draw() const { 319 | 320 | if(!settings.no_bounce || !has_bounced || no_bounce) { 321 | 322 | vec2 offsetpos = pos - offset; 323 | 324 | glColor4f(colour.x, colour.y, colour.z, 1.0f); 325 | 326 | glPushMatrix(); 327 | glTranslatef(offsetpos.x, offsetpos.y, 0.0f); 328 | 329 | glBegin(GL_QUADS); 330 | glTexCoord2f(0.0f,0.0f); 331 | glVertex2f(0.0f, 0.0f); 332 | 333 | glTexCoord2f(1.0f,0.0f); 334 | glVertex2f(size, 0.0f); 335 | 336 | glTexCoord2f(1.0f,1.0f); 337 | glVertex2f(size, size); 338 | 339 | glTexCoord2f(0.0f,1.0f); 340 | glVertex2f(0.0f, size); 341 | glEnd(); 342 | glPopMatrix(); 343 | } 344 | } 345 | 346 | void RequestBall::drawResponseCode(FXFont* font) const { 347 | float prog = getProgress(); 348 | 349 | float alpha = 1.0f - std::min(1.0f, prog * 2.0f); 350 | 351 | if(alpha<=0.001f) return; 352 | 353 | float drift = prog * 100.0f; 354 | 355 | vec2 msgpos = (dir * drift) + vec2(dest.x-45.0f, dest.y); 356 | 357 | font->setColour(vec4(le->response_colour.x, le->response_colour.y, le->response_colour.z, alpha)); 358 | font->draw(msgpos.x, msgpos.y, le->response_code); 359 | } 360 | -------------------------------------------------------------------------------- /src/requestball.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2008 Andrew Caudwell (acaudwell@gmail.com) 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | as published by the Free Software Foundation; either version 7 | 3 of the License, or (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef REQUESTBALL_H 19 | #define REQUESTBALL_H 20 | 21 | #include 22 | #include 23 | 24 | #include "core/vectors.h" 25 | 26 | class FXFont; 27 | class TextArea; 28 | class LogEntry; 29 | 30 | class RequestBall { 31 | protected: 32 | std::vector points; 33 | std::vector line_lengths; 34 | 35 | LogEntry* le; 36 | 37 | float size; 38 | 39 | vec2 pos; 40 | vec2 dest; 41 | vec2 dir; 42 | 43 | vec3 colour; 44 | 45 | float distance_travelled; 46 | float total_distance; 47 | 48 | bool has_bounced; 49 | bool no_bounce; 50 | 51 | vec2 offset; 52 | 53 | void formatRequestDetail(LogEntry *le, TextArea& textarea); 54 | 55 | float getProgress() const; 56 | 57 | void project(); 58 | void bounce(); 59 | 60 | void addPoint(const vec2& p); 61 | 62 | void animate(float dt); 63 | public: 64 | RequestBall(LogEntry* le, const vec3& colour, const vec2& pos, const vec2& dest); 65 | ~RequestBall(); 66 | 67 | bool mouseOver(TextArea& textarea, vec2& mouse); 68 | 69 | float arrivalTime(); 70 | 71 | bool isFinished() const; 72 | bool hasBounced() const; 73 | 74 | void changeDestX(float dest_x); 75 | 76 | const vec2& getFinishPos() const; 77 | 78 | const vec3& getColour() const; 79 | LogEntry* getLogEntry() const; 80 | 81 | int logic(float dt); 82 | 83 | void drawGlow() const; 84 | void draw() const; 85 | void drawResponseCode(FXFont* font) const; 86 | }; 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /src/settings.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2013 Andrew Caudwell (acaudwell@gmail.com) 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | as published by the Free Software Foundation; either version 7 | 3 of the License, or (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef LOGSTALGIA_SETTINGS_H 19 | #define LOGSTALGIA_SETTINGS_H 20 | 21 | #define LOGSTALGIA_VERSION "1.1.4" 22 | 23 | #include "core/settings.h" 24 | 25 | #define PADDLE_NONE 0 26 | #define PADDLE_SINGLE 1 27 | #define PADDLE_PID 2 28 | #define PADDLE_VHOST 3 29 | 30 | class SummarizerGroup { 31 | public: 32 | SummarizerGroup(); 33 | 34 | std::string title; 35 | std::string type; 36 | std::string regex; 37 | std::string separators; 38 | int max_depth; 39 | int abbrev_depth; 40 | int percent; 41 | vec3 colour; 42 | 43 | std::string definition; 44 | 45 | static bool parse(const std::string& group_string, SummarizerGroup& group, std::string& error); 46 | }; 47 | 48 | class LogstalgiaSettings : public SDLAppSettings { 49 | protected: 50 | void commandLineOption(const std::string& name, const std::string& value); 51 | public: 52 | int log_level; 53 | bool ffp; 54 | 55 | std::string path; 56 | std::vector groups; 57 | 58 | std::string load_config; 59 | std::string save_config; 60 | 61 | std::vector display_fields; 62 | bool display_log_entry; 63 | 64 | bool detect_changes; 65 | bool run_tests; 66 | 67 | time_t start_time; 68 | time_t stop_time; 69 | 70 | float splash; 71 | 72 | float simulation_speed; 73 | float pitch_speed; 74 | float update_rate; 75 | 76 | int paddle_mode; 77 | float paddle_position; 78 | 79 | float start_position; 80 | float stop_position; 81 | 82 | bool sync; 83 | 84 | bool hide_response_code; 85 | bool hide_url_prefix; 86 | bool hide_paddle; 87 | bool hide_paddle_tokens; 88 | 89 | bool no_bounce; 90 | 91 | bool disable_auto_skip; 92 | bool disable_progress; 93 | bool disable_glow; 94 | 95 | bool mask_hostnames; 96 | 97 | vec3 background_colour; 98 | 99 | float glow_intensity; 100 | float glow_multiplier; 101 | float glow_duration; 102 | 103 | int address_max_depth; 104 | int address_abbr_depth; 105 | std::string address_separators; 106 | 107 | int path_max_depth; 108 | int path_abbr_depth; 109 | std::string path_separators; 110 | 111 | int font_size; 112 | 113 | std::string title; 114 | 115 | LogstalgiaSettings(); 116 | 117 | void setLogstalgiaDefaults(); 118 | 119 | void importLogstalgiaSettings(ConfFile& conf, ConfSection* settings = 0); 120 | void exportLogstalgiaSettings(ConfFile& conf); 121 | 122 | void help(bool extended_help=false); 123 | }; 124 | 125 | extern LogstalgiaSettings settings; 126 | 127 | #endif 128 | -------------------------------------------------------------------------------- /src/slider.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | as published by the Free Software Foundation; either version 7 | 3 of the License, or (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include "slider.h" 19 | 20 | // PositionSlider 21 | 22 | PositionSlider::PositionSlider(float percent) { 23 | this->percent = percent; 24 | 25 | font = fontmanager.grab("FreeMonoBold.ttf", 16, 72, FT_LOAD_NO_HINTING); 26 | font.dropShadow(true); 27 | 28 | slidercol = vec3(1.0, 1.0, 1.0); 29 | 30 | mouseover = -1.0; 31 | 32 | mouseover_elapsed = 1.0; 33 | fade_time = 1.0; 34 | alpha = 0.0; 35 | 36 | resize(); 37 | } 38 | 39 | const Bounds2D& PositionSlider::getBounds() const { 40 | return bounds; 41 | } 42 | 43 | bool PositionSlider::isVisible() const { 44 | return alpha > 0.0f; 45 | } 46 | 47 | void PositionSlider::resize() { 48 | 49 | int gap = 35; 50 | int offset = 45; 51 | 52 | bounds.reset(); 53 | bounds.update(vec2(gap, display.height - gap - offset)); 54 | bounds.update(vec2(display.width - gap, display.height - offset)); 55 | } 56 | 57 | void PositionSlider::setColour(vec3 col) { 58 | slidercol = col; 59 | } 60 | 61 | void PositionSlider::show() { 62 | mouseover_elapsed = 0.0; 63 | } 64 | 65 | bool PositionSlider::isMouseOver(const vec2& pos) const { 66 | return (isVisible() && bounds.contains(pos)); 67 | } 68 | 69 | bool PositionSlider::mouseMove(const vec2& pos, float* percent_ptr) { 70 | if(bounds.contains(pos)) { 71 | 72 | mouseover_elapsed = 0; 73 | mouseover = pos.x; 74 | 75 | if(percent_ptr != 0) { 76 | *percent_ptr = (float) (pos.x - bounds.min.x) / (bounds.max.x - bounds.min.x); 77 | } 78 | 79 | return true; 80 | } 81 | 82 | mouseover = -1.0; 83 | 84 | return false; 85 | } 86 | 87 | bool PositionSlider::click(const vec2& pos, float* percent_ptr) { 88 | if(mouseMove(pos, &percent)) { 89 | 90 | if(percent_ptr != 0) { 91 | *percent_ptr = percent; 92 | } 93 | 94 | return true; 95 | } 96 | 97 | return false; 98 | } 99 | 100 | void PositionSlider::setCaption(const std::string& caption) { 101 | capwidth = 0.0; 102 | this->caption = caption; 103 | 104 | if(caption.size()) { 105 | capwidth = font.getWidth(caption.c_str()); 106 | } 107 | } 108 | 109 | void PositionSlider::setPercent(float percent) { 110 | this->percent = percent; 111 | } 112 | 113 | void PositionSlider::logic(float dt) { 114 | 115 | if(mouseover < 0.0 && mouseover_elapsed < fade_time) mouseover_elapsed += dt; 116 | 117 | if(mouseover_elapsed < fade_time && alpha < 1.0) { 118 | alpha = std::min(1.0f, alpha+dt); 119 | 120 | } else if(mouseover_elapsed >= fade_time && alpha > 0.0) { 121 | 122 | alpha = std::max(0.0f, alpha-dt); 123 | 124 | } 125 | } 126 | 127 | void PositionSlider::drawSlider(float pos_x) const { 128 | 129 | glLineWidth(2.0f); 130 | 131 | bounds.draw(); 132 | 133 | glLineWidth(2.0f); 134 | 135 | glBegin(GL_LINES); 136 | glVertex2f(pos_x, bounds.min.y); 137 | glVertex2f(pos_x, bounds.max.y); 138 | glEnd(); 139 | } 140 | 141 | void PositionSlider::draw(float dt) { 142 | 143 | glDisable(GL_TEXTURE_2D); 144 | 145 | float pos_x = bounds.min.x + (bounds.max.x - bounds.min.x) * percent; 146 | 147 | glColor4f(0.0f, 0.0f, 0.0f, 0.7*alpha); 148 | 149 | glPushMatrix(); 150 | glTranslatef(2.0, 2.0, 0.0); 151 | drawSlider(pos_x); 152 | glPopMatrix(); 153 | 154 | glColor4f(slidercol.x, slidercol.y, slidercol.z, alpha); 155 | 156 | drawSlider(pos_x); 157 | 158 | glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 159 | glEnable(GL_BLEND); 160 | glEnable(GL_TEXTURE_2D); 161 | 162 | glColor4f(1.0, 1.0, 1.0, 1.0); 163 | 164 | if(caption.size() && mouseover >= 0.0) { 165 | font.draw(std::min((double)display.width - capwidth - 1.0, std::max(1.0, mouseover - (capwidth/2.0))), bounds.min.y - 25.0, caption); 166 | } 167 | 168 | } 169 | 170 | -------------------------------------------------------------------------------- /src/slider.h: -------------------------------------------------------------------------------- 1 | #ifndef POS_SLIDER_H 2 | #define POS_SLIDER_H 3 | 4 | #include "core/bounds.h" 5 | #include "core/fxfont.h" 6 | 7 | class PositionSlider { 8 | 9 | FXFont font; 10 | 11 | Bounds2D bounds; 12 | float percent; 13 | float mouseover; 14 | float mouseover_elapsed; 15 | float fade_time; 16 | float alpha; 17 | 18 | vec3 slidercol; 19 | 20 | float capwidth; 21 | std::string caption; 22 | 23 | void drawSlider(float position) const; 24 | public: 25 | PositionSlider(float percent = 0.0f); 26 | 27 | void setColour(vec3 col); 28 | 29 | void setCaption(const std::string& cap); 30 | 31 | void setPercent(float percent); 32 | 33 | void resize(); 34 | 35 | void show(); 36 | 37 | const Bounds2D& getBounds() const; 38 | 39 | bool isVisible() const; 40 | bool isMouseOver(const vec2& pos) const; 41 | bool mouseMove(const vec2& pos, float* percent_ptr); 42 | bool click(const vec2& pos, float* percent_ptr); 43 | void logic(float dt); 44 | void draw(float dt); 45 | }; 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /src/summarizer.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2008 Andrew Caudwell (acaudwell@gmail.com) 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | as published by the Free Software Foundation; either version 7 | 3 of the License, or (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #ifndef SUMMARIZER_H 19 | #define SUMMARIZER_H 20 | 21 | #include "core/stringhash.h" 22 | #include "core/fxfont.h" 23 | #include "core/regex.h" 24 | 25 | #include "textarea.h" 26 | 27 | extern const char* summ_wildcard; 28 | 29 | class SummNode; 30 | class Summarizer; 31 | 32 | class SummRow { 33 | public: 34 | SummRow(); 35 | SummRow(SummNode* source, bool abbreviated = false); 36 | 37 | SummNode* source; 38 | 39 | int words; 40 | int refs; 41 | std::string str; 42 | bool abbreviated; 43 | 44 | std::vector expanded; 45 | 46 | void prependChar(char c); 47 | void buildSummary(); 48 | }; 49 | 50 | class SummQuery { 51 | protected: 52 | int max_depth; 53 | int abbreviation_depth; 54 | public: 55 | SummQuery(int max_depth, int abbreviation_depth); 56 | 57 | bool limitMaxDepth() const; 58 | bool allowAbbreviations() const; 59 | 60 | int getMaxDepth() const; 61 | int getAbbreviationDepth() const; 62 | }; 63 | 64 | class SummNode { 65 | public: 66 | Summarizer* summarizer; 67 | SummNode* parent; 68 | 69 | SummNode(Summarizer* summarizer); 70 | SummNode(Summarizer* summarizer, SummNode* parent, const std::string& str, size_t offset); 71 | ~SummNode(); 72 | 73 | char c; 74 | int words; 75 | int refs; 76 | int delimiters; 77 | 78 | std::vector children; 79 | bool unsummarized; 80 | bool delimiter; 81 | 82 | void debug(int indent = 0) const; 83 | bool addWord(const std::string& str, size_t offset); 84 | bool removeWord(const std::string& str, size_t offset); 85 | 86 | void expand(std::string prefix, std::vector& expansion, bool unsummarized_only); 87 | 88 | void summarize(const SummQuery& query, std::vector& output, int max_rows, int depth = 0); 89 | 90 | std::string toString() const; 91 | protected: 92 | std::string formatNode(std::string str, int refs); 93 | }; 94 | 95 | class SummItem { 96 | Summarizer* summarizer; 97 | vec2 dest; 98 | vec2 oldpos; 99 | 100 | bool moving; 101 | 102 | float elapsed; 103 | float eta; 104 | public: 105 | SummItem(Summarizer* summarizer, SummRow row); 106 | 107 | bool departing; 108 | bool destroy; 109 | 110 | std::string displaystr; 111 | int width; 112 | 113 | SummRow row; 114 | 115 | vec4 colour; 116 | vec2 pos; 117 | 118 | bool isMoving() const; 119 | 120 | void setDest(const vec2& dest); 121 | void setPos(const vec2& pos); 122 | void setDeparting(bool departing); 123 | 124 | void logic(float dt); 125 | void draw(float alpha); 126 | 127 | void updateRow(const SummRow& row); 128 | }; 129 | 130 | class Summarizer { 131 | protected: 132 | std::vector strings; 133 | 134 | std::vector items; 135 | SummNode root; 136 | 137 | vec3 item_colour; 138 | bool has_colour; 139 | 140 | float pos_x; 141 | int max_strings; 142 | int font_gap; 143 | FXFont font; 144 | 145 | bool showcount; 146 | bool right; 147 | bool changed; 148 | 149 | std::vector delimiters; 150 | int abbreviation_depth; 151 | int max_depth; 152 | 153 | float incrementf; 154 | 155 | float title_top; 156 | float top_gap, bottom_gap; 157 | 158 | float refresh_delay; 159 | float refresh_elapsed; 160 | 161 | int screen_percent; 162 | 163 | std::string title; 164 | std::string display_title; 165 | std::string prefix_filter; 166 | Regex matchre; 167 | protected: 168 | static bool row_sorter(const SummRow &a, const SummRow &b); 169 | static bool item_sorter(const SummItem &a, const SummItem &b); 170 | 171 | const SummItem* itemAtPos(const vec2 &pos); 172 | 173 | void updateDisplayTitle(); 174 | public: 175 | Summarizer(FXFont font, int percent, int max_depth, int abbreviation_depth, float refresh_delay, 176 | std::string matchstr = ".*", std::string title=""); 177 | 178 | void clear(); 179 | 180 | void setPosX(float x); 181 | float getPosX() const; 182 | 183 | const std::string& getTitle() const; 184 | const SummNode* getRoot() const; 185 | 186 | void setSize(int x, float top_gap, float bottom_gap); 187 | bool isAnimating() const; 188 | 189 | int getScreenPercent(); 190 | 191 | bool setPrefixFilterAtPos(const vec2& pos); 192 | void setPrefixFilter(const std::string& prefix_filter); 193 | const std::string& getPrefixFilter() const; 194 | 195 | bool mouseOver(const vec2 &pos) const; 196 | bool getInfoAtPos(TextArea& textarea, const vec2& pos); 197 | 198 | bool hasColour() const; 199 | void setColour(const vec3& col); 200 | const vec3& getColour() const; 201 | 202 | void setShowCount(bool showcount); 203 | bool showCount() const; 204 | 205 | void setMaxDepth(int max_depth); 206 | int getMaxDepth() const; 207 | 208 | void setAbbreviationDepth(int abbreviation_depth); 209 | int getAbbreviationDepth() const; 210 | 211 | FXFont& getFont(); 212 | 213 | bool supportedString(const std::string& str); 214 | bool matchesPrefixFilter(const std::string& str) const; 215 | 216 | void removeString(const std::string& str); 217 | void addString(const std::string& str); 218 | 219 | void addDelimiter(char c); 220 | bool isDelimiter(char c) const; 221 | 222 | const SummNode* getMatchingNode(const std::string& input) const; 223 | const std::string& getBestMatchStr(const std::string& str) const; 224 | int getBestMatchIndex(const std::string& str) const; 225 | float getPosY(const std::string& str) const; 226 | float getMiddlePosY(const std::string& str) const; 227 | 228 | float calcPosY(int i) const; 229 | 230 | void summarize(); 231 | 232 | void getSummary(std::vector& summary) const; 233 | 234 | void recalc_display(); 235 | void logic(float dt); 236 | void draw(float dt, float alpha); 237 | }; 238 | 239 | #endif 240 | -------------------------------------------------------------------------------- /src/tests.cpp: -------------------------------------------------------------------------------- 1 | #include "tests.h" 2 | #include "summarizer.h" 3 | #include "settings.h" 4 | #include "core/regex.h" 5 | 6 | #define test(name,assertion,expected) if((assertion)!=(expected)) {\ 7 | char error[1024];\ 8 | snprintf(error, 1024, "test '%s' failed at %s:%d", name, __FILE__, __LINE__);\ 9 | throw TesterException(error);\ 10 | } 11 | 12 | LogstalgiaTester::LogstalgiaTester() 13 | { 14 | 15 | } 16 | 17 | void LogstalgiaTester::runTests() { 18 | 19 | FXFont font = fontmanager.grab("FreeMonoBold.ttf", settings.font_size, 72, FT_LOAD_NO_HINTING); 20 | 21 | display.width = 1024; 22 | display.height = 768; 23 | 24 | int max_depth = 0; 25 | int abbreviation_depth = 0; 26 | int percent = 50; 27 | float update_rate = 1.0f; 28 | 29 | // group parser tests 30 | 31 | SummarizerGroup failGroup; 32 | std::string parsingError; 33 | bool parsingSuccess = SummarizerGroup::parse("FAIL,CODE=^[45],SEP=/\\,MAX=2,ABBR=1,10", failGroup, parsingError); 34 | 35 | test("parsing succeeded", parsingSuccess, true); 36 | test("no parsing error", parsingError, ""); 37 | 38 | test("expected title", failGroup.title, "FAIL"); 39 | test("expected type", failGroup.type, "CODE"); 40 | test("expected regex", failGroup.regex, "^[45]"); 41 | test("expected separator", failGroup.separators, "/\\"); 42 | test("expected max_depth", failGroup.max_depth, 2); 43 | test("expected abbrev_depth", failGroup.abbrev_depth, 1); 44 | test("expected percent", failGroup.percent, 10); 45 | 46 | SummarizerGroup htmlGroup; 47 | 48 | parsingSuccess = SummarizerGroup::parse("HTML,.html?$,10", htmlGroup, parsingError); 49 | 50 | test("parsing succeeded", parsingSuccess, true); 51 | test("no parsing error", parsingError, ""); 52 | 53 | test("expected title", htmlGroup.title, "HTML"); 54 | test("expected type", htmlGroup.type, "URI"); 55 | test("expected regex", htmlGroup.regex, ".html?$"); 56 | test("expected separator", htmlGroup.separators, settings.path_separators); 57 | test("expected max_depth", htmlGroup.max_depth, settings.path_max_depth); 58 | test("expected abbrev_depth", htmlGroup.abbrev_depth, settings.path_abbr_depth); 59 | test("expected percent", htmlGroup.percent, 10); 60 | 61 | // summarizer tests 62 | 63 | Summarizer* html_summarizer = 0; 64 | std::string html_title = "HTML"; 65 | std::string html_regex = "\\.html?$"; 66 | 67 | try { 68 | html_summarizer = new Summarizer(font, percent, max_depth, abbreviation_depth, update_rate, html_regex, html_title); 69 | } catch(RegexCompilationException&) { 70 | 71 | } 72 | 73 | html_summarizer->addDelimiter('/'); 74 | html_summarizer->setSize(0, 0, 0); 75 | 76 | test("html summarizer created", html_summarizer != 0, true); 77 | test("'/' is a delimiter", html_summarizer->isDelimiter('/'), true); 78 | test("expected title", html_summarizer->getTitle(), html_title); 79 | test("html summarizer accepts index.html", html_summarizer->supportedString("/index.html"), true); 80 | test("html summarizer rejects cat.jpg", html_summarizer->supportedString("/images/cat.jpg"), false); 81 | 82 | Summarizer* image_summarizer = 0; 83 | std::string image_regex = "\\.(jpe?g|png)$"; 84 | std::string image_title = "Images"; 85 | 86 | try { 87 | image_summarizer = new Summarizer(font, percent, max_depth, abbreviation_depth, update_rate, image_regex, image_title); 88 | } catch(RegexCompilationException&) { 89 | 90 | } 91 | 92 | test("image summarizer created", image_summarizer != 0, true); 93 | 94 | image_summarizer->addDelimiter('/'); 95 | image_summarizer->setSize(0, 0, 0); 96 | 97 | test("'/' is a delimiter", image_summarizer->isDelimiter('/'), true); 98 | test("expected title", image_summarizer->getTitle(), image_title); 99 | test("expected abbreivation depth", image_summarizer->getAbbreviationDepth(), abbreviation_depth); 100 | 101 | test("image summarizer accepts cat.jpg", image_summarizer->supportedString("/images/cat.jpg"), true); 102 | test("image summarizer accepts cat.png", image_summarizer->supportedString("/images/cat.png"), true); 103 | test("image summarizer rejects index.html", image_summarizer->supportedString("/index.html"), false); 104 | 105 | image_summarizer->addString("/images/cat.jpg"); 106 | image_summarizer->addString("/images/cat.png"); 107 | image_summarizer->summarize(); 108 | 109 | std::vector summary; 110 | image_summarizer->getSummary(summary); 111 | 112 | test("summary size is 2", summary.size(), 2); 113 | test("summary[0] == /images/cat.jpg", summary[0], "/images/cat.jpg"); 114 | test("summary[1] == /images/cat.png", summary[1], "/images/cat.png"); 115 | 116 | image_summarizer->addString("/images/dog.jpg"); 117 | image_summarizer->summarize(); 118 | 119 | image_summarizer->getSummary(summary); 120 | test("summary size is 3", summary.size(), 3); 121 | test("summary[0] is /images/cat.jpg", summary[0], "/images/cat.jpg"); 122 | test("summary[1] is /images/cat.png", summary[1], "/images/cat.png"); 123 | test("summary[2] is /images/dog.jpg", summary[2], "/images/dog.jpg"); 124 | 125 | test("best match string for dog.jpg", image_summarizer->getBestMatchStr("/images/dog.jpg"), "/images/dog.jpg"); 126 | test("best match index for dog.jpg", image_summarizer->getBestMatchIndex("/images/dog.jpg"), 2); 127 | 128 | // verify expected ref, word counts 129 | 130 | const SummNode* images_node = image_summarizer->getMatchingNode("/images/"); 131 | test("/images/ node found", images_node != 0, true); 132 | test("/images/ refs is 3", images_node->refs, 3); 133 | test("/images/ words is 3", images_node->words, 3); 134 | test("/images/ delimiters is 1", images_node->delimiters, 1); 135 | 136 | const SummNode* cat_node = image_summarizer->getMatchingNode("/images/cat"); 137 | test("/images/cat node found", cat_node != 0, true); 138 | test("/images/cat refs is 2", cat_node->refs, 2); 139 | test("/images/cat words is 2", cat_node->words, 2); 140 | test("/images/cat delimiters is 0", cat_node->delimiters, 0); 141 | 142 | const SummNode* cat_jpg_node = image_summarizer->getMatchingNode("/images/cat.jpg"); 143 | test("/images/cat.jpg node found", cat_jpg_node != 0, true); 144 | test("/images/cat.jpg refs is 1", cat_jpg_node->refs, 1); 145 | test("/images/cat.jpg words is 1", cat_jpg_node->words, 1); 146 | 147 | // NOTE: delimiters is count of delimiters at/after this node 148 | // so the 'g' at the end of the string will have no delimiters 149 | 150 | test("/images/cat.jpg delimiters is 0", cat_jpg_node->delimiters, 0); 151 | 152 | // additional request for cat.jpg 153 | image_summarizer->addString("/images/cat.jpg"); 154 | 155 | cat_jpg_node = image_summarizer->getMatchingNode("/images/cat.jpg"); 156 | test("/images/cat.jpg node found", cat_jpg_node != 0, true); 157 | test("/images/cat.jpg refs is 2", cat_jpg_node->refs, 2); 158 | test("/images/cat.jpg words is 1", cat_jpg_node->words, 1); 159 | 160 | // check state after removing one reference to string /images/cat.jpg 161 | 162 | image_summarizer->removeString("/images/cat.jpg"); 163 | 164 | cat_jpg_node = image_summarizer->getMatchingNode("/images/cat.jpg"); 165 | test("/images/cat.jpg node found", cat_jpg_node != 0, true); 166 | test("/images/cat.jpg refs is 1", cat_jpg_node->refs, 1); 167 | test("/images/cat.jpg words is 1", cat_jpg_node->words, 1); 168 | 169 | // removed all references to cat.jpg 170 | 171 | image_summarizer->removeString("/images/cat.jpg"); 172 | 173 | cat_jpg_node = image_summarizer->getMatchingNode("/images/cat.jpg"); 174 | test("/images/cat.jpg node no longer found", cat_jpg_node == 0, true); 175 | 176 | images_node = image_summarizer->getMatchingNode("/images/"); 177 | test("/images/ refs is 2", images_node->refs, 2); 178 | test("/images/ words is 2", images_node->words, 2); 179 | test("/images/ delimiters is 1", images_node->delimiters, 1); 180 | 181 | const SummNode* dog_jpg_node = image_summarizer->getMatchingNode("/images/dog.jpg"); 182 | test("/images/dog.jpg node found", dog_jpg_node != 0, true); 183 | test("/images/dog.jpg refs is 1", dog_jpg_node->refs, 1); 184 | test("/images/dog.jpg words is 1", dog_jpg_node->words, 1); 185 | test("/images/dog.jpg delimiters is 0", dog_jpg_node->delimiters, 0); 186 | 187 | image_summarizer->removeString("/images/dog.jpg"); 188 | 189 | dog_jpg_node = image_summarizer->getMatchingNode("/images/dog.jpg"); 190 | test("/images/dog.jpg no longer found", dog_jpg_node == 0, true); 191 | 192 | image_summarizer->removeString("/images/cat.png"); 193 | 194 | images_node = image_summarizer->getMatchingNode("/images/"); 195 | test("/images/ node no longer found", images_node == 0, true); 196 | } 197 | -------------------------------------------------------------------------------- /src/tests.h: -------------------------------------------------------------------------------- 1 | #ifndef LOGSTALGIA_TESTER_H 2 | #define LOGSTALGIA_TESTER_H 3 | 4 | #include 5 | 6 | class TesterException : public std::exception { 7 | std::string message; 8 | public: 9 | TesterException(const std::string& message) : message(message) {} 10 | virtual ~TesterException() throw() {}; 11 | const char* what() const noexcept { 12 | return message.c_str(); 13 | } 14 | }; 15 | 16 | class LogstalgiaTester { 17 | public: 18 | LogstalgiaTester(); 19 | 20 | void runTests(); 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/textarea.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2008 Andrew Caudwell (acaudwell@gmail.com) 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | as published by the Free Software Foundation; either version 7 | 3 of the License, or (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include "textarea.h" 19 | 20 | TextArea::TextArea() { 21 | } 22 | 23 | TextArea::TextArea(FXFont font) { 24 | this->colour = vec3(1.0f,1.0f,1.0f); 25 | this->font = font; 26 | this->corner = vec2(0.0f,0.0f); 27 | this->visible = false; 28 | 29 | this->font.dropShadow(true); 30 | } 31 | 32 | TextArea::TextArea(std::vector& content, FXFont font, vec3 colour) { 33 | this->colour = colour; 34 | this->font = font; 35 | this->corner = vec2(0.0f,0.0f); 36 | setText(content); 37 | } 38 | 39 | void TextArea::hide() { 40 | this->visible=false; 41 | } 42 | 43 | int TextArea::getMaxCharacters() { 44 | return (display.width / font.getMaxWidth()) * 0.8; 45 | } 46 | 47 | void TextArea::setColour(vec3 colour) { 48 | this->colour = colour; 49 | } 50 | 51 | void TextArea::setText(const std::vector& content_) { 52 | this->content.clear(); 53 | 54 | //calculate area 55 | rectwidth = 0; 56 | rectheight = content_.size() * (font.getMaxHeight()+4) + 2; 57 | 58 | size_t max_characters = getMaxCharacters(); 59 | 60 | for(std::string s : content_) { 61 | 62 | if(s.size() > max_characters) { 63 | s = s.substr(0,max_characters); 64 | } 65 | 66 | int width = font.getWidth(s) + 6; 67 | if(width>rectwidth) rectwidth = width; 68 | this->content.push_back(s); 69 | } 70 | this->visible=true; 71 | } 72 | 73 | void TextArea::setPos(vec2 pos) { 74 | 75 | corner = pos; 76 | 77 | int fontheight = font.getMaxHeight() + 4; 78 | 79 | corner.y -= rectheight; 80 | 81 | if((corner.x + rectwidth) > display.width) { 82 | if((corner.x - rectwidth - fontheight )>0) { 83 | corner.x -= rectwidth; 84 | } else { 85 | corner.x = display.width - rectwidth; 86 | } 87 | } 88 | 89 | if(corner.y < 0) corner.y += rectheight + fontheight; 90 | if(corner.y +rectheight > display.height) { 91 | corner.y = std::max(0.0f, corner.y-rectheight); 92 | } 93 | 94 | } 95 | 96 | void TextArea::draw() { 97 | if(!visible) return; 98 | 99 | glDisable(GL_TEXTURE_2D); 100 | glEnable(GL_BLEND); 101 | glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 102 | 103 | vec4 col(colour*0.2f, 0.6f); 104 | 105 | glColor4fv(glm::value_ptr(col)); 106 | glBegin(GL_QUADS); 107 | glVertex2f(corner.x, corner.y); 108 | glVertex2f(corner.x, corner.y + rectheight); 109 | glVertex2f(corner.x+rectwidth, corner.y + rectheight); 110 | glVertex2f(corner.x+rectwidth, corner.y); 111 | glEnd(); 112 | 113 | glEnable(GL_TEXTURE_2D); 114 | glColor4f(1.0f, 1.0f, 1.0f, 1.0f); 115 | 116 | int yinc = 2; 117 | 118 | std::vector::iterator it; 119 | for(it = content.begin(); it != content.end(); it++) { 120 | font.draw((int)corner.x+2, (int)corner.y+yinc, (*it).c_str()); 121 | yinc += font.getMaxHeight() + 4; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/textarea.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2008 Andrew Caudwell (acaudwell@gmail.com) 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | as published by the Free Software Foundation; either version 7 | 3 of the License, or (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | #ifndef TEXTAREA_H 18 | #define TEXTAREA_H 19 | 20 | #include 21 | #include 22 | 23 | #include "core/display.h" 24 | #include "core/vectors.h" 25 | #include "core/fxfont.h" 26 | 27 | class TextArea { 28 | 29 | vec3 colour; 30 | vec2 corner; 31 | std::vector content; 32 | FXFont font; 33 | int rectwidth; 34 | int rectheight; 35 | bool visible; 36 | public: 37 | TextArea(); 38 | TextArea(FXFont font); 39 | TextArea(std::vector& content, FXFont font, vec3 colour); 40 | 41 | void hide(); 42 | 43 | int getMaxCharacters(); 44 | 45 | void setText(const std::vector& content); 46 | void setPos(vec2 pos); 47 | void setColour(vec3 colour); 48 | 49 | void draw(); 50 | }; 51 | 52 | #endif 53 | --------------------------------------------------------------------------------