foxygit / doom Log in
commit 356554c22998264769a5c516697cbfbd43847ce4
Author:     Simon Howard <fraggle@soulsphere.org>
AuthorDate: Sat Apr 4 21:29:33 2015 -0400
Commit:     Simon Howard <fraggle@soulsphere.org>
CommitDate: Sat Apr 4 21:29:33 2015 -0400

    textscreen: Add help URL functionality for windows.

    This adds the ability to associate a URL with a window that gives
    some extra information about it and the configuration options found
    in it.
---
 textscreen/examples/guitest.c |  2 +
 textscreen/txt_desktop.c      | 85 ++++++++++++++++++++++++++++++++++++++++---
 textscreen/txt_desktop.h      |  2 +-
 textscreen/txt_gui.c          |  4 +-
 textscreen/txt_window.c       | 74 ++++++++++++++++++++++++++++++-------
 textscreen/txt_window.h       | 22 +++++++++++
 6 files changed, 167 insertions(+), 22 deletions(-)

diff --git a/textscreen/examples/guitest.c b/textscreen/examples/guitest.c
index 04d580c9..46060bf0 100644
--- a/textscreen/examples/guitest.c
+++ b/textscreen/examples/guitest.c
@@ -96,6 +96,8 @@ void SetupWindow(void)

     window = TXT_NewWindow("Window test");

+    TXT_SetWindowHelpURL(window, "https://www.youtube.com/watch?v=dQw4w9WgXcQ");
+
     TXT_AddWidget(window, TXT_NewSeparator("Main section"));
     table = TXT_NewTable(3);

diff --git a/textscreen/txt_desktop.c b/textscreen/txt_desktop.c
index 4c9cf5c1..e56a5ee4 100644
--- a/textscreen/txt_desktop.c
+++ b/textscreen/txt_desktop.c
@@ -25,6 +25,7 @@
 #include "txt_separator.h"
 #include "txt_window.h"

+#define HELP_KEY KEY_F1
 #define MAXWINDOWS 128

 static char *desktop_title;
@@ -188,6 +189,37 @@ static void DrawDesktopBackground(const char *title)
     TXT_Puts(title);
 }

+static void DrawHelpIndicator(void)
+{
+    char keybuf[10];
+    int fgcolor;
+    int x, y;
+
+    TXT_GetKeyDescription(HELP_KEY, keybuf, sizeof(keybuf));
+
+    TXT_GetMousePosition(&x, &y);
+
+    if (y == 0 && x >= TXT_SCREEN_W - 9)
+    {
+        fgcolor = TXT_COLOR_GREY;
+        TXT_BGColor(TXT_COLOR_BLACK, 0);
+    }
+    else
+    {
+        fgcolor = TXT_COLOR_BLACK;
+        TXT_BGColor(TXT_COLOR_GREY, 0);
+    }
+
+    TXT_GotoXY(TXT_SCREEN_W - 9, 0);
+
+    TXT_FGColor(TXT_COLOR_BRIGHT_WHITE);
+    TXT_DrawString(" ");
+    TXT_DrawString(keybuf);
+
+    TXT_FGColor(fgcolor);
+    TXT_DrawString("=Help ");
+}
+
 void TXT_SetDesktopTitle(char *title)
 {
     free(desktop_title);
@@ -197,8 +229,9 @@ void TXT_SetDesktopTitle(char *title)

 void TXT_DrawDesktop(void)
 {
-    int i;
+    txt_window_t *active_window;
     const char *title;
+    int i;

     TXT_InitClipArea();

@@ -209,6 +242,12 @@ void TXT_DrawDesktop(void)

     DrawDesktopBackground(title);

+    active_window = TXT_GetActiveWindow();
+    if (active_window != NULL && active_window->help_url != NULL)
+    {
+        DrawHelpIndicator();
+    }
+
     for (i=0; i<num_windows; ++i)
     {
         TXT_DrawWindow(all_windows[i]);
@@ -217,17 +256,53 @@ void TXT_DrawDesktop(void)
     TXT_UpdateScreen();
 }

+// Fallback function to handle key/mouse events that are not handled by
+// the active window.
+static void DesktopInputEvent(int c)
+{
+    txt_window_t *active_window;
+    int x, y;
+
+    switch (c)
+    {
+        case TXT_MOUSE_LEFT:
+            TXT_GetMousePosition(&x, &y);
+
+            // Clicking the top-right of the screen is equivalent
+            // to pressing the help key.
+            if (y == 0 && x >= TXT_SCREEN_W - 9)
+            {
+                DesktopInputEvent(HELP_KEY);
+            }
+            break;
+
+        case HELP_KEY:
+            active_window = TXT_GetActiveWindow();
+            if (active_window != NULL)
+            {
+                TXT_OpenWindowHelpURL(active_window);
+            }
+            break;
+
+        default:
+            break;
+    }
+
+
+}
+
 void TXT_DispatchEvents(void)
 {
+    txt_window_t *active_window;
     int c;

     while ((c = TXT_GetChar()) > 0)
     {
-        if (num_windows > 0)
-        {
-            // Send the keypress to the top window
+        active_window = TXT_GetActiveWindow();

-            TXT_WindowKeyPress(all_windows[num_windows - 1], c);
+        if (active_window != NULL && !TXT_WindowKeyPress(active_window, c))
+        {
+            DesktopInputEvent(c);
         }
     }
 }
diff --git a/textscreen/txt_desktop.h b/textscreen/txt_desktop.h
index 07164c89..3c6cf12b 100644
--- a/textscreen/txt_desktop.h
+++ b/textscreen/txt_desktop.h
@@ -31,7 +31,7 @@ void TXT_DrawDesktop(void);
 void TXT_DispatchEvents(void);
 void TXT_DrawWindow(txt_window_t *window);
 void TXT_SetWindowFocus(txt_window_t *window, int focused);
-void TXT_WindowKeyPress(txt_window_t *window, int c);
+int TXT_WindowKeyPress(txt_window_t *window, int c);

 /**
  * Set the title displayed at the top of the screen.
diff --git a/textscreen/txt_gui.c b/textscreen/txt_gui.c
index 74e3ec75..bc7017a8 100644
--- a/textscreen/txt_gui.c
+++ b/textscreen/txt_gui.c
@@ -488,8 +488,8 @@ void TXT_InitClipArea(void)
         cliparea = malloc(sizeof(txt_cliparea_t));
         cliparea->x1 = 0;
         cliparea->x2 = TXT_SCREEN_W;
-        cliparea->y1 = 1;
-        cliparea->y2 = TXT_SCREEN_H - 1;
+        cliparea->y1 = 0;
+        cliparea->y2 = TXT_SCREEN_H;
         cliparea->next = NULL;
     }
 }
diff --git a/textscreen/txt_window.c b/textscreen/txt_window.c
index 7fe83662..7b2e3568 100644
--- a/textscreen/txt_window.c
+++ b/textscreen/txt_window.c
@@ -70,6 +70,7 @@ txt_window_t *TXT_NewWindow(char *title)
     win->vert_align = TXT_VERT_CENTER;
     win->key_listener = NULL;
     win->mouse_listener = NULL;
+    win->help_url = NULL;

     TXT_AddWidget(win, TXT_NewSeparator(NULL));

@@ -365,7 +366,7 @@ void TXT_SetWindowPosition(txt_window_t *window,
     window->y = y;
 }

-static void MouseButtonPress(txt_window_t *window, int b)
+static int MouseButtonPress(txt_window_t *window, int b)
 {
     int x, y;
     int i;
@@ -375,7 +376,7 @@ static void MouseButtonPress(txt_window_t *window, int b)
     // Lay out the window, set positions and sizes of all widgets

     TXT_LayoutWindow(window);
-
+
     // Get the current mouse position

     TXT_GetMousePosition(&x, &y);
@@ -390,10 +391,10 @@ static void MouseButtonPress(txt_window_t *window, int b)
         if (window->mouse_listener(window, x, y, b,
                                    window->mouse_listener_data))
         {
-            return;
+            return 1;
         }
     }
-
+
     // Is it within the table range?

     widgets = (txt_widget_t *) window;
@@ -402,7 +403,7 @@ static void MouseButtonPress(txt_window_t *window, int b)
      && y >= widgets->y && y < (signed) (widgets->y + widgets->h))
     {
         TXT_WidgetMousePress(window, x, y, b);
-        return;
+        return 1;
     }

     // Was one of the action area buttons pressed?
@@ -429,21 +430,22 @@ static void MouseButtonPress(txt_window_t *window, int b)
             // Pass through mouse press.

             TXT_WidgetMousePress(widget, x, y, b);
-            return;
+            return 1;
         }
     }
+
+    return 0;
 }

-void TXT_WindowKeyPress(txt_window_t *window, int c)
+int TXT_WindowKeyPress(txt_window_t *window, int c)
 {
     int i;

     // Is this a mouse button ?
-
+
     if (c >= TXT_MOUSE_BASE && c < TXT_MOUSE_BASE + TXT_MAX_MOUSE_BUTTONS)
     {
-        MouseButtonPress(window, c);
-        return;
+        return MouseButtonPress(window, c);
     }

     // Try the window key spy
@@ -454,15 +456,15 @@ void TXT_WindowKeyPress(txt_window_t *window, int c)

         if (window->key_listener(window, c, window->key_listener_data))
         {
-            return;
+            return 1;
         }
     }

-    // Send to the currently selected widget
+    // Send to the currently selected widget:

     if (TXT_WidgetKeyPress(window, c))
     {
-        return;
+        return 1;
     }

     // Try all of the action buttons
@@ -472,9 +474,11 @@ void TXT_WindowKeyPress(txt_window_t *window, int c)
         if (window->actions[i] != NULL
          && TXT_WidgetKeyPress(window->actions[i], c))
         {
-            return;
+            return 1;
         }
     }
+
+    return 0;
 }

 void TXT_SetKeyListener(txt_window_t *window, TxtWindowKeyPress key_listener,
@@ -497,6 +501,48 @@ void TXT_SetWindowFocus(txt_window_t *window, int focused)
     TXT_SetWidgetFocus(window, focused);
 }

+void TXT_SetWindowHelpURL(txt_window_t *window, char *help_url)
+{
+    window->help_url = help_url;
+}
+
+void TXT_OpenURL(char *url)
+{
+    char *cmd;
+    size_t cmd_len;
+
+    cmd_len = strlen(url) + 30;
+    cmd = malloc(cmd_len);
+
+#if defined(_WIN32)
+    TXT_snprintf(cmd, cmd_len, "start \"%s\"", url);
+#elif defined(__MACOSX__)
+    TXT_snprintf(cmd, cmd_len, "open \"%s\"", url);
+#else
+    // The Unix situation sucks as usual, but the closest thing to a
+    // standard that exists is the xdg-utils package.
+    if (system("xdg-open --version 2>/dev/null") != 0)
+    {
+        fprintf(stderr,
+                "xdg-utils is not installed. Can't open this URL:\n%s\n", url);
+        return;
+    }
+
+    TXT_snprintf(cmd, cmd_len, "xdg-open \"%s\"", url);
+#endif
+
+    system(cmd);
+    free(cmd);
+}
+
+void TXT_OpenWindowHelpURL(txt_window_t *window)
+{
+    if (window->help_url != NULL)
+    {
+        TXT_OpenURL(window->help_url);
+    }
+}
+
 txt_window_t *TXT_MessageBox(char *title, char *message, ...)
 {
     txt_window_t *window;
diff --git a/textscreen/txt_window.h b/textscreen/txt_window.h
index 4d1ec991..412bad4f 100644
--- a/textscreen/txt_window.h
+++ b/textscreen/txt_window.h
@@ -85,6 +85,10 @@ struct txt_window_s

     int window_x, window_y;
     unsigned int window_w, window_h;
+
+    // URL of a webpage with help about this window. If set, a help key
+    // indicator is shown while this window is active.
+    char *help_url;
 };

 /**
@@ -194,5 +198,23 @@ void TXT_SetMouseListener(txt_window_t *window,

 txt_window_t *TXT_MessageBox(char *title, char *message, ...);

+/**
+ * Set the help URL for the given window.
+ *
+ * @param window          The window.
+ * @param help_url        String containing URL of the help page for this
+ *                        window, or NULL to set no help for this window.
+ */
+
+void TXT_SetWindowHelpURL(txt_window_t *window, char *help_url);
+
+/**
+ * Open the help URL for the given window, if one is set.
+ *
+ * @param window          The window.
+ */
+
+void TXT_OpenWindowHelpURL(txt_window_t *window);
+
 #endif /* #ifndef TXT_WINDOW_H */