diff options
Diffstat (limited to 'Build/source/texk/web2c/hitexdir/hintview/src/main.c')
-rw-r--r-- | Build/source/texk/web2c/hitexdir/hintview/src/main.c | 406 |
1 files changed, 406 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/hitexdir/hintview/src/main.c b/Build/source/texk/web2c/hitexdir/hintview/src/main.c new file mode 100644 index 00000000000..f8e4b9e16f5 --- /dev/null +++ b/Build/source/texk/web2c/hitexdir/hintview/src/main.c @@ -0,0 +1,406 @@ +#include <stdio.h> +#include <stdlib.h> +#include <setjmp.h> +#include <string.h> +#include <stdarg.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <math.h> + +#include <GL/glew.h> +#include <GLFW/glfw3.h> + +#define VERSION 1 +#define REVISION 0 +#define PATCHLEVEL 0 + +#if 0 +#include "rendernative.h" /* rendernative needs gcache_s */ +#else +extern void nativeInit(void); +extern void nativeClear(void); +extern void nativeSetDark(int dark); +#endif +#include "error.h" +#include "basetypes.h" +#include "format.h" +#include "get.h" +#include "hint.h" +#include "hrender.h" + +FILE* hlog; +jmp_buf error_exit; + +/* Error Handling */ +int herror(const char *title, const char *message) +{ fprintf(stderr,"ERROR %s: %s\n",title,message); + return 0; +} + +int hmessage(char *title, char *format, ...) +{ va_list vargs; + va_start(vargs,format); + vfprintf(stderr, format, vargs); + return 0; +} + +void error_callback(int error, const char* description) +{ herror("OpenGL",description); + longjmp(error_exit,1); +} + +GLFWwindow* window; +int px_h=1024, px_v=768; // size in pixel +int page_h, page_v; // size in scaled points +double x_dpi, y_dpi; +#define SCALE_MIN 0.2 +#define SCALE_NORMAL 1.0 +#define SCALE_MAX 5.0 +double scale=SCALE_NORMAL; +uint64_t pos; /* position of current page */ + +void framebuffer_size_callback(GLFWwindow* window, int w, int h) +{ px_h=w; px_v=h; + glViewport(0, 0, w, h); + //LOG("w=%d, h=%d\n",w,h); + hint_resize(px_h,px_v,scale*x_dpi,scale*y_dpi); + hint_page(); +} + +void getDPI(void) +{ int widthMM, heightMM; + GLFWmonitor* monitor = glfwGetPrimaryMonitor(); + glfwGetMonitorPhysicalSize(monitor, &widthMM, &heightMM); + const GLFWvidmode* mode = glfwGetVideoMode(monitor); + x_dpi = mode->width / (widthMM / 25.4); + y_dpi = mode->height / (heightMM / 25.4); + //LOG("xdpi=%f, ydpi=%f\n",x_dpi,y_dpi); +} + +void hint_unmap(void) +{ hget_unmap(); +} + +bool hint_map(void) +{ return hget_map(); +} + +int open_file(int home) +{ hint_clear_fonts(true); + if (!hint_begin()) return 0; + if (home) + hint_page_home(); + else + hint_page_top(0); + // strncpy(title_name,hin_name,MAX_PATH); + // SetNavigationTree(); + //SetWindowText(hMainWnd,title_name); +return 1; +} + +static void reload_file(void) +{ double fpos=hint_get_fpos(); + hint_begin(); + pos=hint_set_fpos(fpos); + //LOG("reloading...\n"); +} + +static int new_file_time(void) +{ struct stat st; + if (hin_name!=NULL && + stat(hin_name,&st)==0 && + st.st_size>0) + { + //LOG("file %s %lu\n",hin_name,st.st_mtime); + if (st.st_mtime>hin_time) + return 1; + else + return 0; + } + return 0; +} + +int dark = 0, loading=0, autoreload=0, home=0; + +int usage(void) +{ return herror("Usage:", "hintview [options] file\n" + "Call 'hintview --help' for details.\n"); +} + +int help(void) +{ fprintf(stdout,"%s", + "Usage: hintview [options] file\n" + "Options:\n" + " -a Start in autoreload mode.\n" + " -h Start with the documents home page.\n" + " -n Start in night mode.\n" +#if 0 + " -o Show the documents outline.\n" +#endif + " -z Start with zoom level 100%.\n" + " --help Display this message.\n" + " --version Display the version.\n" + "\n" + "See the hintview man page for more details.\n" + ); + return 0; +} + +int command_line(int argc, char *argv[]) +{ size_t sl; + int i; + for (i=1; argv[i]!=NULL && argv[i][0]=='-'; i++) + { switch (argv[i][1]) + { case '-': + if (strcmp(argv[i]+2,"help")==0) return help(); + else if (strcmp(argv[i]+2,"version")==0) + { fprintf(stdout,"hintview version %d.%d.%d\n", VERSION, REVISION, PATCHLEVEL); + return 0; + } + else + return usage(); + case 'a': autoreload=1; break; + case 'n': dark=1; break; + case 'o': break; + case 'z': scale=SCALE_NORMAL; break; + case 'h': home=1; break; + default: return usage(); + } + } + if (argv[i]==NULL) + return usage(); + if (hin_name!=NULL) free(hin_name); + hin_name=malloc(strlen(argv[i])+1); + if (hin_name==NULL) + return herror("Out of memory for file name", argv[i]); + strcpy(hin_name,argv[i]); + sl=strlen(hin_name); + if (sl>4 && strncmp(hin_name+sl-4,".hnt",4)!=0) + return herror("Unknown File Type,I dont know how to open this file", argv[1]); +return 1; +} + +GLFWcursor *drag_cursor, *hand_cursor, *arrow_cursor; +int mouse_down=0, drag=0, on_link=0; + +void clear_cursor(void) +{ if (on_link||drag) + { glfwSetCursor(window, arrow_cursor); on_link=drag=0;} +} + +/* combining the key with the shift, control, alt or super flag */ +#define KEY_MOD(K,M) (((K)<<4)|((M)&0xF)) +#define KEY(K) KEY_MOD(K,0) +#define CTRL(K) KEY_MOD(K,GLFW_MOD_CONTROL) + +void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) +{ if (action!=GLFW_PRESS) return; + switch (KEY_MOD(key,mods)) { + case CTRL(GLFW_KEY_Q): + glfwSetWindowShouldClose(window,1); + break; + case CTRL(GLFW_KEY_N): + dark=!dark; + nativeSetDark(dark); + break; + case KEY(GLFW_KEY_HOME): + case CTRL(GLFW_KEY_H): + hint_page_home(); + clear_cursor(); + break; + case CTRL(GLFW_KEY_Z): + case CTRL(GLFW_KEY_Y): /* US keyboard */ + scale=SCALE_NORMAL; + hint_resize(px_h,px_v,scale*x_dpi,scale*y_dpi); + hint_page(); + hint_clear_fonts(true); + clear_cursor(); + break; + case KEY(GLFW_KEY_PAGE_DOWN): + pos=hint_page_next(); + hint_page(); + clear_cursor(); + break; + case KEY(GLFW_KEY_PAGE_UP): + pos=hint_page_prev(); + hint_page(); + clear_cursor(); + break; + case CTRL(GLFW_KEY_A): /* auto reload */ + autoreload=!autoreload; + if (!autoreload) + break; /* else fall through to reload */ + case CTRL(GLFW_KEY_R): /* reload */ + if (!loading) + { loading=1; + HINT_TRY reload_file(); + loading=0; + } + clear_cursor(); + break; + break; + case CTRL(GLFW_KEY_F): /* find */ + break; + case CTRL(GLFW_KEY_O): /* outlines */ + break; + default: + // LOG("key %d, scan %d, action %d, mosd %d\n",key, scancode, action, mods); + break; + } +} + +/* convert pixel to scaled points (including scale) */ + +#define PX2SP(X,DPI) floor((X)*ONE*72.27/((DPI)*scale)) + +void mouse_click(void) +{ double x,y; + int link; + glfwGetCursorPos(window, &x, &y); + //LOG("xy= %fx%f\n", x,y); + HINT_TRY { + link=hint_find_link(PX2SP(x,x_dpi),PX2SP(y,y_dpi),2*ONE); + if (link>=0) + { hint_link_page(link); + clear_cursor(); + } + } +} + +double x_start, y_start, xy_start, scale_start, time_start; +#define DELTA_T 0.4 +#define DELTA_XY 16.0 + +static void cursor_position_callback(GLFWwindow* window, double x, double y) +{ //LOG("xy= %fx%f\n", x-x_start,y-y_start); + double f; + if (!mouse_down) + { int link; + link=hint_find_link(PX2SP(x,x_dpi),PX2SP(y,y_dpi),2*ONE); + if (link>=0 && !on_link) + { glfwSetCursor(window, hand_cursor); on_link=1; } + else if (link<0 && on_link) + { glfwSetCursor(window, arrow_cursor); on_link=0; } + return; + } + if (!drag) /* we dont know whether this is a click or a drag */ + { double d = (x-x_start)*(x-x_start)+(y-y_start)*(y-y_start); + if (d<= DELTA_XY) + { double t=glfwGetTime(); + if (t<=time_start+DELTA_T) + return; + } + /* start dragging */ + drag=1; + glfwSetCursor(window, drag_cursor); + xy_start=x_start*x_start+y_start*y_start; + } + /* dragging */ + f=(x_start*x+y_start*y)/xy_start; /* projection of (x,y) on (x_start,y_start) */ + scale=scale_start*f; + if (scale < SCALE_MIN) scale=SCALE_MIN; + if (scale > SCALE_MAX) scale=SCALE_MAX; + hint_resize(px_h,px_v,scale*x_dpi,scale*y_dpi); + hint_page(); +} + + +void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) +{ if (button == GLFW_MOUSE_BUTTON_LEFT) + { if (action == GLFW_PRESS) + { glfwGetCursorPos(window, &x_start, &y_start); + time_start=glfwGetTime(); + scale_start=scale; + drag=0; + mouse_down =1; + } + else if (action == GLFW_RELEASE) + { mouse_down=0; + if (drag) /* end dragging */ + { hint_clear_fonts(true); + clear_cursor(); + } + else + mouse_click(); + } + } +} + +void cursor_enter_callback(GLFWwindow* window, int entered) +{ if (entered && autoreload && new_file_time()) + reload_file(); + //LOG("entered=%d auto=%d\n",entered, autoreload); +} + +int create_window(void) +{ if( !glfwInit() ) + { + herror("GLFW", "Failed to initialize GLFW\n" ); + getchar(); + return 0; + } + glfwSetErrorCallback(error_callback); + glfwWindowHint(GLFW_SAMPLES, 4); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + + /* Open a window and create its OpenGL context */ + window = glfwCreateWindow( px_h, px_v, "HintView", NULL, NULL); + if( window == NULL ){ + herror("GLFW","Failed to open GLFW window.\n" + "If you have an Intel GPU, they are not 3.3 compatible.\n" + "Try the 2.1 version of the tutorials.\n" ); + glfwTerminate(); + return 0; + } + glfwMakeContextCurrent(window); + + glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE); + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + + drag_cursor = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR); + hand_cursor = glfwCreateStandardCursor(GLFW_HAND_CURSOR); + arrow_cursor = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); + + getDPI(); + + glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); + glfwSetKeyCallback(window, key_callback); + glfwSetCursorEnterCallback(window,cursor_enter_callback); + glfwSetMouseButtonCallback(window, mouse_button_callback); + glfwSetCursorPosCallback(window, cursor_position_callback); + + glfwSetCursorPos(window, px_h/2, px_v/2); + + nativeInit(); + return 1; +} + +int main(int argc, char *argv[]) +{ hlog=stderr; + if (setjmp(error_exit)!=0) return 1; + if (!command_line(argc,argv)) + return 1; + if (!create_window()) + return 1; + nativeSetDark(dark); + hint_resize(px_h,px_v,scale*x_dpi,scale*y_dpi); + if (!open_file(home)) + return 1; + hint_page_home(); + if (setjmp(error_exit)==0) + do + { hint_render(); + glfwSwapBuffers(window); + glfwWaitEvents(); + } // Check if the ESC key was pressed or the window was closed + while(glfwWindowShouldClose(window) == 0 ); + nativeClear(); + glfwDestroyWindow(window); // part of glfwTerminate + glfwTerminate(); + return 0; +} + |