/[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.74 - (hide annotations)
Mon Nov 10 14:24:37 2025 UTC (4 months ago) by sysadm
Branch: MAIN
Changes since 1.73: +1 -1 lines
Content type: text/x-csrc
Replace ":" with ":"

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

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