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

Diff of /lbbs/src/section_list_display.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 1.1 by sysadm, Wed May 28 07:30:23 2025 UTC Revision 1.19 by sysadm, Sun Jun 8 09:25:25 2025 UTC
# Line 16  Line 16 
16    
17  #include "section_list_display.h"  #include "section_list_display.h"
18  #include "section_list_loader.h"  #include "section_list_loader.h"
19    #include "article_cache.h"
20  #include "common.h"  #include "common.h"
21  #include "io.h"  #include "io.h"
22  #include "screen.h"  #include "screen.h"
23  #include "log.h"  #include "log.h"
24    #include "user_priv.h"
25    #include "article_view_log.h"
26  #include "str_process.h"  #include "str_process.h"
27  #include <time.h>  #include <time.h>
28    #include <sys/param.h>
29  #define _POSIX_C_SOURCE 200809L  #define _POSIX_C_SOURCE 200809L
30  #include <string.h>  #include <string.h>
31    
32    static int section_topic_view_mode = 0;
33    static int section_topic_view_tid = -1;
34    
35  enum select_cmd_t  enum select_cmd_t
36  {  {
37          EXIT_SECTION = 0,          EXIT_SECTION = 0,
38          VIEW_ARTICLE = 1,          VIEW_ARTICLE = 1,
39          CHANGE_PAGE = 2,          CHANGE_PAGE = 2,
40          REFRESH_SCREEN = 3,          REFRESH_SCREEN = 3,
41            CHANGE_NAME_DISPLAY = 4,
42  };  };
43    
44  static int section_list_draw_items(SECTION_LIST *p_section, int page_id, ARTICLE *p_articles[], int article_count)  static int section_list_draw_items(int page_id, ARTICLE *p_articles[], int article_count, int display_nickname)
45  {  {
46          char str_time[LINE_BUFFER_LEN];          char str_time[LINE_BUFFER_LEN];
47          struct tm tm_sub;          struct tm tm_sub;
# Line 42  static int section_list_draw_items(SECTI Line 50  static int section_list_draw_items(SECTI
50          int eol;          int eol;
51          int len;          int len;
52          int i;          int i;
53            char article_flag;
54            int is_viewed;
55            time_t tm_now;
56    
57            time(&tm_now);
58    
59          clrline(4, 23);          clrline(4, 23);
60    
61          for (i = 0; i < article_count; i++)          for (i = 0; i < article_count; i++)
62          {          {
63                    if (p_articles[i]->uid == BBS_priv.uid)
64                    {
65                            is_viewed = 1;
66                    }
67                    else
68                    {
69                            is_viewed = article_view_log_is_viewed(p_articles[i]->aid, &BBS_article_view_log);
70                            if (is_viewed < 0)
71                            {
72                                    log_error("article_view_log_is_viewed(aid=%d) error\n", p_articles[i]->aid);
73                                    is_viewed = 0;
74                            }
75                    }
76    
77                    article_flag = (is_viewed ? ' ' : 'N');
78    
79                    if (p_articles[i]->excerption)
80                    {
81                            article_flag = (is_viewed ? 'm' : 'M');
82                    }
83                    else if (p_articles[i]->lock && is_viewed)
84                    {
85                            article_flag = 'x';
86                    }
87    
88                  localtime_r(&p_articles[i]->sub_dt, &tm_sub);                  localtime_r(&p_articles[i]->sub_dt, &tm_sub);
89                  strftime(str_time, sizeof(str_time), "%b %e", &tm_sub);                  if (tm_now - p_articles[i]->sub_dt < 3600 * 24 * 365)
90                  strncpy(title_f, p_articles[i]->title, sizeof(title_f) - 1);                  {
91                            strftime(str_time, sizeof(str_time), "%b %e ", &tm_sub);
92                    }
93                    else
94                    {
95                            strftime(str_time, sizeof(str_time), "%m/%Y", &tm_sub);
96                    }
97    
98                    strncpy(title_f, (p_articles[i]->tid == 0 ? "● " : ""), sizeof(title_f) - 1);
99                  title_f[sizeof(title_f) - 1] = '\0';                  title_f[sizeof(title_f) - 1] = '\0';
100                  len = split_line(title_f, (p_articles[i]->tid == 0 ? 40 : 37), &eol, &title_f_len);                  strncat(title_f, (p_articles[i]->transship ? "[转载]" : ""), sizeof(title_f) - 1 - strnlen(title_f, sizeof(title_f)));
101                    strncat(title_f, p_articles[i]->title, sizeof(title_f) - 1 - strnlen(title_f, sizeof(title_f)));
102                    len = split_line(title_f, 47 - (display_nickname ? 8 : 0), &eol, &title_f_len);
103                  if (title_f[len] != '\0')                  if (title_f[len] != '\0')
104                  {                  {
105                          title_f[len] = '\0';                          title_f[len] = '\0';
106                  }                  }
107    
108                  moveto(4 + i, 1);                  moveto(4 + i, 1);
109                  prints("  %7d %s%*s %s  %s%s",                  prints("  %s%7d\033[m %c %s%*s %s %s%s\033[m",
110                               (p_articles[i]->aid == section_topic_view_tid ? "\033[1;33m" : (p_articles[i]->tid == section_topic_view_tid ? "\033[1;36m" : "")),
111                             p_articles[i]->aid,                             p_articles[i]->aid,
112                             p_articles[i]->username,                             article_flag,
113                             BBS_username_max_len - (int)strnlen(p_articles[i]->username, sizeof(p_articles[i]->username)),                             (display_nickname ? p_articles[i]->nickname : p_articles[i]->username),
114                               (display_nickname ? BBS_nickname_max_len - (int)strnlen(p_articles[i]->nickname, sizeof(p_articles[i]->nickname))
115                                                                     : BBS_username_max_len - (int)strnlen(p_articles[i]->username, sizeof(p_articles[i]->username))),
116                             "",                             "",
117                             str_time,                             str_time,
118                             (p_articles[i]->tid == 0 ? "● " : ""),                             (p_articles[i]->aid == section_topic_view_tid ? "\033[1;33m" : (p_articles[i]->tid == section_topic_view_tid ? "\033[1;36m" : "")),
119                             title_f);                             title_f);
120          }          }
121    
122          return 0;          return 0;
123  }  }
124    
125  static int section_list_draw_screen(SECTION_LIST *p_section)  static int section_list_draw_screen(const char *sname, const char *stitle, const char *master_list, int display_nickname)
126  {  {
127          char str_section_master[LINE_BUFFER_LEN] = "诚征版主中";          char str_section_master[LINE_BUFFER_LEN] = "诚征版主中";
128          char str_section_name[LINE_BUFFER_LEN];          char str_section_name[LINE_BUFFER_LEN];
129    
130          if (p_section->master_list[0] != '\0')          if (master_list[0] != '\0')
131          {          {
132                  snprintf(str_section_master, sizeof(str_section_master), "版主:%s", p_section->master_list);                  snprintf(str_section_master, sizeof(str_section_master), "版主:%s", master_list);
133          }          }
134          snprintf(str_section_name, sizeof(str_section_name), "讨论区 [%s]", p_section->sname);          snprintf(str_section_name, sizeof(str_section_name), "讨论区 [%s]", sname);
135    
136          clearscr();          clearscr();
137          show_top(str_section_master, p_section->stitle, str_section_name);          show_top(str_section_master, stitle, str_section_name);
138          moveto(2, 0);          moveto(2, 0);
139          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] 阅读[\033[1;32m→\033[0;37m,\033[1;32mENTER\033[0;37m]\033[m");          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] "
140                       "阅读[\033[1;32m→\033[0;37m,\033[1;32mENTER\033[0;37m]\033[m %s[\033[1;32mn\033[0;37m]\033[m",
141                       (display_nickname ? "显示用户名" : "显示昵称"));
142          moveto(3, 0);          moveto(3, 0);
143          prints("\033[44;37m  \033[1;37m 编 号  发 布 者     日  期  文 章 标 题                                      \033[m");          if (display_nickname)
144          show_bottom("");          {
145                    prints("\033[44;37m  \033[1;37m 编  号   发布者昵称           日  期  文章标题                               \033[m");
146            }
147            else
148            {
149                    prints("\033[44;37m  \033[1;37m 编  号   发 布 者     日  期  文章标题                                       \033[m");
150            }
151    
152          return 0;          return 0;
153  }  }
# Line 124  static enum select_cmd_t section_list_se Line 183  static enum select_cmd_t section_list_se
183                                  return EXIT_SECTION; // exit section                                  return EXIT_SECTION; // exit section
184                          }                          }
185                          continue;                          continue;
186                    case 'n':
187                            return CHANGE_NAME_DISPLAY;
188                  case CR:                  case CR:
189                          igetch_reset();                          igetch_reset();
190                  case KEY_RIGHT:                  case KEY_RIGHT:
# Line 205  static enum select_cmd_t section_list_se Line 266  static enum select_cmd_t section_list_se
266          return EXIT_SECTION;          return EXIT_SECTION;
267  }  }
268    
269    static int display_article_key_handler(int *p_key, DISPLAY_CTX *p_ctx)
270    {
271            switch (*p_key)
272            {
273            case 'p':
274                    section_topic_view_mode = !section_topic_view_mode;
275            case 0: // Set msg
276                    if (section_topic_view_mode)
277                    {
278                            snprintf(p_ctx->msg, sizeof(p_ctx->msg),
279                                             "| 返回[\033[32m←\033[33m,\033[32mESC\033[33m] | "
280                                             "同主题阅读[\033[32m↑\033[33m/\033[32m↓\033[33m] | "
281                                             "模式[\033[32mp\033[33m] | 帮助[\033[32mh\033[33m] |");
282                    }
283                    else
284                    {
285                            snprintf(p_ctx->msg, sizeof(p_ctx->msg),
286                                             "| 返回[\033[32m←\033[33m,\033[32mESC\033[33m] | "
287                                             "移动[\033[32m↑\033[33m/\033[32m↓\033[33m/\033[32mPgUp\033[33m/\033[32mPgDn\033[33m] | "
288                                             "模式[\033[32mp\033[33m] | 帮助[\033[32mh\033[33m] |");
289                    }
290                    *p_key = 0;
291                    break;
292            case KEY_UP:
293            case KEY_PGUP:
294            case KEY_HOME:
295                    if (p_ctx->reach_begin)
296                    {
297                            if (section_topic_view_mode)
298                            {
299                                    *p_key = KEY_PGUP;
300                            }
301                            else
302                            {
303                                    *p_key = KEY_UP;
304                            }
305                            return 1;
306                    }
307                    break;
308            case KEY_DOWN:
309            case KEY_PGDN:
310            case KEY_END:
311                    if (p_ctx->reach_end)
312                    {
313                            if (section_topic_view_mode)
314                            {
315                                    *p_key = KEY_PGDN;
316                            }
317                            else
318                            {
319                                    *p_key = KEY_DOWN;
320                            }
321                            return 1;
322                    }
323                    break;
324            }
325    
326            return 0;
327    }
328    
329  int section_list_display(const char *sname)  int section_list_display(const char *sname)
330  {  {
331            static int display_nickname = 0;
332    
333          SECTION_LIST *p_section;          SECTION_LIST *p_section;
334            char stitle[BBS_section_title_max_len + 1];
335            char master_list[(BBS_username_max_len + 1) * 3 + 1];
336            char page_info_str[LINE_BUFFER_LEN];
337          ARTICLE *p_articles[BBS_article_limit_per_page];          ARTICLE *p_articles[BBS_article_limit_per_page];
338          int article_count;          int article_count;
339            int page_count;
340          int page_id = 0;          int page_id = 0;
341          int selected_index = 0;          int selected_index = 0;
342            ARTICLE_CACHE cache;
343          int ret;          int ret;
344            int loop;
345            int direction;
346    
347          p_section = section_list_find_by_name(sname);          p_section = section_list_find_by_name(sname);
348          if (p_section == NULL)          if (p_section == NULL)
# Line 221  int section_list_display(const char *sna Line 351  int section_list_display(const char *sna
351                  return -1;                  return -1;
352          }          }
353    
354          if (section_list_draw_screen(p_section) < 0)          if ((ret = section_list_rd_lock(p_section)) < 0)
355            {
356                    log_error("section_list_rd_lock(sid = 0) error\n");
357                    return -2;
358            }
359    
360            strncpy(stitle, p_section->stitle, sizeof(stitle) - 1);
361            stitle[sizeof(stitle) - 1] = '\0';
362            strncpy(master_list, p_section->master_list, sizeof(master_list) - 1);
363            master_list[sizeof(master_list) - 1] = '\0';
364    
365            if ((ret = section_list_rd_unlock(p_section)) < 0)
366            {
367                    log_error("section_list_rd_unlock(sid = 0) error\n");
368                    return -2;
369            }
370    
371            if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
372          {          {
373                  log_error("section_list_draw_screen() error\n");                  log_error("section_list_draw_screen() error\n");
374                  return -2;                  return -2;
375          }          }
376    
377          if (p_section->visible_article_count > 0)          ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count);
378            if (ret < 0)
379          {          {
380                  ret = query_section_articles(p_section, page_id, p_articles, &article_count);                  log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
381                  if (ret < 0)                  return -3;
                 {  
                         log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);  
                         return -3;  
                 }  
382          }          }
383          else // empty section  
384            if (article_count == 0) // empty section
385          {          {
                 article_count = 0;  
386                  selected_index = 0;                  selected_index = 0;
387          }          }
388    
389          while (!SYS_server_exit)          while (!SYS_server_exit)
390          {          {
391                  ret = section_list_draw_items(p_section, page_id, p_articles, article_count);                  ret = section_list_draw_items(page_id, p_articles, article_count, display_nickname);
392                  if (ret < 0)                  if (ret < 0)
393                  {                  {
394                          log_error("section_list_draw_items(sid=%d, page_id=%d) error\n", p_section->sid, page_id);                          log_error("section_list_draw_items(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
395                          return -4;                          return -4;
396                  }                  }
397    
398                    snprintf(page_info_str, sizeof(page_info_str),
399                                     "\033[33m[第\033[36m%d\033[33m/\033[36m%d\033[33m页]",
400                                     page_id + 1, MAX(page_count, 1));
401    
402                    show_bottom(page_info_str);
403                  iflush();                  iflush();
404    
405                  ret = section_list_select(p_section->page_count, article_count, &page_id, &selected_index);                  ret = section_list_select(page_count, article_count, &page_id, &selected_index);
406                  switch (ret)                  switch (ret)
407                  {                  {
408                  case EXIT_SECTION:                  case EXIT_SECTION:
409                          return 0;                          return 0;
410                  case CHANGE_PAGE:                  case CHANGE_PAGE:
411                          if (p_section->visible_article_count > 0)                          ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count);
412                            if (ret < 0)
413                          {                          {
414                                  ret = query_section_articles(p_section, page_id, p_articles, &article_count);                                  log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
415                                  if (ret < 0)                                  return -3;
                                 {  
                                         log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);  
                                         return -3;  
                                 }  
416                          }                          }
417                          else // empty section                          if (article_count == 0) // empty section
418                          {                          {
                                 article_count = 0;  
419                                  selected_index = 0;                                  selected_index = 0;
420                          }                          }
421                          if (selected_index >= article_count)                          else if (selected_index >= article_count)
422                          {                          {
423                                  selected_index = article_count - 1;                                  selected_index = article_count - 1;
424                          }                          }
425                          break;                          break;
426                  case VIEW_ARTICLE:                  case VIEW_ARTICLE:
427                          log_std("Debug: article %d selected\n", p_articles[selected_index]->aid);                          do
428                            {
429                                    loop = 0;
430    
431                                    if (article_cache_load(&cache, VAR_ARTICLE_CACHE_DIR, p_articles[selected_index]) < 0)
432                                    {
433                                            log_error("article_cache_load(aid=%d, cid=%d) error\n", p_articles[selected_index]->aid, p_articles[selected_index]->cid);
434                                            break;
435                                    }
436    
437                                    ret = display_data(cache.p_data, cache.line_total, cache.line_offsets, 0,
438                                                                       display_article_key_handler, DATA_READ_HELP);
439    
440                                    if (article_cache_unload(&cache) < 0)
441                                    {
442                                            log_error("article_cache_unload(aid=%d, cid=%d) error\n", p_articles[selected_index]->aid, p_articles[selected_index]->cid);
443                                            break;
444                                    }
445    
446                                    // Update article_view_log
447                                    if (article_view_log_set_viewed(p_articles[selected_index]->aid, &BBS_article_view_log) < 0)
448                                    {
449                                            log_error("article_view_log_set_viewed(aid=%d) error\n", p_articles[selected_index]->aid);
450                                    }
451    
452                                    switch (ret)
453                                    {
454                                    case KEY_UP:
455                                            if (selected_index <= 0)
456                                            {
457                                                    if (page_id > 0)
458                                                    {
459                                                            page_id--;
460                                                            selected_index = BBS_article_limit_per_page - 1;
461    
462                                                            ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count);
463                                                            if (ret < 0)
464                                                            {
465                                                                    log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
466                                                                    return -3;
467                                                            }
468    
469                                                            if (article_count != BBS_article_limit_per_page) // page is not full
470                                                            {
471                                                                    selected_index = MAX(0, article_count - 1);
472                                                            }
473                                                            else
474                                                            {
475                                                                    loop = 1;
476                                                            }
477                                                    }
478                                            }
479                                            else
480                                            {
481                                                    selected_index--;
482                                                    loop = 1;
483                                            }
484                                            break;
485                                    case KEY_DOWN:
486                                            if (selected_index + 1 >= article_count) // next page
487                                            {
488                                                    if (page_id + 1 < page_count)
489                                                    {
490                                                            page_id++;
491                                                            selected_index = 0;
492    
493                                                            ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count);
494                                                            if (ret < 0)
495                                                            {
496                                                                    log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
497                                                                    return -3;
498                                                            }
499    
500                                                            if (article_count == 0) // empty page
501                                                            {
502                                                                    selected_index = 0;
503                                                            }
504                                                            else
505                                                            {
506                                                                    loop = 1;
507                                                            }
508                                                    }
509                                            }
510                                            else
511                                            {
512                                                    selected_index++;
513                                                    loop = 1;
514                                            }
515                                            break;
516                                    case KEY_PGUP:
517                                    case KEY_PGDN:
518                                            direction = (ret == KEY_PGUP ? -1 : 1);
519                                            ret = locate_article_in_section(p_section, p_articles[selected_index], direction, &page_id, &selected_index, &page_count);
520                                            if (ret < 0)
521                                            {
522                                                    log_error("locate_article_in_section(sid=%d, aid=%d, direction=%d) error\n",
523                                                                      p_section->sid, p_articles[selected_index]->aid, direction);
524                                                    return -3;
525                                            }
526                                            else if (ret > 0)
527                                            {
528                                                    ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count);
529                                                    if (ret < 0)
530                                                    {
531                                                            log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
532                                                            return -3;
533                                                    }
534                                                    loop = 1;
535                                            }
536                                            break;
537                                    }
538                            } while (loop);
539    
540                            // Update current topic
541                            section_topic_view_tid = (p_articles[selected_index]->tid == 0 ? p_articles[selected_index]->aid : p_articles[selected_index]->tid);
542                  case REFRESH_SCREEN:                  case REFRESH_SCREEN:
543                          if (section_list_draw_screen(p_section) < 0)                          if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
544                            {
545                                    log_error("section_list_draw_screen() error\n");
546                                    return -2;
547                            }
548                            break;
549                    case CHANGE_NAME_DISPLAY:
550                            display_nickname = !display_nickname;
551                            if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
552                          {                          {
553                                  log_error("section_list_draw_screen() error\n");                                  log_error("section_list_draw_screen() error\n");
554                                  return -2;                                  return -2;


Legend:
Removed lines/characters  
Changed lines/characters
  Added lines/characters

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