/[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.70 - (hide annotations)
Tue Nov 4 14:58:56 2025 UTC (4 months, 1 week ago) by sysadm
Branch: MAIN
Changes since 1.69: +1 -1 lines
Content type: text/x-csrc
Refine file header information comments

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

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