Reset parser in grace_set_project().
[grace.git] / src / helpwin.c
blobc3e69f13dc7c301f271aad3974f7493149e65b16
1 /*
2 * Grace - GRaphing, Advanced Computation and Exploration of data
3 *
4 * Home page: http://plasma-gate.weizmann.ac.il/Grace/
5 *
6 * Copyright (c) 1991-1995 Paul J Turner, Portland, OR
7 * Copyright (c) 1996-2003 Grace Development Team
8 *
9 * Maintained by Evgeny Stambulchik
12 * All Rights Reserved
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #include <config.h>
31 #include <stdlib.h>
32 #include <string.h>
34 #include "globals.h"
35 #include "utils.h"
36 #include "files.h"
37 #include "protos.h"
39 #include "motifinc.h"
41 #define NO_HELP "doc/nohelp.html"
43 #ifdef WITH_XMHTML
44 # include <XmHTML/XmHTML.h>
45 void create_helper_frame(char *fname);
46 #endif
48 int force_external_viewer =
49 #if defined WITH_XMHTML
50 FALSE;
51 #else
52 TRUE;
53 #endif
55 void HelpCB(Widget w, void *data)
57 char *URL, *ha;
58 int remote;
60 ha = (char *) data;
62 if (ha == NULL) {
63 ha = NO_HELP;
66 if (strstr(ha, "http:") || strstr(ha, "ftp:") || strstr(ha, "mailto:")) {
67 URL = copy_string(NULL, ha);
68 remote = TRUE;
69 } else {
70 char *p, *pa;
72 if (ha == strstr(ha, "file:")) {
73 p = (ha + 5);
74 } else {
75 p = ha;
78 pa = strchr(p, '#');
79 if (pa) {
80 char *base = copy_string(NULL, p);
81 base[pa - p] = '\0';
82 URL = copy_string(NULL, grace_path(grace, base));
83 URL = concat_strings(URL, pa);
84 xfree(base);
85 } else {
86 URL = copy_string(NULL, grace_path(grace, p));
89 remote = FALSE;
92 if (remote || force_external_viewer) {
93 char *help_viewer, *command;
94 int i, j, len, urllen, comlen;
96 help_viewer = get_help_viewer(grace);
97 len = strlen(help_viewer);
98 urllen = strlen(URL);
99 for (i = 0, comlen = len; i < len - 1; i++) {
100 if ((help_viewer[i] == '%') && (help_viewer[i + 1] == 's')){
101 comlen += urllen - 2;
102 i++;
105 command = xmalloc((comlen + 1)*SIZEOF_CHAR);
106 command[comlen] = '\0';
107 for (i = 0, j = 0; i < len; i++) {
108 if ((help_viewer[i] == '%') && (help_viewer[i + 1] == 's')){
109 strcpy (&command[j], URL);
110 j += urllen;
111 i++;
112 } else {
113 command[j++] = help_viewer[i];
116 #ifdef VMS
117 system_spawn(command);
118 #else
119 command = concat_strings(command, "&");
120 system_wrap(command);
121 #endif
122 xfree(command);
123 } else {
124 #ifdef WITH_XMHTML
125 create_helper_frame(URL);
126 #endif
129 xfree(URL);
133 * say a few things about Grace
135 static Widget about_frame;
137 void create_about_grtool(Widget but, void *data)
139 set_wait_cursor();
141 if (about_frame == NULL) {
142 Widget wbut, fr, rc, about_panel;
143 char buf[1024];
145 about_frame = CreateDialogForm(app_shell, "About");
147 about_panel = CreateVContainer(about_frame);
148 AddDialogFormChild(about_frame, about_panel);
150 fr = CreateFrame(about_panel, NULL);
151 rc = CreateVContainer(fr);
152 CreateLabel(rc, bi_version_string());
153 #ifdef DEBUG
154 CreateLabel(rc, "Debugging is enabled");
155 #endif
157 fr = CreateFrame(about_panel, "Legal stuff");
158 rc = CreateVContainer(fr);
159 CreateLabel(rc, "Copyright (c) 1991-1995 Paul J Turner");
160 CreateLabel(rc, "Copyright (c) 1996-2004 Grace Development Team");
161 CreateLabel(rc, "Maintained by Evgeny Stambulchik");
162 CreateLabel(rc, "All rights reserved");
163 CreateLabel(rc,
164 "The program is distributed under the terms of the GNU General Public License");
166 fr = CreateFrame(about_panel, "Third party copyrights");
167 rc = CreateVContainer(fr);
168 CreateLabel(rc,
169 "Tab widget, Copyright (c) 1997 Pralay Dakua");
170 CreateLabel(rc, "Xbae widget,");
171 CreateLabel(rc,
172 " Copyright (c) 1991, 1992 Bell Communications Research, Inc. (Bellcore)");
173 CreateLabel(rc,
174 " Copyright (c) 1995-1999 Andrew Lister");
175 #ifdef HAVE_LIBPDF
176 CreateLabel(rc, "PDFlib library, Copyright (c) 1997-2004 Thomas Merz and PDFlib GmbH");
177 #endif
179 fr = CreateFrame(about_panel, "Build info");
180 rc = CreateVContainer(fr);
181 sprintf(buf, "Host: %s", bi_system());
182 CreateLabel(rc, buf);
183 sprintf(buf, "Time: %s", bi_date());
184 CreateLabel(rc, buf);
185 sprintf(buf, "GUI toolkit: %s ", bi_gui());
186 CreateLabel(rc, buf);
187 sprintf(buf, "Xbae version: %s ", bi_gui_xbae());
188 CreateLabel(rc, buf);
189 sprintf(buf, "T1lib: %s ", bi_t1lib());
190 CreateLabel(rc, buf);
192 fr = CreateFrame(about_panel, "Home page");
193 rc = CreateVContainer(fr);
194 CreateLabel(rc, "http://plasma-gate.weizmann.ac.il/Grace/");
196 CreateSeparator(about_panel);
198 wbut = CreateButton(about_panel, "Close");
199 AlignLabel(wbut, ALIGN_CENTER);
200 AddButtonCB(wbut, destroy_dialog_cb, GetParent(about_frame));
202 ManageChild(about_frame);
205 RaiseWindow(GetParent(about_frame));
207 unset_wait_cursor();
211 #ifdef WITH_XMHTML
213 * Simplistic HTML viewer
216 typedef struct _html_ui {
217 Widget top;
218 Widget html;
219 TextStructure *location;
220 Widget track;
222 char *url;
223 char *base;
224 char *anchor;
226 TextStructure *input;
227 Widget case_sensitive;
228 Widget find_backwards;
230 XmHTMLTextFinder finder;
231 char *last;
232 } html_ui;
234 static char *loadFile(char *URL)
236 FILE *file;
237 int size;
238 char *content;
240 /* open the given file */
241 if ((file = grace_openr(grace, URL, SOURCE_DISK)) == NULL) {
242 return NULL;
245 /* see how large this file is */
246 fseek(file, 0, SEEK_END);
247 size = ftell(file);
248 rewind(file);
250 /* allocate a buffer large enough to contain the entire file */
251 if ((content = xmalloc(size + 1)) == NULL) {
252 errmsg("xmalloc failed");
253 return NULL;
256 /* now read the contents of this file */
257 if ((fread(content, 1, size, file)) != size) {
258 errmsg("Warning: did not read entire file!");
261 grace_close(file);
263 /* sanity */
264 content[size] = '\0';
266 return content;
269 static char *translateURL(char *url, char *base)
271 char *fname;
272 URLType type;
274 if (url == NULL) {
275 return NULL;
278 type = XmHTMLGetURLType(url);
279 if (type != ANCHOR_FILE_LOCAL || url[0] == '/') {
280 fname = copy_string(NULL, url);
281 } else {
282 char *p;
283 fname = copy_string(NULL, base);
284 p = strrchr(fname, '/');
285 if (p) {
286 p++;
287 *p = '\0';
288 fname = concat_strings(fname, url);
289 } else {
290 fname = copy_string(NULL, url);
294 return fname;
297 static void anchorCB(Widget w, XtPointer client_data, XtPointer call_data)
299 int id;
300 XmHTMLAnchorPtr href_data = (XmHTMLAnchorPtr) call_data;
301 html_ui *ui = (html_ui *) client_data;
302 char *turl;
304 /* see if we have been called with a valid reason */
305 if (href_data->reason != XmCR_ACTIVATE) {
306 return;
309 switch (href_data->url_type) {
310 /* a named anchor */
311 case ANCHOR_JUMP:
312 /* see if XmHTML knows this anchor */
313 if ((id = XmHTMLAnchorGetId(w, href_data->href)) != -1) {
314 /* and let XmHTML jump and mark as visited */
315 href_data->doit = True;
316 href_data->visited = True;
318 ui->url = copy_string(ui->url, ui->base);
319 ui->url = concat_strings(ui->url, href_data->href);
320 SetTextString(ui->location, ui->url);
322 break;
323 /* let HelpCB check all other types */
324 default:
325 turl = translateURL(href_data->href, ui->base);
326 HelpCB(NULL, turl);
327 xfree(turl);
328 break;
332 static void trackCB(Widget w, XtPointer client_data, XtPointer call_data)
334 XmHTMLAnchorPtr href_data = (XmHTMLAnchorPtr) call_data;
335 html_ui *ui = (html_ui *) client_data;
337 /* see if we have been called with a valid reason */
338 if (href_data->reason != XmCR_HTML_ANCHORTRACK) {
339 return;
342 if (href_data->href) {
343 /* a valid anchor, eg, moving into an anchor */
344 SetLabel(ui->track, href_data->href);
345 } else {
346 /* a valid anchor, eg, moving away from an anchor */
347 SetLabel(ui->track, "");
351 static int find_cb(void *data)
353 char *s, *ptr;
354 int case_sensitive, find_backwards;
355 XmHTMLTextPosition start, end;
356 html_ui *ui = (html_ui *) data;
358 if (!ui->input) {
359 return RETURN_FAILURE;
362 s = GetTextString(ui->input);
364 if (is_empty_string(s)) {
365 xfree(s);
366 return RETURN_FAILURE;
369 if (ui->finder == NULL) {
370 ui->finder = XmHTMLTextFinderCreate(ui->html);
371 if (ui->finder == NULL) {
372 errmsg("XmHTMLTextFinderCreate failed!");
373 xfree(s);
374 return RETURN_FAILURE;
378 case_sensitive = GetToggleButtonState(ui->case_sensitive);
379 find_backwards = GetToggleButtonState(ui->find_backwards);
381 /*****
382 * The second arg represent regcomp flags, the default being
383 * REG_EXTENDED. Using -1 for this arg instructs the finder to
384 * keep the current flags. See man regcomp on possible values for
385 * your system. The third arg specifies whether or not the search
386 * should be done case-insensitive (True) or not (False). The last arg
387 * specifies the search direction. Currently only forward (top to
388 * bottom) is supported.
389 *****/
390 XmHTMLTextFinderSetPatternFlags(ui->finder,
392 case_sensitive ? False : True,
393 find_backwards ? XmHTML_BACKWARD : XmHTML_FORWARD);
395 if (ui->last == NULL || strcmp(ui->last, s)) {
396 if(!XmHTMLTextFinderSetPattern(ui->finder, s)) {
397 /* failure dialog */
398 ptr = XmHTMLTextFinderGetErrorString(ui->finder);
400 errmsg(ptr ? ptr : "(unknown error)");
402 /* must free this */
403 xfree(ptr);
404 xfree(ui->last);
405 ui->last = s;
406 return RETURN_FAILURE;
410 switch (XmHTMLTextFindString(ui->html, ui->finder)) {
411 case XmREG_ERROR:
412 ptr = XmHTMLTextFinderGetErrorString(ui->finder);
413 errmsg(ptr ? ptr : "(unknown error)");
414 xfree(ptr);
415 break;
416 case XmREG_NOMATCH:
417 if (yesno("End of document reached; continue from beginning?",
418 NULL, NULL, NULL) == TRUE) {
419 xfree(s);
420 XCFREE(ui->last);
421 return find_cb(ui);
423 break;
424 case XmREG_MATCH:
425 if (XmHTMLTextFindToPosition(ui->html, ui->finder, &start, &end)) {
426 XmHTMLTextShowPosition(ui->html, start);
427 XmHTMLTextSetHighlight(ui->html, start, end, XmHIGHLIGHT_SELECTED);
429 break;
432 xfree(ui->last);
433 ui->last = s;
435 return RETURN_SUCCESS;
438 static void create_find_dialog(Widget but, void *data)
440 static Widget dialog = NULL;
441 html_ui *ui = (html_ui *) data;
443 if (!dialog) {
444 Widget rc, rc2;
446 dialog = CreateDialogForm(ui->html, "Find Dialog");
448 rc = CreateVContainer(dialog);
449 ui->input = CreateTextInput(rc, "Find:");
450 rc2 = CreateHContainer(rc);
451 ui->case_sensitive = CreateToggleButton(rc2, "Case sensitive");
452 ui->find_backwards = CreateToggleButton(rc2, "Find backwards (N/I)");
454 CreateAACDialog(dialog, rc, find_cb, data);
456 ManageChild(dialog);
459 RaiseWindow(GetParent(dialog));
462 static void refresh_cb(Widget but, void *data)
464 html_ui *ui = (html_ui *) data;
465 XmHTMLRedisplay(ui->html);
468 static XmImageInfo *loadImage(Widget w,
469 String url, Dimension width, Dimension height, XtPointer client_data)
471 char *fname;
472 XmImageInfo *image;
473 html_ui *ui = (html_ui *) client_data;
475 fname = translateURL(url, ui->base);
476 if (fname == NULL) {
477 return NULL;
480 image = XmHTMLImageDefaultProc(w, fname, NULL, 0);
482 xfree(fname);
484 return image;
487 void location_cb(TextStructure *cst, char *s, void *data)
489 HelpCB(NULL, s);
492 static void find_again_cb(Widget but, void *data)
494 find_cb(data);
497 void create_helper_frame(char *URL)
499 static html_ui *ui = NULL;
500 char *content;
502 set_wait_cursor();
504 if (ui == NULL) {
505 Widget fr1, fr2, menubar, menupane, rc;
507 ui = xmalloc(sizeof(html_ui));
508 memset(ui, 0, sizeof(html_ui));
510 ui->top = CreateDialogForm(app_shell, "Gracilla");
512 menubar = CreateMenuBar(ui->top);
513 ManageChild(menubar);
514 AddDialogFormChild(ui->top, menubar);
516 menupane = CreateMenu(menubar, "File", 'F', FALSE);
517 CreateMenuCloseButton(menupane, ui->top);
519 menupane = CreateMenu(menubar, "Edit", 'E', FALSE);
520 CreateMenuButton(menupane, "Find", 'F', create_find_dialog, ui);
521 CreateMenuButton(menupane, "Find again", 'g', find_again_cb, ui);
523 menupane = CreateMenu(menubar, "View", 'V', FALSE);
524 CreateMenuButton(menupane, "Refresh", 'R', refresh_cb, ui);
526 menupane = CreateMenu(menubar, "Help", 'H', TRUE);
527 CreateMenuButton(menupane, "User's Guide", 'G', HelpCB, "doc/UsersGuide.html");
528 CreateMenuButton(menupane, "FAQ", 'Q', HelpCB, "doc/FAQ.html");
529 CreateMenuButton(menupane, "Changes", 'C', HelpCB, "doc/CHANGES.html");
530 CreateMenuSeparator(menupane);
531 CreateMenuButton(menupane, "License terms", 'L', HelpCB, "doc/GPL.html");
533 ui->location = CreateTextInput(ui->top, "Location:");
534 AddTextInputCB(ui->location, location_cb, ui->location);
535 AddDialogFormChild(ui->top, ui->location->form);
537 fr1 = CreateFrame(ui->top, NULL);
538 AddDialogFormChild(ui->top, fr1);
539 ui->html = XtVaCreateManagedWidget("html",
540 xmHTMLWidgetClass, fr1,
541 XmNimageProc, loadImage,
542 XmNclientData, (XtPointer) ui,
543 XmNenableBadHTMLWarnings, XmHTML_NONE,
544 XmNanchorButtons, False,
545 XmNmarginWidth, 20,
546 XmNmarginHeight, 20,
547 NULL);
549 XtAddCallback(ui->html, XmNactivateCallback, anchorCB, ui);
550 XtAddCallback(ui->html, XmNanchorTrackCallback, trackCB, ui);
552 fr2 = CreateFrame(ui->top, NULL);
553 AddDialogFormChild(ui->top, fr2);
554 rc = CreateVContainer(fr2);
555 ui->track = CreateLabel(rc, "Welcome to Gracilla!");
557 XtVaSetValues(fr1,
558 XmNbottomAttachment, XmATTACH_WIDGET,
559 XmNbottomWidget, fr2,
560 NULL);
561 XtVaSetValues(fr2,
562 XmNtopAttachment, XmATTACH_NONE,
563 NULL);
565 ManageChild(ui->top);
567 XtVaSetValues(rc, XmNresizeHeight, False, NULL);
569 ManageChild(GetParent(ui->top));
572 ui->url = copy_string(ui->url, URL);
573 ui->base = copy_string(ui->base, URL);
574 if (ui->url) {
575 char *p;
577 p = strchr(ui->url, '#');
578 if (p) {
579 ui->base[p - ui->url] = '\0';
580 ui->anchor = copy_string(ui->anchor, p);
581 } else {
582 XCFREE(ui->anchor);
586 SetTextString(ui->location, ui->url);
588 if (ui->finder) {
589 XmHTMLTextFinderDestroy(ui->finder);
590 ui->finder = NULL;
591 ui->last = NULL;
594 content = loadFile(ui->base);
595 if (content != NULL) {
596 XmHTMLTextSetString(ui->html, content);
597 if (ui->anchor) {
598 int id = XmHTMLAnchorGetId(ui->html, ui->anchor);
599 if (id != -1) {
600 XmHTMLAnchorScrollToId(ui->html, id);
602 } else {
603 XmHTMLTextScrollToLine(ui->html, 0);
605 xfree(content);
607 RaiseWindow(GetParent(ui->top));
610 unset_wait_cursor();
612 #endif /* WITH_XMHTML */