X-Git-Url: https://git.armaanb.net/?a=blobdiff_plain;f=mmenu.c;h=4e4283ca7bb5c555bc212303aede7819ec07ad05;hb=504a7161d0c5b7d96993125badb80bdfe4669057;hp=2dd8c75bbbdcb342ff7b1ff8b69400170f79f34a;hpb=2ac505237e584aa36ddc2f7e55d2657c0685194f;p=mmenu.git diff --git a/mmenu.c b/mmenu.c index 2dd8c75..4e4283c 100644 --- a/mmenu.c +++ b/mmenu.c @@ -2,26 +2,35 @@ #include #include +#include #include +#include +#include + #include -struct MemoryStruct { +struct memstruct { char *memory; size_t size; }; +char *days[] = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday"}; + +int +memfail(void) +{ + printf("ERROR: Out of memory\n"); + exit(4); +} + static size_t memback(void *contents, size_t size, size_t nmemb, void *userp) { size_t realsize = size * nmemb; - struct MemoryStruct *mem = (struct MemoryStruct *)userp; + struct memstruct *mem = (struct memstruct *)userp; char *ptr = realloc(mem->memory, mem->size + realsize + 1); - if(!ptr) { - /* out of memory! */ - printf("not enough memory (realloc returned NULL)\n"); - return 0; - } + if (!ptr) memfail(); mem->memory = ptr; memcpy(&(mem->memory[mem->size]), contents, realsize); @@ -31,10 +40,9 @@ memback(void *contents, size_t size, size_t nmemb, void *userp) return realsize; } -int -main(int argc, char *argv[]) +char * +getmenu(char *date) { - // Get webpage CURL *curl = curl_easy_init(); CURLcode res; @@ -43,22 +51,28 @@ main(int argc, char *argv[]) exit(1); } - struct MemoryStruct chunk; - chunk.memory = malloc(1); // will be grown as needed by the realloc above - chunk.size = 0; // no data at this point - - curl_easy_setopt(curl, CURLOPT_URL, - "https://nobilis.nobles.edu/skyworld/castlemenu.php"); + struct memstruct chunk; + chunk.memory = malloc(1); // Grown as needed by the realloc in memback() + chunk.size = 0; // No data yet + + const char *baseurl = + "https://nobilis.nobles.edu/skyworld/castlemenu.php?Date="; + int len = strlen(baseurl) + strlen(date) + 1; + char *url = (char *)malloc(len); + snprintf(url, len, "%s%s", baseurl, date); + printf("INFO: Using URL %s\n", url); + curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, memback); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); - printf("INFO: Fetching wepage\n"); + printf("INFO: Fetching webpage\n"); res = curl_easy_perform(curl); + free(url); if (res != CURLE_OK) { fprintf(stderr,"ERROR: Could not fetch webpage\n%s\n", - curl_easy_strerror(res)); + curl_easy_strerror(res)); exit(2); } @@ -67,47 +81,114 @@ main(int argc, char *argv[]) // Parse HTML printf("INFO: Parsing HTML\n"); bool intag = false; - char *outp = (char *) malloc(strlen(chunk.memory) + 1); // TODO: Realloc? - strcpy(outp, ""); + char *outp = (char *) calloc(1, sizeof(char)); + if (!outp) memfail(); // Extract text from between HTML tags - for (int i = 345; i < strlen(chunk.memory); i++) { + int j = 1; + char next[2]; + next[1] = '\0'; + for (int i = 345; chunk.memory[i]; i++) { char c = chunk.memory[i]; if (c == '<') intag = true; - if (!intag) strncat(outp, &c, 1); + if (!intag) { + j++; + outp = (char *) realloc(outp, j); + if (!outp) memfail(); + next[0] = c; + strncat(outp, next, 2); + } if (c == '>') intag = false; } + free(chunk.memory); + // Strip empty newlines - char *nl = (char *) malloc(strlen(outp)); - strncpy(nl, "\0", 1); - for (int i = 0; i < strlen(outp) - 1; i++) { - if (outp[i] == '\n' && outp[i+1] == '\n') i+=4; - strncat(nl, &outp[i], 1); + char *nl = (char *) calloc(1, sizeof(char)); + if (!nl) memfail(); + + j = 1; + for (int i = 0; outp[i]; i++) { + j++; + if (!((outp[i] == '\n' && outp[i+1] == '\n') || + (outp[i] == ' ' && outp[i+1] == ' '))) { + nl = (char *) realloc(nl, j); + if (!nl) memfail(); + next[0] = outp[i+1]; + strncat(nl, next, 2); + } } + free(outp); + return nl; +} + +void +dayback(Widget unused, XtPointer client_data, XtPointer call_data) +{ + (void)unused; + Widget disp = (Widget) client_data; + XmListCallbackStruct *list_cbs = (XmListCallbackStruct *) call_data; + char *nl = getmenu(days[list_cbs->item_position - 1]); + char *oldtext = XmTextGetString(disp) ; + XmTextReplace((Widget) disp, 0, strlen(oldtext), nl); + free(nl); + free(oldtext); +} + +// Convert an array of string to an array of compound strings +XmStringTable ArgvToXmStringTable (int argc, char **argv) +{ + XmStringTable new = + (XmStringTable) XtMalloc ((argc+1) * sizeof (XmString)); + if (!new) + return (XmStringTable) 0; + new[argc] = (XmString) 0; + while (--argc >= 0) + new[argc] = XmStringGenerate ((XtPointer) argv[argc], "tag2", + XmCHARSET_TEXT, NULL); + return new; +} + +int +main(int argc, char *argv[]) +{ // Initialize motif - Widget toplevel; - XtAppContext app; - Widget text_w; - Arg args[4]; + Widget toplevel, rowcol, daysel, disp; + XmStringTable strs; + XtAppContext app; + Arg args[5]; - XtSetLanguageProc (NULL, NULL, NULL); - toplevel = XtVaOpenApplication (&app, "Castle Menu", NULL, 0, &argc, argv, - NULL, sessionShellWidgetClass, NULL); + XtSetLanguageProc(NULL, NULL, NULL); + toplevel = XtVaOpenApplication(&app, "Castle Menu", NULL, 0, &argc, argv, + NULL, sessionShellWidgetClass, NULL); - // Set textbox settings int n = 0; - XtSetArg(args[n], XmNvalue, nl); n++; - XtSetArg(args[n], XmNeditable, False); n++; - XtSetArg(args[n], XmNcolumns, 80); n++; + XtSetArg (args[n], XmNorientation, XmHORIZONTAL); n++; + rowcol = XmCreateRowColumn(toplevel, "rowcol", args, n); + XtManageChild(rowcol); + + // Create text widget to display menu + n = 0; + char *nl = getmenu(""); + XtSetArg(args[n], XmNvalue, nl); n++; + XtSetArg(args[n], XmNeditable, False); n++; + XtSetArg(args[n], XmNcolumns, 80); n++; + XtSetArg(args[n], XmNrows, 20); n++; + XtSetArg (args[n], XmNeditMode, XmMULTI_LINE_EDIT); n++; XtSetArg(args[n], XmNcursorPositionVisible, False); n++; - text_w = XmCreateScrolledText(toplevel, "text", args, n); - free(outp); + disp = XmCreateScrolledText(rowcol, "text", args, n); + XtManageChild(disp); free(nl); + // Create day selector + strs = ArgvToXmStringTable (XtNumber(days), days); + daysel = XmCreateScrolledList(rowcol, "list", NULL, 0); + XtVaSetValues(daysel, XmNitems, strs, XmNitemCount, XtNumber(days), NULL); + XtAddCallback(daysel, XmNbrowseSelectionCallback, dayback, (XtPointer) disp); + XtManageChild(daysel); + // Display everything - XtManageChild(text_w); XtRealizeWidget(toplevel); XtAppMainLoop(app); }