Guest User

Untitled

a guest
Dec 9th, 2018
54
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 25.47 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <conio.h>
  3. #include <stdlib.h>
  4. #include <windows.h>
  5. #include <string.h>
  6. #include <time.h>
  7.  
  8. // constants
  9. #define CYN "\x1B[36m"
  10. #define WHT "\x1B[0m"
  11.  
  12. #define width   85
  13. #define height  31
  14.  
  15. #define menuTop     5
  16. #define menuLeft    20
  17. #define menuRight   66
  18. #define menuBottom  26
  19.  
  20. #define partitions 4
  21.  
  22. const CONSOLE_CURSOR_INFO hide = {1, FALSE};
  23. const CONSOLE_CURSOR_INFO show = {1, TRUE};
  24. const char *menuItems[6] = {"LOG IN / SIGN UP", "BROWSE QUESTIONS", "ASK A QUESTION", "SEARCH", "SIGN OUT", "QUIT"};
  25.  
  26. // global variables
  27. FILE *f;
  28. HANDLE out;
  29. int menuCurrent, page, answerPage, UICurrent, postCount, answerCount, postsAdded = 1, *lineValues, postCurrent = 0;
  30.  
  31. // definitions
  32. typedef struct User {
  33.     char *password;
  34.     char *username;
  35. } User;
  36. User *current;
  37.  
  38. typedef struct Answer {
  39.     int post;
  40.     char *author;
  41.     char *content;
  42. } Answer;
  43.  
  44. typedef struct Post {
  45.     Answer *answers[8];
  46.     char *title;
  47.     char *author;
  48.     char *date;
  49.     char *content;
  50.     int ansNum;
  51.     int id;
  52.     int points;
  53.     int voted;
  54. } Post;
  55. Post **posts;
  56.  
  57. typedef int menuFunction(void);
  58. menuFunction login, UI, addPost, search, signout, quit;
  59. menuFunction *menuFunctions[6] = {login, UI, addPost, search, signout, quit};
  60.  
  61. // utility functions
  62. void goTo(int x, int y) { COORD c = {x, y}; SetConsoleCursorPosition(out, c); }
  63. void setCursor(const CONSOLE_CURSOR_INFO *info) { SetConsoleCursorInfo(out, info); }
  64. char *crypt(char *string, int size) { while (size--) *string++ ^= 420; return string; }
  65. char *currentTime() {
  66.     time_t mytime = time(0);
  67.     char *time_str = ctime(&mytime);
  68.     time_str[strlen(time_str) - 1] = '\0';
  69.     return time_str;
  70. }
  71. int signedIn() {
  72.     if (strcmp(current -> username, "weed")) return 1;
  73.     return 0;
  74. }
  75. void checkEmpty() {
  76.     fseek(f, 0, 2);
  77.     if (!ftell(f)) fprintf(f, "0\n");
  78.     rewind(f);
  79. }
  80. void trim(char *string) {
  81.     int index = 0, i = 0;
  82.     while (string[index] == 32) index++;
  83.     if (index) {
  84.         while (string[i + index] != '\0') string[i] = string[i++ + index];
  85.         string[i] = '\0';
  86.     } string[strcspn(string, "\n")] = 0;
  87. }
  88.  
  89. // signatures
  90. // UI instantiators
  91. void initialize();
  92. void menu();
  93. int login();
  94. int UI();
  95. int addPost();
  96. int addAnswer();
  97. int search();
  98. int info();
  99. int quit();
  100. int postUI();
  101. int signout();
  102. void answerUI(Answer **, int);
  103. // menu drawing
  104. void drawMenu();
  105. void eraseMenu();
  106. void menuSelect(int);
  107. void menuDeselect(int);
  108. // UI drawing
  109. void drawUI();
  110. void printPosts(int);
  111. void eraseUI();
  112. void UISelect(int);
  113. // post UI drawing
  114. void drawPostUI(Post *, char *);
  115. void postUISelect(int, int, char *);
  116. // answer UI drawing
  117. void drawAnswerUI();
  118. int printAnswers(Answer **, int, int);
  119. // filing
  120. Post *loadPost(char *, char *, char *, char *, int, int, int);
  121. Post **loadPosts();
  122. void updatePoints(int, int);
  123. void appendPost(Post *);
  124. Answer *loadAnswer(int, char *, char *);
  125. void loadAnswers(Post **);
  126. void appendAnswer(Post **, Answer*);
  127. // login
  128. void appendUser(char *, char *);
  129. void updateUser(char *, char *);
  130. int checkUser(char *, char *);
  131. // search
  132. int searchPosts(char *);
  133.  
  134. void main() {
  135.     initialize();
  136.     menu();
  137. }
  138.  
  139. void initialize() {
  140.     out = GetStdHandle(STD_OUTPUT_HANDLE);
  141.     SetConsoleTitle("ASKode - Resolve any C query!");
  142.     setCursor(&hide);
  143.     SMALL_RECT window = {0, 0, width, height};
  144.     SetConsoleWindowInfo(out, 1, &window);
  145.     posts = loadPosts();
  146.     current = (User *) malloc(sizeof(User));
  147.     current -> username = strdup("weed");
  148. }
  149. int signout() {
  150.     current -> username = "weed";
  151.     system("cls");
  152.     return 1;
  153. }
  154.  
  155. int quit() {
  156.     eraseMenu();
  157.     exit(0);
  158. }
  159.  
  160. int searchPosts(char *query) {
  161.     int i, j, k;
  162.     for (int i = 0; i < postCount; i++) {
  163.         char *title = strdup(posts[i] -> title);
  164.         int len = strlen(title);
  165.         if (!stricmp(title ,query)) return i;
  166.         for (j = 0; j < len; j++) {
  167.             for (k = 0; k < strlen(query); k++) {
  168.                 if (title[j + k] != query[k]) break;
  169.             }
  170.             if (k == strlen(query)) return i;
  171.         }
  172.     } return -1;
  173. }
  174.  
  175. int addAnswer() {
  176.     system("cls");
  177.     int i, j, k, x = width / 2;
  178.     for (i = 0; i < 20; i++) {
  179.         goTo(x - i, height / 2 - 6);
  180.         for (j = 0; j < 2 * i + 1; j++) printf(CYN "%c", 196);
  181.         goTo(x - i, height / 2 + 6);
  182.         for (j = 0; j < 2 * i + 1; j++) printf("%c", 196);
  183.         Sleep(20);
  184.     }
  185.     goTo(x - strlen("Add answer") / 2, height / 2 - 5);
  186.     printf(WHT "Add answer");
  187.     for (i = 0; i < 4; i++) {
  188.         goTo(x - 19, height / 2 + i * 2 - 2);
  189.         for (j = 0; j < 39; j++) printf("%c", 196);
  190.     }
  191.     char *content;
  192.     int debounce = 1;
  193.     Answer *a;
  194.     while (debounce) {
  195.         content = calloc(300, sizeof(char));
  196.         debounce = 0;
  197.         goTo(x - 19, height / 2 - 3);
  198.         for (i = 0; i < 195; i++) {
  199.             if (!(i % 39)) goTo(x - 19, height / 2 + 2 * (i / 39 - 1) - 1);
  200.             char c = getche();
  201.             if (c == 9 || c == 13) break;
  202.             if (c == 8) {
  203.                 for (j = 0; j < 5; j++) {
  204.                     goTo(x - 19, height / 2 + 2 * (j - 1) - 1);
  205.                     for (k = 0; k < 39; k++) printf(" ");
  206.                 }
  207.                 debounce = 1;
  208.                 break;
  209.             }
  210.             if (c == 27) return 1;
  211.             content[i] = c;
  212.         } content[i] = '\0';
  213.     }
  214.     goTo(x - strlen("POST") / 2, height / 2 + 8);
  215.     printf(CYN "POST" WHT);
  216.     char in;
  217.     while (420) {
  218.         in = getch();
  219.         switch (in) {
  220.             case 27: return 1;
  221.             case 13: a = loadAnswer(UICurrent, current -> username, content);
  222.                      appendAnswer(posts, a);
  223.                      return 1;
  224.             default: break;
  225.         }
  226.     }
  227. }
  228.  
  229. int search() {
  230.     system("cls");
  231.     int i, j, x = width / 2;
  232.     for (i = 0; i < 20; i++) {
  233.         goTo(x - i, height / 2 - 2);
  234.         for (j = 0; j < 2 * i + 1; j++) printf(CYN "%c", 196);
  235.         goTo(x - i, height / 2 + 2);
  236.         for (j = 0; j < 2 * i + 1; j++) printf("%c", 196);
  237.         Sleep(20);
  238.     }
  239.     goTo(x - strlen("Search by title") / 2, height / 2 - 1);
  240.     printf(WHT "Search by title");
  241.     goTo(x - 19, height / 2 + 1);
  242.     for (i = 0 ; i < 39; i++) printf("%c", 196);
  243.     char *query, in;
  244.     int debounce = 1, index = 0;
  245.     while (debounce) {
  246.         query = calloc(33, sizeof(char));
  247.         debounce = 0;
  248.         goTo(x - 19, height / 2);
  249.         for (i = 0; i < 32; i++) {
  250.             char c = getche();
  251.             if (c == 9 || c == 13) break;
  252.             if (c == 8) {
  253.                 goTo(x - 19, height / 2);
  254.                 for (j = 0; j < 27; j++) printf(" ");
  255.                 debounce = 1;
  256.                 break;
  257.             }
  258.             if (c == 27) return 1;
  259.             query[i] = c;
  260.         } query[i] = '\0';
  261.     }
  262.     goTo(x - strlen("Search") / 2, height / 2 + 3);
  263.     printf(CYN "Search" WHT);
  264.     while (420) {
  265.         in = getch();
  266.         switch (in) {
  267.             case 27: return 1;
  268.             case 13: index = searchPosts(query);
  269.                      if (index != -1) {
  270.                          Post *p = posts[index];
  271.                          postUI(p);
  272.                      } return 1;
  273.             default: break;
  274.         }
  275.     }
  276.     getch();
  277. }
  278.  
  279. int addPost() {
  280.     system("cls");
  281.     int i, j, k, x = width / 2;
  282.     for (i = 0; i < 20; i++) {
  283.         goTo(x - i, height / 2 - 7);
  284.         for (j = 0; j < 2 * i + 1; j++) printf(CYN "%c", 196);
  285.         goTo(x - i, height / 2 + 7);
  286.         for (j = 0; j < 2 * i + 1; j++) printf("%c", 196);
  287.         Sleep(20);
  288.     }
  289.     goTo(x - strlen("Title") / 2, height / 2 - 6);
  290.     printf(WHT "Title");
  291.     goTo(x - 13, height / 2 - 4);
  292.     for (i = 0; i < 27; i++) printf("%c", 196);
  293.     goTo(x - strlen("Question") / 2, height / 2 - 3);
  294.     printf("Question");
  295.     for (i = 0; i < 4; i++) {
  296.         goTo(x - 19, height / 2 + i * 2 - 1);
  297.         for (j = 0; j < 39; j++) printf("%c", 196);
  298.     }
  299.     char *title, *content;
  300.     int debounce = 1;
  301.     while (debounce) {
  302.         title = calloc(29, sizeof(char));
  303.         debounce = 0;
  304.         goTo(x - 13, height / 2 - 5);
  305.         for (i = 0; i < 27; i++) {
  306.             char c = getche();
  307.             if (c == 9 || c == 13) break;
  308.             if (c == 8) {
  309.                 goTo(x - 13, height / 2 - 5);
  310.                 for (j = 0; j < 27; j++) printf(" ");
  311.                 debounce = 1;
  312.                 break;
  313.             }
  314.             if (c == 27) return 1;
  315.             title[i] = c;
  316.         } title[i] = '\0';
  317.     } debounce = 1;
  318.     while (debounce) {
  319.         content = calloc(300, sizeof(char));
  320.         debounce = 0;
  321.         goTo(x - 19, height / 2 - 2);
  322.         for (i = 0; i < 195; i++) {
  323.             if (!(i % 39)) goTo(x - 19, height / 2 + 2 * (i / 39 - 1));
  324.             char c = getche();
  325.             if (c == 9 || c == 13) break;
  326.             if (c == 8) {
  327.                 for (j = 0; j < 5; j++) {
  328.                     goTo(x - 19, height / 2 + 2 * (j - 1));
  329.                     for (k = 0; k < 39; k++) printf(" ");
  330.                 }
  331.                 debounce = 1;
  332.                 break;
  333.             }
  334.             if (c == 27) return 1;
  335.             content[i] = c;
  336.         } content[i] = '\0';
  337.     }
  338.     goTo(x - strlen("POST") / 2, height / 2 + 8);
  339.     printf(CYN "POST" WHT);
  340.     char in;
  341.     while (420) {
  342.         in = getch();
  343.         switch (in) {
  344.             case 27: return 1;
  345.             case 13: appendPost(loadPost(title, current -> username, currentTime(), content, 0, 1, 0));
  346.                      break;
  347.             default: break;
  348.         }
  349.     }
  350. }
  351.  
  352. int login() {
  353.     system("cls");
  354.     int i, j, x = width / 2;
  355.     for (i = 0; i < 20; i++) {
  356.         goTo(x - i, height / 2 - 4);
  357.         for (j = 0; j < 2 * i + 1; j++) printf(CYN "%c", 196);
  358.         goTo(x - i, height / 2 + 4);
  359.         for (j = 0; j < 2 * i + 1; j++) printf("%c", 196);
  360.         Sleep(20);
  361.     }
  362.     goTo(x - strlen("Username") / 2, height / 2 - 3);
  363.     printf(WHT "Username");
  364.     goTo(x - 13, height / 2 - 1);
  365.     for(i = 0; i < 27; i++) printf("%c", 196);
  366.     goTo(x - strlen("Password") / 2, height / 2 + 1);
  367.     printf("Password");
  368.     goTo(x - 13, height / 2 + 3);
  369.     for(i = 0; i < 27; i++) printf("%c", 196);
  370.     goTo(x - 19, height / 2 + 5);
  371.     printf("LOG IN");
  372.     goTo(x + 20 - strlen("SIGN UP"), height / 2 + 5);
  373.     printf("SIGN UP");
  374.     char *username, *password;
  375.     int debounce = 1;
  376.     while (debounce) {
  377.         username = calloc(29, sizeof(char));
  378.         debounce = 0;
  379.         goTo(x - 13, height / 2 - 2);
  380.         for (i = 0; i < 27; i++) {
  381.             char c = getche();
  382.             if (c == 9 || c == 13) break;
  383.             if (c == 8) {
  384.                 goTo(x - 13, height / 2 - 2);
  385.                 for (j = 0; j < 27; j++) printf(" ");
  386.                 debounce = 1;
  387.                 break;
  388.             }
  389.             if (c == 27) return 1;
  390.             username[i] = c;
  391.         } username[i] = '\0';
  392.     } debounce = 1;
  393.     while (debounce) {
  394.         password = calloc(29, sizeof(char));
  395.         debounce = 0;
  396.         goTo(x - 13, height / 2 + 2);
  397.         for (i = 0; i < 27; i++) {
  398.             char c = getche();
  399.             if (c == 9 || c == 13) break;
  400.             if (c == 8) {
  401.                 goTo(x - 13, height / 2 + 2);
  402.                 for (j = 0; j < 27; j++) printf(" ");
  403.                 debounce = 1;
  404.                 break;
  405.             }
  406.             if (c == 27) return 1;
  407.             password[i] = c;
  408.         } password[i] = '\0';
  409.     }
  410.     goTo(width / 2 - 19, height / 2 + 6);
  411.     for (i = 0 ; i < 6; i++) printf(CYN "%c" WHT, 196);
  412.     int select = 0;
  413.     char in;
  414.     while (420) {
  415.         in = getch();
  416.         switch (in) {
  417.             case -32: switch (getch()) {
  418.                 case 77: if (!select) {
  419.                             goTo(x - 19, height / 2 + 6);
  420.                             for (i = 0; i < 7; i++) printf(" ");
  421.                             goTo(x + 19 - strlen("SIGNUP"), height / 2 + 6);
  422.                             for (i = 0; i < 7; i++) printf(CYN "%c" WHT, 196);
  423.                             select++;
  424.                          } break;
  425.                 case 75: if (select) {
  426.                             goTo(x + 13, height / 2 + 6);
  427.                             for (i = 0; i < 7; i++) printf(" ");
  428.                             goTo(x - 19, height / 2 + 6);
  429.                             for (i = 0; i < 6; i++) printf(CYN "%c" WHT, 196);
  430.                             select--;
  431.                          } break;
  432.             } break;
  433.             case 27: return 1;
  434.             case 13: goTo(x - 19, height / 2 - 5);
  435.                      if (!select) {
  436.                         switch(checkUser(username, password)) {
  437.                             case 0: printf("Username not found!");
  438.                                     break;
  439.                             case 1: printf("Incorrect password!");
  440.                                     break;
  441.                             case 2: printf("Succesfully logged in as: %s", username);
  442.                                     updateUser(username, password);
  443.                                     break;
  444.                         }
  445.                      }
  446.                      else {
  447.                         switch(checkUser(username, password)) {
  448.                             case 0: printf("Succesfully created account: %s", username);
  449.                                     appendUser(username, password);
  450.                                     updateUser(username, password);
  451.                                     break;
  452.                             case 1: printf("Username already exists!");
  453.                                     break;
  454.                         }
  455.                      } break;
  456.             default: break;
  457.         }
  458.     }
  459. }
  460. void appendUser(char *username, char *password) {
  461.     f = fopen("users.txt", "a+");
  462.     char *pass = strdup(password);
  463.     crypt(pass, strlen(pass));
  464.     fprintf(f, "%s\t%s\n", username, pass);
  465.     fclose(f);
  466. }
  467.  
  468. void updateUser(char *username, char *password) {
  469.     current = (User *) malloc(sizeof(User));
  470.     current -> username = strdup(username);
  471.     current -> password = strdup(password);
  472. }
  473.  
  474.  
  475. int checkUser(char *username, char *password) {
  476.     int ret = 0;
  477.     f = fopen("users.txt", "a+");
  478.     char user[32], pass[32];
  479.     while (!feof(f)) {
  480.         fscanf(f, "%s\t%s\t\n", user, pass);
  481.         crypt(pass, strlen(pass));
  482.         if (!stricmp(user, username)) {
  483.             ret = 1;
  484.             if (!strcmp(pass, password)) ret = 2;
  485.             fclose(f);
  486.             return ret;
  487.         }
  488.     }
  489.     fclose(f);
  490.     return 0;
  491. }
  492.  
  493. void menu() {
  494.     char in;
  495.     drawMenu(menuItems);
  496.     int debounce = 0;
  497.     while (420) {
  498.         if (debounce) drawMenu(menuItems);
  499.         debounce = 0;
  500.         in = getch();
  501.         switch (in) {
  502.             case -32: switch (getch()) {
  503.                 case 72: if (menuCurrent > 0) menuSelect(menuCurrent - 1); break;
  504.                 case 77: break; // right arrow
  505.                 case 75: break; // left arrow
  506.                 case 80: if (menuCurrent < 5) menuSelect(menuCurrent + 1); break;
  507.             } break;
  508.             case 27: eraseMenu();
  509.                      return;
  510.             case 13: eraseMenu();
  511.                      debounce = (*menuFunctions[menuCurrent])();
  512.                      break;
  513.             default: break;
  514.         }
  515.     }
  516. }
  517.  
  518. int postUI(Post *p) {
  519.     char in, *commentString = malloc(12);
  520.     int debounce = 0;
  521.     switch(p -> ansNum) {
  522.         case 0: sprintf(commentString, "No answers");
  523.                 break;
  524.         case 1: sprintf(commentString, "1 answer");
  525.                 break;
  526.         default: sprintf(commentString, "%d answers", p -> ansNum);
  527.                  break;
  528.     }
  529.     drawPostUI(p, commentString);
  530.     while (420) {
  531.         if (debounce) drawPostUI(p, commentString);
  532.         debounce = 0;
  533.         in = getch();
  534.         switch (in) {
  535.             case -32: switch (getch()) {
  536.                 case 72: break;
  537.                 case 77: if (postCurrent < 2)
  538.                          postCurrent++;
  539.                          postUISelect(postCurrent, p -> points, commentString);
  540.                          break;
  541.                 case 75: if (postCurrent > 0)
  542.                          postCurrent--;
  543.                          postUISelect(postCurrent, p -> points, commentString);
  544.                          break;
  545.                 case 80: break;
  546.             } break;
  547.             case 27: return 1;
  548.             case 13: switch(postCurrent) {
  549.                         case 0: if (!p -> voted) {
  550.                                 p -> points++;
  551.                                 updatePoints(p -> id, p -> points);
  552.                                 p -> voted = 1;
  553.                                 return 1;
  554.                                 } break;
  555.                         case 1: debounce = addAnswer();
  556.                                 break;
  557.                         case 2: if (signedIn) debounce = printAnswers(p -> answers, 0, p -> ansNum);
  558.                                 break;
  559.                      } 
  560.                      break;
  561.             default: break;
  562.         }
  563.     }
  564. }
  565.  
  566. void postUISelect(int x, int points, char *commentString) {
  567.     int i, inc = width / 2;
  568.     goTo(width / 2 - 29, height / 2 + 7);
  569.     for (i = 0; i < 60; i++) printf(" ");
  570.     if (!x) {
  571.         goTo(inc + 30 - strlen(commentString), height / 2 + 6);
  572.         printf(WHT "%s", commentString);
  573.         goTo(inc - strlen("Add an answer") / 2, height / 2 + 6);
  574.         printf("Add an answer");
  575.         goTo(inc - 29, height / 2 + 6);
  576.         printf(CYN "%d %s", points, points == 1 ? "Point" : "Points");
  577.         goTo(inc - 29, height / 2 + 7);
  578.         printf("Upvote this post");
  579.     } else if (x == 1) {
  580.         goTo(inc - 29, height / 2 + 6);
  581.         printf(WHT "%d %s", points, points == 1 ? "Point" : "Points");
  582.         goTo(inc + 30 - strlen(commentString), height / 2 + 6);
  583.         printf("%s", commentString);
  584.         goTo(inc - strlen("Add an answer") / 2, height / 2 + 6);
  585.         printf(CYN "Add an answer");
  586.     }
  587.     else if (x == 2) {
  588.         goTo(inc - 29, height / 2 + 6);
  589.         printf(WHT "%d %s", points, points == 1 ? "Point" : "Points");
  590.         goTo(inc - strlen("Add an answer") / 2, height / 2 + 6);
  591.         printf("Add an answer");
  592.         goTo(inc + 30 - strlen(commentString), height / 2 + 6);
  593.         printf(CYN "%s", commentString);
  594.         goTo(inc + 30 - strlen("View answers"), height / 2 + 7);
  595.         printf("View answers");
  596.     }
  597. }
  598.  
  599. void drawPostUI(Post *p, char *commentString) {
  600.     system("cls");
  601.     int i, j, x = width / 2;
  602.     for (i = 0; i < 30; i++) {
  603.         goTo(x - i, height / 2 - 5);
  604.         for (j = 0; j < 2 * i + 1; j++) printf(CYN "%c", 196);
  605.         goTo(x - i, height / 2 + 5);
  606.         for (j = 0; j < 2 * i + 1; j++) printf("%c", 196);
  607.         Sleep(7);
  608.     }
  609.     goTo(x - 29, height / 2 - 6);
  610.     printf(WHT "u/%s", p -> author);
  611.     goTo(x + 6, height / 2 - 6);
  612.     printf("%s", p -> date);
  613.     goTo(x - 29, height / 2 + 6);
  614.     printf("%d %s", p -> points, p -> points == 1 ? "Point" : "Points");
  615.     goTo(x - strlen("Add an answer") / 2, height / 2 + 6);
  616.     printf("Add an answer");
  617.     goTo(x + 30 - strlen(commentString), height / 2 + 6);  
  618.     printf("%s", commentString);
  619.     goTo(x - strlen(p -> title) / 2, 11);
  620.     printf("%s", strupr(p -> title));
  621.     goTo(x - 29, 13);
  622.     int len = strlen(p -> content);
  623.     j = 0;
  624.     for (i = 0; i < len; i++) {
  625.         if (j == 59) {
  626.             j = 0;
  627.             goTo(x - 29, 13 + i / 59);
  628.         }
  629.         printf("%c", p -> content[i]);
  630.         j++;
  631.     } postUISelect(postCurrent, p -> points, commentString);
  632. }
  633.  
  634. void menuDeselect(int x) {
  635.     int i, end = (menuRight - menuLeft) / 2 - strlen(menuItems[x]) / 2 - 2;
  636.     goTo(menuLeft, menuTop + 3 * (x + 1));
  637.     for (i = 0; i <= end; i++) printf(" ");
  638.     goTo((menuRight - menuLeft) / 2 + menuLeft + strlen(menuItems[x]) / 2 + 1, menuTop + 3 * (x + 1));
  639.     for (i = 0; i <= end; i++) printf(" ");
  640. }
  641.  
  642. void menuSelect(int x) {
  643.     if (x != menuCurrent) menuDeselect(menuCurrent);
  644.     int i, end = (menuRight - menuLeft) / 2 - strlen(menuItems[x]) / 2 - 2;
  645.     goTo(menuLeft, menuTop + 3 * (x + 1));
  646.     printf(CYN "%c" WHT, 195);
  647.     for (i = 0; i < end; i++) printf("%c", 196);
  648.     goTo((menuRight - menuLeft) / 2 + menuLeft + strlen(menuItems[x]) / 2 + 1, menuTop + 3 * (x + 1));
  649.     for (i = 0; i < end; i++) printf("%c", 196);
  650.     printf(CYN "%c" WHT, 180);
  651.     menuCurrent = x;
  652. }
  653.  
  654. void drawMenu(char *items[6]) {
  655.     system("cls");
  656.     int i, j, x = (menuRight - menuLeft) / 2 + menuLeft - 1;
  657.     for (i = 0; i < (menuRight - menuLeft) / 2; i++) {
  658.         goTo(x - i, menuTop + 1);
  659.         for (j = 0; j < 2 * i + 1; j++) printf(CYN "%c", 196);
  660.         goTo(x - i, menuBottom - 1);
  661.         for (j = 0; j < 2 * i + 1; j++) printf("%c", 196);
  662.         Sleep(22 - i);
  663.     } printf("%c" WHT, 196);
  664.     for (i = 0; i < 6; i++) {
  665.         goTo((menuRight - menuLeft) / 2 + menuLeft - strlen(items[i]) / 2, menuTop + 3 * (i + 1));
  666.         puts(items[i]);
  667.     } menuSelect(menuCurrent);
  668. }
  669.  
  670. void eraseMenu() {
  671.     int i, j, x = (menuRight - menuLeft) / 2 + menuLeft - 1;
  672.     menuDeselect(menuCurrent);
  673.     for (i = 0; i < (menuRight - menuLeft) / 2; i++) {
  674.         goTo(x - i, menuTop + 1);
  675.         for (j = 0; j < 2 * i + 1; j++) printf(" ");
  676.         goTo(x - i, menuBottom - 1);
  677.         for (j = 0; j < 2 * i + 1; j++) printf(" ");
  678.         Sleep(i);
  679.     } system("cls");
  680. }
  681.  
  682. void drawUI() {
  683.     system("cls");
  684.     int i, j, increment = height / partitions;
  685.     goTo(width / 2 - strlen("PRESS S TO SEARCH...") / 2, 0);
  686.     printf(CYN "PRESS S TO SEARCH..." WHT);
  687.     for (i = 0; i < width + 1; i++) {
  688.         for (j = 1; j < height + 1; j += increment) {
  689.             goTo(i, j);
  690.             printf("%c", 196);
  691.         } Sleep(1);
  692.     } UISelect(UICurrent);
  693. }
  694.  
  695. int printAnswers(Answer **answers, int page, int ansNum) {
  696.     system("cls");
  697.     drawUI();
  698.     int i, increment = height / partitions;
  699.     goTo(width / 2 - strlen("PAGE 1 OF 5") / 2, 30);
  700.     printf(CYN "PAGE %d OF %d" WHT, answerPage + 1, 1 + ansNum / 4);
  701.     for (i = 0; i < partitions; i++)
  702.     if (i + (4 * answerPage) < ansNum) {
  703.         Answer *a = answers[i + (4 * answerPage)];
  704.         goTo(0, i * increment + 3);
  705.         printf("%s", a -> content);
  706.         goTo(width - strlen(a -> author) - 10, i * (increment) + 6);
  707.         printf("Posted by: %s", a -> author);
  708.     }
  709.     char in;
  710.     while (420) {
  711.         in = getch();
  712.         if (in == 27) return 1;
  713.     }
  714. }
  715.  
  716. void drawAnswerUI() {
  717.     system("cls");
  718.     int i, j, increment = height / partitions;
  719.     goTo(width / 2 - strlen("PRESS S TO SEARCH...") / 2, 0);
  720.     printf(CYN "PRESS S TO SEARCH..." WHT);
  721.     for (i = 0; i < width + 1; i++) {
  722.         for (j = 1; j < height + 1; j += increment) {
  723.             goTo(i, j);
  724.             printf("%c", 196);
  725.         } Sleep(3);
  726.     }
  727. }
  728.  
  729. void printPosts(int page) {
  730.     int i, increment = height / partitions;
  731.     goTo(width / 2 - strlen("PAGE 1 OF 5") / 2, 30);
  732.     printf(CYN "PAGE %d OF %d" WHT, page + 1, 1 + postCount / 4);
  733.     for (i = 0; i < partitions; i++)
  734.     if (i + (4 * page) < postCount) {
  735.         Post *p = posts[i + (4 * page)];
  736.         goTo(0, i * increment + 3);
  737.         printf("%s (%d)", p -> title, p -> points);
  738.         goTo(width - strlen(p -> author) - 10, i * increment + 3);
  739.         printf("Posted by: %s", p -> author);
  740.         goTo(0, i * (increment) + 6);
  741.         printf("Posted on: %s", p -> date);
  742.         char *string = (char *) malloc(12 * sizeof(char));
  743.         switch(p -> ansNum) {
  744.             case 0: sprintf(string, "No answers");
  745.                     break;
  746.             case 1: sprintf(string, "1 answer");
  747.                     break;
  748.             default: sprintf(string, "%d answers", p -> ansNum);
  749.                      break;
  750.         }  
  751.         goTo(width - strlen(string) + 1, i * increment + 6);
  752.         printf("%s", string);
  753.     }
  754. }
  755. void eraseUI() {
  756.     int i, j, increment = height / partitions;
  757.     for (i = 0; i < width + 1; i++) {
  758.         for (j = 1; j < height + 1; j += increment) {
  759.             goTo(i, j);
  760.             printf(" ");
  761.         } Sleep(3);
  762.     } system("cls");
  763. }
  764.  
  765. void UISelect(int x) {
  766.     int i;
  767.     for (i = 0; i < width  + 1; i += 3) {
  768.         goTo(i, (UICurrent % 4) * 7 + 1);
  769.         printf("%c", 196);
  770.         goTo(i, (UICurrent % 4 + 1) * 7 + 1);
  771.         printf("%c", 196);
  772.     }
  773.     for (i = 0; i < width  + 1; i += 3) {
  774.         goTo(i, (x % 4) * 7 + 1);
  775.         printf("%c", 194);
  776.         goTo(i, ((x % 4) + 1) * 7 + 1);
  777.         printf("%c", 193);
  778.     } UICurrent = x;
  779. }
  780.  
  781. void answerUI(Answer **answers, int ansNum) {
  782.     drawAnswerUI();
  783.     printAnswers(answers, 0, ansNum);
  784.     char in;
  785.     while (420) {
  786.         in = getch();
  787.         switch (in) {
  788.             case -32: switch (getch()) {
  789.                 case 72: break;
  790.                 case 77: if (answerPage < (ansNum / 4)) {
  791.                             printf("%d %d\n", answerPage, 1 + ansNum / 4);
  792.                             answerPage++;
  793.                             drawAnswerUI();
  794.                             printAnswers(answers, page, ansNum);
  795.                         } break;
  796.                 case 75: if (answerPage > 0) {
  797.                             answerPage--;
  798.                             drawAnswerUI();
  799.                             printAnswers(answers, page, ansNum);
  800.                         } break;
  801.                 case 80: break;
  802.             } break;
  803.             case 27: eraseUI();
  804.                      return;
  805.             case 13: eraseUI();
  806.                      printf("Selected: %s", menuItems[UICurrent]); 
  807.                      break;
  808.             default: break;
  809.         }
  810.     }
  811. }
  812.  
  813. int UI() {
  814.     drawUI();
  815.     printPosts(0);
  816.     char in;
  817.     int debounce = 0;
  818.     while (420) {
  819.         if (debounce) {
  820.             drawUI();
  821.             printPosts(0);
  822.         }
  823.         debounce = 0;
  824.         in = getch();
  825.         switch (in) {
  826.             case -32: switch (getch()) {
  827.                 case 72: if (UICurrent % 4 > 0) UISelect(UICurrent - 1); break;
  828.                 case 77: if (page < (postCount % 4 - 2)) {
  829.                             page++;
  830.                             drawUI();
  831.                             printPosts(page);
  832.                             UISelect(4 * page);
  833.                         } break;
  834.                 case 75: if (page > 0) {
  835.                             page--;
  836.                             drawUI();
  837.                             printPosts(page);
  838.                             UISelect(4 * page);
  839.                         } break;
  840.                 case 80: if (UICurrent % 4 < 3) UISelect(UICurrent + 1); break;
  841.             } break;
  842.             case 27: eraseUI();
  843.                      return 1;
  844.             case 13: if (UICurrent < postCount) debounce = postUI(posts[UICurrent]);
  845.                      break;
  846.         }
  847.     }
  848. }
  849.  
  850. Post *loadPost(char *title, char *author, char *date, char *content, int points, int increment, int override) {
  851.     Post *p = (Post *) malloc(sizeof(Post));
  852.     p -> title = malloc(32);
  853.     p -> title = strdup(title);
  854.     p -> author = malloc(32);
  855.     p -> author = strdup(author);
  856.     p -> date = malloc(32);
  857.     p -> date = strdup(date);
  858.     p -> content = malloc(300);
  859.     p -> content = strdup(content);
  860.     p -> points = points;
  861.     p -> id = postsAdded;
  862.     p -> ansNum = 0;
  863.     p -> voted = 0;
  864.     if (increment) postsAdded++;
  865.     if (override) p -> id = override;
  866.     return p;
  867. }
  868.  
  869. Post **loadPosts() {
  870.     f = fopen("posts.txt", "a+");
  871.     checkEmpty();
  872.     fclose(f);
  873.     f = fopen("posts.txt", "r+");
  874.     fscanf(f, "%d", &postCount);
  875.     lineValues = calloc(postCount + 1, sizeof(int));
  876.     Post **posts = (Post **) malloc(postCount * sizeof(Post *));
  877.     int i, points, digits = 0, x = postCount;
  878.     do { ++digits; } while (x /= 10);
  879.     fseek(f, digits + 1, 0);
  880.     char title[32], author[32], date[32], content[300];
  881.     for (i = 0; i < postCount; i++) {
  882.         lineValues[i] = ftell(f);
  883.         fscanf(f, "%d %d", &x, &points);
  884.         trim(fgets(title, 32, f));
  885.         trim(fgets(author, 32, f));
  886.         trim(fgets(content, 300, f));
  887.         trim(fgets(date, 32, f));
  888.         posts[i] = loadPost(title, author, date, content, points, 1, 0);
  889.     }
  890.     fclose(f);
  891.     loadAnswers(posts);
  892.     return posts;
  893. }
  894.  
  895. void updatePoints(int id, int points) {
  896.     if (id > postCount) return;
  897.     f = fopen("posts.txt", "r+");
  898.     fseek(f, lineValues[id - 1], 0);
  899.     int trash1, trash2;
  900.     fscanf(f, "%d %d", &trash1, &trash2);
  901.     fseek(f, lineValues[id - 1], 0);
  902.     fprintf(f, "%d %d", id, points);
  903.     posts[id - 1] -> points = points;
  904.     fclose(f);
  905. }
  906.  
  907. void appendPost(Post *post) {
  908.     f = fopen("posts.txt", "r+");
  909.     fprintf(f, "%d", ++postCount);
  910.     fseek(f, 0, 2);
  911.     lineValues[postCount - 1] = ftell(f);
  912.     fprintf(f, "%d %d %s\n%s\n%s\n%s\n", post -> id, post -> points, post -> title, post -> author, post -> content, post -> date);
  913.     posts[postCount - 1] = loadPost(post -> title, post -> author, post -> date, post -> content, post -> points, 1, 0);
  914.     fclose(f);
  915. }
  916.  
  917. Answer *loadAnswer(int post, char *author, char *content) {
  918.     Answer *a = (Answer *) malloc(sizeof(Answer));
  919.     a -> post = post;
  920.     a -> author = malloc(32);
  921.     a -> author = strdup(author);
  922.     a -> content = malloc(300);
  923.     a -> content = strdup(content);
  924.     return a;
  925. }
  926.  
  927. void loadAnswers(Post** posts) {
  928.     f = fopen("answers.txt", "a+");
  929.     checkEmpty();
  930.     fclose(f);
  931.     f = fopen("answers.txt", "r+");
  932.     fscanf(f, "%d", &answerCount);
  933.     int i, digits = 0, x = answerCount;
  934.     do { ++digits; } while (x /= 10);
  935.     fseek(f, digits + 1, 0);
  936.     char author[32], content[300];
  937.     for (i = 0; i < answerCount; i++) {
  938.         fscanf(f, "%d", &x);
  939.         x--;
  940.         trim(fgets(author, 32, f));
  941.         trim(fgets(content, 300, f));
  942.         Post *p = posts[x];
  943.         p -> answers[p -> ansNum] = loadAnswer(x, author, content);
  944.         p -> ansNum++;
  945.     }
  946.     fclose(f);
  947. }
  948.  
  949. void appendAnswer(Post **posts, Answer *answer) {
  950.     f = fopen("answers.txt", "r+");
  951.     fprintf(f, "%d", ++answerCount);
  952.     fseek(f, 0, 2);
  953.     fprintf(f, "%d %s\n%s\n", answer -> post, answer -> author, answer -> content);
  954.     int index = (answer -> post) - 1;
  955.     int ansIndex = posts[index] -> ansNum;
  956.     posts[index] -> answers[ansIndex] = loadAnswer(answer -> post, answer -> author, answer -> content);
  957.     posts[index] -> ansNum++;
  958.     fclose(f);
  959. }
Add Comment
Please, Sign In to add comment