/[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.81 - (hide annotations)
Wed Dec 17 03:47:00 2025 UTC (2 months, 4 weeks ago) by sysadm
Branch: MAIN
Changes since 1.80: +4 -0 lines
Content type: text/x-csrc
Refine debug log

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

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