/[LeafOK_CVS]/lbbs/src/section_list_display.c
ViewVC logotype

Annotation of /lbbs/src/section_list_display.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.78 - (hide annotations)
Sun Nov 23 04:28:24 2025 UTC (3 months, 3 weeks ago) by sysadm
Branch: MAIN
Changes since 1.77: +7 -9 lines
Content type: text/x-csrc
Fix bug: regard Ctrl-C as EXITMENU by mistake

1 sysadm 1.69 /* SPDX-License-Identifier: GPL-3.0-or-later */
2     /*
3     * section_list_display
4     * - user interactive feature of section articles list
5     *
6 sysadm 1.70 * Copyright (C) 2004-2025 Leaflet <leaflet@leafok.com>
7 sysadm 1.69 */
8 sysadm 1.1
9 sysadm 1.75 #ifdef HAVE_CONFIG_H
10     #include "config.h"
11     #endif
12    
13 sysadm 1.9 #include "article_cache.h"
14 sysadm 1.53 #include "article_favor.h"
15 sysadm 1.41 #include "article_op.h"
16 sysadm 1.20 #include "article_post.h"
17 sysadm 1.34 #include "article_view_log.h"
18 sysadm 1.26 #include "article_del.h"
19 sysadm 1.1 #include "common.h"
20     #include "io.h"
21 sysadm 1.34 #include "log.h"
22     #include "login.h"
23 sysadm 1.37 #include "menu.h"
24 sysadm 1.48 #include "menu_proc.h"
25 sysadm 1.34 #include "section_list_display.h"
26     #include "section_list_loader.h"
27 sysadm 1.1 #include "screen.h"
28 sysadm 1.34 #include "str_process.h"
29 sysadm 1.57 #include "user_info_display.h"
30 sysadm 1.63 #include "user_list_display.h"
31 sysadm 1.18 #include "user_priv.h"
32 sysadm 1.65 #include <ctype.h>
33 sysadm 1.59 #include <errno.h>
34 sysadm 1.29 #include <string.h>
35 sysadm 1.1 #include <time.h>
36 sysadm 1.6 #include <sys/param.h>
37 sysadm 1.1
38 sysadm 1.72 enum _section_list_display_constant_t
39     {
40     TITLE_SEARCH_MAX_LEN = 60,
41     };
42 sysadm 1.66
43 sysadm 1.59 static int32_t section_aid_locations[BBS_max_section] = {0};
44 sysadm 1.11 static int section_topic_view_mode = 0;
45 sysadm 1.13 static int section_topic_view_tid = -1;
46 sysadm 1.11
47 sysadm 1.1 enum select_cmd_t
48     {
49     EXIT_SECTION = 0,
50 sysadm 1.41 VIEW_ARTICLE,
51     CHANGE_PAGE,
52     SHOW_HELP,
53     CHANGE_NAME_DISPLAY,
54     POST_ARTICLE,
55     EDIT_ARTICLE,
56     DELETE_ARTICLE,
57     QUERY_ARTICLE,
58 sysadm 1.57 QUERY_USER,
59 sysadm 1.53 SET_FAVOR_ARTICLE,
60     UNSET_FAVOR_ARTICLE,
61 sysadm 1.41 FIRST_TOPIC_ARTICLE,
62     LAST_TOPIC_ARTICLE,
63 sysadm 1.68 LAST_SECTION_ARTICLE,
64 sysadm 1.45 SCAN_NEW_ARTICLE,
65 sysadm 1.64 SCAN_ARTICLE_BACKWARD_BY_USER,
66     SCAN_ARTICLE_FORWARD_BY_USER,
67 sysadm 1.66 SCAN_ARTICLE_BACKWARD_BY_TITLE,
68     SCAN_ARTICLE_FORWARD_BY_TITLE,
69 sysadm 1.41 VIEW_EX_DIR,
70 sysadm 1.48 SHOW_TOP10,
71 sysadm 1.63 SEARCH_USER,
72 sysadm 1.1 };
73    
74 sysadm 1.36 static int section_list_draw_items(int page_id, ARTICLE *p_articles[], int article_count, int display_nickname, int ontop_start_offset)
75 sysadm 1.1 {
76     char str_time[LINE_BUFFER_LEN];
77     struct tm tm_sub;
78     char title_f[BBS_article_title_max_len + 1];
79     int title_f_len;
80     int eol;
81     int len;
82     int i;
83 sysadm 1.42 size_t j;
84 sysadm 1.3 char article_flag;
85 sysadm 1.17 int is_viewed;
86 sysadm 1.53 int is_favor;
87 sysadm 1.3 time_t tm_now;
88    
89     time(&tm_now);
90 sysadm 1.1
91     clrline(4, 23);
92    
93     for (i = 0; i < article_count; i++)
94     {
95 sysadm 1.18 if (p_articles[i]->uid == BBS_priv.uid)
96 sysadm 1.17 {
97 sysadm 1.18 is_viewed = 1;
98     }
99     else
100     {
101     is_viewed = article_view_log_is_viewed(p_articles[i]->aid, &BBS_article_view_log);
102     if (is_viewed < 0)
103     {
104     log_error("article_view_log_is_viewed(aid=%d) error\n", p_articles[i]->aid);
105     is_viewed = 0;
106     }
107 sysadm 1.17 }
108    
109 sysadm 1.53 if (p_articles[i]->tid == 0)
110     {
111     is_favor = article_favor_check(p_articles[i]->aid, &BBS_article_favor);
112     if (is_favor < 0)
113     {
114     log_error("article_favor_check(aid=%d) error\n", p_articles[i]->aid);
115     is_favor = 0;
116     }
117     }
118     else
119     {
120     is_favor = 0;
121     }
122    
123 sysadm 1.3 if (p_articles[i]->excerption)
124     {
125 sysadm 1.17 article_flag = (is_viewed ? 'm' : 'M');
126 sysadm 1.3 }
127 sysadm 1.17 else if (p_articles[i]->lock && is_viewed)
128 sysadm 1.3 {
129     article_flag = 'x';
130     }
131 sysadm 1.35 else
132     {
133     article_flag = (is_viewed ? ' ' : 'N');
134     }
135 sysadm 1.3
136 sysadm 1.1 localtime_r(&p_articles[i]->sub_dt, &tm_sub);
137 sysadm 1.3 if (tm_now - p_articles[i]->sub_dt < 3600 * 24 * 365)
138     {
139     strftime(str_time, sizeof(str_time), "%b %e ", &tm_sub);
140     }
141     else
142     {
143     strftime(str_time, sizeof(str_time), "%m/%Y", &tm_sub);
144     }
145    
146 sysadm 1.40 strncpy(title_f, (p_articles[i]->tid == 0 ? "● " : ""), sizeof(title_f) - 1);
147 sysadm 1.1 title_f[sizeof(title_f) - 1] = '\0';
148 sysadm 1.40 strncat(title_f, (p_articles[i]->transship ? "[转载]" : ""), sizeof(title_f) - 1 - strnlen(title_f, sizeof(title_f)));
149 sysadm 1.42
150     // Rewrite title with "Re: Re: " prefix into "Re: ... "
151     j = 0;
152     if (p_articles[i]->tid != 0)
153     {
154     while (strncmp(p_articles[i]->title + j, "Re: ", strlen("Re: ")) == 0)
155     {
156     j += strlen("Re: ");
157     }
158     if (j >= strlen("Re: Re: "))
159     {
160     strncat(title_f, "Re: ... ", sizeof(title_f) - 1 - strnlen(title_f, sizeof(title_f)));
161     }
162     else
163     {
164     j = 0;
165     }
166     }
167     strncat(title_f, p_articles[i]->title + j, sizeof(title_f) - 1 - strnlen(title_f, sizeof(title_f)));
168    
169 sysadm 1.51 len = split_line(title_f, 59 - (display_nickname ? BBS_nickname_max_len / 2 : BBS_username_max_len), &eol, &title_f_len, 1);
170 sysadm 1.1 if (title_f[len] != '\0')
171     {
172     title_f[len] = '\0';
173     }
174    
175     moveto(4 + i, 1);
176 sysadm 1.36 if (i >= ontop_start_offset)
177     {
178 sysadm 1.53 prints(" \033[1;33m[提示]\033[m%c%c %s%*s %s %s%s\033[m",
179     (is_favor ? '@' : ' '),
180 sysadm 1.36 article_flag,
181     (display_nickname ? p_articles[i]->nickname : p_articles[i]->username),
182 sysadm 1.43 (display_nickname ? BBS_nickname_max_len / 2 - str_length(p_articles[i]->nickname, 1)
183     : BBS_username_max_len - str_length(p_articles[i]->username, 1)),
184 sysadm 1.36 "",
185     str_time,
186     (p_articles[i]->aid == section_topic_view_tid
187     ? "\033[1;33m"
188     : (p_articles[i]->tid == section_topic_view_tid
189     ? "\033[1;36m"
190     : "")),
191     title_f);
192     }
193     else
194     {
195 sysadm 1.53 prints(" %s%7d\033[m%c%c %s%*s %s %s%s\033[m",
196 sysadm 1.36 (p_articles[i]->aid == section_topic_view_tid
197     ? "\033[1;33m"
198     : (p_articles[i]->tid == section_topic_view_tid
199     ? "\033[1;36m"
200     : "")),
201     p_articles[i]->aid,
202 sysadm 1.53 (is_favor ? '@' : ' '),
203 sysadm 1.36 article_flag,
204     (display_nickname ? p_articles[i]->nickname : p_articles[i]->username),
205 sysadm 1.43 (display_nickname ? BBS_nickname_max_len / 2 - str_length(p_articles[i]->nickname, 1)
206     : BBS_username_max_len - str_length(p_articles[i]->username, 1)),
207 sysadm 1.36 "",
208     str_time,
209     (p_articles[i]->aid == section_topic_view_tid
210     ? "\033[1;33m"
211     : (p_articles[i]->tid == section_topic_view_tid
212     ? "\033[1;36m"
213     : "")),
214     title_f);
215     }
216 sysadm 1.1 }
217    
218     return 0;
219     }
220    
221 sysadm 1.5 static int section_list_draw_screen(const char *sname, const char *stitle, const char *master_list, int display_nickname)
222 sysadm 1.1 {
223 sysadm 1.40 char str_section_master[LINE_BUFFER_LEN] = "诚征版主中";
224 sysadm 1.1 char str_section_name[LINE_BUFFER_LEN];
225    
226 sysadm 1.5 if (master_list[0] != '\0')
227 sysadm 1.1 {
228 sysadm 1.74 snprintf(str_section_master, sizeof(str_section_master), "版主: %s", master_list);
229 sysadm 1.1 }
230 sysadm 1.40 snprintf(str_section_name, sizeof(str_section_name), "讨论区 [%s]", sname);
231 sysadm 1.1
232     clearscr();
233 sysadm 1.5 show_top(str_section_master, stitle, str_section_name);
234 sysadm 1.1 moveto(2, 0);
235 sysadm 1.40 prints("返回[\033[1;32m←\033[0;37m,\033[1;32mESC\033[0;37m] 选择[\033[1;32m↑\033[0;37m,\033[1;32m↓\033[0;37m] "
236     "阅读[\033[1;32m→\033[0;37m,\033[1;32mENTER\033[0;37m] 发表[\033[1;32mCtrl-P\033[0;37m] "
237     "%s[\033[1;32mn\033[0;37m] 精华区[\033[1;32mx\033[0;37m] 帮助[\033[1;32mh\033[0;37m]\033[m",
238     (display_nickname ? "用户名" : "昵称"));
239 sysadm 1.1 moveto(3, 0);
240 sysadm 1.4 if (display_nickname)
241     {
242 sysadm 1.40 prints("\033[44;37m \033[1;37m 编 号 发布者昵称 日 期 文章标题 \033[m");
243 sysadm 1.4 }
244     else
245     {
246 sysadm 1.40 prints("\033[44;37m \033[1;37m 编 号 发 布 者 日 期 文章标题 \033[m");
247 sysadm 1.4 }
248 sysadm 1.1
249     return 0;
250     }
251    
252     static enum select_cmd_t section_list_select(int total_page, int item_count, int *p_page_id, int *p_selected_index)
253     {
254     int old_page_id = *p_page_id;
255     int old_selected_index = *p_selected_index;
256     int ch;
257 sysadm 1.30 time_t last_refresh_tm = time(NULL);
258 sysadm 1.1
259     if (item_count > 0 && *p_selected_index >= 0)
260     {
261     moveto(4 + *p_selected_index, 1);
262     outc('>');
263     iflush();
264     }
265    
266     while (!SYS_server_exit)
267     {
268     ch = igetch(100);
269    
270 sysadm 1.54 if (ch != KEY_NULL && ch != KEY_TIMEOUT)
271     {
272     BBS_last_access_tm = time(NULL);
273     }
274    
275 sysadm 1.1 switch (ch)
276     {
277 sysadm 1.57 case KEY_NULL: // broken pipe
278 sysadm 1.54 log_error("KEY_NULL\n");
279     return EXIT_SECTION;
280 sysadm 1.1 case KEY_TIMEOUT:
281 sysadm 1.71 if (time(NULL) - BBS_last_access_tm >= BBS_max_user_idle_time)
282 sysadm 1.1 {
283 sysadm 1.54 log_error("User input timeout\n");
284     return EXIT_SECTION;
285 sysadm 1.1 }
286     continue;
287 sysadm 1.54 case KEY_ESC:
288     case KEY_LEFT:
289     return EXIT_SECTION;
290 sysadm 1.4 case 'n':
291     return CHANGE_NAME_DISPLAY;
292 sysadm 1.1 case CR:
293 sysadm 1.28 case 'r':
294 sysadm 1.1 case KEY_RIGHT:
295     if (item_count > 0)
296     {
297     return VIEW_ARTICLE;
298     }
299     break;
300 sysadm 1.20 case Ctrl('P'):
301     return POST_ARTICLE;
302     case 'E':
303 sysadm 1.41 if (item_count > 0)
304     {
305     return EDIT_ARTICLE;
306     }
307     break;
308 sysadm 1.26 case 'd':
309 sysadm 1.41 if (item_count > 0)
310     {
311     return DELETE_ARTICLE;
312     }
313     break;
314     case Ctrl('Q'):
315     if (item_count > 0)
316     {
317     return QUERY_ARTICLE;
318     }
319     break;
320 sysadm 1.57 case Ctrl('A'):
321     if (item_count > 0)
322     {
323     return QUERY_USER;
324     }
325     break;
326 sysadm 1.53 case 'F':
327     if (item_count > 0)
328     {
329     return SET_FAVOR_ARTICLE;
330     }
331     break;
332     case '-':
333     if (item_count > 0)
334     {
335     return UNSET_FAVOR_ARTICLE;
336     }
337     break;
338 sysadm 1.1 case KEY_HOME:
339     *p_page_id = 0;
340 sysadm 1.28 case 'P':
341 sysadm 1.1 case KEY_PGUP:
342     *p_selected_index = 0;
343 sysadm 1.28 case 'k':
344 sysadm 1.1 case KEY_UP:
345     if (*p_selected_index <= 0)
346     {
347     if (*p_page_id > 0)
348     {
349     (*p_page_id)--;
350     *p_selected_index = BBS_article_limit_per_page - 1;
351     }
352 sysadm 1.44 else if (ch == KEY_UP || ch == 'k') // Rotate to the tail of section list
353     {
354     if (total_page > 0)
355     {
356     *p_page_id = total_page - 1;
357     }
358     if (item_count > 0)
359     {
360     *p_selected_index = item_count - 1;
361     }
362     }
363 sysadm 1.1 }
364     else
365     {
366     (*p_selected_index)--;
367     }
368     break;
369 sysadm 1.28 case '$':
370 sysadm 1.1 case KEY_END:
371 sysadm 1.68 if (*p_page_id + 1 == total_page && *p_selected_index + 1 == item_count) // Press END at end of list
372     {
373     return LAST_SECTION_ARTICLE;
374     }
375 sysadm 1.1 if (total_page > 0)
376     {
377     *p_page_id = total_page - 1;
378     }
379 sysadm 1.28 case 'N':
380 sysadm 1.1 case KEY_PGDN:
381     if (item_count > 0)
382     {
383     *p_selected_index = item_count - 1;
384     }
385 sysadm 1.28 case 'j':
386 sysadm 1.1 case KEY_DOWN:
387     if (*p_selected_index + 1 >= item_count) // next page
388     {
389     if (*p_page_id + 1 < total_page)
390     {
391     (*p_page_id)++;
392     *p_selected_index = 0;
393     }
394 sysadm 1.44 else if (ch == KEY_DOWN || ch == 'j') // Rotate to the head of section list
395 sysadm 1.25 {
396 sysadm 1.44 *p_page_id = 0;
397     *p_selected_index = 0;
398 sysadm 1.25 }
399 sysadm 1.1 }
400     else
401     {
402     (*p_selected_index)++;
403     }
404     break;
405 sysadm 1.31 case '=':
406 sysadm 1.41 if (item_count > 0)
407     {
408     return FIRST_TOPIC_ARTICLE;
409     }
410     break;
411 sysadm 1.31 case '\\':
412 sysadm 1.41 if (item_count > 0)
413     {
414     return LAST_TOPIC_ARTICLE;
415     }
416     break;
417 sysadm 1.45 case 'S':
418     if (item_count > 0)
419     {
420     return SCAN_NEW_ARTICLE;
421     }
422     break;
423 sysadm 1.64 case 'A':
424     if (item_count > 0)
425     {
426     return SCAN_ARTICLE_BACKWARD_BY_USER;
427     }
428     break;
429     case 'a':
430     if (item_count > 0)
431     {
432     return SCAN_ARTICLE_FORWARD_BY_USER;
433     }
434     break;
435 sysadm 1.66 case '?':
436     if (item_count > 0)
437     {
438     return SCAN_ARTICLE_BACKWARD_BY_TITLE;
439     }
440     break;
441     case '/':
442     if (item_count > 0)
443     {
444     return SCAN_ARTICLE_FORWARD_BY_TITLE;
445     }
446     break;
447 sysadm 1.63 case 'u':
448     return SEARCH_USER;
449 sysadm 1.28 case 'h':
450     return SHOW_HELP;
451 sysadm 1.37 case 'x':
452     return VIEW_EX_DIR;
453 sysadm 1.49 case 'H':
454 sysadm 1.48 return SHOW_TOP10;
455 sysadm 1.1 default:
456 sysadm 1.56 break;
457 sysadm 1.1 }
458    
459     if (old_page_id != *p_page_id)
460     {
461     return CHANGE_PAGE;
462     }
463    
464     if (item_count > 0 && old_selected_index != *p_selected_index)
465     {
466     if (old_selected_index >= 0)
467     {
468     moveto(4 + old_selected_index, 1);
469     outc(' ');
470     }
471     if (*p_selected_index >= 0)
472     {
473     moveto(4 + *p_selected_index, 1);
474     outc('>');
475     }
476     iflush();
477    
478     old_selected_index = *p_selected_index;
479     }
480    
481 sysadm 1.30 if (BBS_last_access_tm - last_refresh_tm >= BBS_section_list_load_interval)
482     {
483     return CHANGE_PAGE; // force section list refresh
484     }
485 sysadm 1.1 }
486    
487     return EXIT_SECTION;
488     }
489    
490 sysadm 1.11 static int display_article_key_handler(int *p_key, DISPLAY_CTX *p_ctx)
491 sysadm 1.10 {
492 sysadm 1.11 switch (*p_key)
493 sysadm 1.10 {
494 sysadm 1.11 case 'p':
495 sysadm 1.28 case Ctrl('X'):
496 sysadm 1.11 section_topic_view_mode = !section_topic_view_mode;
497 sysadm 1.10 case 0: // Set msg
498 sysadm 1.11 if (section_topic_view_mode)
499 sysadm 1.10 {
500 sysadm 1.11 snprintf(p_ctx->msg, sizeof(p_ctx->msg),
501 sysadm 1.40 "| 返回[\033[32m←\033[33m,\033[32mESC\033[33m] "
502     "同主题阅读[\033[32m↑\033[33m/\033[32m↓\033[33m] "
503     "切换[\033[32mp\033[33m] 回复[\033[32mr\033[33m] 帮助[\033[32mh\033[33m] |");
504 sysadm 1.10 }
505     else
506     {
507 sysadm 1.11 snprintf(p_ctx->msg, sizeof(p_ctx->msg),
508 sysadm 1.40 "| 返回[\033[32m←\033[33m,\033[32mESC\033[33m] "
509     "移动[\033[32m↑\033[33m/\033[32m↓\033[33m/\033[32mPgUp\033[33m/\033[32mPgDn\033[33m] "
510     "切换[\033[32mp\033[33m] 回复[\033[32mr\033[33m] 帮助[\033[32mh\033[33m] |");
511 sysadm 1.10 }
512 sysadm 1.11 *p_key = 0;
513 sysadm 1.10 break;
514 sysadm 1.20 case 'r': // Reply article
515     return 1;
516 sysadm 1.31 case '=': // First topic article
517     return 1;
518     case '\\': // Last topic article
519     return 1;
520 sysadm 1.12 case KEY_UP:
521 sysadm 1.16 case KEY_PGUP:
522     case KEY_HOME:
523 sysadm 1.12 if (p_ctx->reach_begin)
524     {
525     if (section_topic_view_mode)
526     {
527     *p_key = KEY_PGUP;
528     }
529 sysadm 1.16 else
530     {
531     *p_key = KEY_UP;
532     }
533 sysadm 1.12 return 1;
534     }
535     break;
536 sysadm 1.28 case 'k':
537     if (section_topic_view_mode)
538     {
539     *p_key = KEY_PGUP;
540     }
541     else
542     {
543     *p_key = KEY_UP;
544     }
545     return 1;
546 sysadm 1.12 case KEY_DOWN:
547 sysadm 1.16 case KEY_PGDN:
548     case KEY_END:
549 sysadm 1.12 if (p_ctx->reach_end)
550     {
551     if (section_topic_view_mode)
552     {
553     *p_key = KEY_PGDN;
554     }
555 sysadm 1.16 else
556     {
557     *p_key = KEY_DOWN;
558     }
559 sysadm 1.12 return 1;
560     }
561     break;
562 sysadm 1.28 case 'j':
563     if (section_topic_view_mode)
564     {
565     *p_key = KEY_PGDN;
566     }
567     else
568     {
569     *p_key = KEY_DOWN;
570     }
571     return 1;
572 sysadm 1.10 }
573    
574     return 0;
575     }
576    
577 sysadm 1.46 int section_list_display(const char *sname, int32_t aid)
578 sysadm 1.1 {
579 sysadm 1.4 static int display_nickname = 0;
580    
581 sysadm 1.1 SECTION_LIST *p_section;
582 sysadm 1.46 int64_t section_index;
583     int32_t aid_location;
584 sysadm 1.5 char stitle[BBS_section_title_max_len + 1];
585     char master_list[(BBS_username_max_len + 1) * 3 + 1];
586 sysadm 1.6 char page_info_str[LINE_BUFFER_LEN];
587 sysadm 1.1 ARTICLE *p_articles[BBS_article_limit_per_page];
588     int article_count;
589 sysadm 1.6 int page_count;
590 sysadm 1.36 int ontop_start_offset;
591 sysadm 1.1 int page_id = 0;
592     int selected_index = 0;
593 sysadm 1.10 ARTICLE_CACHE cache;
594 sysadm 1.1 int ret;
595 sysadm 1.12 int loop;
596     int direction;
597 sysadm 1.24 ARTICLE article_new;
598 sysadm 1.31 int page_id_cur;
599 sysadm 1.46 const ARTICLE *p_article_locate;
600 sysadm 1.57 USER_INFO user_info;
601 sysadm 1.66 char user_intro[BBS_user_intro_max_len + 1];
602 sysadm 1.64 char username[BBS_username_max_len + 1];
603     char username_list[1][BBS_username_max_len + 1];
604     int32_t uid;
605     int i;
606     int ok;
607 sysadm 1.66 char title[BBS_article_title_max_len + 1] = "\0";
608 sysadm 1.1
609 sysadm 1.50 p_section = section_list_find_by_name(sname);
610 sysadm 1.1 if (p_section == NULL)
611     {
612     log_error("Section %s not found\n", sname);
613     return -1;
614     }
615    
616 sysadm 1.52 if (!checkpriv(&BBS_priv, p_section->sid, S_LIST))
617     {
618     log_error("Forbid access to unauthorized section, sid=%d, uid=%d\n",
619     p_section->sid, BBS_priv.uid);
620     return -1;
621     }
622    
623 sysadm 1.50 section_index = get_section_index(p_section);
624    
625 sysadm 1.58 if (get_section_info(p_section, NULL, stitle, master_list) < 0)
626 sysadm 1.5 {
627 sysadm 1.58 log_error("get_section_info(sid=%d) error\n", p_section->sid);
628     return -4;
629 sysadm 1.5 }
630    
631 sysadm 1.46 if (aid == 0)
632     {
633     aid_location = section_aid_locations[section_index];
634     }
635     else
636     {
637     aid_location = aid;
638 sysadm 1.51 }
639 sysadm 1.46
640     // Locate at article with aid_locate
641     if (aid_location > 0)
642     {
643     p_article_locate = article_block_find_by_aid(aid_location);
644     if (p_article_locate == NULL)
645     {
646     log_error("article_block_find_by_aid(%d) error\n", aid_location);
647     return -3;
648     }
649    
650     ret = locate_article_in_section(p_section, p_article_locate, 0, 0,
651     &page_id, &selected_index, &article_count);
652     if (ret < 0)
653     {
654     log_error("locate_article_in_section(sid=%d, aid=%d, direction=0, step=0) error\n",
655     p_section->sid, p_article_locate->aid);
656     return -3;
657     }
658     }
659    
660 sysadm 1.5 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
661 sysadm 1.1 {
662     log_error("section_list_draw_screen() error\n");
663     return -2;
664     }
665    
666 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
667 sysadm 1.5 if (ret < 0)
668 sysadm 1.1 {
669 sysadm 1.5 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
670     return -3;
671 sysadm 1.1 }
672 sysadm 1.5
673 sysadm 1.46 section_topic_view_tid = -1;
674    
675 sysadm 1.5 if (article_count == 0) // empty section
676 sysadm 1.1 {
677     selected_index = 0;
678     }
679 sysadm 1.46 else if (aid > 0)
680     {
681     // Update current topic
682     section_topic_view_tid = (p_articles[selected_index]->tid == 0 ? p_articles[selected_index]->aid : p_articles[selected_index]->tid);
683    
684     // Update current aid location
685     section_aid_locations[section_index] = p_articles[selected_index]->aid;
686     }
687 sysadm 1.1
688     while (!SYS_server_exit)
689     {
690 sysadm 1.36 ret = section_list_draw_items(page_id, p_articles, article_count, display_nickname, ontop_start_offset);
691 sysadm 1.1 if (ret < 0)
692     {
693     log_error("section_list_draw_items(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
694     return -4;
695     }
696 sysadm 1.6
697 sysadm 1.7 snprintf(page_info_str, sizeof(page_info_str),
698 sysadm 1.40 "\033[33m[第\033[36m%d\033[33m/\033[36m%d\033[33m页]",
699 sysadm 1.7 page_id + 1, MAX(page_count, 1));
700 sysadm 1.8
701 sysadm 1.6 show_bottom(page_info_str);
702 sysadm 1.1 iflush();
703    
704 sysadm 1.33 if (user_online_update(sname) < 0)
705     {
706     log_error("user_online_update(%s) error\n", sname);
707     }
708    
709 sysadm 1.6 ret = section_list_select(page_count, article_count, &page_id, &selected_index);
710 sysadm 1.60
711 sysadm 1.1 switch (ret)
712     {
713     case EXIT_SECTION:
714 sysadm 1.62 // Update current aid location
715 sysadm 1.77 if (selected_index < article_count && p_articles[selected_index] != NULL)
716 sysadm 1.62 {
717 sysadm 1.68 if (selected_index >= ontop_start_offset)
718     {
719     ret = last_article_in_section(p_section, &p_article_locate);
720     if (ret < 0)
721     {
722     log_error("last_article_in_section(sid=%d) error\n", p_section->sid);
723     return -3;
724     }
725     else if (ret == 0)
726     {
727     section_aid_locations[section_index] = 0;
728     }
729     else // ret > 0
730     {
731     section_aid_locations[section_index] = p_article_locate->aid;
732     }
733     }
734     else
735     {
736     section_aid_locations[section_index] = (p_articles[selected_index]->visible ? p_articles[selected_index]->aid : 0);
737     }
738 sysadm 1.62 }
739 sysadm 1.1 return 0;
740     case CHANGE_PAGE:
741 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
742 sysadm 1.5 if (ret < 0)
743 sysadm 1.1 {
744 sysadm 1.5 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
745     return -3;
746 sysadm 1.1 }
747 sysadm 1.5 if (article_count == 0) // empty section
748 sysadm 1.1 {
749     selected_index = 0;
750     }
751 sysadm 1.5 else if (selected_index >= article_count)
752 sysadm 1.1 {
753     selected_index = article_count - 1;
754     }
755     break;
756     case VIEW_ARTICLE:
757 sysadm 1.12 do
758 sysadm 1.9 {
759 sysadm 1.12 loop = 0;
760 sysadm 1.9
761 sysadm 1.12 if (article_cache_load(&cache, VAR_ARTICLE_CACHE_DIR, p_articles[selected_index]) < 0)
762     {
763     log_error("article_cache_load(aid=%d, cid=%d) error\n", p_articles[selected_index]->aid, p_articles[selected_index]->cid);
764     break;
765     }
766    
767 sysadm 1.33 if (user_online_update("VIEW_ARTICLE") < 0)
768     {
769     log_error("user_online_update(VIEW_ARTICLE) error\n");
770     }
771    
772 sysadm 1.19 ret = display_data(cache.p_data, cache.line_total, cache.line_offsets, 0,
773 sysadm 1.12 display_article_key_handler, DATA_READ_HELP);
774    
775     if (article_cache_unload(&cache) < 0)
776     {
777     log_error("article_cache_unload(aid=%d, cid=%d) error\n", p_articles[selected_index]->aid, p_articles[selected_index]->cid);
778     break;
779     }
780    
781 sysadm 1.17 // Update article_view_log
782     if (article_view_log_set_viewed(p_articles[selected_index]->aid, &BBS_article_view_log) < 0)
783     {
784     log_error("article_view_log_set_viewed(aid=%d) error\n", p_articles[selected_index]->aid);
785     }
786    
787 sysadm 1.12 switch (ret)
788     {
789     case KEY_UP:
790     if (selected_index <= 0)
791     {
792     if (page_id > 0)
793     {
794     page_id--;
795     selected_index = BBS_article_limit_per_page - 1;
796    
797 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
798 sysadm 1.12 if (ret < 0)
799     {
800     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
801     return -3;
802     }
803    
804     if (article_count != BBS_article_limit_per_page) // page is not full
805     {
806     selected_index = MAX(0, article_count - 1);
807     }
808     else
809     {
810     loop = 1;
811     }
812     }
813     }
814     else
815     {
816     selected_index--;
817     loop = 1;
818     }
819     break;
820     case KEY_DOWN:
821     if (selected_index + 1 >= article_count) // next page
822     {
823     if (page_id + 1 < page_count)
824     {
825     page_id++;
826     selected_index = 0;
827    
828 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
829 sysadm 1.12 if (ret < 0)
830     {
831     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
832     return -3;
833     }
834    
835     if (article_count == 0) // empty page
836     {
837     selected_index = 0;
838     }
839     else
840     {
841     loop = 1;
842     }
843     }
844     }
845     else
846     {
847     selected_index++;
848     loop = 1;
849     }
850     break;
851     case KEY_PGUP:
852     case KEY_PGDN:
853     direction = (ret == KEY_PGUP ? -1 : 1);
854 sysadm 1.31 ret = locate_article_in_section(p_section, p_articles[selected_index], direction, 1,
855     &page_id, &selected_index, &article_count);
856 sysadm 1.12 if (ret < 0)
857     {
858 sysadm 1.31 log_error("locate_article_in_section(sid=%d, aid=%d, direction=%d, step=1) error\n",
859 sysadm 1.12 p_section->sid, p_articles[selected_index]->aid, direction);
860     return -3;
861     }
862 sysadm 1.31 else if (ret > 0) // found
863 sysadm 1.12 {
864 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
865 sysadm 1.12 if (ret < 0)
866     {
867     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
868     return -3;
869     }
870     loop = 1;
871     }
872     break;
873 sysadm 1.20 case 'r': // Reply article
874 sysadm 1.33 if (user_online_update("REPLY_ARTICLE") < 0)
875     {
876     log_error("user_online_update(REPLY_ARTICLE) error\n");
877     }
878    
879 sysadm 1.24 if (article_reply(p_section, p_articles[selected_index], &article_new) < 0)
880 sysadm 1.20 {
881 sysadm 1.33 log_error("article_reply(aid=%d) error\n", p_articles[selected_index]->aid);
882 sysadm 1.20 }
883 sysadm 1.67 else if (ret > 0) // Article replied
884     {
885     ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
886     if (ret < 0)
887     {
888     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
889     return -3;
890     }
891     }
892 sysadm 1.20 loop = 1;
893     break;
894 sysadm 1.31 case '=': // First topic article
895     case '\\': // Last topic article
896     page_id_cur = page_id;
897     direction = (ret == '=' ? -1 : 1);
898     ret = locate_article_in_section(p_section, p_articles[selected_index], direction, BBS_article_limit_per_section,
899     &page_id, &selected_index, &article_count);
900     if (ret < 0)
901     {
902     log_error("locate_article_in_section(sid=%d, aid=%d, direction=%d, step=%d) error\n",
903     p_section->sid, p_articles[selected_index]->aid, direction, BBS_article_limit_per_section);
904     return -3;
905     }
906     else if (ret > 0) // found
907     {
908     if (page_id != page_id_cur) // page changed
909     {
910 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
911 sysadm 1.31 if (ret < 0)
912     {
913     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
914     return -3;
915     }
916     }
917     loop = 1;
918     }
919     break;
920 sysadm 1.12 }
921     } while (loop);
922 sysadm 1.13
923     // Update current topic
924     section_topic_view_tid = (p_articles[selected_index]->tid == 0 ? p_articles[selected_index]->aid : p_articles[selected_index]->tid);
925 sysadm 1.46
926 sysadm 1.35 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
927     {
928     log_error("section_list_draw_screen() error\n");
929     return -2;
930     }
931     break;
932 sysadm 1.4 case CHANGE_NAME_DISPLAY:
933     display_nickname = !display_nickname;
934 sysadm 1.5 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
935 sysadm 1.1 {
936     log_error("section_list_draw_screen() error\n");
937     return -2;
938     }
939     break;
940 sysadm 1.20 case POST_ARTICLE:
941 sysadm 1.33 if (user_online_update("POST_ARTICLE") < 0)
942     {
943     log_error("user_online_update(POST_ARTICLE) error\n");
944     }
945    
946 sysadm 1.30 if ((ret = article_post(p_section, &article_new)) < 0)
947 sysadm 1.20 {
948 sysadm 1.26 log_error("article_post(sid=%d) error\n", p_section->sid);
949 sysadm 1.20 }
950 sysadm 1.24 else if (ret > 0) // New article posted
951     {
952 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
953 sysadm 1.24 if (ret < 0)
954     {
955 sysadm 1.67 log_error("query_section_articles(sid=%d, page_id=%d) error: %d\n", p_section->sid, page_id, ret);
956 sysadm 1.24 return -3;
957     }
958     }
959 sysadm 1.20 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
960     {
961     log_error("section_list_draw_screen() error\n");
962     return -2;
963     }
964     break;
965     case EDIT_ARTICLE:
966 sysadm 1.26 if (!checkpriv(&BBS_priv, p_section->sid, S_POST) ||
967     p_articles[selected_index]->uid != BBS_priv.uid)
968 sysadm 1.20 {
969 sysadm 1.26 break; // No permission
970 sysadm 1.20 }
971 sysadm 1.33
972     if (user_online_update("EDIT_ARTICLE") < 0)
973     {
974     log_error("user_online_update() error\n");
975     }
976    
977 sysadm 1.24 if (article_modify(p_section, p_articles[selected_index], &article_new) < 0)
978 sysadm 1.20 {
979 sysadm 1.26 log_error("article_modify(aid=%d) error\n", p_articles[selected_index]->aid);
980     }
981 sysadm 1.67 else if (ret > 0) // Article modified
982     {
983     ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
984     if (ret < 0)
985     {
986     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
987     return -3;
988     }
989     }
990 sysadm 1.26 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
991     {
992     log_error("section_list_draw_screen() error\n");
993     return -2;
994     }
995     break;
996     case DELETE_ARTICLE:
997     if (!checkpriv(&BBS_priv, p_section->sid, S_POST) ||
998     (!checkpriv(&BBS_priv, p_section->sid, S_MAN_S) && p_articles[selected_index]->uid != BBS_priv.uid))
999     {
1000     break; // No permission
1001     }
1002 sysadm 1.30 if ((ret = article_del(p_section, p_articles[selected_index])) < 0)
1003 sysadm 1.26 {
1004     log_error("article_del(aid=%d) error\n", p_articles[selected_index]->aid);
1005 sysadm 1.20 }
1006 sysadm 1.30 else if (ret > 0) // Article deleted
1007     {
1008 sysadm 1.67 do
1009 sysadm 1.30 {
1010 sysadm 1.67 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
1011     if (ret >= 0 && selected_index > article_count - 1)
1012     {
1013     selected_index = article_count - 1;
1014     break;
1015     }
1016     else if (ret < 0 && page_id > 0)
1017     {
1018     page_id--;
1019     selected_index = BBS_article_limit_per_page - 1;
1020     }
1021     else if (ret < 0 && page_id <= 0)
1022     {
1023     selected_index = 0;
1024     break;
1025     }
1026     } while (ret < 0);
1027 sysadm 1.30 }
1028 sysadm 1.20 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1029     {
1030     log_error("section_list_draw_screen() error\n");
1031     return -2;
1032     }
1033     break;
1034 sysadm 1.41 case QUERY_ARTICLE:
1035     if ((ret = display_article_meta(p_articles[selected_index]->aid)) < 0)
1036     {
1037     log_error("display_article_meta(aid=%d) error\n", p_articles[selected_index]->aid);
1038     }
1039     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1040     {
1041     log_error("section_list_draw_screen() error\n");
1042     return -2;
1043     }
1044     break;
1045 sysadm 1.57 case QUERY_USER:
1046 sysadm 1.61 if ((ret = query_user_info_by_uid(p_articles[selected_index]->uid, &user_info, user_intro, sizeof(user_intro))) < 0)
1047 sysadm 1.57 {
1048     log_error("query_user_info_by_uid(uid=%d) error\n", p_articles[selected_index]->uid);
1049     return -2;
1050     }
1051     else if (ret == 0)
1052     {
1053     clearscr();
1054     prints("该用户已升天");
1055     press_any_key();
1056     }
1057     else if (user_info_display(&user_info) < 0) // && ret > 0
1058     {
1059     log_error("user_info_display(uid=%d) error\n", p_articles[selected_index]->uid);
1060     }
1061    
1062     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1063     {
1064     log_error("section_list_draw_screen() error\n");
1065     return -2;
1066     }
1067     break;
1068 sysadm 1.53 case SET_FAVOR_ARTICLE:
1069     ret = article_favor_set(p_articles[selected_index]->tid == 0
1070     ? p_articles[selected_index]->aid
1071     : p_articles[selected_index]->tid,
1072     &BBS_article_favor, 1);
1073     if (ret < 0)
1074     {
1075     log_error("article_favor_set(aid=%d, 1) error\n",
1076     p_articles[selected_index]->tid == 0 ? p_articles[selected_index]->aid : p_articles[selected_index]->tid);
1077     }
1078     break;
1079     case UNSET_FAVOR_ARTICLE:
1080     ret = article_favor_set(p_articles[selected_index]->tid == 0
1081     ? p_articles[selected_index]->aid
1082     : p_articles[selected_index]->tid,
1083     &BBS_article_favor, 0);
1084     if (ret < 0)
1085     {
1086     log_error("article_favor_set(aid=%d, 0) error\n",
1087     p_articles[selected_index]->tid == 0 ? p_articles[selected_index]->aid : p_articles[selected_index]->tid);
1088     }
1089     break;
1090 sysadm 1.31 case FIRST_TOPIC_ARTICLE:
1091     case LAST_TOPIC_ARTICLE:
1092     page_id_cur = page_id;
1093     direction = (ret == FIRST_TOPIC_ARTICLE ? -1 : 1);
1094     ret = locate_article_in_section(p_section, p_articles[selected_index], direction, BBS_article_limit_per_section,
1095     &page_id, &selected_index, &article_count);
1096     if (ret < 0)
1097     {
1098     log_error("locate_article_in_section(sid=%d, aid=%d, direction=%d, step=%d) error\n",
1099     p_section->sid, p_articles[selected_index]->aid, direction, BBS_article_limit_per_section);
1100     return -3;
1101     }
1102     else if (ret > 0 && page_id != page_id_cur) // found and page changed
1103     {
1104 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
1105 sysadm 1.31 if (ret < 0)
1106     {
1107     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
1108     return -3;
1109     }
1110     }
1111     break;
1112 sysadm 1.68 case LAST_SECTION_ARTICLE:
1113     page_id_cur = page_id;
1114     ret = last_article_in_section(p_section, &p_article_locate);
1115     if (ret < 0)
1116     {
1117     log_error("last_article_in_section(sid=%d) error\n", p_section->sid);
1118     return -3;
1119     }
1120     else if (ret == 0)
1121     {
1122     break;
1123     }
1124     ret = locate_article_in_section(p_section, p_article_locate, 0, 0,
1125     &page_id, &selected_index, &article_count);
1126     if (ret < 0)
1127     {
1128     log_error("locate_article_in_section(sid=%d, aid=%d, direction=0, step=0) error\n",
1129     p_section->sid, p_article_locate->aid);
1130     return -3;
1131     }
1132     else if (ret > 0 && page_id != page_id_cur) // found and page changed
1133     {
1134     ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
1135     if (ret < 0)
1136     {
1137     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
1138     return -3;
1139     }
1140     }
1141     break;
1142 sysadm 1.45 case SCAN_NEW_ARTICLE:
1143 sysadm 1.46 ret = scan_unread_article_in_section(p_section, p_articles[selected_index], &p_article_locate);
1144 sysadm 1.45 if (ret < 0)
1145     {
1146     log_error("scan_unread_article_in_section(sid=%d, aid=%d) error\n",
1147     p_section->sid, p_articles[selected_index]->aid);
1148     return -3;
1149     }
1150     else if (ret == 0) // not found
1151     {
1152     break;
1153     }
1154     page_id_cur = page_id;
1155 sysadm 1.46 ret = locate_article_in_section(p_section, p_article_locate, 0, 0,
1156 sysadm 1.45 &page_id, &selected_index, &article_count);
1157     if (ret < 0)
1158     {
1159     log_error("locate_article_in_section(sid=%d, aid=%d, direction=0, step=0) error\n",
1160 sysadm 1.46 p_section->sid, p_article_locate->aid);
1161 sysadm 1.45 return -3;
1162     }
1163     else if (ret > 0 && page_id != page_id_cur) // found and page changed
1164     {
1165     ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
1166     if (ret < 0)
1167     {
1168     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
1169     return -3;
1170     }
1171     }
1172     break;
1173 sysadm 1.64 case SCAN_ARTICLE_BACKWARD_BY_USER:
1174     case SCAN_ARTICLE_FORWARD_BY_USER:
1175     direction = (ret == SCAN_ARTICLE_FORWARD_BY_USER ? 1 : -1);
1176     strncpy(username, p_articles[selected_index]->username, sizeof(username) - 1);
1177     username[sizeof(username) - 1] = '\0';
1178     uid = 0;
1179    
1180     moveto(SCREEN_ROWS, 1);
1181     clrtoeol();
1182     get_data(SCREEN_ROWS, 1,
1183 sysadm 1.73 (direction == 1 ? "↓搜寻作者: " : "↑搜寻作者: "),
1184 sysadm 1.64 username, sizeof(username), BBS_username_max_len);
1185    
1186     if (username[0] == '\0')
1187     {
1188     break;
1189     }
1190    
1191     // Verify format
1192     for (i = 0, ok = 1; ok && username[i] != '\0'; i++)
1193     {
1194 sysadm 1.76 if (!(isalpha((int)username[i]) || (i > 0 && (isdigit((int)username[i]) || username[i] == '_'))))
1195 sysadm 1.64 {
1196     ok = 0;
1197     }
1198     }
1199     if (ok && i > BBS_username_max_len)
1200     {
1201     ok = 0;
1202     }
1203     if (!ok)
1204     {
1205     break;
1206     }
1207    
1208     ret = query_user_info_by_username(username, 1, &uid, username_list);
1209     if (ret < 0)
1210     {
1211     log_error("query_user_info_by_username(%s) error\n", username);
1212     break;
1213     }
1214    
1215     if (uid > 0)
1216     {
1217     ret = scan_article_in_section_by_uid(p_section, p_articles[selected_index],
1218     direction, uid, &p_article_locate);
1219     if (ret < 0)
1220     {
1221     log_error("scan_article_in_section_by_uid(sid=%d, aid=%d, direction=%d, uid=%d) error\n",
1222     p_section->sid, p_articles[selected_index]->aid, direction, uid);
1223     return -3;
1224     }
1225     else if (ret == 0) // not found
1226     {
1227     break;
1228     }
1229     }
1230     else // uid == 0
1231     {
1232     ret = scan_article_in_section_by_username(p_section, p_articles[selected_index],
1233     direction, username, &p_article_locate);
1234     if (ret < 0)
1235     {
1236     log_error("scan_article_in_section_by_username(sid=%d, aid=%d, direction=%d, username=%s) error\n",
1237     p_section->sid, p_articles[selected_index]->aid, direction, username);
1238     return -3;
1239     }
1240     else if (ret == 0) // not found
1241     {
1242     break;
1243     }
1244     }
1245    
1246     page_id_cur = page_id;
1247     ret = locate_article_in_section(p_section, p_article_locate, 0, 0,
1248     &page_id, &selected_index, &article_count);
1249     if (ret < 0)
1250     {
1251     log_error("locate_article_in_section(sid=%d, aid=%d, direction=0, step=0) error\n",
1252     p_section->sid, p_article_locate->aid);
1253     return -3;
1254     }
1255     else if (ret > 0 && page_id != page_id_cur) // found and page changed
1256     {
1257     ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
1258     if (ret < 0)
1259     {
1260     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
1261     return -3;
1262     }
1263     }
1264     break;
1265 sysadm 1.66 case SCAN_ARTICLE_BACKWARD_BY_TITLE:
1266     case SCAN_ARTICLE_FORWARD_BY_TITLE:
1267     direction = (ret == SCAN_ARTICLE_FORWARD_BY_TITLE ? 1 : -1);
1268    
1269     moveto(SCREEN_ROWS, 1);
1270     clrtoeol();
1271     get_data(SCREEN_ROWS, 1,
1272 sysadm 1.73 (direction == 1 ? "↓搜寻标题: " : "↑搜寻标题: "),
1273 sysadm 1.66 title, sizeof(title), TITLE_SEARCH_MAX_LEN);
1274    
1275     if (title[0] == '\0')
1276     {
1277     break;
1278     }
1279    
1280     ret = scan_article_in_section_by_title(p_section, p_articles[selected_index],
1281     direction, title, &p_article_locate);
1282     if (ret < 0)
1283     {
1284     log_error("scan_article_in_section_by_title(sid=%d, aid=%d, direction=%d, title=%s) error\n",
1285     p_section->sid, p_articles[selected_index]->aid, direction, title);
1286     return -3;
1287     }
1288     else if (ret == 0) // not found
1289     {
1290     break;
1291     }
1292    
1293     page_id_cur = page_id;
1294     ret = locate_article_in_section(p_section, p_article_locate, 0, 0,
1295     &page_id, &selected_index, &article_count);
1296     if (ret < 0)
1297     {
1298     log_error("locate_article_in_section(sid=%d, aid=%d, direction=0, step=0) error\n",
1299     p_section->sid, p_article_locate->aid);
1300     return -3;
1301     }
1302     else if (ret > 0 && page_id != page_id_cur) // found and page changed
1303     {
1304     ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
1305     if (ret < 0)
1306     {
1307     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
1308     return -3;
1309     }
1310     }
1311     break;
1312 sysadm 1.63 case SEARCH_USER:
1313     user_list_search();
1314     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1315     {
1316     log_error("section_list_draw_screen() error\n");
1317     return -2;
1318     }
1319     break;
1320 sysadm 1.28 case SHOW_HELP:
1321     // Display help information
1322     display_file(DATA_READ_HELP, 1);
1323     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1324     {
1325     log_error("section_list_draw_screen() error\n");
1326     return -2;
1327     }
1328     break;
1329 sysadm 1.37 case VIEW_EX_DIR:
1330     if (section_list_ex_dir_display(p_section) < 0)
1331     {
1332     log_error("section_list_ex_dir_display(sid=%d) error\n", p_section->sid);
1333     }
1334     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1335     {
1336     log_error("section_list_draw_screen() error\n");
1337     return -2;
1338     }
1339     break;
1340 sysadm 1.48 case SHOW_TOP10:
1341     show_top10_menu(NULL);
1342     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1343     {
1344     log_error("section_list_draw_screen() error\n");
1345     return -2;
1346     }
1347     break;
1348 sysadm 1.1 default:
1349     log_error("Unknown command %d\n", ret);
1350     }
1351     }
1352    
1353     return 0;
1354     }
1355 sysadm 1.37
1356     int section_list_ex_dir_display(SECTION_LIST *p_section)
1357     {
1358     MENU_SET ex_menu_set;
1359     int ch = 0;
1360 sysadm 1.78 int loop;
1361 sysadm 1.37
1362     if (p_section == NULL)
1363     {
1364     log_error("NULL pointer error\n");
1365     return -1;
1366     }
1367    
1368 sysadm 1.39 if (p_section->ex_menu_tm == 0) // N/A
1369     {
1370     moveto(2, 1);
1371     clrtoeol();
1372 sysadm 1.40 prints("该版块精华区未开放");
1373 sysadm 1.39 press_any_key();
1374     return 0;
1375     }
1376    
1377 sysadm 1.37 if (get_section_ex_menu_set(p_section, &ex_menu_set) < 0)
1378     {
1379     log_error("get_section_ex_menu_set(sid=%d) error\n", p_section->sid);
1380     return -3;
1381     }
1382     if (get_menu_shm_readonly(&ex_menu_set) < 0)
1383     {
1384 sysadm 1.39 log_error("get_menu_shm_readonly(sid=%d) error\n", p_section->sid);
1385 sysadm 1.37 return -3;
1386     }
1387    
1388     clearscr();
1389 sysadm 1.38 show_bottom("");
1390 sysadm 1.37
1391     if (display_menu(&ex_menu_set) == 0)
1392     {
1393 sysadm 1.78 for (loop = 1; !SYS_server_exit && loop;)
1394 sysadm 1.37 {
1395     iflush();
1396     ch = igetch(100);
1397 sysadm 1.54
1398     if (ch != KEY_NULL && ch != KEY_TIMEOUT)
1399     {
1400     BBS_last_access_tm = time(NULL);
1401     }
1402    
1403 sysadm 1.37 switch (ch)
1404     {
1405     case KEY_NULL: // broken pipe
1406 sysadm 1.54 log_error("KEY_NULL\n");
1407 sysadm 1.78 loop = 0;
1408     break;
1409 sysadm 1.37 case KEY_TIMEOUT:
1410 sysadm 1.71 if (time(NULL) - BBS_last_access_tm >= BBS_max_user_idle_time)
1411 sysadm 1.37 {
1412 sysadm 1.54 log_error("User input timeout\n");
1413 sysadm 1.78 loop = 0;
1414     break;
1415 sysadm 1.37 }
1416     continue;
1417     case CR:
1418     default:
1419     switch (menu_control(&ex_menu_set, ch))
1420     {
1421     case EXITMENU:
1422 sysadm 1.78 loop = 0;
1423 sysadm 1.37 break;
1424     case REDRAW:
1425     clearscr();
1426 sysadm 1.38 show_bottom("");
1427 sysadm 1.37 display_menu(&ex_menu_set);
1428     break;
1429     case NOREDRAW:
1430     case UNKNOWN_CMD:
1431     default:
1432     break;
1433     }
1434     }
1435     }
1436     }
1437    
1438     detach_menu_shm(&ex_menu_set);
1439    
1440     return 0;
1441     }
1442 sysadm 1.59
1443     int section_aid_locations_save(int uid)
1444     {
1445     char filename[FILE_PATH_LEN];
1446     FILE *fp;
1447     int i;
1448     int ret = 0;
1449    
1450     snprintf(filename, sizeof(filename), "%s/%d", VAR_SECTION_AID_LOC_DIR, uid);
1451    
1452     if ((fp = fopen(filename, "wb")) == NULL)
1453     {
1454     log_error("fopen(%s, wb) error: %d\n", filename, errno);
1455     return -1;
1456     }
1457    
1458     for (i = 0; i < p_section_list_pool->section_count; i++)
1459     {
1460     if (fwrite(&(p_section_list_pool->sections[i].sid), sizeof(p_section_list_pool->sections[i].sid), 1, fp) != 1)
1461     {
1462     log_error("fwrite(%s, sid) error\n", filename);
1463     ret = -2;
1464     break;
1465     }
1466    
1467     if (fwrite(&(section_aid_locations[i]), sizeof(section_aid_locations[i]), 1, fp) != 1)
1468     {
1469     log_error("fwrite(%s, aid) error\n", filename);
1470     ret = -2;
1471     break;
1472     }
1473     }
1474    
1475     if (fclose(fp) < 0)
1476     {
1477     log_error("fclose(%s) error: %d\n", filename, errno);
1478     ret = -1;
1479     }
1480    
1481     return ret;
1482     }
1483    
1484     int section_aid_locations_load(int uid)
1485     {
1486     char filename[FILE_PATH_LEN];
1487     FILE *fp;
1488     int i;
1489     int32_t sid;
1490     int32_t aid;
1491     SECTION_LIST *p_section;
1492     int ret = 0;
1493    
1494     snprintf(filename, sizeof(filename), "%s/%d", VAR_SECTION_AID_LOC_DIR, uid);
1495    
1496     if ((fp = fopen(filename, "rb")) == NULL)
1497     {
1498     if (errno == ENOENT) // file not exist
1499     {
1500     return 0;
1501     }
1502     log_error("fopen(%s, rb) error: %d\n", filename, errno);
1503     return -1;
1504     }
1505    
1506     while (!feof(fp))
1507     {
1508     if (fread(&sid, sizeof(sid), 1, fp) != 1)
1509     {
1510     if (ferror(fp) == 0)
1511     {
1512     break;
1513     }
1514     log_error("fread(%s, sid) error: %d\n", filename, ferror(fp));
1515     ret = -2;
1516     break;
1517     }
1518    
1519     if (fread(&aid, sizeof(aid), 1, fp) != 1)
1520     {
1521     if (ferror(fp) == 0)
1522     {
1523     break;
1524     }
1525     log_error("fread(%s, aid) error: %d\n", filename, ferror(fp));
1526     ret = -2;
1527     break;
1528     }
1529    
1530     p_section = section_list_find_by_sid(sid);
1531     if (p_section == NULL)
1532     {
1533     continue; // skip section no longer exist
1534     }
1535    
1536     i = get_section_index(p_section);
1537     if (i < 0)
1538     {
1539     log_error("get_section_index(sid=%d) error\n", sid);
1540     ret = -3;
1541     break;
1542     }
1543     section_aid_locations[i] = aid;
1544     }
1545    
1546     if (fclose(fp) < 0)
1547     {
1548     log_error("fclose(%s) error: %d\n", filename, errno);
1549     ret = -1;
1550     }
1551    
1552     return ret;
1553     }

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1