diff --git a/include/date.cpp b/include/date.cpp index 47cfedbbb..4ad74d5b8 100755 --- a/include/date.cpp +++ b/include/date.cpp @@ -12,10 +12,15 @@ #define DAYBIAS 36525L #define NULLDATE -99999L -HIDDEN TDate __tmp_date; -HIDDEN char __date_tmp_string[20]; +#include -TDate::TDate(const TDate &d) : _val(d._val) {} +HIDDEN TDate __tmp_date; +HIDDEN char __date_tmp_string[64]; + +TDate::TDate(const TDate &d) : _val(d._val) +{ + memcpy(_format, "1444-", 5); +} TDate::TDate(long l) : _val(l) { @@ -24,11 +29,11 @@ TDate::TDate(long l) : _val(l) char s[10]; cgetdata(&_val, s); } + memcpy(_format, "1444-", 5); } TDate::TDate(const char* s) - { _val = NULLDATE; if (!isdate(s)) return; @@ -67,11 +72,11 @@ TDate::TDate(const char* s) _val = makedata(day, month, year) + off; } else _val = cpackdata((char*)s); + + memcpy(_format, "1444-", 5); } - TDate::TDate(int day, int month, int year) - { if (day == TODAY) { @@ -94,13 +99,19 @@ TDate::TDate(int day, int month, int year) _val = makedata(day, month, year) + off; if (!ok()) _val = NULLDATE; } + memcpy(_format, "1444-", 5); +} + +void TDate::set_format(const char* f) +{ + memcpy(_format, f, 5); } int TDate::last_day(int month, int year) // parse_filastrok( // "trenta giorni case novembre // con april, giugno e settembre - // case ventotto ce n'e' uno + // son ventotto case uno // per default ce n'ha trentuno"); { int d; @@ -132,13 +143,30 @@ bool TDate::is_end_month() return day() == last_day(month(),year()); } +int TDate::wday() const +{ + // day of week (1=lunedi) + // DDJ algorithm (4/1995) + int m = month(); + int d = day(); + int y = year(); + + if (m <= 2) + { + y --; + m += 12; + } + + return ((d + 2*m + 3*(m+1)/5 + y + y/4 - y/100 + y/400) % 7) + 1; +} + void TDate::set_day(int n) { _val = makedata(n, month(), year()); } void TDate::set_month(int n) { _val = makedata(day(), n, year()); } void TDate::set_year(int n) { _val = makedata(day(), month(), n); } TDate::operator const char*() const { - return string(4); + return string(); } @@ -164,57 +192,152 @@ void TDate::read_from(istream& in) } -char* TDate::string(int yeardgts, char sep, TDate_order ord) const - -{ +char* TDate::string(TDate_mgafmt yearf, char sep, TDate_mgafmt dayf, + TDate_mgafmt monthf, TDate_order ord) const +{ if (!ok()) return ""; - long wv = _val; - int cnt = wv >= DAYBIAS ? 2000 : 1900; + + int yeardgts = (int)yearf; - while (wv < 0) - { - cnt -= 100; - wv += DAYBIAS; - } - ceditdata(wv, __date_tmp_string); - if (strcmp(__date_tmp_string, " - - ") == 0) return ""; - if (sep != '-') - for (char* s = __date_tmp_string; *s; s++) - if (*s == '-') *s = sep; - if (yeardgts > 2) - { - char s[8]; - int year = cnt + atoi(__date_tmp_string + 6); + if (yearf == def || dayf != def || monthf != def || ord > amg_date) + { + // nonstandard: use new format + // yearf == def significa usa il formato standard specificato + TString dfm(32); - if (yeardgts == 3) sprintf(s, "%03d", year % 1000); - else sprintf(s, "%04d", year); - __date_tmp_string[6] = '\0'; - strcat(__date_tmp_string, s); - - if (ord == amg_date) + if (yearf == def) { - char* d = __date_tmp_string; - const char g[3] = { d[0], d[1], '\0' }; - const char m[3] = { d[3], d[4], '\0' }; - sprintf(d, "%s%c%s%c%s", &d[6], sep, m, sep, g); - } - else if (ord == mga_date) - { - char* d = __date_tmp_string; - char c = d[0]; d[0] = d[3]; d[3] = c; - c = d[1]; d[1] = d[4]; d[4] = c; + yearf = (TDate_mgafmt)(_format[3] - '0'); + ord = (TDate_order)(_format[0] - '0'); + sep = _format[4]; } + if (dayf == def) dayf = (TDate_mgafmt)(_format[1] - '0'); + if (monthf== def) monthf = (TDate_mgafmt)(_format[2] - '0'); + + TString df(2), yf(4), mf(2); + + bool letterflag = FALSE; + + // format each one + if (dayf == letters) + { + real ddd(day()); + letterflag = TRUE; + df = ddd.string("LETTERE"); + } + else if (dayf == weekday) + { + letterflag = TRUE; + df = format("%s %d", itow(wday()), day()); + } + else df = format(dayf == brief ? "%d" : "%02d", day()); + + if (yearf == letters) + { + real ddd(year()); + letterflag = TRUE; + yf = ddd.string("LETTERE"); + } + else if (yearf == brief && year() < 2000) + yf = format("%d", year() - 1900); + else + yf = format("%d", year()); + + if (monthf == letters) + { + letterflag = TRUE; + mf = itom(month()); + } + else if (monthf == quarter) + { + if (ord < m_date) ord = ma_date; + mf = format("%do trimestre", (month() / 3) + 1); + } + else + mf = format(monthf == brief ? "%d" : "%02d", month()); + + if (letterflag || sep == 'S') sep = ' '; + + // build date string + // single field + dfm = ""; + + switch (ord) + { + case gma_date: + dfm << df << sep << mf << sep << yf; + break; + case mga_date: + dfm << mf << sep << df << sep << yf; + break; + case amg_date: + dfm << yf << sep << mf << sep << df; + break; + case a_date: + dfm << yf; + break; + case m_date: + dfm << mf; + break; + case g_date: + dfm << df; + break; + case ma_date: + dfm << mf << sep << yf; + break; + } + strcpy(__date_tmp_string, (const char*)dfm); } else - if (yeardgts == ANSI) + { + long wv = _val; + int cnt = wv >= DAYBIAS ? 2000 : 1900; + + while (wv < 0) { - char* s = __date_tmp_string; s[2] = '\0'; s[5] = '\0'; - const int day = atoi(s); - const int month = atoi(s + 3); - const int year = atoi(s + 6); - - sprintf(__date_tmp_string, "%04d%02d%02d", year, month, day); + cnt -= 100; + wv += DAYBIAS; } + ceditdata(wv, __date_tmp_string); + if (strcmp(__date_tmp_string, " - - ") == 0) return ""; + if (sep != '-') + for (char* s = __date_tmp_string; *s; s++) + if (*s == '-') *s = sep; + if (yeardgts > 2) + { + char s[8]; + int year = cnt + atoi(__date_tmp_string + 6); + + if (yeardgts == 3) sprintf(s, "%03d", year % 1000); + else sprintf(s, "%04d", year); + __date_tmp_string[6] = '\0'; + strcat(__date_tmp_string, s); + + if (ord == amg_date) + { + char* d = __date_tmp_string; + const char g[3] = { d[0], d[1], '\0' }; + const char m[3] = { d[3], d[4], '\0' }; + sprintf(d, "%s%c%s%c%s", &d[6], sep, m, sep, g); + } + else if (ord == mga_date) + { + char* d = __date_tmp_string; + char c = d[0]; d[0] = d[3]; d[3] = c; + c = d[1]; d[1] = d[4]; d[4] = c; + } + } + else + if (yeardgts == ANSI) + { + char* s = __date_tmp_string; s[2] = '\0'; s[5] = '\0'; + const int day = atoi(s); + const int month = atoi(s + 3); + const int year = atoi(s + 6); + + sprintf(__date_tmp_string, "%04d%02d%02d", year, month, day); + } + } return __date_tmp_string; } diff --git a/include/date.h b/include/date.h index 6fa44a6ad..b04ea3921 100755 --- a/include/date.h +++ b/include/date.h @@ -10,14 +10,16 @@ // @END #define TODAY -1 -#define ANSI -1 -enum TDate_order { gma_date, mga_date, amg_date }; +enum TDate_order { gma_date = 1, mga_date, amg_date, a_date, m_date, g_date, ma_date }; +enum TDate_mgafmt { ANSI = -1, brief = 2, full = 4, letters = 5, weekday = 6, quarter = 7, + def = 99 }; class TDate : public TObject { // @DPRIV - long _val; // Valore data in formato packed + long _val; // Valore data in formato packed + byte _format[5]; // formato per tutti i pezzettini // @DES Operatori esterni < > <= >= == != // @FPUB @@ -30,13 +32,15 @@ class TDate : public TObject public: // @FPUB - char* string(int yeardgts = 4, char sep = '-', TDate_order ord = gma_date) const ; + char* string(TDate_mgafmt year = def, char sep = '-', TDate_mgafmt day = def, + TDate_mgafmt month = def, TDate_order ord = gma_date) const ; // @DES Ritorna la data in formato di stringa (anche in formato ANSI) // @FPUB int day() const ; // Ritorna il giorno int month() const ; // Ritorna il mese int year() const ; // Ritorna l'anno + int wday() const ; // ritorna il giorno della settimana (0 = domenica) void addmonth(int nmonth = 1); // Aggiunge dei mesi void addyear(int nyear = 1); // Aggiunge degli anni bool ok() const; // Vero se la data e' corretta @@ -50,6 +54,7 @@ public: void set_day(int n); void set_month(int n); void set_year(int n); + void set_format(const char* f); // @DES Ridefiniti gli operatori: += -= ++ -- >> e << // @FPUB diff --git a/include/files.cpp b/include/files.cpp index 4ab71c626..ca71e9e86 100755 --- a/include/files.cpp +++ b/include/files.cpp @@ -2,6 +2,8 @@ #include #include +#include +#include #ifndef FOXPRO #include @@ -11,7 +13,6 @@ #endif #include -#include #define BLOCKLEN 512 #define INVFLD 255 @@ -123,8 +124,24 @@ const char *TDir::des () const return _dir->Des; } -const char *TDir::expr () const +const char *TDir::tab_des (const char* tab) const +{ + CHECK (_num > 3 && _num < 7, "Non e' una tabella! Cojon!"); + + TString dfile(36); + int ind = (tab[0] == '$' || tab[0] == '%') ? 1 : 0; + dfile << DESCDIR << "/d" << tab+ind << ".des"; + if (!fexist(dfile)) + return ""; + + TConfig cnf(dfile, DESCTAB); + dfile = cnf.get("Description"); + + return strcpy(__tmp_string, dfile); +} + +const char *TDir::expr () const { return _dir->FCalc; } diff --git a/include/files.h b/include/files.h index 2e9290433..312894149 100755 --- a/include/files.h +++ b/include/files.h @@ -13,6 +13,10 @@ #include #endif +#define DESCPAR "FieldDescr" +#define DESCTAB "TabDescr" +#define DESCDIR "recdesc" + // @C // Classe TFile : public TObject // @@ -71,6 +75,7 @@ public: const char* name() const; const char* des() const; + const char* tab_des(const char* tabname) const; const char* expr() const; TRecnotype& eod() const; TRecnotype& eox() const; diff --git a/include/form.cpp b/include/form.cpp index e4b3d239d..501f176b0 100755 --- a/include/form.cpp +++ b/include/form.cpp @@ -108,7 +108,6 @@ void TForm_flags::read_from(const TMask& m) class TForm_item : public TObject { TPrint_section* _section; - TString _desc; TForm_flags _flag; TBit_array _group; TString_array _message; @@ -116,13 +115,12 @@ class TForm_item : public TObject protected: int _x, _y, _width, _height; TString _prompt; + TString _desc; + TString16 _permissions; virtual void print_on(ostream& out) const; virtual void print_body(ostream& out) const; - int width() const { return _width; } - int height() const { return _height; } - bool shown() const { return _flag.shown; } bool hidden() const { return !_flag.shown; } bool enabled() const { return _flag.enabled; } @@ -138,26 +136,46 @@ protected: TToken_string& message(int m = 0); void send_message(const TString& cmd, TForm_item& dest) const; bool do_message(int m = 0); - + void string_at(int x, int y, const char* s); - + + public: + + // permissions + // X : coordinate modificabili; + // F : field modificabile + // E : enable/disable concessi + // H : hide/show concessi + // C : compulsory (non si puo' cancellare nemmeno se il form lo consente + bool has_coord_permission() const { return _permissions.find('X') != -1; } + bool has_field_permission() const { return _permissions.find('F') != -1; } + bool has_enable_permission() const { return _permissions.find('E') != -1; } + bool has_hide_permission() const { return _permissions.find('H') != -1; } + bool has_remove_permission() const { return _permissions.find('C') == -1; } + + virtual int width() const { return _width; } + virtual int height() const { return _height; } + virtual bool parse(TScanner&); virtual bool update(); virtual void print_on(TMask& m); virtual void read_from(const TMask& m); - bool edit(TMask& m); + virtual bool edit(TMask& m); + virtual bool has_file() { return FALSE; } - TPrint_section& section() const { return *_section; } - bool in_group(byte g) const { return g == 0 || _group[g]; } + TPrint_section& section() const { return *_section; } + TForm& form() const { return _section->form(); } + + bool in_group(byte g) const { return g == 0 || _group[g]; } const TString& key() const { return _desc; } void print_on(TToken_string& row) const; - void show(bool on = TRUE) { _flag.shown = on; } + virtual void show(bool on = TRUE) { _flag.shown = on; } // TBI void hide() { show(FALSE); } - void enable(bool on = TRUE); + virtual void enable(bool on = TRUE); void disable() { enable(FALSE); } TForm_item(TPrint_section* section); @@ -166,7 +184,7 @@ public: TForm_item::TForm_item(TPrint_section* section) -: _section(section), _x(-1), _y(-1), _width(0), _height(0) +: _section(section), _x(-1), _y(-1), _width(0), _height(0), _permissions("XFEH") {} @@ -212,7 +230,9 @@ void TForm_item::print_body(ostream& out) const const TToken_string& m = (TToken_string&)_message[0]; if (!m.empty_items()) out << " MESSAGE " << m << endl; - } + } + + out << " PERMISSIONS \"" << _permissions << "\"\n"; } @@ -224,6 +244,12 @@ bool TForm_item::parse_item(TScanner& scanner) _y = scanner.integer(); _prompt = scanner.string(); return TRUE; + } + + if (scanner.key() == "PE") + { + _permissions = scanner.string(); + return TRUE; } if (scanner.key() == "FL") @@ -416,7 +442,13 @@ void TForm_item::print_on(TMask& m) m.set(F_Y, _y); m.set(F_PROMPT, _prompt); m.set(F_WIDTH, _width); - m.set(F_HEIGHT, _height); + m.set(F_HEIGHT, _height); + + if (has_file()) + { + // TBI add file/field description + } + _flag.print_on(m); for (int g = 1; g <= 24; g++) @@ -442,18 +474,189 @@ void TForm_item::read_from(const TMask& m) bool TForm_item::edit(TMask& m) { m.reset(); - - if (m.insert_mode()) m.enable(F_CLASS); + + if (m.insert_mode()) + m.enable(F_CLASS); else print_on(m); - const bool dirty = (m.run() == K_ENTER) && m.dirty(); - - if (m.insert_mode()) m.disable(F_CLASS); - else if (dirty) read_from(m); + // handle permissions + if (!has_field_permission()) + { + m.disable(F_BUT_FILE); + m.disable(F_BUT_FIELD); + } + if (!has_coord_permission()) + { + m.disable(F_X); + m.disable(F_Y); + m.disable(F_WIDTH); + m.disable(F_HEIGHT); + } + + if (!has_hide_permission()) + m.disable(F_HIDDEN); + + if (!has_enable_permission()) + m.disable(F_DISABLED); + + bool dirty = FALSE; // (m.run() == K_ENTER) && m.dirty(); + + for(KEY k = 0; k != K_ENTER && k != K_ESC; k = m.run()) + { + switch(k) + { + case K_ENTER: + dirty = (bool)m.dirty(); + break; + case K_ESC: + break; + case F_BUT_FILE: + // TBI + if (form().reldef() != NULL && form().reldef()->choose_file()) + { + m.set(F_FILE, form().reldef()->file_desc()); + } + break; + case F_BUT_FIELD: + // TBI + if (form().reldef() != NULL && form().reldef()->choose_field()) + { + m.set(F_FIELD, form().reldef()->field_desc()); + } + break; + } + } + + if (m.insert_mode()) + m.disable(F_CLASS); + else if (dirty) + read_from(m); + + m.enable(F_Y); + m.enable(F_X); + m.enable(F_WIDTH); + m.enable(F_HEIGHT); + m.enable(F_HIDDEN); + m.enable(F_DISABLED); + m.enable(F_FILE); + m.enable(F_FIELD); + return dirty; } +/////////////////////////////////////////////////////////// +// TForm_subsection +/////////////////////////////////////////////////////////// + +class TForm_subsection : public TForm_item +{ + TPrint_section _ssec; + TString _name; + +protected: + + virtual void print_on(ostream& out) const; + +public: + + virtual int width() const; + virtual int height() const; + + virtual bool parse(TScanner& s) { name(s.pop()); return _ssec.parse(s); } + virtual bool update() { return _ssec.update(); } + virtual bool edit(TMask& m); + + virtual const char* class_name() const { return "SEZIONE"; } + + TPrint_section& subsection() { return _ssec; } + + virtual void show(bool on = TRUE); + virtual void enable(bool on = TRUE); + void hide() { show(FALSE); } + void disable() { enable(FALSE); } + + void name(const char* s) { _name = s; _desc << "Sottosezione " << s; } + const char* name() const { return _name; } + + TForm_subsection(TPrint_section* section, const char* name = ""); + virtual ~TForm_subsection() {} +}; + + +TForm_subsection::TForm_subsection(TPrint_section* s, const char* nm) : +TForm_item(s), _ssec(&(s->form())), _name(nm) +{} + + +bool TForm_subsection::edit(TMask& m) +{ + // mask con nome e bottone edit contents / annulla + TMask mu("ba2100u"); + mu.set(F_CAPTION, _name); + + KEY k; + + // vedere se e' nuova etc. + // gestire aggiunta / modifica menu + + while ((k = mu.run()) != K_ESC) + { + if (mu.field(F_CAPTION).dirty()) + _name = mu.get(F_CAPTION); + + if (k == K_INS) + _ssec.edit(_name, TRUE); // TBI god mode only if... + else if (k == K_DEL) + { + // remove myself + } + else if (k == K_ENTER) + break; + } + + return k != K_ESC; +} + + +void TForm_subsection::print_on(ostream& out) const +{ + out << "SEZIONE " << _name << "\n"; + for (word i = 0; i < _ssec.fields(); i++) + out << _ssec.field(i); + out << "END" << "\n"; +} + + +int TForm_subsection::width() const +{ + + int w = 0; + for (word i = 0; i < _ssec.fields(); i++) + if (_ssec.field(i).width() > w) + w = _ssec.field(i).width(); + return w; +} + +int TForm_subsection::height() const +{ + int h = 0; + for (word i = 0; i < _ssec.fields(); i++) + h += _ssec.field(i).height(); + return h; +} + +void TForm_subsection::show(bool on) +{ + for (unsigned int i = 0; i < _ssec.fields(); i++) + _ssec.field(i).show(on); +} + +void TForm_subsection::enable(bool on) +{ + for (unsigned int i = 0; i < _ssec.fields(); i++) + _ssec.field(i).enable(on); +} /////////////////////////////////////////////////////////// // TForm_string @@ -474,6 +677,7 @@ protected: virtual bool parse_item(TScanner&); virtual bool read(); virtual bool update(); + virtual bool has_file() { return _field.items() > 0; } const char* get() const; bool set(const char*); @@ -653,20 +857,31 @@ bool TForm_number::update() class TForm_date : public TForm_string { + + TString _format; + protected: virtual const char* class_name() const { return "DATA"; } virtual bool read(); virtual bool set(const char*); bool set(const TDate& d); - + virtual bool parse_item(TScanner& scanner); + virtual void print_body(ostream& out) const; + virtual void print_on(TMask& m); + virtual void read_from(const TMask& m); + + static bool dateformat_handler(TMask_field& f, KEY k); + public: + + virtual bool edit(TMask& m); TForm_date(TPrint_section* section); virtual ~TForm_date() {} }; TForm_date::TForm_date(TPrint_section* section) -: TForm_string(section) +: TForm_string(section), _format("1444-") {} bool TForm_date::read() @@ -677,16 +892,94 @@ bool TForm_date::read() return ok; } +void TForm_date::print_body(ostream& out) const +{ + out << " FORMAT \"" << _format << "\"\n"; + TForm_string::print_body(out); +} + +bool TForm_date::parse_item(TScanner& scanner) +{ + if (scanner.key() == "FO") + { + _format = scanner.string(); + return TRUE; + } + return TForm_string::parse_item(scanner); +} + bool TForm_date::set(const char* s) { const TDate d(s); - TForm_string::set(d.string((width() == 8) ? 2 : 4)); + TForm_string::set(d.string((width() == 8) ? brief : full)); return TRUE; } bool TForm_date::set(const TDate& d) { - TForm_string::set(d.string((width() == 8) ? 2 : 4)); + TForm_string::set(d.string((width() == 8) ? brief : full)); + return TRUE; +} + +void TForm_date::print_on(TMask& m) +{ + TDate d(TODAY); d.set_format(_format); + m.set(F_DEXAMPLE, d.string()); + + m.set(F_DFORMAT, _format.mid(0,1)); + m.set(F_DDAY, _format.mid(1,1)); + m.set(F_DMONTH, _format.mid(2,1)); + m.set(F_DYEAR, _format.mid(3,1)); + m.set(F_DSEP, _format.mid(4,1)); + + TForm_string::print_on(m); +} + +void TForm_date::read_from(const TMask& m) +{ + // adjust format string + _format[0] = (m.field(F_DFORMAT).get())[0]; + _format[1] = (m.field(F_DDAY).get())[0]; + _format[2] = (m.field(F_DMONTH).get())[0]; + _format[3] = (m.field(F_DYEAR).get())[0]; + _format[4] = (m.field(F_DSEP).get())[0]; + + TForm_string::read_from(m); +} + +bool TForm_date::edit(TMask& m) +{ + m.set_handler(F_DFORMAT, dateformat_handler); + m.set_handler(F_DYEAR, dateformat_handler); + m.set_handler(F_DMONTH, dateformat_handler); + m.set_handler(F_DDAY, dateformat_handler); + m.set_handler(F_DSEP, dateformat_handler); + + return TForm_string::edit(m); +} + +bool TForm_date::dateformat_handler(TMask_field& f, KEY k) +{ + if (k != K_SPACE) + return TRUE; + + TMask_field& df = f.mask().field(F_DFORMAT); + TMask_field& dd = f.mask().field(F_DDAY); + TMask_field& dm = f.mask().field(F_DMONTH); + TMask_field& dy = f.mask().field(F_DYEAR); + TMask_field& ds = f.mask().field(F_DSEP); + + char fmt[5]; TDate ex(TODAY); + + fmt[0] = (df.get())[0]; + fmt[1] = (dd.get())[0]; + fmt[2] = (dm.get())[0]; + fmt[3] = (dy.get())[0]; + fmt[4] = (ds.get())[0]; + + ex.set_format(fmt); + f.mask().set(F_DEXAMPLE, ex.string()); + return TRUE; } @@ -887,6 +1180,8 @@ void TPrint_section::offset(int& x, int& y) const TForm_item* TPrint_section::parse_item(const TString& s) { + if (s == "SE") + return new TForm_subsection(this); // TBI if (s == "ST") return new TForm_string(this); if (s == "NU") @@ -972,7 +1267,13 @@ bool TPrint_section::edit(const char* title, bool all) _y = m.get_int(F_Y); } - TArray_sheet a(-1, -1, 0, 0, title, "Tipo@8|Riga@R|Col.@R|Gr.@R|Descrizione@40", all ? 0xE : 0x8); + word flags = 0x08; + + if (form().has_add_permission()) flags |= 0x02; + if (form().has_remove_permission()) flags |= 0x04; + + TArray_sheet a(-1, -1, 0, 0, title, "Tipo@8|Riga@R|Col.@R|Gr.@R|Descrizione@40", + flags); for (word i = 0; i < fields(); i++) { @@ -989,9 +1290,12 @@ bool TPrint_section::edit(const char* title, bool all) if (_msk == NULL && (k == K_ENTER || k == K_INS)) { _msk = new TMask("ba2100f"); - if (!all) _msk->disable(-7); + // if (!all) _msk->disable(-7); } + TForm_string dummy(this); + TForm_item& it = (TForm_item&)_item[i]; + switch(k) { case K_ENTER: @@ -1003,33 +1307,31 @@ bool TPrint_section::edit(const char* title, bool all) } break; case K_INS: - if (all) - { - _msk->set_mode(MODE_INS); - TForm_string dummy(this); - if (dummy.edit(*_msk)) - { - const TString& c = _msk->get(F_CLASS).left(2); - TForm_item* item = parse_item(c); - if (item != NULL) - { - item->read_from(*_msk); - _item.insert(item, i); - - TToken_string s(128); item->print_on(s); - a.insert(s, i); - dirty = TRUE; - } - } - } else error_box("L'inserimento e' disabilitato"); + _msk->set_mode(MODE_INS); + if (dummy.edit(*_msk)) + { + const TString& c = _msk->get(F_CLASS).left(2); + TForm_item* item = parse_item(c); + if (item != NULL) + { + item->read_from(*_msk); + _item.insert(item, i); + + TToken_string s(128); item->print_on(s); + a.insert(s, i); + dirty = TRUE; + } + } break; - case K_DEL: - if (all && yesno_box("Confermare la cancellazione")) + case K_DEL: + if (it.has_remove_permission()) + warning_box("Non e' possibile cancellare questo campo"); + else if (yesno_box("Confermare la cancellazione")) { _item.destroy(i, TRUE); a.destroy(i); dirty = TRUE; - } else error_box("La cancellazione e' disabilitata"); + } break; default: break; @@ -1147,14 +1449,32 @@ bool TForm::parse_use(TScanner& scanner) tab = scanner.pop(); _relation = new TRelation(tab); } - + int key = 1; if (scanner.popkey() == "KE") key = scanner.integer(); else scanner.push(); - _cursor = new TCursor(_relation, "", key); + TString tok = scanner.pop(); + if (tok == "DESCR") + tok = scanner.string(); + else if (tok != "NODESCR") + { + scanner.push(); + tok = ""; + } + + _cursor = new TCursor(_relation, "", key); + + if (!tok.empty()) + { + if (tok == "NODESCR") + _relation->set_description(NULL); + else + _relation->set_description(tok); + } + return TRUE; } @@ -1194,15 +1514,72 @@ bool TForm::parse_join(TScanner& scanner) if (exp.empty()) yesnofatal_box("JOIN senza espressioni INTO"); scanner.push(); - + + TString tok = scanner.pop(); + if (tok == "DESCR") + tok = scanner.string(); + else if (tok != "NODESCR") + { + scanner.push(); + tok = ""; + } + if (isdigit(j[0])) _relation->add(atoi(j), exp, key, to, alias); // join file else _relation->add(j, exp, key, to, alias); // join table + + if (!tok.empty()) + { + if (tok == "NODESCR") + // remove description + _relation->set_description(NULL, _relation->items()-1); + else + // change description + _relation->set_description(tok, _relation->items()-1); + } + + return TRUE; +} + +bool TForm::parse_permissions(TScanner& scanner) +{ + TString16 s; + scanner.popkey(); // eat BEGIN + + memset(_permissions, 'X', 8); + _permissions[8] = '\0'; // solo per leggerlo col debuggerator + + while ((s = scanner.pop()) != "END") + { + if (s == "ADD") _permissions[0] = 'A'; + else if (s == "REMOVE") _permissions[1] = 'R'; + else if (s == "MODIFY") _permissions[2] = 'M'; + else if (s == "RELATION") _permissions[3] = 'L'; + else return FALSE; + } return TRUE; } +bool TForm::parse_descfield(TScanner& scanner) +{ + scanner.popkey(); // eat BEGIN + + while (scanner.pop() != "END") + { + TString16 fld = scanner.token(); + TString16 fil = scanner.pop(); + TString des = scanner.string(); + + if (atoi(fil) == 0) + reldef()->set_field_description(fil, fld, des); + else + reldef()->set_field_description(atoi(fil), fld, des); + } + + return TRUE; +} TPrint_section* TForm::exist(char s, pagetype t, bool create) { @@ -1435,6 +1812,15 @@ void TForm::print_on(ostream& out) const if (relation()) out << *relation() << "\nEND" << endl; + out << "PERMISSIONS\nBEGIN\n"; + + if (has_add_permission()) out << " ADD" << endl; + if (has_remove_permission()) out << " REMOVE" << endl; + if (has_modify_permission()) out << " MODIFY" << endl; + if (has_relation_permission()) out << " RELATION" << endl; + + out << "END\n"; + print_section(out, 'G'); print_section(out, 'H'); print_section(out, 'B'); @@ -1466,8 +1852,8 @@ word TForm::height() } -TForm::TForm(const char* name) -: _name(name), _relation(NULL), _cursor(NULL) +TForm::TForm(const char* name, bool is_base) +: _name(name), _relation(NULL), _cursor(NULL), _reldef(NULL), _isbase(is_base) { main_app().begin_wait(); @@ -1479,8 +1865,19 @@ TForm::TForm(const char* name) { ok = parse_use(scanner); while (ok && scanner.popkey() == "JO") - ok = parse_join(scanner); + ok = parse_join(scanner); + + // build descriptions + _reldef = new TRelation_description(*_relation); } + else scanner.push(); + + if (scanner.popkey() == "DE") // DESCFIELD + ok = parse_descfield(scanner); + else scanner.push(); + + if (scanner.popkey() == "PE") // PERMISSIONS + ok = parse_permissions(scanner); else scanner.push(); while (ok) @@ -1493,6 +1890,11 @@ TForm::TForm(const char* name) ok = ps->parse(scanner); // Parse section } + if (!has_add_permission()) + { + // TBI lascia solo la descrizione dei campi gia' utilizzati + } + main_app().end_wait(); } @@ -1502,6 +1904,7 @@ TForm::~TForm() if (_cursor) { delete _cursor; - delete _relation; + delete _relation; + delete _reldef; } } diff --git a/include/form.h b/include/form.h index bfec41068..6dff54b16 100755 --- a/include/form.h +++ b/include/form.h @@ -15,6 +15,7 @@ class TMask; #ifndef __RELATION_H class TRelation; +class TRelation_description; class TCursor; #endif @@ -74,18 +75,21 @@ class TForm : public TObject TRelation* _relation; // Can be NULL TCursor* _cursor; // Can be NULL + TRelation_description* _reldef; // pure TArray _head; // Headers TArray _body; // Bodies TArray _foot; // Footers TArray _back; // Graphic background - - bool _lastpage; // I am about to print the last page + + char _permissions[9]; // user permissions + bool _lastpage; // I am about to print the last page + bool _isbase; // base form (.frm file) TPrint_section* exist(char s, pagetype t, bool create = FALSE); // Can be NULL static void header_handler(TPrinter& p); - static void footer_handler(TPrinter& p); + static void footer_handler(TPrinter& p); protected: // H = Header, B = Body, F = Footer, R = Relation @@ -98,6 +102,8 @@ protected: bool parse_use(TScanner&); bool parse_join(TScanner&); + bool parse_permissions(TScanner&); + bool parse_descfield(TScanner&); word page(const TPrinter& p) const; @@ -107,16 +113,24 @@ protected: virtual word set_body(word p, bool u); virtual word set_footer(word p, bool u); -public: +public: + + bool has_add_permission() const { return _permissions[0] == 'A'; } + bool has_remove_permission() const { return _permissions[1] == 'R'; } + bool has_modify_permission() const { return _permissions[2] == 'M'; } + bool has_relation_permission() const { return _permissions[3] == 'L'; } + bool print(long from = 0L, long to = -1L); const TFilename& name() const { return _name; } TRelation* relation() const { return _relation; } + TRelation_description* reldef() const { return _reldef; } + TCursor* cursor() const { return _cursor; } virtual const char* validate(const char* cur, TToken_string& val); - TForm(const char* form); + TForm(const char* form, bool base = FALSE); virtual ~TForm(); }; diff --git a/include/isam.cpp b/include/isam.cpp index 895c66b60..f6b2fb4d1 100755 --- a/include/isam.cpp +++ b/include/isam.cpp @@ -1846,7 +1846,7 @@ void TRectype::put(const char* fieldname, const TDate& val) { // NOT_LINKED(_i, "put"); TRecfield f(*this, fieldname); - f = val.string(4); + f = val.string(full); setempty(FALSE); } @@ -2046,7 +2046,7 @@ HIDDEN void __getfieldbuff(byte l, byte t, const char* recin, char *s) if (t == _datefld && *s) { TDate dt(atol(s)); - strcpy(s, dt.string(4)); + strcpy(s, dt.string(full)); } } diff --git a/include/lffiles.h b/include/lffiles.h index d056be02d..8c60250c3 100755 --- a/include/lffiles.h +++ b/include/lffiles.h @@ -50,6 +50,7 @@ #define LF_DIPEND 45 #define LF_DETH 46 #define LF_PROF 50 +#define LF_FORMS 54 #define CNF_GENERAL 10000 #define CNF_STUDIO CNF_GENERAL + 1 diff --git a/include/printapp.cpp b/include/printapp.cpp index 024ae129c..a86fd380d 100755 --- a/include/printapp.cpp +++ b/include/printapp.cpp @@ -1,4 +1,4 @@ -// $Id: printapp.cpp,v 1.24 1995-05-05 09:15:02 pirro Exp $ +// $Id: printapp.cpp,v 1.25 1995-05-09 09:12:14 villa Exp $ #include #include @@ -1039,7 +1039,7 @@ bool TPrint_application::print_one (int file) else if (ft->_flags & DATE_FLAG) { const TDate d(f.get(fn)); - toprint = d.string (ft->_flags & LONG_FLAG ? 4 : 2); + toprint = d.string (ft->_flags & LONG_FLAG ? full : brief); if (toprint.empty ()) { toprint = (ft->_flags & LONG_FLAG ? diff --git a/include/printer.cpp b/include/printer.cpp index 9b0c03114..57ce49c28 100755 --- a/include/printer.cpp +++ b/include/printer.cpp @@ -967,10 +967,10 @@ bool TPrinter::printrow(TPrintrow* rowtoprint) rw.overwrite (format("%-5u", _currentpage), idx++); break; case '>': - rw.overwrite (_date.string (4), idx++); + rw.overwrite (_date.string (full), idx++); break; case '<': - rw.overwrite (_date.string (2), idx++); + rw.overwrite (_date.string (brief), idx++); break; default: break; diff --git a/include/relation.cpp b/include/relation.cpp index 568bf5b0d..90f28da46 100755 --- a/include/relation.cpp +++ b/include/relation.cpp @@ -1,4 +1,4 @@ -// $Id: relation.cpp,v 1.39 1995-04-20 14:34:26 guy Exp $ +// $Id: relation.cpp,v 1.40 1995-05-09 09:12:24 villa Exp $ // relation.cpp // fv 12/8/93 // relation class for isam files @@ -15,6 +15,7 @@ #include #include #include +#include // *** check if not already defined #define NOTFOUND (-1) @@ -24,6 +25,25 @@ #define print_name(out, f) out << (f.num() == LF_TABCOM ? "%" : "") << f.name() +HIDDEN const char* field_type_str(TFieldtypes f) +{ + const char* c = ""; + switch(f) + { + case _realfld: c = "Reale"; break; + case _datefld: c = "Data"; break; + case _charfld: c = "Carattere"; break; + case _boolfld: c = "Logico"; break; + case _wordfld: + case _intzerofld: + case _longzerofld: + case _intfld: + case _longfld: c = "Intero"; break; + default: break; + } + return c; +} + /////////////////////////////////////////////////////////// // TRelationdef /////////////////////////////////////////////////////////// @@ -42,6 +62,7 @@ class TRelationdef : public TObject TArray _exprs; // Condizioni di uguaglianza TArray _altexprs; // Condizioni di uguaglianza alternative TBit_array _forced; + TString _description; bool _first_match : 1; // primo match (ed esiste) bool _allow_lock : 1; // ????? bool _write_enable : 1; @@ -59,6 +80,7 @@ public: void write_enable(bool we) { _write_enable = we; } TRectype& load_rec(TRectype& r, const TBaseisamfile& from) const; const char* evaluate_expr(int j, const TLocalisamfile& to); + void set_description(const char* s) { _description = s; } TRelationdef(const TRelation* rel, int file, byte key, int linkto, const char* relexprs, int alias, @@ -85,7 +107,7 @@ TRelationdef::TRelationdef(const TRelation* rel, int idx_file, byte key, r = g; int eq = r.find('='); - CHECKS(eq > 0, "Ahoo! E l'uguale 'ndo sta'? ", (const char*)g); + CHECKS(eq > 0, "Ahoo! E l'uguale 'ndo sta? ", (const char*)g); s = r.left(eq); // Parte a sinistra dell' = @@ -118,7 +140,19 @@ TRelationdef::TRelationdef(const TRelation* rel, int idx_file, byte key, } else _exprs.add(new TExpression(s, _strexpr), i); - } + } + + // add description + TString16 name = _rel->file(_num).name(); + + if (_rel->file(_num).tab()) + { + // tabella + TDir dir; + dir.get(TTable::name2log(name), _nolock, _nordir, _sysdirop); + _description = dir.tab_des(name); + } + else _description = prefix().description(name); } @@ -163,7 +197,7 @@ void TRelationdef::print_on(TToken_string& out) const out = ""; print_name(out, f); - out.add(prefix().description(f.name())); + out.add(_description); out << '|'; if (_numto > 0) @@ -240,6 +274,13 @@ TRelation::TRelation(TLocalisamfile* f) TRelation::~TRelation() {} +void TRelation::set_description(const char* d, int index) +{ + if (index == -1) _main_desc = d == NULL ? "" : d; + else reldef(index)._description = d == NULL ? "" : d; +} + + void TRelation::print_on(ostream& out) const { const TLocalisamfile& f = file(); @@ -259,7 +300,16 @@ void TRelation::print_on(TArray& a) const const TLocalisamfile& f = file(); TToken_string s(128); print_name(s, f); - s.add(prefix().description(f.name())); + + if (f.tab()) + { + // tabella + TDir dir; + dir.get(TTable::name2log(f.name()), _nolock, _nordir, _sysdirop); + s.add(dir.tab_des(f.name())); + } + else s.add(prefix().description(f.name())); + s.add(""); s.add(f.getkey()); s.add(" | "); @@ -529,7 +579,7 @@ bool TRelation::next_match(int logicnum, const char* fieldlist, int nkey) reldef(j)._first_match = FALSE; if (from.bad()) - return FALSE; // && vaffanculo() + return FALSE; // && vaffanculo(); const TRecnotype last = from.recno(); @@ -1480,6 +1530,243 @@ int TRecord_array::remove() return rewrite(); } +// TRelation_description + +void TRelation_description::read_rel() +{ + int which_file; + + // scan files and build description arrays + _rel->print_on(_files); + + for (int i = 0; i < _files.items(); i++) + { + TToken_string& tt = (TToken_string&)_files[i]; + TString descfname(36); + descfname << DESCDIR << "/d"; + + TString tn(tt.get(0)); + if (tn[0] == '%' || tn[0] == '$') + descfname << tn.mid(1); + else descfname << tn; + descfname << ".des"; + + if ((which_file = atoi(tn)) == 0) + which_file = TTable::name2log(tn); + + if (fexist(descfname)) + { + TConfig conf(descfname, DESCPAR); + // new record descriptor for _fields array + TString_array* rdesc = new TString_array; + + TTrec trec; trec.get(which_file); + TToken_string ttmp(64); + + for (int f = 0; f < trec.fields(); f++) + { + ttmp = trec.fielddef(f); + TString16 name = ttmp.get(0); + TString80 dfld; + + if (!name.blank()) + { + dfld = conf.get(name); + if (!dfld.blank() && dfld[0] != '#') + { + ttmp.add(dfld,4); + // contiene: nome campo, tipo, lunghezza, + // decimali, descrizione + rdesc->add(ttmp); + } + } + } + if (rdesc->items() > 0) _fields.add(rdesc); + else + { + _files.destroy(i); + delete rdesc; + } + } + else _files.destroy(i); + } + + _files.pack(); +} + +bool TRelation_description::choose_file (int file) +{ + TArray_sheet sht(-1,-1,0,0,"Selezione archivio", "Descrizione archivio@70"); + TToken_string tt(80); + + for (int i = 0; i < _files.items(); i++) + { + TToken_string& tf = _files.row(i); + tt = tf.get(1); tt.cut(70); + sht.add(tt); + } + if (sht.run() == K_ENTER) + { + _cur_file = (int)sht.selected(); + _cfile = _files.row(_cur_file); + return TRUE; + } + return FALSE; +} + +bool TRelation_description::choose_field(const char* fld) +{ + TArray_sheet sht(-1,-1,0,0,"Selezione campo", + "Descrizione campo@50|Tipo@10|Dim."); + TString_array& fd = (TString_array&)_fields[_cur_file]; + TToken_string tt(80); + + for (int i = 0; i < fd.items(); i++) + { + TToken_string& tf = fd.row(i); + tt = tf.get(4); tt.cut(50); + tt.add(field_type_str((TFieldtypes)tf.get_int(1))); + tt.add(tf.get(2)); + sht.add(tt); + } + if (sht.run() == K_ENTER) + { + _cur_field = (int)sht.selected(); + _cfield = fd.row(_cur_field); + return TRUE; + } + return FALSE; +} + +bool TRelation_description::build_menu(const char* title) +{ + return FALSE; +} + +bool TRelation_description::remove_menu() +{ + return FALSE; +} + +bool TRelation_description::is_table() +{ + return _cfile.get_int(0) == 0; +} + +int TRelation_description::file() +{ + return _cfile.get_int(0); +} + +const char* TRelation_description::table() +{ + return _cfile.get(0); +} + +const char* TRelation_description::file_desc() +{ + return _cfile.get(1); +} + +const char* TRelation_description::field_desc() +{ + return _cfield.get(4); +} + +const char* TRelation_description::field() +{ + return _cfield.get(0); +} + +int TRelation_description::field_len() +{ + return _cfield.get_int(2); +} + +TFieldtypes TRelation_description::field_type() +{ + return (TFieldtypes)_cfield.get_int(1); +} + +bool TRelation_description::set_field_description(int id, const char* field, const char* des) +{ + for (int i = 0; i < _files.items(); i++) + { + TToken_string& tt = _files.row(i); + if (tt.get_int(0) == id || tt.get_int(4) == id) + break; + } + if (i == _files.items()) return FALSE; + + TString_array& fld = (TString_array&)_fields[i]; + + for (i = 0; i < fld.items(); i++) + { + TToken_string& tt = fld.row(i); + if (strcmp(tt.get(0),field) == 0) + { + if (*des) tt.add(des,4); + else + { + fld.destroy(i); + fld.pack(); + } + break; + } + } + + return i < fld.items(); +} + +bool TRelation_description::set_field_description(const char* id, const char* field, const char* des) +{ + for (int i = 0; i < _files.items(); i++) + { + TToken_string& tt = _files.row(i); + if (tt.get(0) == id) + break; + } + if (i == _files.items()) return FALSE; + + TString_array& fld = (TString_array&)_fields[i]; + + for (i = 0; i < fld.items(); i++) + { + TToken_string& tt = fld.row(i); + if (strcmp(tt.get(0),field) == 0) + { + if (*des) tt.add(des,4); + else + { + fld.destroy(i); + fld.pack(); + } + break; + } + } + + return i < fld.items(); +} + + +TRelation_description::TRelation_description(TRelation& r) : +_rel(&r), _menu(FALSE), _cur_file(0), _cur_field(0), +_cfile(80), _cfield(80) +{ + read_rel(); + + if (_files.items() > 0) + { + _cfile = _files.row(0); + _cfield = ((TString_array&)_fields[0]).row(0); + } +} + +TRelation_description::~TRelation_description() +{ + if (_menu) remove_menu(); +} + + // *** EOF relation.cpp - diff --git a/include/relation.h b/include/relation.h index 2468f9452..5e142dbde 100755 --- a/include/relation.h +++ b/include/relation.h @@ -1,4 +1,4 @@ -/* $Id: relation.h,v 1.16 1995-04-18 11:03:46 alex Exp $ */ +/* $Id: relation.h,v 1.17 1995-05-09 09:12:26 villa Exp $ */ // join.h // fv 12/8/93 // join class for isam files @@ -15,14 +15,17 @@ class TRelation : public TObject { friend class TRelationdef; + friend class TRelation_description; + friend class TCursor; // class TRelation : public TLocalisamfile // @END // @DPRIV TToken_string _status; // stato della relazione - TArray _files; // file descriptors - TArray _reldefs; // TRelationdef array + TString _main_desc; // descrizione file principale + TArray _files; // file descriptors + TArray _reldefs; // TRelationdef array int _errors; // @END @@ -44,7 +47,6 @@ protected: // @END int position_rels(TIsamop op = _isequal, TReclock lockop = _nolock, TDate& atdate = (TDate&)botime, int first = 0); - friend class TCursor; public: // @FPUB @@ -121,6 +123,13 @@ public: // position_rels) bool is_first_match(int logicnum); + // items() ritorna il numero di files collegati + int items() { return _reldefs.items(); } + + // set_description modifica la descrizione del file passato (per indice) + // o del principale + void set_description(const char* d, int index = -1); + void save_status () ; void restore_status () ; @@ -311,8 +320,63 @@ public: const char* read(const TRectype&) const; void write(const char* val, TRelation* = NULL) const; void write(const char* val, TRectype& rec) const; -}; +}; + // Converte una stringa in numero logico o numero tabella int name2log(const char* name); + +class TRelation_description : public TObject +{ + // gestisce l'uso interattivo di una relazione (scelta campi, descrizione) + // domani o doman l'altro gestira' l'editing interattivo e grafico + + TRelation* _rel; + TString_array _files; + TArray _fields; + int _cur_file; + int _cur_field; + bool _menu; + TToken_string _cfile, _cfield; + + void read_rel(); + +public: + + // "choose" interface: after choosing a field (must return TRUE) + // methods allow to know all data concerning the field + // parameters set the one initially selected + bool choose_file (int file = -1); + + // file must have been chosen: first file in list if called + // before choose_file + bool choose_field(const char* fld = ""); + + // if wanted, build a menu tree and set current field upon + // selecting it (should be popup) + bool build_menu(const char* title = "Database"); + bool remove_menu(); + + bool set_field_description(int id, const char* field, const char* des); + bool set_field_description(const char* tab, const char* field, const char* des); + + // if choose_field == TRUE or menu has been used + // these return valid data + bool is_table(); + int file(); + const char* table(); + const char* field(); + const char* file_desc(); + const char* field_desc(); + const char* field_name(); + int field_len(); + TFieldtypes field_type(); + + virtual bool ok() { return _files.items() > 0; } + + TRelation_description(TRelation& r); + virtual ~TRelation_description(); +}; + + #endif // ** EOF relation.h