6
#include <LYBookmark.h>
7
#include <LYGlobalDefs.h>
10
#include <LYCharUtils.h> /* need for META charset */
12
#include <LYCharSets.h> /* need for LYHaveCJKCharacterSet */
23
PUBLIC char *MBM_A_subbookmark[MBM_V_MAXFILES+1];
24
PUBLIC char *MBM_A_subdescript[MBM_V_MAXFILES+1];
26
PRIVATE BOOLEAN is_mosaic_hotlist = FALSE;
27
PRIVATE char * convert_mosaic_bookmark_file PARAMS((char *filename_buffer));
29
PUBLIC int LYindex2MBM ARGS1(int, n)
31
static char MBMcodes[MBM_V_MAXFILES+2] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
32
return n >= 0 && n <= MBM_V_MAXFILES ? MBMcodes[n] : '?';
35
PUBLIC int LYMBM2index ARGS1(int, ch)
37
if ((ch = TOUPPER(ch)) > 0) {
38
char *letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
39
char *result = strchr(letters, ch);
41
&& (result - letters) <= MBM_V_MAXFILES)
42
return (result - letters);
48
show_bookmark_not_defined NOARGS
50
char *string_buffer = 0;
52
HTSprintf0(&string_buffer,
53
BOOKMARK_FILE_NOT_DEFINED,
54
key_for_func(LYK_OPTIONS));
55
LYMBM_statusline(string_buffer);
60
* Tries to open a bookmark file for reading, which may be
61
* the default, or based on offering the user a choice from
62
* the MBM_A_subbookmark[] array. If successful the file is
63
* closed, and the filename in system path specs is returned,
64
* the URL is allocated into *URL, and the MBM_A_subbookmark[]
65
* filepath is allocated into the BookmarkPage global. Returns
66
* a zero-length pointer to flag a cancel, or a space to flag
67
* an undefined selection, without allocating into *URL or
68
* BookmarkPage. Returns NULL with allocating into BookmarkPage
69
* but not *URL is the selection is valid but the file doesn't
72
PUBLIC char * get_bookmark_filename ARGS1(
75
static char filename_buffer[LY_MAXPATH];
76
char *string_buffer = 0;
81
* Multi_Bookmarks support. - FMG & FM
82
* Let user select a bookmark file.
84
MBM_tmp = select_multi_bookmarks();
87
* Zero-length pointer flags a cancel. - FM
91
show_bookmark_not_defined();
93
* Space flags an undefined selection. - FMG
98
* Save the filepath as a global. The system path will be
99
* loaded into to the (static) filename_buffer as the return
100
* value, the URL will be allocated into *URL, and we also
101
* need the filepath available to calling functions. This
102
* is all pitifully non-reentrant, a la the original Lynx,
103
* and should be redesigned someday. - FM
105
StrAllocCopy(BookmarkPage, MBM_A_subbookmark[MBM_tmp]);
109
* Seek it in the home path. - FM
111
LYAddPathToHome(filename_buffer,
112
sizeof(filename_buffer),
114
CTRACE((tfp, "\nget_bookmark_filename: SEEKING %s\n AS %s\n\n",
115
BookmarkPage, filename_buffer));
116
if ((fp = fopen(filename_buffer, TXT_R)) != NULL) {
118
* We now have the file open.
119
* Check if it is a mosaic hotlist.
121
if (LYSafeGets(&string_buffer, fp) != 0
122
&& *LYTrimNewline(string_buffer) != '\0'
123
&& !strncmp(string_buffer, "ncsa-xmosaic-hotlist-format-1", 29)) {
126
* It is a mosaic hotlist file.
128
is_mosaic_hotlist = TRUE;
129
newname = convert_mosaic_bookmark_file(filename_buffer);
130
LYLocalFileToURL(URL, newname);
132
is_mosaic_hotlist = FALSE;
133
LYLocalFileToURL(URL, filename_buffer);
138
return(filename_buffer); /* bookmark file exists */
145
* Converts a Mosaic hotlist file into an HTML
146
* file for handling as a Lynx bookmark file. - FM
148
PRIVATE char * convert_mosaic_bookmark_file ARGS1(
149
char *, filename_buffer)
151
static char newfile[LY_MAXPATH];
156
LYRemoveTemp(newfile);
157
if ((nfp = LYOpenTemp(newfile, HTML_SUFFIX, "w")) == NULL) {
158
LYMBM_statusline(NO_TEMP_FOR_HOTLIST);
163
if ((fp = fopen(filename_buffer, TXT_R)) == NULL)
164
return (""); /* should always open */
166
fprintf(nfp,"<head>\n<title>%s</title>\n</head>\n",MOSAIC_BOOKMARK_TITLE);
167
fprintf(nfp, "%s\n\n<p>\n<ol>\n", gettext("\
168
This file is an HTML representation of the X Mosaic hotlist file.\n\
169
Outdated or invalid links may be removed by using the\n\
170
remove bookmark command, it is usually the 'R' key but may have\n\
171
been remapped by you or your system administrator."));
173
while ((LYSafeGets(&buf, fp)) != NULL) {
176
if ((line % 2) == 0) { /* even lines */
178
strtok(buf," "); /* kill everything after the space */
179
fprintf(nfp,"<LI><a href=\"%s\">",buf); /* the URL */
181
} else { /* odd lines */
182
fprintf(nfp,"%s</a>\n",buf); /* the title */
185
/* else - ignore the line (this gets rid of first two lines) */
193
PRIVATE BOOLEAN havevisible PARAMS((CONST char *Title));
194
PRIVATE BOOLEAN have8bit PARAMS((CONST char *Title));
195
PRIVATE char* title_convert8bit PARAMS((CONST char *Title));
198
* Adds a link to a bookmark file, creating the file
199
* if it doesn't already exist, and making sure that
200
* no_cache is set for a pre-existing, cached file,
201
* so that the change will be evident on return to
204
PUBLIC void save_bookmark_link ARGS2(
209
BOOLEAN first_time = FALSE;
211
char *bookmark_URL = NULL;
212
char filename_buffer[LY_MAXPATH];
213
char string_buffer[BUFSIZ];
214
char tmp_buffer[BUFSIZ];
215
char *Address = NULL;
219
HTParentAnchor *tmpanchor;
223
* Make sure we were passed something to save. - FM
225
if (!(address && *address)) {
226
HTAlert(MALFORMED_ADDRESS);
231
* Offer a choice of bookmark files,
232
* or get the default. - FMG
234
filename = get_bookmark_filename(&bookmark_URL);
237
* If filename is NULL, must create a new file. If
238
* filename is a space, an invalid bookmark file was
239
* selected, or if zero-length, the user cancelled.
240
* Ignore request in both cases. Otherwise, make
241
* a copy before anything might change the static
242
* get_bookmark_filename() buffer. - FM
244
if (filename == NULL) {
246
filename_buffer[0] = '\0';
248
if (*filename == '\0' || !strcmp(filename," ")) {
252
LYstrncpy(filename_buffer, filename, sizeof(filename_buffer)-1);
256
* If BookmarkPage is NULL, something went
257
* wrong, so ignore the request. - FM
259
if (BookmarkPage == NULL) {
265
* If the link will be added to the same
266
* bookmark file, get confirmation. - FM
268
if (LYMultiBookmarks != MBM_OFF) {
269
CONST char *url = HTLoadedDocumentURL();
270
CONST char *page = (*BookmarkPage == '.')
273
if (strstr(url, page) != NULL) {
274
LYMBM_statusline(MULTIBOOKMARKS_SELF);
275
c = LYgetch_single();
284
* Allow user to change the title. - FM
287
if (HTCJK == JAPANESE) {
290
TO_EUC((CONST unsigned char *) title, (unsigned char *) tmp_buffer);
293
TO_SJIS((CONST unsigned char *) title, (unsigned char *) tmp_buffer);
298
LYstrncpy(string_buffer, tmp_buffer, sizeof(string_buffer)-1);
300
LYstrncpy(string_buffer, title, sizeof(string_buffer)-1);
302
convert_to_spaces(string_buffer, FALSE);
303
LYMBM_statusline(TITLE_PROMPT);
304
LYgetstr(string_buffer, VISIBLE, sizeof(string_buffer), NORECALL);
305
if (*string_buffer == '\0') {
306
LYMBM_statusline(CANCELLED);
311
} while(!havevisible(string_buffer));
314
* Create the Title with any left-angle-brackets
315
* converted to < entities and any ampersands
316
* converted to & entities. - FM
318
* Convert 8-bit letters to &#xUUUU to avoid dependencies
319
* from display character set which may need changing.
320
* Do NOT convert any 8-bit chars if we have CJK display. - LP
322
LYformTitle(&Title, string_buffer);
323
LYEntify(&Title, TRUE);
324
if (UCSaveBookmarksInUnicode &&
325
have8bit(Title) && (!LYHaveCJKCharacterSet)) {
326
char *p = title_convert8bit(Title);
332
* Create the bookmark file, if it doesn't exist already,
333
* Otherwise, open the pre-existing bookmark file. - FM
335
SetDefaultMode(O_TEXT);
338
* Seek it in the home path. - FM
340
LYAddPathToHome(filename_buffer,
341
sizeof(filename_buffer),
344
CTRACE((tfp, "\nsave_bookmark_link: SEEKING %s\n AS %s\n\n",
345
BookmarkPage, filename_buffer));
346
if ((fp = fopen(filename_buffer, (first_time ? TXT_W : TXT_A))) == NULL) {
347
LYMBM_statusline(BOOKMARK_OPEN_FAILED);
355
* Convert all ampersands in the address to & entities. - FM
357
StrAllocCopy(Address, address);
358
LYEntify(&Address, FALSE);
361
* If we created a new bookmark file, write the headers. - FM
362
* Once and forever...
365
fprintf(fp, "<head>\n");
366
#if defined(SH_EX) && !defined(_WINDOWS) /* 1997/12/11 (Thu) 19:13:40 */
367
if (HTCJK != JAPANESE)
368
LYAddMETAcharsetToFD(fp, -1);
370
fprintf(fp, "<META %s %s>\n",
371
"http-equiv=\"content-type\"",
372
"content=\"text/html;charset=iso-2022-jp\"");
374
LYAddMETAcharsetToFD(fp, -1);
375
#endif /* !_WINDOWS */
376
fprintf(fp,"<title>%s</title>\n</head>\n", BOOKMARK_TITLE);
379
gettext(" You can delete links by the 'R' key<br>\n<ol>\n"));
381
fprintf(fp, "%s<br>\n%s\n\n<!--\n%s\n-->\n\n<p>\n<ol>\n",
383
You can delete links using the remove bookmark command. It is usually\n\
384
the 'R' key but may have been remapped by you or your system\n\
387
This file also may be edited with a standard text editor to delete\n\
388
outdated or invalid links, or to change their order."),
390
Note: if you edit this file manually\n\
391
you should not change the format within the lines\n\
392
or add other HTML markup.\n\
393
Make sure any bookmark link is saved as a single line."));
394
#endif /* _WINDOWS */
398
* Add the bookmark link, in Mosaic hotlist or Lynx format. - FM
400
if (is_mosaic_hotlist) {
401
time_t NowTime = time(NULL);
402
char *TimeString = (char *)ctime (&NowTime);
404
* TimeString has a \n at the end.
406
fprintf(fp,"%s %s%s\n", Address, TimeString, Title);
408
fprintf(fp,"<LI><a href=\"%s\">%s</a>\n", Address, Title);
412
SetDefaultMode(O_BINARY);
414
* If this is a cached bookmark file, set nocache for
415
* it so we'll see the new bookmark link when that
416
* cache is retrieved. - FM
418
if (!first_time && nhist > 0 && bookmark_URL) {
419
for (i = 0; i < nhist; i++) {
420
if (HDOC(i).bookmark &&
421
!strcmp(HDOC(i).address, bookmark_URL)) {
422
WWWDoc.address = HDOC(i).address;
423
WWWDoc.post_data = NULL;
424
WWWDoc.post_content_type = NULL;
425
WWWDoc.bookmark = HDOC(i).bookmark;
426
WWWDoc.isHEAD = FALSE;
428
tmpanchor = HTAnchor_findAddress(&WWWDoc);
429
if ((text = (HText *)HTAnchor_document(tmpanchor)) != NULL) {
430
HText_setNoCache(text);
438
* Clean up and report success.
443
LYMBM_statusline(OPERATION_DONE);
448
* Remove a link from a bookmark file. The calling
449
* function is expected to have used get_filename_link(),
450
* pass us the link number as cur, the MBM_A_subbookmark[]
451
* string as cur_bookmark_page, and to have set up no_cache
454
PUBLIC void remove_bookmark_link ARGS2(
456
char *, cur_bookmark_page)
462
char filename_buffer[NAM$C_MAXRSS+12];
463
char newfile[NAM$C_MAXRSS+12];
464
#define keep_tempfile FALSE
466
char filename_buffer[LY_MAXPATH];
467
char newfile[LY_MAXPATH];
468
BOOLEAN keep_tempfile = FALSE;
470
struct stat stat_buf;
472
BOOLEAN regular = FALSE;
475
char homepath[LY_MAXPATH];
477
CTRACE((tfp, "remove_bookmark_link: deleting link number: %d\n", cur));
479
if (!cur_bookmark_page)
481
LYAddPathToHome(filename_buffer,
482
sizeof(filename_buffer),
484
CTRACE((tfp, "\nremove_bookmark_link: SEEKING %s\n AS %s\n\n",
485
cur_bookmark_page, filename_buffer));
486
if ((fp = fopen(filename_buffer, TXT_R)) == NULL) {
487
HTAlert(BOOKMARK_OPEN_FAILED_FOR_DEL);
491
LYAddPathToHome(homepath, sizeof(homepath), "");
492
if ((nfp = LYOpenScratch(newfile, homepath)) == 0) {
494
HTAlert(BOOKSCRA_OPEN_FAILED_FOR_DEL);
500
* Explicitly preserve bookmark file mode on Unix. - DSL
502
if (stat(filename_buffer, &stat_buf) == 0) {
503
regular = (S_ISREG(stat_buf.st_mode) && stat_buf.st_nlink == 1);
504
mode = ((stat_buf.st_mode & 0777) | 0600); /* make it writable */
505
(void) chmod(newfile, mode);
506
if ((nfp = LYReopenTemp(newfile)) == NULL) {
507
(void) LYCloseInput(fp);
508
HTAlert(BOOKTEMP_REOPEN_FAIL_FOR_DEL);
514
if (is_mosaic_hotlist) {
515
int del_line = cur*2; /* two lines per entry */
516
n = -3; /* skip past cookie and name lines */
517
while (LYSafeGets(&buf, fp) != NULL) {
519
if (n == del_line || n == del_line+1)
520
continue; /* remove two lines */
521
if (fputs(buf, nfp) == EOF)
531
while (LYSafeGets(&buf, fp) != NULL) {
536
if ((cur == 0) && (cp2 = LYstrstr(cp,"<ol><LI>")))
537
keep_ol = TRUE; /* Do not erase, this corrects a bug in an
539
while (n < cur && (cp = LYstrstr(cp, "<a href="))) {
542
if (seen != 1 || !LYstrstr(buf, "</a>") ||
543
LYstrstr((cp + 1), "<a href=")) {
544
HTAlert(BOOKMARK_LINK_NOT_ONE_LINE);
547
CTRACE((tfp, "remove_bookmark_link: skipping link %d\n", n));
549
fprintf(nfp,"<ol>\n");
554
if (retain && fputs(buf, nfp) == EOF)
560
CTRACE((tfp, "remove_bookmark_link: files: %s %s\n",
561
newfile, filename_buffer));
565
if (fflush(nfp) == EOF) {
566
CTRACE((tfp, "fflush(nfp): %s", LYStrerror(errno)));
571
#if defined(DOSPATH) || defined(__EMX__)
572
remove(filename_buffer);
577
* By copying onto the bookmark file, rather than renaming it, we
578
* can preserve the original ownership of the file, provided that
579
* it is writable by the current process.
580
* Changed to copy 1998-04-26 -- gil
581
* But if the copy fails, for example because the filesystem is full,
582
* we are left with a corrupt bookmark file. Changed back to use
583
* the previous mechanism [try rename(), then mv for EXDEV], except
584
* in usual cases (not a regular file e.g., symbolic link, or has hard
585
* links). This will let bookmarks survive a filesystem full condition
586
* in the "normal" case (bookmark is on same filesystem as home directory,
587
* is a regular file, has no additional hard links).
588
* If we first tried LYCopyFile, and that fails, also fall back to trying
589
* the other stuff. That gives a chance to recover in case the LYCopyFile
590
* left a corrupt target file.
591
* If there is an error, and that error may mean that the bookmark file
592
* has been corrupted, don't remove the temporary newfile (which should
593
* always be uncorrupted) in place, it may still be used to recover
594
* manually. If this applies, produce an additional message to that
595
* effect. The temp file will still be removed by normal program exit
596
* cleanup. - kw 1999-11-12
599
if (LYCopyFile(newfile, filename_buffer) == 0) {
600
LYRemoveTemp(newfile);
603
LYSleepAlert(); /* give a chance to see error from cp - kw */
604
HTUserMsg(BOOKTEMP_COPY_FAIL);
605
keep_tempfile = TRUE;
609
if (rename(newfile, filename_buffer) != -1) {
610
#ifdef MULTI_USER_UNIX
612
chmod(filename_buffer, stat_buf.st_mode & 07777);
614
HTSYS_purge(filename_buffer);
619
* Rename won't work across file systems.
620
* Check if this is the case and do something appropriate.
621
* Used to be ODD_RENAME
623
#if defined(_WINDOWS) || defined(WIN_EX)
625
if (GetLastError() == ERROR_NOT_SAME_DEVICE)
627
if (errno == ENOTSAM)
630
if (rename(newfile, filename_buffer) != 0) {
631
if (LYCopyFile(newfile, filename_buffer) == 0)
636
if (errno == EXDEV) {
637
static CONST char MV_FMT[] = "%s %s %s";
641
if ((program = HTGetProgramPath(ppMV)) != NULL) {
642
HTAddParam(&buffer, MV_FMT, 1, program);
643
HTAddParam(&buffer, MV_FMT, 2, newfile);
644
HTAddParam(&buffer, MV_FMT, 3, filename_buffer);
645
HTEndParam(&buffer, MV_FMT, 3);
646
if (LYSystem(buffer) == 0) {
647
#ifdef MULTI_USER_UNIX
649
chmod(filename_buffer, stat_buf.st_mode & 07777);
656
keep_tempfile = TRUE;
659
CTRACE((tfp, "rename(): %s", LYStrerror(errno)));
660
#endif /* _WINDOWS */
664
HTAlert(ERROR_RENAMING_SCRA);
666
HTAlert(ERROR_RENAMING_TEMP);
669
perror("renaming the file");
675
HTAlert(BOOKMARK_DEL_FAILED);
681
HTUserMsg2(gettext("File may be recoverable from %s during this session"),
684
LYRemoveTemp(newfile);
689
* Allows user to select sub-bookmarks files. - FMG & FM
691
PUBLIC int select_multi_bookmarks NOARGS
696
* If not enabled, pick the "default" (0).
698
if (LYMultiBookmarks == MBM_OFF || LYHaveSubBookmarks() == FALSE) {
699
if (MBM_A_subbookmark[0]) /* If it exists! */
706
* For ADVANCED users, we can just mess with the status line to save
707
* the 2 redraws of the screen, if LYMBMAdvnced is TRUE. '=' will
708
* still show the screen and let them do it the "long" way.
710
if (LYMultiBookmarks == MBM_ADVANCED && user_mode == ADVANCED_MODE) {
711
LYMBM_statusline(MULTIBOOKMARKS_SELECT);
715
if (HadVMSInterrupt) {
716
HadVMSInterrupt = FALSE;
717
c = LYCharINTERRUPT2;
720
if (LYisNonAlnumKeyname(c, LYK_PREV_DOC) || LYCharIsINTERRUPT_HARD(c)) {
722
* Treat left-arrow, ^G, or ^C as cancel.
726
if (LYisNonAlnumKeyname(c, LYK_REFRESH)) {
728
* Refresh the screen.
730
lynx_force_repaint();
732
goto get_advanced_choice;
734
if (LYisNonAlnumKeyname(c, LYK_ACTIVATE)) {
736
* Assume default bookmark file on ENTER or right-arrow.
738
return (MBM_A_subbookmark[0] ? 0 : -1);
743
* Get the choice via the menu.
745
return(select_menu_multi_bookmarks());
749
* Convert to an array index, act on it if valid.
750
* Otherwise, get another keystroke.
752
if ((c = LYMBM2index(c)) < 0) {
753
goto get_advanced_choice;
757
* See if we have a bookmark like that.
759
return (MBM_A_subbookmark[c] ? c : -1);
762
* Get the choice via the menu.
764
return(select_menu_multi_bookmarks());
769
* Allows user to select sub-bookmarks files. - FMG & FM
771
PUBLIC int select_menu_multi_bookmarks NOARGS
773
int c, d, MBM_tmp_count, MBM_allow;
774
int MBM_screens, MBM_from, MBM_to, MBM_current;
777
* If not enabled, pick the "default" (0).
779
if (LYMultiBookmarks == MBM_OFF)
783
* Filip M. Gieszczykiewicz (filipg@paranoia.com) & FM
784
* ---------------------------------------------------
785
* MBM_A_subbookmark[n] - Hold values of the respective
786
* "multi_bookmarkn" in the lynxrc file.
788
* MBM_A_subdescript[n] - Hold description entries in the
791
* Note: MBM_A_subbookmark[0] is defined to be same value as
792
* "bookmark_file" in the lynxrc file and/or the startup
795
* We make the display of bookmarks depend on rows we have
798
* We load BookmarkPage with the valid MBM_A_subbookmark[n]
799
* via get_bookmark_filename(). Otherwise, that function
800
* returns a zero-length string to indicate a cancel, a
801
* single space to indicate an invalid choice, or NULL to
802
* indicate an inaccessible file.
804
MBM_allow=(LYlines-7); /* We need 7 for header and footer */
808
if (MBM_allow <= 0) {
812
HTAlert(MULTIBOOKMARKS_SMALL);
816
MBM_screens = (MBM_V_MAXFILES/MBM_allow)+1; /* int rounds off low. */
818
MBM_current = 1; /* Gotta start somewhere :-) */
821
MBM_from = MBM_allow * MBM_current - MBM_allow;
823
MBM_from = 0; /* 0 is default bookmark... */
824
if (MBM_current != 1)
827
MBM_to = (MBM_allow * MBM_current);
828
if (MBM_to > MBM_V_MAXFILES)
829
MBM_to = MBM_V_MAXFILES;
832
* Display menu of bookmarks. NOTE that we avoid printw()'s
833
* to increase the chances that any non-ASCII or multibyte/CJK
834
* characters will be handled properly. - FM
838
lynx_start_h1_color ();
839
if (MBM_screens > 1) {
840
char *shead_buffer = 0;
841
HTSprintf0(&shead_buffer,
842
MULTIBOOKMARKS_SHEAD_MASK, MBM_current, MBM_screens);
843
LYaddstr(shead_buffer);
846
LYaddstr(MULTIBOOKMARKS_SHEAD);
849
lynx_stop_h1_color ();
852
for (c = MBM_from; c <= MBM_to; c++) {
853
LYmove(3+MBM_tmp_count, 5);
854
LYaddch(LYindex2MBM(c));
856
if (MBM_A_subdescript[c])
857
LYaddstr(MBM_A_subdescript[c]);
858
LYmove(3+MBM_tmp_count,36);
860
if (MBM_A_subbookmark[c])
861
LYaddstr(MBM_A_subbookmark[c]);
867
* Don't need to show it if it all fits on one screen!
869
if (MBM_screens > 1) {
870
LYmove(LYlines-2, 0);
882
LYaddstr(NEXT_SCREEN);
885
LYMBM_statusline(MULTIBOOKMARKS_SAVE);
890
if (HadVMSInterrupt) {
891
HadVMSInterrupt = FALSE;
896
if ((d = LYMBM2index(c)) >= 0) {
898
* See if we have a bookmark like that.
900
if (MBM_A_subbookmark[d] != NULL)
903
show_bookmark_not_defined();
904
LYMBM_statusline(MULTIBOOKMARKS_SAVE);
905
} else if (LYisNonAlnumKeyname(c, LYK_PREV_DOC) ||
908
* Treat left-arrow, ^G, or ^C as cancel.
911
} else if (LYisNonAlnumKeyname(c, LYK_REFRESH)) {
913
* Refresh the screen.
915
lynx_force_repaint();
917
} else if (LYisNonAlnumKeyname(c, LYK_ACTIVATE)) {
919
* Assume default bookmark file on ENTER or right-arrow.
921
return(MBM_A_subbookmark[0] ? 0 : -1);
922
} else if ((c == ']' || LYisNonAlnumKeyname(c, LYK_NEXT_PAGE)) &&
925
* Next range, if available.
927
if (++MBM_current > MBM_screens)
932
else if ((c == '[' || LYisNonAlnumKeyname(c, LYK_PREV_PAGE)) &&
935
* Previous range, if available.
937
if (--MBM_current <= 0)
938
MBM_current = MBM_screens;
946
* This function returns TRUE if we have sub-bookmarks defined.
947
* Otherwise (i.e., only the default bookmark file is defined),
948
* it returns FALSE. - FM
950
PUBLIC BOOLEAN LYHaveSubBookmarks NOARGS
954
for (i = 1; i < MBM_V_MAXFILES; i++) {
955
if (MBM_A_subbookmark[i] != NULL && *MBM_A_subbookmark[i] != '\0')
963
* This function passes a string to _statusline(), making
964
* sure it is at the bottom of the screen if LYMultiBookmarks
965
* is not MBM_OFF, otherwise, letting it go to the normal statusline
966
* position based on the current user mode. We want to use
967
* _statusline() so that any multibyte/CJK characters in the
968
* string will be handled properly. - FM
970
PUBLIC void LYMBM_statusline ARGS1(
973
if (LYMultiBookmarks != MBM_OFF && user_mode == NOVICE_MODE) {
974
LYStatusLine = (LYlines - 1);
983
* Check whether we have any visible (non-blank) chars.
985
PRIVATE BOOLEAN havevisible ARGS1(CONST char *, Title)
987
CONST char *p = Title;
992
c = UCH(TOASCII(*p));
993
if (c > 32 && c < 127)
995
if (c <= 32 || c == 127)
997
if (LYHaveCJKCharacterSet || !UCCanUniTranslateFrom(current_char_set))
999
unicode = UCTransToUni(*p, current_char_set);
1000
if (unicode > 32 && unicode < 127)
1002
if (unicode <= 32 || unicode == 0xa0 || unicode == 0xad)
1004
if (unicode >= 0x2000 && unicode < 0x200f)
1008
return(FALSE); /* if we came here */
1012
* Check whether string have 8 bit chars.
1014
PRIVATE BOOLEAN have8bit ARGS1(CONST char *, Title)
1016
CONST char *p = Title;
1022
return(FALSE); /* if we came here */
1026
* Ok, title have 8-bit characters and they are in display charset.
1027
* Bookmarks is a permanent file. To avoid dependencies from display
1028
* character set which may be changed with time
1029
* we store 8-bit characters as numeric character reference (NCR),
1030
* so where the character encoded as unicode number in form of &#xUUUU;
1032
* To make bookmarks more readable for human (&#xUUUU certainly not)
1033
* we add a comment with '7-bit approximation' from the converted string.
1034
* This is a valid HTML and bookmarks code.
1036
* We do not want use META charset tag in bookmarks file:
1037
* it will never be changed later :-(
1038
* NCR's translation is part of I18N and HTML4.0
1039
* supported starting with Lynx 2.7.2,
1040
* Netscape 4.0 and MSIE 4.0.
1041
* Older versions fail.
1044
PRIVATE char* title_convert8bit ARGS1(CONST char *, Title)
1046
CONST char *p = Title;
1049
char *comment = NULL;
1052
int charset_in = current_char_set;
1053
int charset_out = UCGetLYhndl_byMIME("us-ascii");
1057
LYstrncpy(temp, p, sizeof(temp)-1);
1058
if (UCH(*temp) <= 127) {
1059
StrAllocCat(comment, temp);
1060
StrAllocCat(ncr, temp);
1063
char replace_buf [32];
1065
if (UCTransCharStr(replace_buf, sizeof(replace_buf), *temp,
1066
charset_in, charset_out, YES) > 0)
1067
StrAllocCat(comment, replace_buf);
1069
unicode = UCTransToUni( *temp, charset_in);
1071
StrAllocCat(ncr, "&#");
1072
sprintf(replace_buf, "%ld", unicode);
1073
StrAllocCat(ncr, replace_buf);
1074
StrAllocCat(ncr, ";");
1079
* Cleanup comment, collapse multiple dashes into one dash,
1082
for (q = p0 = comment; *p0; p0++) {
1083
if (UCH(TOASCII(*p0)) >= 32 &&
1085
(q == comment || *p0 != '-' || *(q-1) != '-')) {
1092
* valid bookmark should be a single line (no linebreaks!).
1094
StrAllocCat(buf, "<!-- ");
1095
StrAllocCat(buf, comment);
1096
StrAllocCat(buf, " -->");
1097
StrAllocCat(buf, ncr);
1105
* Since this is the "Default Bookmark File", we save it as a global, and as
1106
* the first MBM_A_subbookmark entry.
1108
PUBLIC void set_default_bookmark_page ARGS1(
1112
if (bookmark_page == 0
1113
|| strcmp(bookmark_page, value)) {
1114
StrAllocCopy(bookmark_page, value);
1116
StrAllocCopy(BookmarkPage, bookmark_page);
1117
StrAllocCopy(MBM_A_subbookmark[0], bookmark_page);
1118
StrAllocCopy(MBM_A_subdescript[0], MULTIBOOKMARKS_DEFAULT);