#include #include #include #include #include #include #include #include "../framework/framework.h" #include "todo.h" #include "todo.m" #include #include using namespace std; const char K_TYPE[]="type"; const char K_DATE[]="date"; const char K_PROJECT[]="project"; const char K_REMIND[]="remind"; const char K_EVENT[]="event"; static const char K_INDEX[]="index"; static const char *todo_getpath(SSTRING &path) { path.setfromf ("%s/.TODO",getenv("HOME")); return path.get(); } static void update_index( const char *key, const SSTRING &val, SSTRINGS &tb) { if (tb.lookup(val.get())==-1){ tb.add (new SSTRING(val)); linuxconf_replace (key,K_INDEX,tb); linuxconf_save(); } } /* Convert a date in yyyy/mm/dd format to unix time_t format */ static time_t todo_date2sec (const char *line) { struct tm t; t.tm_isdst = -1; t.tm_year = atoi(line) - 1900; t.tm_mon = atoi(line+5)-1; t.tm_mday = atoi(line+8); t.tm_hour = 0; t.tm_min = 0; t.tm_sec = 0; return mktime (&t); } /* Check one criterion of the filter. Set select to false is the criterion is not matched. An empty filter means "don't care" */ static void todo_filter( const SSTRING &filter, const char *data, bool &select) { if (filter.is_filled() && filter.cmp(data)!=0){ select = false; } } /* Encode a text line to escape some character so it is XML compliant */ static void todo_encode (const char *line, SSTRING &enc) { enc.setempty(); while (*line != '\0'){ char carac = *line++; if (carac == '&'){ enc.append ("&"); }else if(carac == '<'){ enc.append (">"); }else if(carac == '<'){ enc.append (">"); }else if(carac == '\''){ enc.append ("'"); }else{ enc.append (carac); } } } #if 0 static void todo_writetext (FILE *fout, const char *text) { SSTRINGS lines; str_cnv2lines (text,lines); for (int i=0; iget(),enc); fprintf (fout,"%s\n",enc.get()); } } #endif int main (int argc, char *argv[]) { glocal SSTRING path; int ret = (argc,argv,"tlmpwork"); todo_getpath(glocal.path); setproginfo ("todo",TLMPWORK_VERSION,TLMPWORK_RELEASE,MSG_R(I_ABOUT)); setarg ('f',"file","XML file",glocal.path,false); glocal FRAMEWORK *fram; (MSG_U(T_TODO,"Todo notepad")); layout_area1(true); topmenu (MSG_U(M_FILE,"File")); menuentry (3,MSG_U(M_BROWSE,"Browse")); menuentry (1,MSG_U(M_QUIT,"Quit")); endmenu(); helpmenu(); endmenu(); if (id == 1){ end(); }else if (id == 3){ glocal PRIVATE_MESSAGE timer; // Filter glocal SSTRING f_project,f_type,f_date_start,f_date_end; glocal SSTRING f_remind,f_event,f_text; glocal vector tbno; dialog_settimer (glocal.timer,3,true); (MSG_U(T_TODOS,"Todos"),"",help_nil); newf_head (MSG_U(H_TODOS,"Project\tType\tDate\tRemind\tEvent\tDescription")); sortable(); sortpolicy ("llll"); waitfor (glocal.timer); setbutinfo (MENU_USR1,MSG_U(B_FILTER,"Filter") ,MSG_R(B_FILTER)); setbutinfo (MENU_USR2,MSG_U(B_REPORT,"Report") ,MSG_R(B_REPORT)); glocal.tbno.erase(glocal.tbno.begin(),glocal.tbno.end()); (glocal.path.get()); bool select = true; todo_filter (glocal.f_project,info.project,select); todo_filter (glocal.f_type,info.type,select); todo_filter (glocal.f_remind,info.remind,select); todo_filter (glocal.f_event,info.event,select); if (glocal.f_date_start.is_filled() && glocal.f_date_start.ncmp(info.date ,glocal.f_date_start.getlen()) > 0){ select = false; } if (glocal.f_date_end.is_filled() && glocal.f_date_end.ncmp(info.date ,glocal.f_date_end.getlen()) <= 0){ select = false; } if (glocal.f_text.is_filled() && stristr(info.text,glocal.f_text.get())==NULL){ select = false; } if (select){ SSTRING firstline; const char *text = info.text; const char *nl = strchr(text,'\n'); if (nl != NULL){ firstline.setfrom (text,(int)(nl-text)); text = firstline.get(); } glocal.editrecords.new_menuitemf(info.project ,"%s\t%s\t%s\t%s\t%s" ,info.type,info.date,info.remind,info.event,text); glocal.tbno.push_back(no); } no = glocal.tbno[no]; glocal.fram->newdocument ((void*)(long)no); if (code == MENU_USR1){ DIALOG dia; dia.settype (DIATYPE_POPUP); SSTRINGS projects,types; linuxconf_getall (K_TYPE,K_INDEX,types,true); types.sort(); linuxconf_getall (K_PROJECT,K_INDEX,projects,true); projects.sort(); FIELD_COMBO *comb = dia.newf_combo (MSG_R(F_PROJECT),glocal.f_project); for (int i=0; iaddopt (projects.getitem(i)->get()); } comb = dia.newf_combo (MSG_R(F_TYPE),glocal.f_type); for (int i=0; iaddopt (types.getitem(i)->get()); } dia.newf_str (MSG_U(F_DATE_START,"Date >= "),glocal.f_date_start); dia.newf_str (MSG_U(F_DATE_END,"Date <"),glocal.f_date_end); dia.newf_str (MSG_U(F_BODY,"Body"),glocal.f_text); dia.newf_str (MSG_R(F_EVENT),glocal.f_event); dia.newf_str (MSG_R(F_REMIND),glocal.f_remind); dia.setbutinfo (MENU_USR1,MSG_R(B_CLEAR) ,MSG_R(B_CLEAR)); int nof = 0; while (1){ MENU_STATUS code = dia.edit ( MSG_U(T_FILTER,"Filter"),"",help_nil ,nof,MENUBUT_CANCEL|MENUBUT_ACCEPT|MENUBUT_USR1); if (code == MENU_USR1){ glocal.f_project.setempty(); glocal.f_type.setempty(); glocal.f_date_start.setempty(); glocal.f_date_end.setempty(); glocal.f_event.setempty(); glocal.f_remind.setempty(); glocal.f_text.setempty(); dia.reload(); }else{ break; } } }else if (code == MENU_USR2){ DIALOG dia; dia.settype (DIATYPE_POPUP); SSTRING path; dia.newf_str (MSG_U(F_PATH,"File to produce"),path); dia.last_noempty(); if (dia.edit (MSG_U(T_REPORT,"Report generation") ,"",help_nil)==MENU_ACCEPT){ (path.get(),false); glocal FILE *fout = fout; (glocal.path.get()); if (find(glocal.tbno.begin(),glocal.tbno.end(),no) != glocal.tbno.end()){ fprintf (glocal.fout,"Projet %s, %s, %s\n",info.project,info.type,info.date); fputs ("\n",glocal.fout); SSTRINGS lines; str_cnv2lines (info.text,lines); for (int i=0; iget()); } fputs ("\n",glocal.fout); } return 0; } } dialog_deltimer (glocal.timer); } ("todo",TLMPWORK_VERSION,TLMPWORK_RELEASE); printf ("Jacques Gélinas jack@solucorp.qc.ca\n"); setgpl(); printf (MSG_U(I_ABOUT ,"This program is useful to collect ideas in your\n" "home TODO file\n." "The idea is to collect ideas/bugs/whatever\n" "as they come, without investing to much in proper\n" "classification. Later you must revisit the TODO file\n" "to remeber those idea. Trying to classify all ideas\n" "as they come only slow you down...")); printf (MSG_U(I_INTRO ,"Part of the TLMPWORK package\n" "available from http://www.solucorp.qc.ca/tlmp") ); { DIALOG dia; info.msgs.waitfor (dia); glocal SSTRING date,type,text,project,remind,event; glocal int node = info.data == NULL ? -1 : (int)(long)info.data; (); time_t t = time(NULL); struct tm *tt = localtime (&t); glocal.date.setfromf ("%04d/%02d/%02d",tt->tm_year+1900 ,tt->tm_mon+1,tt->tm_mday); if (glocal.node != -1){ (glocal.path.get()); if (no == glocal.node){ glocal.project.setfrom (info.project); glocal.date.setfrom(info.date); glocal.type.setfrom(info.type); glocal.remind.setfrom(info.remind); glocal.event.setfrom(info.event); glocal.text.setfrom(info.text); end = true; } }else{ sub.exec(); } dia.newf_str (MSG_U(F_DATE,"Date"),glocal.date); SSTRINGS types,projects; linuxconf_getall (K_TYPE,K_INDEX,types,true); types.sort(); linuxconf_getall (K_PROJECT,K_INDEX,projects,true); projects.sort(); FIELD_COMBO *comb = dia.newf_combo (MSG_U(F_TYPE,"Type"),glocal.type); for (int i=0; iaddopt (types.getitem(i)->get()); } dia.newline(); comb = dia.newf_combo (MSG_U(F_PROJECT,"Project"),glocal.project); for (int i=0; iaddopt (projects.getitem(i)->get()); } dia.newf_str (MSG_U(F_EVENT,"Event"),glocal.event); dia.newline(); dia.gui_form(); int remind_field = dia.getnb(); dia.newf_str (MSG_U(F_REMIND,"Remind date"),glocal.remind,15); PRIVATE_MESSAGE today,add_day,add_week,add_month,b_clear; dia.new_button (MSG_U(B_TODAY,"Today"),"",today); dia.new_button (MSG_U(B_ADDONEDAY,"+ day"),"",add_day); dia.new_button (MSG_U(B_ADDONEWEEK,"+ week"),"",add_week); dia.new_button (MSG_U(B_ADDONEMONTH,"+ month"),"",add_month); dia.new_button (MSG_R(B_CLEAR),"",b_clear); dia.gui_end(); dia.gui_dispolast (GUI_H_LEFT,10,GUI_V_CENTER,1); dia.newline(); dia.newf_textarea (NULL,glocal.text,80,10); dia.gui_dispolast (GUI_H_LEFT,4,GUI_V_CENTER,1); dia.newline(); int nof = 0; dia.setbutinfo (MENU_USR1,MSG_U(B_CLEAR,"Clear"),MSG_R(B_CLEAR)); while (1){ MENU_STATUS code = dia.edit ("","",help_nil,nof ,MENUBUT_CANCEL|MENUBUT_ACCEPT|MENUBUT_USR1); if (code == MENU_ESCAPE || code == MENU_CANCEL){ break; }else if (code == MENU_USR1){ glocal.project.setempty(); glocal.type.setempty(); glocal.event.setempty(); glocal.remind.setempty(); glocal.text.setempty(); sub.exec(); dia.reload(); }else if (code == MENU_MESSAGE){ if (must_end (info.msgs)){ break; }else if (dialog_testmessage (b_clear)){ glocal.remind.setempty(); dia.reload (remind_field); }else{ time_t date = time(NULL); if (glocal.remind.is_filled()){ date = todo_date2sec (glocal.remind.get()); } if (dialog_testmessage (today)){ date = time(NULL); }else if (dialog_testmessage (add_day)){ date += (24*60*60)*1; }else if (dialog_testmessage (add_week)){ date += (24*60*60)*7; }else if (dialog_testmessage (add_month)){ date += (24*60*60)*28; } struct tm *tt = localtime (&date); glocal.remind.setfromf ("%04d/%02d/%02d",tt->tm_year+1900 ,tt->tm_mon+1,tt->tm_mday); dia.reload (remind_field); } }else{ update_index (K_TYPE,glocal.type,types); update_index (K_PROJECT,glocal.project,projects); if (glocal.node == -1){ // New node, added to .TODO int ok = (glocal.path.get(),true); fprintf (fout,"\n"); SSTRING enc; todo_encode (glocal.text.get(),enc); fprintf (fout,"%s\n",enc.get()); fprintf (fout,"\n\n"); xconf_notice (MSG_U(N_UPDATED,"File %s updated") ,fname); return 0; if (ok == 0){ glocal.text.setempty(); dia.reload(); } }else{ (glocal.path.get()); if (no == glocal.node){ setproject (glocal.project.get()); settype (glocal.type.get()); setdate (glocal.date.get()); setremind (glocal.remind.get()); setevent (glocal.event.get()); SSTRING enc; todo_encode (glocal.text.get(),enc); settext (enc.get()); end = true; } break; } } } } glocal.fram = &fram; fram.newdocument (); fram.loop(); return 0; return ret; }