1 /*
2  * Copyright (c) 1993-1997 by Alexander V. Lukyanov (lav@yars.free.net)
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 
19 #include <config.h>
20 #include <ctype.h>
21 #include "edit.h"
22 #include "keymap.h"
23 #include <string.h>
24 #include <stdlib.h>
25 
26 #if 0
27 void  Help(char ***h,char *title)
28 {
29    static   struct   menu
30    c[]={
31    {"  &Cancel  ",MIDDLE,FDOWN-2},
32    {NULL}},
33    pnc[]={
34    {" &Previous ",MIDDLE-12,FDOWN-2},
35    {"   &Next   ",MIDDLE,FDOWN-2},
36    {"  &Cancel  ",MIDDLE+12,FDOWN-2},
37    {NULL}},
38    npc[]={
39    {"   &Next   ",MIDDLE-12,FDOWN-2},
40    {" &Previous ",MIDDLE,FDOWN-2},
41    {"  &Cancel  ",MIDDLE+12,FDOWN-2},
42    {NULL}},
43    pc[]={
44    {" &Previous ",MIDDLE-6,FDOWN-2},
45    {"  &Cancel  ",MIDDLE+6,FDOWN-2},
46    {NULL}},
47    nc[]={
48    {"   &Next   ",MIDDLE-6,FDOWN-2},
49    {"  &Cancel  ",MIDDLE+6,FDOWN-2},
50    {NULL}};
51    WIN   *HelpWin;
52    int   page=0;
53    int   backward=0,res,line;
54 
55    HelpWin=CreateWin(MIDDLE,MIDDLE,42,21,HELP_WIN_ATTR,title,0);
56    DisplayWin(HelpWin);
57 
58    do
59    {
60       Clear();
61       for(line=2; line<Upper->h-4 && h[page][line-2]; line++)
62          PutStr(2,line,h[page][line-2]);
63       if(page==0 && !h[1])
64          res=ReadMenu(c,HORIZ,HELP_WIN_ATTR,CURR_BUTTON_ATTR);
65       else if(page==0)
66          res=ReadMenu(nc,HORIZ,HELP_WIN_ATTR,CURR_BUTTON_ATTR);
67       else if(!h[page+1])
68          res=ReadMenu(pc,HORIZ,HELP_WIN_ATTR,CURR_BUTTON_ATTR);
69       else
70          res=ReadMenu(backward?pnc:npc,HORIZ,HELP_WIN_ATTR,CURR_BUTTON_ATTR);
71       switch(res)
72       {
73       case('C'):
74          res=0;
75          break;
76       case('N'):
77          page++;
78          backward=0;
79          break;
80       case('P'):
81          page--;
82          backward=1;
83          break;
84       }
85    }
86    while(res);
87 
88    CloseWin();
89    DestroyWin(HelpWin);
90 }
91 #endif //0
92 
LoadHelp(const char * tag)93 static char *LoadHelp(const char *tag)
94 {
95    FILE *hf=fopen(PKGDATADIR "/le.hlp","r");
96    if(!hf)
97       return 0;
98 
99    int help_size=0;
100    char *help=0;
101    char *help_end=0;
102 
103    char buf[256];
104    char this_tag[256];
105    bool tag_match=false;
106    buf[255]=0;
107    while(fgets(buf,sizeof(buf)-1,hf)!=0)
108    {
109       if(1==sscanf(buf,"[%[^]]]",this_tag))
110       {
111 	 if(tag_match) {
112 	    fclose(hf);
113 	    return help;
114 	 }
115 	 if(!strcasecmp(tag,this_tag))
116 	    tag_match=true;
117 	 continue;
118       }
119       if(tag_match)
120       {
121 	 int buf_len=strlen(buf);
122 	 if(!help || help_end-help>help_size-buf_len-1)
123 	 {
124 	    // allocate more memory
125 	    int help_len=help_end-help;
126 	    help_size=(help_size?help_size*2:0x10000);
127 	    char *new_help=(char*)realloc(help,help_size);
128 	    if(!new_help)
129 	    {
130 	       // out of memory
131 	       fclose(hf);
132 	       return help;
133 	    }
134 	    help=new_help;
135 	    help_end=help+help_len;
136 	 }
137 	 char *subst=strchr(buf,'$');
138 	 if(subst && subst[1]=='{') {
139 	    char *end_brace=strchr(subst+2,'}');
140 	    if(end_brace) {
141 	       char action[256];
142 	       memcpy(action,subst+2,end_brace-subst-2);
143 	       action[end_brace-subst-2]=0;
144 	       char *fmt_len_ptr=strchr(action,':');
145 	       int fmt_len=0;
146 	       if(fmt_len_ptr) {
147 		  *fmt_len_ptr=0;
148 		  fmt_len=atoi(fmt_len_ptr+1);
149 	       }
150 	       const char *code=ShortcutPrettyPrint(FindActionCode(action),NULL);
151 	       int code_len=strlen(code);
152 	       int final_width=(code_len>fmt_len?code_len:fmt_len);
153 	       memmove(subst+final_width,end_brace+1,strlen(end_brace));
154 	       memcpy(subst,code,code_len);
155 	       if(code_len<fmt_len)
156 		  memset(subst+code_len,' ',fmt_len-code_len);
157 	       buf_len=strlen(buf);
158 	    }
159 	 }
160 	 memcpy(help_end,buf,buf_len+1);
161 	 help_end+=buf_len;
162       }
163    }
164    fclose(hf);
165    if(tag_match)
166       return help;
167    free(help);
168    return 0;
169 }
170 
Help(const char * helpf,const char * title)171 void  Help(const char *helpf,const char *title)
172 {
173    char *help=LoadHelp(helpf);
174    if(!help)
175       return;
176    const char  *ptr=help;
177    WIN   *HelpWin;
178    const int v_m=1;
179    const int h_m=2;
180 
181    HelpWin=CreateWin(MIDDLE,MIDDLE,48,22,HELP_WIN_ATTR,title,0);
182    DisplayWin(HelpWin);
183 
184    for(;;)
185    {
186       int line=v_m;
187       const char *c;
188 
189       SetAttr(HELP_WIN_ATTR);
190       for(c=ptr; *c; c++)
191       {
192          if(line >= HelpWin->h-v_m)
193             break;
194          int col=h_m;
195          for( ; *c && *c!='\n'; c++)
196          {
197             if(col >= HelpWin->w-h_m)
198                break;
199 
200             PutCh(col++,line,(unsigned char)*c);
201          }
202          while(col < HelpWin->w-h_m)
203             PutCh(col++,line,' ');
204          c=strchr(c,'\n');
205          if(!c)
206             break;
207          line++;
208       }
209       while(line < HelpWin->h-v_m)
210       {
211          for(int col=h_m; col<HelpWin->w-h_m; col++)
212             PutCh(col,line,' ');
213          line++;
214       }
215       Message("Use Up,Down,PageUp,PageDown to scroll help text. Ctrl-X - cancel");
216       curs_set(0);
217       move(LINES-1,COLS-1);
218 
219       int action=GetNextAction();
220       int i;
221       switch(action)
222       {
223       case(LINE_DOWN):
224          c=strchr(ptr,'\n');
225          if(!c)
226             break;
227          ptr=c+1;
228          break;
229       case(NEXT_PAGE):
230          c=ptr;
231          for(i=HelpWin->h-v_m*2-1; i>0; i--)
232          {
233             c=strchr(c,'\n');
234             if(!c)
235                break;
236             c++;
237          }
238          if(c)
239             ptr=c;
240          break;
241       case(LINE_UP):
242          if(ptr==help)
243             break;
244          ptr--;
245          while(ptr>help && ptr[-1]!='\n')
246             ptr--;
247          break;
248       case(PREV_PAGE):
249          c=ptr;
250          for(i=HelpWin->h-v_m*2-1; i>0; i--)
251          {
252             if(c==help)
253                break;
254             c--;
255             while(c>help && c[-1]!='\n') c--;
256          }
257          ptr=c;
258          break;
259       case(NEWLINE):
260       case(QUIT_EDITOR):
261          goto quit;
262       }
263       c=help+strlen(help);
264       for(i=HelpWin->h-v_m*2-1; i>0; i--)
265       {
266          if(c>help && c[-1]=='\n')
267             c--;
268          while(c>help && c[-1]!='\n')
269             c--;
270       }
271       if(c<ptr)
272          ptr=c;
273    }
274 quit:
275    CloseWin();
276    DestroyWin(HelpWin);
277    free(help);
278 }
279