home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 2 / goldfish_vol2_cd1.bin / files / biz / misc / banker / src / common2.c < prev    next >
C/C++ Source or Header  |  1993-12-17  |  17KB  |  634 lines

  1. /*
  2.  * common2.c
  3.  */
  4.  
  5. /* $Id: common2.c,v 1.6 1993/09/03 01:04:12 beust Exp $ */
  6.  
  7. #include <libraries/asl.h>
  8.  
  9. #include "common.h"
  10.  
  11. /***********
  12.  * Private
  13.  ***********/
  14.  
  15. static void
  16. removeFakes(Entries list)
  17. /* Remove all fake entries */
  18. {
  19.    DataBase db = (DataBase) list -> list;
  20.    Entry entry;
  21.  
  22.    DB_Rewind(db);
  23.    while ((entry = (Entry) DB_NextEntry(db))) {
  24.       if (entry -> fake) {
  25.          DB_RemoveEntry(db, entry);
  26.       }
  27.    }
  28. }
  29.  
  30. static void
  31. calculateNewFakes(Entries list)
  32. {
  33.    struct DateStamp current;
  34.    struct DateTime dt;
  35.    Automatic aut;
  36.    struct _Entry entry;
  37.    ULONG day, min, tick;
  38.    ULONG date, month, year;
  39.    ULONG s, ps, stop;
  40.    char *resultDate, bool;
  41.    DataBase db = (DataBase) list -> automatic;
  42.  
  43.    DateStamp(& current);
  44.    resultDate = (char *) malloc(64);
  45.  
  46.    DB_Rewind(db);
  47.    while ((aut = (Automatic) DB_NextEntry(db))) {
  48.       s = aut -> first.ds_Days;
  49.  
  50. /* Build the fake entry */
  51.       strcpy(entry.amount, aut -> amount);
  52.       strcpy(entry.transaction, aut -> transaction);
  53.       strcpy(entry.imputation, aut -> imputation);
  54.       entry.validated = 1;
  55.  
  56. /* If no end has been given, use the current time as a stop value */
  57.  
  58.       stop = (aut -> last.ds_Days ? aut -> last.ds_Days : current.ds_Days);
  59.  
  60.       while (s < stop) {
  61.  
  62.        /* Get month and year corresponding to this date */
  63.          dt.dat_Stamp.ds_Days = s;
  64.          dt.dat_Stamp.ds_Minute = 0;
  65.          dt.dat_Stamp.ds_Tick = 0;
  66.  
  67.        /* Copy it to the fake entry, and add it to the global list */
  68.          memcpy(& entry.date, & dt.dat_Stamp, sizeof(dt.dat_Stamp));
  69.          addEntryDatabase(list, & entry, 1, aut);
  70.                  /* 1 because it's a fake entry, generated by aut */
  71.  
  72.        /* Now compute the next automatic occurence */
  73.          dt.dat_StrDate = resultDate;
  74.          dt.dat_StrDay = NULL;
  75.          dt.dat_StrTime = NULL;
  76.          dt.dat_Format = FORMAT_CDN;
  77.          dt.dat_Flags = NULL; /* could be DTF_SUBST to have Monday when possible */
  78.          bool = DateToStr(& dt);
  79.          sscanf(resultDate,"%d-%d-%d", & date, & month, & year);
  80.  
  81.        /* Now we have the human-readable form, perform an intelligent increment */
  82.          ps = s;
  83.          s += aut -> repeatDays;
  84.          s += aut -> repeatWeeks * 7;
  85.          s += daysInNMonths(ps, aut -> repeatMonths, month, year);
  86.          s += daysInNYears(ps, aut -> repeatYears, year);
  87.       }
  88.    }
  89. }
  90.  
  91.  
  92. /***********
  93.  * Public
  94.  ***********/
  95.  
  96. TotalType
  97. computeTotal(Entries list)
  98. {
  99.    TotalType result = 0.0, tmp = 0.0;
  100.    char *p;
  101.    DataBase db = (DataBase) list -> list;
  102.    Entry entry;
  103.    int i;
  104.  
  105.    DB_Rewind(db);
  106.    while (1) {
  107.       entry = (Entry) DB_NextEntry(db);
  108.       if (! entry) break;
  109.       p = entry -> amount;
  110.       result += STRINGTOTOTAL(p);
  111.    }
  112.  
  113.    return result;
  114. }
  115.  
  116. TotalType
  117. computeValidatedTotal(Entries list)
  118. {
  119.    TotalType result = 0.0, tmp = 0.0;
  120.    char *p;
  121.    DataBase db = (DataBase) list -> list;
  122.    Entry entry;
  123.    int i;
  124.  
  125.    DB_Rewind(db);
  126.    while (1) {
  127.       entry = (Entry) DB_NextEntry(db);
  128.       if (! entry) break;
  129.       p = entry -> amount;
  130.       if (entry -> validated) result += STRINGTOTOTAL(p);
  131.    }
  132.  
  133.    return result;
  134. }
  135.  
  136.  
  137. void
  138. addEntryDatabase(Entries entries, Entry entry, char fake, Automatic generatedBy)
  139. {
  140.    entry -> generatedBy = generatedBy;
  141.    entry -> fake = fake;
  142.    DB_AddEntry((DataBase) entries -> list, entry);
  143.  
  144. }
  145.  
  146. void
  147. buildDataBase(Entries entries)
  148. {
  149.    removeFakes(entries);
  150.    calculateNewFakes(entries);
  151. }
  152.  
  153. char *
  154. returnFormattedString(struct StringAspect *sa, Entry entry)
  155. {
  156.    int i;
  157.    char *result, string[128], substring[128];
  158.    char *value;
  159.  
  160.    string[0] = '\0';
  161.    for (i = 0; i < sa -> numberOfFields; i++) {
  162.       switch(sa -> field[i]) {
  163.          case DATEFIELD :
  164.             value = myDateToStr(& entry -> date);
  165.             break;
  166.          case AMOUNTFIELD :
  167.             value = entry -> amount;
  168.             break;
  169.          case TRANSACTIONFIELD :
  170.             value = entry -> transaction;
  171.             break;
  172.          case IMPUTATIONFIELD :
  173.             value = entry -> imputation;
  174.             break;
  175.          case REASONFIELD :
  176.             value = entry -> reason;
  177.             break;
  178.          case CHECKNUMBERFIELD:
  179.             value = entry -> checkNumber;
  180.             break;
  181.          default :
  182.             myMsg1("returnformattedstring, unexpected case");
  183.       }
  184.       sprintf(substring, sa -> format[i], value);
  185.       strcat(string, substring);
  186.    }
  187.  
  188.    result = (char *) malloc(strlen(string) + strlen(sa -> after) + 2);
  189.  
  190. /* Add trailing characters */
  191.    strcpy(result, string);
  192.    strcat(result, sa -> after);
  193.  
  194.    return result;
  195. }
  196.  
  197. void
  198. sortList(Entries list)
  199. {
  200. /*
  201.    int count = DB_Count((DataBase) list -> list);
  202.    DB_Sort((DataBase) list -> list, compareTwoEntries);
  203. */
  204. }
  205.  
  206.  
  207. int
  208. daysInNMonths(ULONG days, ULONG n, ULONG month, ULONG year)
  209. {
  210.    int result = 0;
  211.    ULONG months[] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
  212.    char monthName[10];
  213.  
  214.  
  215.    month--;
  216.    while (n--) {
  217.       result += months[month];
  218.       if (year % 4 == 0 && month == 1) result++;
  219.       month++;
  220.       month %= 12;
  221.       if (month == 0) year++;
  222.    }
  223.    return result;
  224. }
  225.  
  226. int
  227. daysInNYears(ULONG days, ULONG n, ULONG year)
  228. {
  229.    int result = 0;
  230.  
  231.    while (n--) {
  232.       result += 365;
  233.       if (year % 4 == 0) result++;
  234.       year++;
  235.    }
  236.    return result;
  237. }
  238.  
  239. char *
  240. printEntry(Entries list, int number, char *s)
  241. {
  242.    Entry entry = DB_NthEntry((DataBase) list -> list, number);
  243.  
  244.    sprintf(s, ENTRYFORMATSTRING, (entry -> validated ? ' ' : '*'),
  245.                          entry -> date, entry -> transaction, entry -> amount,
  246.                          entry -> checkNumber, entry -> imputation, entry -> reason);
  247.  
  248.    return s;
  249. }
  250.  
  251. void
  252. printEntries(Entries list)
  253. {
  254.    int count, i;
  255.    char s[132];
  256.  
  257.    count = DB_Count((DataBase) list);
  258.    printf("%d entries\n", count);
  259.  
  260.    printf("------------------\n");
  261.    for (i=0; i < count; i++)
  262.       printf("%s\n", printEntry(list, i, s));
  263.    printf("------------------\n");
  264. }
  265.  
  266.  
  267. void
  268. parseListEntry(char *p, struct ListEntry *le)
  269. {
  270.    int columnNumber = 0, fieldNumber = 0;
  271.    char format[256];    /* will hold the format, one per column */
  272.    char *pb, before[60];
  273.    char *pk, keyword[60];
  274.  
  275.    strcpy(le -> col[0].fields, "");
  276.    while (1) {
  277.       if (*p && ! isalpha(*p) && *p != '|' && *p != '"') { p++; continue; }
  278.       strcpy(before, "");
  279.  
  280.       if (*p == '\0' || *p == '|') {
  281.          le -> col[columnNumber].format = strdup(format);
  282.          le -> col[columnNumber].numberOfFields = fieldNumber;
  283.          strcpy(format, "");
  284.  
  285.          columnNumber++;
  286.     fieldNumber = 0;
  287.          strcpy(le -> col[columnNumber].fields, "");
  288.          if (*p == '|') p++;
  289.          while (*p && isblank(*p)) p++;    /* skip possible blanks before the # */
  290.     if (*p =='\0') break;
  291.       }
  292.  
  293.       if (*p == '"') {         /* *p is not blank */
  294.          p++;
  295.          pb = before;
  296.          while (*p && *p != '"') *pb++ = *p++;
  297.          *pb++ = '\0';
  298.          if (*p == '"') p++;
  299.          while (*p && isblank(*p)) p++;    /* skip possible blanks before the # */
  300.     strcat(format, before);
  301.          continue;
  302.       }
  303.  
  304.       pk = keyword;            /* *p is not blank */
  305.       while (*p && isalpha(*p)) *pk++ = *p++;
  306.       *pk++ = '\0';
  307.       if (stricmp(keyword, "date") == 0) {
  308.          le -> col[columnNumber].fields[fieldNumber++] = (char) DATEFIELD;
  309.     strcat(format, "%s");
  310.       }
  311.       else if (stricmp(keyword, "amount") == 0) {
  312.          le -> col[columnNumber].fields[fieldNumber++] = (char) AMOUNTFIELD;
  313.     strcat(format, "%s");
  314.       }
  315.       else if (stricmp(keyword, "transaction") == 0) {
  316.          le -> col[columnNumber].fields[fieldNumber++] = (char) TRANSACTIONFIELD;
  317.     strcat(format, "%s");
  318.       }
  319.       else if (stricmp(keyword, "imputation") == 0) {
  320.          le -> col[columnNumber].fields[fieldNumber++] = (char) IMPUTATIONFIELD;
  321.     strcat(format, "%s");
  322.       }
  323.       else if (stricmp(keyword, "reason") == 0) {
  324.          le -> col[columnNumber].fields[fieldNumber++] = (char) REASONFIELD;
  325.     strcat(format, "%s");
  326.       }
  327.       else if (stricmp(keyword, "checknumber") == 0) {
  328.          le -> col[columnNumber].fields[fieldNumber++] = (char) CHECKNUMBERFIELD;
  329.     strcat(format, "%s");
  330.       }
  331.  
  332.       else myMsg2("readconfig : unknown keyword", keyword);
  333.  
  334.       strcat(format, before);
  335.    }
  336.  
  337.    le -> numberOfColumns = columnNumber;
  338. }
  339.  
  340. struct StringAspect *
  341. parseFormatString(char *string)
  342. /* [[@n &n] keyword string] * */
  343. {
  344.    struct StringAspect *result;
  345.    char *p, *pk, keyword[32], finalString[64], subString[64],
  346.         field[64], before[64], *pa;
  347.    long mask = 0;
  348.    int col = 0, fieldNumber = 0, size = 0;
  349.  
  350.    p = string;
  351.  
  352.    NEW(result, struct StringAspect);
  353.  
  354.    col = size = 0;
  355.    before[0] = '\0';
  356.    while (1) {
  357.       if (! *p) break;
  358.       if (! isalpha(*p) && *p != '@' && *p != '&' && *p != '"') { p++; continue; }
  359.  
  360.       if (*p == '@') {         /* *p is not blank */
  361.          p++;
  362.          col = atoi(p); 
  363.          while (*p && isblank(*p)) p++;    /* skip possible blanks before the # */
  364.          while (*p && isdigit(*p)) p++;    /* now the number is read, skip it */
  365.          continue;
  366.       }
  367.  
  368.       if (*p == '&') {         /* *p is not blank */
  369.          p++;
  370.          size = atoi(p); 
  371.          while (*p && isblank(*p)) p++;    /* skip possible blanks before the # */
  372.          while (*p && isdigit(*p)) p++;    /* now the number is read, skip it */
  373.          continue;
  374.       }
  375.  
  376.       if (*p == '"') {         /* *p is not blank */
  377.          p++;
  378.          pa = before;
  379.          while (*p && *p != '"') *pa++ = *p++;
  380.          *pa++ = '\0';
  381.          if (*p == '"') p++;
  382.          while (*p && isblank(*p)) p++;    /* skip possible blanks before the # */
  383.          continue;
  384.       }
  385.  
  386.       pk = keyword;            /* *p is not blank */
  387.       while (*p && isalpha(*p)) *pk++ = *p++;
  388.       *pk++ = '\0';
  389.       if (stricmp(keyword, "date") == 0) {
  390.          result -> field[fieldNumber] = DATEFIELD;
  391.       }
  392.       else if (stricmp(keyword, "amount") == 0) {
  393.          result -> field[fieldNumber] = AMOUNTFIELD;
  394.       }
  395.       else if (stricmp(keyword, "transaction") == 0) {
  396.          result -> field[fieldNumber] = TRANSACTIONFIELD;
  397.       }
  398.       else if (stricmp(keyword, "imputation") == 0) {
  399.          result -> field[fieldNumber] = IMPUTATIONFIELD;
  400.       }
  401.       else if (stricmp(keyword, "reason") == 0) {
  402.          result -> field[fieldNumber]= REASONFIELD;
  403.       }
  404.       else if (stricmp(keyword, "checknumber") == 0) {
  405.          result -> field[fieldNumber]= CHECKNUMBERFIELD;
  406.       }
  407.  
  408.       else myMsg2("readconfig : unknown keyword", keyword);
  409.  
  410.    /* Now we have result -> field[fieldNumber]. Take care of result -> format */
  411.       finalString[0] = 0;
  412.  
  413.    /* Add the possible "before" field */
  414.       strcat(finalString, before);
  415.  
  416.       if (size)
  417.          sprintf(subString, "%%%ds", size);
  418.       else
  419.          sprintf(subString, "%%s");
  420.       strcat(finalString, subString);
  421.  
  422.       result -> format[fieldNumber] = (char *) malloc(strlen(finalString) + 2);
  423.       strcpy(result -> format[fieldNumber], finalString);
  424.  
  425.       if (fieldNumber < MAX_FIELDS - 1) fieldNumber++;
  426.       col = size = 0;
  427.       before[0] = '\0';
  428.    }
  429.  
  430. /* And finally, store the number of fields the user wants */
  431.    result -> numberOfFields = fieldNumber;
  432.  
  433.    result -> after = (char *) malloc(strlen(before) + 2);
  434.    strcpy(result -> after, before);
  435.  
  436.    return result;
  437. }
  438.  
  439. void
  440. clearDataBase(Entries entries)
  441. {
  442.    DB_ClearDataBase((DataBase) entries -> list);
  443.    DB_ClearDataBase((DataBase) entries -> automatic);
  444.    strcpy(FileName, getString(MSG_NO_FILE_LOADED));
  445. }
  446.  
  447. void
  448. getFileName(Gui_t gui, char *initial, char *hail, char *result, char *pattern)
  449. {
  450.    struct FileRequester *fr;
  451.    char *path, *file;
  452.    APTR winObject = gui -> mainWindowObject;
  453.    struct Window *win;
  454.  
  455.    get(winObject, MUIA_Window_Window, & win);
  456.    fr = (struct FileRequester *) AllocAslRequestTags(ASL_FileRequest,
  457.                               ASL_Hail, hail,
  458.                               TAG_DONE);
  459.  
  460.    if (AslRequestTags(fr,
  461.             ASLFR_Locale, MyLocale,
  462. /*
  463.             ASLFR_Screen, MyScreen,
  464. */
  465.             ASLFR_SleepWindow, TRUE,
  466.             ASLFR_Window, win,
  467.             ASLFR_InitialDrawer, myPathPart(initial),
  468.             ASLFR_InitialFile, FilePart(initial),
  469.             ASLFR_InitialPattern, pattern,
  470.             TAG_END)) {
  471.  
  472.       path = fr -> rf_Dir;
  473.       file = fr -> rf_File;
  474.  
  475.    /* update the filename */
  476.       if (path[0] && path[strlen(path)-1] != ':')
  477.          sprintf(result,"%s/%s", path, file);
  478.       else
  479.          sprintf(result,"%s%s", path, file);
  480.  
  481.    /* update the pattern if the user changed it */
  482.       strcpy(pattern, fr -> fr_Pattern);
  483.    }
  484. }
  485.  
  486. int
  487. showRequester(Gui_t gui, char *title, char *text, char *choices)
  488. {
  489.    int result;
  490.    struct EasyStruct es;
  491.    struct Window *win;
  492.    APTR winObject;
  493.    extern struct Window *MyWindow;
  494.  
  495.    get(gui -> app, MUIA_Application_Window, & winObject);
  496.    if (winObject) {
  497.       result = MUI_Request(gui -> app, NULL, 0, title, choices, text);
  498. /*
  499.      es.es_StructSize = sizeof(es);
  500.      es.es_Flags = 0;
  501.      es.es_Title = title;
  502.      es.es_TextFormat = text;
  503.      es.es_GadgetFormat = choices;
  504.  
  505.      result = EasyRequest(win, & es, NULL, NULL);
  506. */
  507.    }
  508.    else {
  509.      result = -1;
  510.    }
  511.  
  512.    return result;
  513. }
  514.  
  515. char *
  516. myPathPart(char *path)
  517. {
  518.    char *p = path, *result, isAPath = 0, *endPath;
  519.    while (*p) {
  520.       if (*p == '/' || *p == ':') { isAPath = 1; endPath = p; }
  521.       p++;
  522.    }
  523.    if (! isAPath) return NULL;
  524.    else {
  525.       int len = endPath - path;
  526.       result = (char *) malloc(len + 2);
  527.       memcpy(result, path, len+1);
  528.       result[len+1] = 0;
  529.       return result;
  530.    }
  531. }
  532.  
  533. char *
  534. mySprintf(char *s, char *f, LONG *arg)
  535. {
  536.    int n = 0;
  537.    LONG *p = arg;
  538.    while (*p != NULL) p++;
  539.    n = p - arg;
  540.    switch (n) {
  541.       case 0 : sprintf(s, f); break;
  542.       case 1 : sprintf(s, f, arg[0]); break;
  543.       case 2 : sprintf(s, f, arg[0], arg[1]); break;
  544.       case 3 : sprintf(s, f, arg[0], arg[1], arg[2]); break;
  545.       case 4 : sprintf(s, f, arg[0], arg[1], arg[2], arg[3]); break;
  546.       case 5 : sprintf(s, f, arg[0], arg[1], arg[2], arg[3], arg[4]); break;
  547.    }
  548.    return f;
  549. }
  550.  
  551. void
  552. buildList(Gui_t gui, Entries entries, BOOL entry, BOOL sorted,
  553.      struct SmartAlloc *sn)
  554. {
  555.    int countEntry, countAuto, i = 0, count;
  556.    char *date, *name;
  557.    Entry nextEntry;
  558.    Automatic nextAuto;
  559.    Generic gen;
  560.    DataBase db;
  561.    APTR object, newEntry;
  562.    char result[256];
  563.  
  564.    buildDataBase(entries);
  565.    if (sorted) sortList(entries);
  566.  
  567.    db = (entry ? (DataBase) entries -> list : (DataBase) entries -> automatic);
  568.    object = (entry ? gui -> liListObject : gui -> auListObject);
  569.    DoMethod(object, MUIM_List_Clear);
  570.  
  571.    countEntry = DB_Count((DataBase) entries -> list);
  572.    countAuto = DB_Count((DataBase) entries -> automatic);
  573.    if (entry && countEntry == 0) return;
  574.    if (! entry && countAuto == 0) return;
  575.  
  576.  
  577.    count = DB_Count(db);
  578.    if (sn -> count < count) {   /* must allocate a new list */
  579.      char **oldStrings = sn -> strings, **newStrings;
  580.      newStrings = (char **) malloc(sizeof(char *) * count);
  581.      for (i = 0; i < count; i++) {
  582.        newStrings[i] = (char *) malloc(256);
  583. /*
  584.    printf("freeing 1\n");
  585.        if (oldNodes[i].ln_Name) free(oldNodes[i].ln_Name);
  586.    printf("freeing 2\n");
  587.        free(& oldNodes[i]);
  588. */
  589.      }
  590.      sn -> count = count;
  591.      sn -> strings = newStrings;
  592.    }
  593.  
  594. /* Disable and clear the list object */
  595.    set(object, MUIA_List_Quiet, TRUE);
  596.  
  597. /* Build up the node list, with a different string if it is an Entry or an Auto */
  598.    i = 0;
  599.    DB_Rewind(db);
  600.    while (! DB_EndOfDataBase(db)) {
  601.       name = sn -> strings[i];
  602.       gen = DB_NextEntry(db);
  603.       if (entry) {
  604.          nextEntry = (Entry) gen;
  605.          sprintf(name, "%c %s",
  606.                   (nextEntry -> fake ? '+' : (nextEntry -> validated ? ' ' : '*')),
  607.                   returnFormattedString(& DisplayFormatStructure, nextEntry));
  608.          nextEntry -> formattedString = name;
  609.          newEntry = (APTR) nextEntry;
  610.       }
  611.       else {
  612.          nextAuto = (Automatic) gen;
  613.          date = myDateToStr(& nextAuto -> first);
  614.          sprintf(name, AUTOFORMATSTRING,
  615.                                            '+',
  616.                                            date,
  617.                                            nextAuto -> repeatDays,
  618.                                            nextAuto -> repeatWeeks,
  619.                                            nextAuto -> repeatMonths,
  620.                                            nextAuto -> repeatYears,
  621.                                            nextAuto -> transaction);
  622.     nextAuto -> formattedString = name;
  623.     newEntry = (APTR) nextAuto;
  624.       
  625.       }
  626.       DoMethod(object, MUIM_List_Insert, & newEntry, 1, MUIV_List_Insert_Sorted);
  627.       i++;
  628.    }
  629.  
  630. /* Enable the list object */
  631.    set(object, MUIA_List_Quiet, FALSE);
  632. }
  633.  
  634.