1// This file is part of SmallBASIC
2//
3// Copyright(C) 2001-2019 Chris Warren-Smith.
4//
5// This program is distributed under the terms of the GPL v2.0 or later
6// Download the GNU Public License (GPL) from www.gnu.org
7//
8
9#include <config.h>
10#include <dirent.h>
11#include <unistd.h>
12#include <sys/stat.h>
13#include "platform/fltk/HelpView.h"
14#include "ui/kwp.h"
15#include "ui/strlib.h"
16
17const char *aboutText =
18 "<b>About SmallBASIC...</b><br><br>"
19 "Version " SB_STR_VER "<br>"
20 "Copyright (c) 2002-2020 Chris Warren-Smith.<br><br>"
21 "Copyright (c) 2000-2006 Nicholas Christopoulos.<br><br>"
22 "<a href=https://smallbasic.github.io>"
23 "https://smallbasic.github.io</a><br><br>"
24 "SmallBASIC comes with ABSOLUTELY NO WARRANTY. "
25 "This program is free software; you can use it "
26 "redistribute it and/or modify it under the terms of the "
27 "GNU General Public License version 2 as published by "
28 "the Free Software Foundation.<br><br>" "<i>Press F1 for help";
29
30const char CMD_LEVEL1_OPEN = '+';
31const char CMD_LEVEL2_OPEN = '!';
32const char CMD_MORE = '^';
33
34HelpView *helpView;
35
36const char *getBriefHelp(const char *selection) {
37 const char *result = NULL;
38 int len = selection != NULL ? strlen(selection) : 0;
39 if (len > 0) {
40 for (int i = 0; i < keyword_help_len && !result; i++) {
41 if (strcasecmp(selection, keyword_help[i].keyword) == 0) {
42 result = keyword_help[i].signature;
43 break;
44 }
45 }
46 }
47 return result;
48}
49
50static void helpViewClick_event(void *) {
51 Fl::remove_check(helpViewClick_event);
52 helpView->anchorClick();
53 helpView = NULL;
54}
55
56// post message and return
57static void helpViewClick_cb(Fl_Widget *w, void *v) {
58 helpView = (HelpView *)w;
59 Fl::add_check(helpViewClick_event);
60}
61
62HelpView::HelpView(Fl_Widget *rect, int fontSize) :
63 HelpWidget(rect, fontSize),
64 _openKeyword(-1),
65 _openPackage(0) {
66}
67
68HelpView::~HelpView() {
69}
70
71void HelpView::about() {
72 loadBuffer(aboutText);
73}
74
75//
76// anchor link clicked
77//
78void HelpView::anchorClick() {
79 const char *target = (const char *)user_data();
80
81 switch (target[0]) {
82 case CMD_LEVEL1_OPEN:
83 for (int i = 0; i < keyword_help_len; i++) {
84 if (strcasecmp(target + 1, keyword_help[i].package) == 0) {
85 _openPackage = i;
86 _openKeyword = i;
87 break;
88 }
89 }
90 helpIndex();
91 break;
92
93 case CMD_LEVEL2_OPEN:
94 for (int i = 0; i < keyword_help_len; i++) {
95 if (strcasecmp(target + 1, keyword_help[i].keyword) == 0) {
96 _openKeyword = i;
97 break;
98 }
99 }
100 helpIndex();
101 break;
102
103 case CMD_MORE:
104 if (_openKeyword != -1) {
105 showHelp(keyword_help[_openKeyword].nodeId);
106 }
107 break;
108 }
109}
110
111//
112// display help index
113//
114void HelpView::helpIndex() {
115 callback(helpViewClick_cb);
116
117 String html;
118 const char *package = NULL;
119
120 for (int i = 0; i < keyword_help_len; i++) {
121 if (package == NULL || strcasecmp(package, keyword_help[i].package) != 0) {
122 package = keyword_help[i].package;
123 bool bold = (_openPackage != -1 && strcasecmp(keyword_help[_openPackage].package,
124 keyword_help[i].package) == 0);
125 if (bold) {
126 html.append("<b>");
127 }
128 html.append("<a href='")
129 .append(CMD_LEVEL1_OPEN)
130 .append(package)
131 .append("'>")
132 .append(package)
133 .append("</a>");
134 if (strcasecmp("System", package) != 0) {
135 html.append(" | ");
136 }
137 if (bold) {
138 html.append("</b>");
139 }
140 }
141 }
142
143 if (_openKeyword != -1) {
144 // display opened keyword
145 html.append("<br><br><b>")
146 .append(keyword_help[_openKeyword].signature)
147 .append("</b><br>")
148 .append(keyword_help[_openKeyword].help)
149 .append("<br><u><a href=")
150 .append(CMD_MORE)
151 .append(">Online...</a></u>");
152 }
153
154 html.append("<br><br>");
155
156 for (int i = 0; i < keyword_help_len; i++) {
157 if (_openPackage != -1 && strcasecmp(keyword_help[_openPackage].package,
158 keyword_help[i].package) == 0) {
159 if (_openKeyword == i) {
160 html.append("<b>");
161 }
162 // display opened package
163 html.append("<a href='")
164 .append(CMD_LEVEL2_OPEN)
165 .append(keyword_help[i].keyword)
166 .append("'>")
167 .append(keyword_help[i].keyword)
168 .append("</a> | ");
169 if (_openKeyword == i) {
170 html.append("</b>");
171 }
172 }
173 }
174
175 loadBuffer(html);
176 take_focus();
177}
178
179bool HelpView::loadHelp(const char *path) {
180 char localFile[PATH_MAX];
181 dev_file_t df;
182 bool result;
183
184 memset(&df, 0, sizeof(dev_file_t));
185 strcpy(df.name, path);
186 if (http_open(&df) && cacheLink(&df, localFile, sizeof(localFile))) {
187 loadFile(localFile);
188 result = true;
189 } else {
190 result = false;
191 }
192 return result;
193}
194
195void HelpView::showContextHelp(const char *selection) {
196 int len = selection != NULL ? strlen(selection) : 0;
197 if (len > 0) {
198 for (int i = 0; i < keyword_help_len; i++) {
199 if (strcasecmp(selection, keyword_help[i].keyword) == 0) {
200 _openPackage = _openKeyword = i;
201 break;
202 }
203 }
204 }
205 helpIndex();
206}
207
208void HelpView::showHelp(const char *nodeId) {
209 char path[PATH_MAX];
210 sprintf(path, "http://smallbasic.github.io/reference/ide/%s.html", nodeId);
211 loadHelp(path);
212}
213