curses++.h

00001 // curses++.h  (this is -*-c++-*-)
00002 //
00003 //  Copyright 1999-2005, 2007 Daniel Burrows
00004 //
00005 //  This program is free software; you can redistribute it and/or modify
00006 //  it under the terms of the GNU General Public License as published by
00007 //  the Free Software Foundation; either version 2 of the License, or
00008 //  (at your option) any later version.
00009 //
00010 //  This program is distributed in the hope that it will be useful,
00011 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 //  GNU General Public License for more details.
00014 //
00015 //  You should have received a copy of the GNU General Public License
00016 //  along with this program; see the file COPYING.  If not, write to
00017 //  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018 //  Boston, MA 02111-1307, USA.
00019 //
00020 //  Simple class wrappers around various CURSES functions.
00021 
00022 #ifndef CURSES_PLUSPLUS_H
00023 #define CURSES_PLUSPLUS_H
00024 
00025 #include <string>
00026 #define _XOPEN_SOURCE_EXTENDED
00027 #include <ncursesw/curses.h>
00028 #undef _XOPEN_SOURCE_EXTENDED
00029 
00030 #include <cwidget/generic/util/eassert.h>
00031 
00032 // For isspace
00033 #include <ctype.h>
00034 
00035 #include <string.h>
00036 
00037 #include <cwidget-config.h>
00038 
00039 namespace cwidget
00040 {
00049   struct wchtype
00050   {
00056     wchar_t ch;
00057 
00061     attr_t attrs;
00062 
00063     wchtype()
00064     {
00065     }
00066 
00067     wchtype(const wchar_t &_ch, const attr_t &_attrs)
00068       :ch(_ch), attrs(_attrs)
00069     {
00070     }
00071 
00072     bool operator==(const wchtype &other) const
00073     {
00074       return ch==other.ch && attrs==other.attrs;
00075     }
00076 
00077     bool operator!=(const wchtype &other) const
00078     {
00079       return ch!=other.ch || attrs!=other.attrs;
00080     }
00081 
00082     bool operator<(const wchtype &other) const
00083     {
00084       return ch<other.ch || (ch==other.ch && attrs<other.attrs);
00085     }
00086 
00087     bool operator<=(const wchtype &other) const
00088     {
00089       return (*this) == other || (*this) < other;
00090     }
00091 
00092     bool operator>(const wchtype &other) const
00093     {
00094       return !((*this)<=other);
00095     }
00096 
00097     bool operator>=(const wchtype &other) const
00098     {
00099       return !((*this)<other);
00100     }
00101   };
00102 }
00103 
00104 namespace std {
00105   template <>
00115   struct TRAITS_CLASS<chtype> {
00116     typedef chtype char_type;
00117 
00118     static void assign (char_type& c1, const char_type& c2)
00119     { c1 = c2; }
00120     static bool eq (const char_type & c1, const char_type& c2)
00121     { return (c1 == c2); }
00122     static bool ne (const char_type& c1, const char_type& c2)
00123     { return (c1 != c2); }
00124     static bool lt (const char_type& c1, const char_type& c2)
00125     { return (c1 < c2); }
00126     static char_type eos () { return 0; }
00127     static bool is_del(char_type a) { return isspace(a|A_CHARTEXT); }
00128 
00129     static int compare (const char_type* s1, const char_type* s2, size_t n);
00130     static size_t length (const char_type* s);
00131     static char_type* copy (char_type* s1, const char_type* s2, size_t n)
00132     { return (char_type*) memcpy (s1, s2, n*sizeof(char_type)); }
00133     static char_type* move (char_type* s1, const char_type* s2, size_t n)
00134     { return (char_type*) memmove (s1, s2, n*sizeof(char_type)); }
00135     static char_type* assign (char_type* s1, size_t n, const char_type& c);
00136   };
00137 
00138   template <>
00139   struct TRAITS_CLASS<cwidget::wchtype> {
00140     typedef cwidget::wchtype char_type;
00141 
00142     static void assign (char_type& c1, const char_type& c2)
00143     { c1 = c2; }
00144     static bool eq (const char_type & c1, const char_type& c2)
00145     { return (c1 == c2); }
00146     static bool ne (const char_type& c1, const char_type& c2)
00147     { return (c1 != c2); }
00148     static bool lt (const char_type& c1, const char_type& c2)
00149     { return (c1 < c2); }
00150     static char_type eos () { return cwidget::wchtype(0,0); }
00151     static bool is_del(char_type a) { return isspace(a.ch); }
00152 
00153     static int compare (const char_type* s1, const char_type* s2, size_t n);
00154     static size_t length (const char_type* s);
00155     static char_type* copy (char_type* s1, const char_type* s2, size_t n)
00156     { return (char_type*) memcpy (s1, s2, n*sizeof(char_type)); }
00157     static char_type* move (char_type* s1, const char_type* s2, size_t n)
00158     { return (char_type*) memmove (s1, s2, n*sizeof(char_type)); }
00159     static char_type* assign (char_type* s1, size_t n, const char_type& c);
00160   };
00161 }
00162 
00163 namespace cwidget
00164 {
00165   class style;
00166 
00172   class chstring:public std::basic_string<chtype>
00173   {
00174     typedef std::basic_string<chtype> super;
00175   public:
00176     chstring(const std::basic_string<chtype> &s)
00177       :std::basic_string<chtype>(s) {}
00178 
00179     chstring(const std::string &s);
00180     chstring(const std::string &s, const style &st);
00181 
00182     chstring(const chstring &s):super(s) {}
00186     chstring(const chstring &s, const style &st);
00187 
00188     chstring(const chstring &s, size_t loc, size_t n=npos)
00189       :super(s, loc, n) {}
00190 
00191     chstring(size_t n, chtype c)
00192       :super(n, c) {}
00193 
00195     chstring &operator=(const std::string &s);
00196 
00198     void apply_style(const style &st);
00199   };
00200 
00201   class wchstring:public std::basic_string<wchtype>
00202   {
00203     typedef std::basic_string<wchtype> super;
00204   public:
00205     wchstring(const std::basic_string<wchtype> &s)
00206       :std::basic_string<wchtype>(s) {}
00207 
00209     wchstring(const std::wstring &s);
00210 
00214     wchstring(const std::wstring &s, const style &st);
00215 
00216     wchstring(const wchstring &s):super(s) {}
00220     wchstring(const wchstring &s, const style &st);
00221 
00222     wchstring(const wchstring &s, size_t loc, size_t n=npos)
00223       :super(s, loc, n) {}
00224 
00225     wchstring(size_t n, wchtype c)
00226       :super(n, c) {}
00227 
00228     wchstring(size_t n, wchar_t c, attr_t a)
00229       :super(n, wchtype(c, a)) {}
00230 
00232     void apply_style(const style &st);
00233 
00235     int width() const;
00236   };
00237 
00238   inline chtype _getbkgd(WINDOW *win)
00239   {
00240     return getbkgd(win);
00241   }
00242 
00243   inline int _box(WINDOW *win, chtype verch, chtype horch)
00244   {
00245     return box(win, verch, horch);
00246   }
00247 
00248   inline void _getyx(WINDOW *win, int &y, int &x)
00249   {
00250     getyx(win, y, x);
00251   }
00252 
00253   inline void _getparyx(WINDOW *win, int &y, int &x)
00254   {
00255     getparyx(win, y, x);
00256   }
00257 
00258   inline void _getbegyx(WINDOW *win, int &y, int &x)
00259   {
00260     getbegyx(win, y, x);
00261   }
00262 
00263   inline void _getmaxyx(WINDOW *win, int &y, int &x)
00264   {
00265     getmaxyx(win, y, x);
00266   }
00267 
00268   inline int _getmaxy(WINDOW *win)
00269   {
00270     return getmaxy(win);
00271   }
00272 
00273   inline int _getmaxx(WINDOW *win)
00274   {
00275     return getmaxx(win);
00276   }
00277 
00278   inline int _touchwin(WINDOW *win)
00279   {
00280     return touchwin(win);
00281   }
00282 
00283   inline int _untouchwin(WINDOW *win)
00284   {
00285     return untouchwin(win);
00286   }
00287 
00288 #undef getbkgd
00289 #undef box
00290 
00291 #undef getyx
00292 #undef getparyx
00293 #undef getbegyx
00294 #undef getmaxyx
00295 #undef getmaxy
00296 #undef getmaxx
00297 
00298 #undef addch
00299 #undef addchnstr
00300 #undef addchstr
00301 #undef add_wch
00302 #undef addnstr
00303 #undef addstr
00304 #undef attroff
00305 #undef attron
00306 #undef attrset
00307 #undef attr_set
00308 #undef bkgd
00309 #undef bkgdset
00310 #undef clear
00311 #undef clrtobot
00312 #undef clrtoeol
00313 #undef delch
00314 #undef deleteln
00315 #undef echochar
00316 #undef erase
00317 #undef getch
00318 #undef get_wch
00319 #undef getstr
00320 #undef inch
00321 #undef inchnstr
00322 #undef innstr
00323 #undef insch
00324 #undef insdelln
00325 #undef insertln
00326 #undef insnstr
00327 #undef insstr
00328 #undef instr
00329 #undef move
00330 #undef refresh
00331 #undef scrl
00332 #undef scroll
00333 #undef setscrreg
00334 #undef standend
00335 #undef standout
00336 #undef timeout
00337 
00338 #undef mvaddch
00339 #undef mvadd_wch
00340 #undef mvaddchnstr
00341 #undef mvaddchstr
00342 #undef mvaddnstr
00343 #undef mvaddstr
00344 #undef mvdelch
00345 #undef mvgetch
00346 #undef mvget_wch
00347 #undef mvgetnstr
00348 #undef mvgetstr
00349 #undef mvhline
00350 #undef mvinch
00351 #undef mvinchnstr
00352 #undef mvinchstr
00353 #undef mvinnstr
00354 #undef mvinsch
00355 #undef mvinsnstr
00356 #undef mvinsstr
00357 #undef mvinstr
00358 #undef mvvline
00359 
00360 #undef border
00361 #undef hline
00362 #undef vline
00363 
00364 #undef touchline
00365 
00366   //  The following class encapsulates a CURSES window, mostly with inlined
00367   // versions of w* and mvw*.  subwin and newwin are encapsulated with
00368   // constructors; casting to WINDOW * is also supported.
00369   //
00370   //  er, these will be inlined.  Right?
00371   class cwindow
00372   {
00373     // Blech.  Used to memory-manage WINDOW *s
00374     class cwindow_master
00375     {
00376       WINDOW *win;
00377       int refs;
00378       cwindow_master *parent;
00379 
00380       friend class cwindow;
00381 
00382       ~cwindow_master()
00383       {
00384         eassert(refs==0);
00385 
00386         if(win)
00387           delwin(win);
00388         if(parent)
00389           parent->deref();
00390       }
00391     public:
00392       cwindow_master(WINDOW *_win, cwindow_master *_parent)
00393         :win(_win), refs(0), parent(_parent)
00394       {
00395         if(parent)
00396           parent->ref();
00397       }
00398 
00399       inline void ref()
00400       {
00401         refs++;
00402       }
00403 
00404       // ??????
00405       inline void deref()
00406       {
00407         refs--;
00408 
00409         if(refs==0)
00410           delete this;
00411       }
00412     };
00413 
00414     WINDOW *win;
00415     // The actual curses window
00416 
00417     cwindow_master *master;
00418     // Keeps track of where we got this from (so we can deref() it later)
00419 
00420     cwindow(WINDOW *_win, cwindow_master *_master)
00421       :win(_win), master(_master)
00422     {
00423       master->ref();
00424     }
00425   public:
00426     cwindow(WINDOW *_win):win(_win), master(new cwindow_master(_win, NULL))
00427     {
00428       master->ref();
00429     }
00430     cwindow(const cwindow &a):win(a.win), master(a.master)
00431     {
00432       master->ref();
00433     }
00434 
00435     ~cwindow()
00436     {
00437       master->deref();
00438     }
00439 
00440     cwindow derwin(int h, int w, int y, int x)
00441     {
00442       WINDOW *new_win=::derwin(win, h, w, y, x);
00443       return cwindow(new_win, new cwindow_master(new_win, master));
00444     }
00445 
00446     int mvwin(int y, int x) {return ::mvwin(win, y, x);}
00447 
00448     void syncup() {wsyncup(win);}
00449     int syncok(bool bf) {return ::syncok(win, bf);}
00450     void cursyncup() {wcursyncup(win);}
00451     void syncdown() {wsyncdown(win);}
00452 
00453     int scroll(int n=1) {return wscrl(win, n);}
00454     // Does both scroll() and wscsrl()
00455 
00456     int addch(chtype ch) {return waddch(win, ch);}
00457     int mvaddch(int y, int x, chtype ch) {return mvwaddch(win, y, x, ch);}
00458 
00459     int add_wch(wchar_t wch)
00460     {
00461       wchar_t tmp[2];
00462       tmp[0]=wch;
00463       tmp[1]=0;
00464 
00465       cchar_t cch;
00466       if(setcchar(&cch, tmp, 0, 0, 0)==ERR)
00467         return ERR;
00468       else
00469         return wadd_wch(win, &cch);
00470     }
00471 
00472     int mvadd_wch(int y, int x, wchar_t wch)
00473     {
00474       move(y, x);
00475       return add_wch(wch);
00476     }
00477 
00478     int add_wch(const cchar_t *cch)
00479     {
00480       return wadd_wch(win, cch);
00481     }
00482 
00483     int mvadd_wch(int y, int x, const cchar_t *cch)
00484     {
00485       return mvwadd_wch(win, y, x, cch);
00486     }
00487 
00488     int addstr(const std::wstring &str) {return addstr(str.c_str());}
00489     int addnstr(const std::wstring &str, int n) {return addnstr(str.c_str(), n);}
00490     int mvaddstr(int y, int x, const std::wstring &str) {return mvaddstr(y, x, str.c_str());}
00491     int mvaddnstr(int y, int x, const std::wstring &str, int n) {return mvaddnstr(y, x, str.c_str(), n);}
00492 
00493     int addstr(const wchar_t *str) {return waddwstr(win, str);}
00494     int addnstr(const wchar_t *str, int n) {return waddnwstr(win, str, n);}
00495     int mvaddstr(int y, int x, const wchar_t *str) {return mvwaddwstr(win, y, x, str);}
00496     int mvaddnstr(int y, int x, const wchar_t *str, int n) {return mvwaddnwstr(win, y, x, str, n);}
00497 
00498     int addstr(const char *str) {return waddstr(win, str);}
00499     int addnstr(const char *str, int n) {return waddnstr(win, str, n);}
00500     int mvaddstr(int y, int x, const char *str) {return mvwaddstr(win, y, x, str);}
00501     int mvaddnstr(int y, int x, const char *str, int n) {return mvwaddnstr(win, y, x, str, n);}
00502 
00503     // The following are implemented hackily due to the weirdness of
00504     // curses.  NB: they don't work with characters of negative width.
00505     int addstr(const wchstring &str);
00506     int addnstr(const wchstring &str, size_t n);
00507     int mvaddstr(int y, int x, const wchstring &str);
00508     int mvaddnstr(int y, int x, const wchstring &str, size_t n);
00509 
00510     int addstr(const chstring &str) {return waddchstr(win, str.c_str());}
00511     int addnstr(const chstring &str, int n) {return waddchnstr(win, str.c_str(), n);}
00512     int mvaddstr(int y, int x, const chstring &str) {return mvwaddchstr(win, y, x, str.c_str());}
00513     int mvaddnstr(int y, int x, const chstring &str, int n) {return mvwaddchnstr(win, y, x, str.c_str(), n);}
00514 
00515     int attroff(int attrs) {return wattroff(win, attrs);}
00516     int attron(int attrs) {return wattron(win, attrs);}
00517     int attrset(int attrs) {return wattrset(win, attrs);}
00518     //  int attr_set(int attrs, void *opts) {return wattr_set(win, attrs, opts);}
00519 
00520     void bkgdset(const chtype ch) {wbkgdset(win, ch);}
00521     int bkgd(const chtype ch) {return wbkgd(win, ch);}
00522     chtype getbkgd() {return _getbkgd(win);}
00523 
00524     int border(chtype ls, chtype rs, chtype ts, chtype bs, chtype tl, chtype tr, chtype bl, chtype br)
00525     {return wborder(win, ls, rs, ts, bs, tl, tr, bl, br);}
00526 
00527     int box(chtype verch, chtype horch) {return _box(win, verch, horch);}
00528     int hline(chtype ch, int n) {return whline(win, ch, n);}
00529     int vline(chtype ch, int n) {return wvline(win, ch, n);}
00530     int mvhline(int y, int x, chtype ch, int n) {return mvwhline(win, y, x, ch, n);}
00531     int mvvline(int y, int x, chtype ch, int n) {return mvwvline(win, y, x, ch, n);}
00532 
00533     int delch() {return wdelch(win);}
00534     int mvdelch(int y, int x) {return mvwdelch(win, y, x);}
00535 
00536     int deleteln() {return wdeleteln(win);}
00537     int insdelln(int n) {return winsdelln(win,n);}
00538     int insertln() {return winsertln(win);}
00539 
00540     int echochar(chtype ch) {return wechochar(win, ch);}
00541 
00542     int getch() {return wgetch(win);}
00543     int mvgetch(int y, int x) {return mvwgetch(win, y, x);}
00544 
00545     int get_wch(wint_t *wch) {return wget_wch(win, wch);}
00546     int mvget_wch(int y, int x, wint_t *wch) {return mvwget_wch(win, y, x, wch);}
00547 
00548     int move(int y, int x) {return wmove(win, y, x);}
00549     void getyx(int &y, int &x) {_getyx(win, y, x);}
00550     void getparyx(int &y, int &x) {_getparyx(win, y, x);}
00551     void getbegyx(int &y, int &x) {_getbegyx(win, y, x);}
00552     void getmaxyx(int &y, int &x) {_getmaxyx(win, y, x);}
00553     int getmaxy() {return _getmaxy(win);}
00554     int getmaxx() {return _getmaxx(win);}
00555 
00556     void show_string_as_progbar(int x, int y, const std::wstring &s,
00557                                 int attr1, int attr2, int size1,
00558                                 int totalsize);
00559     // Glitz bit :) Displays the given string with a progress bar behind it.
00560 
00561     void display_header(std::wstring s, const attr_t attr);
00562     void display_status(std::wstring s, const attr_t attr);
00563     // Make it easier to write interfaces that have a header and status line..
00564     // they do what they say :)
00565 
00566     int overlay(cwindow &dstwin) {return ::overlay(win, dstwin.win);}
00567     int overwrite(cwindow &dstwin) {return ::overwrite(win, dstwin.win);}
00568     int copywin(cwindow &dstwin, int sminrow, int smincol, int dminrow, int dmincol, int dmaxrow, int dmaxcol, int overlay)
00569     {return ::copywin(win, dstwin.win, sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol, overlay);}
00570 
00571     int refresh() {return wrefresh(win);}
00572     int noutrefresh() {return wnoutrefresh(win);}
00573 
00574     int touch() {return _touchwin(win);}
00575     int untouch() {return _untouchwin(win);}
00576     int touchln(int y, int n, int changed) {return ::wtouchln(win, y, n, changed);}
00577     int touchline(int start, int count) {return touchln(start, count, 1);}
00578     int untouchline(int start, int count) {return touchln(start, count, 0);}
00579 
00580     int erase() {return werase(win);}
00581     int clear() {return wclear(win);}
00582     int clrtobot() {return wclrtobot(win);}
00583     int clrtoeol() {return wclrtoeol(win);}
00584 
00585     int keypad(bool bf) {return ::keypad(win,bf);}
00586     int meta(bool bf) {return ::meta(win,bf);}
00587     int nodelay(bool bf) {return ::nodelay(win, bf);}
00588     int notimeout(bool bf) {return ::notimeout(win, bf);}
00589     void timeout(int delay) {wtimeout(win, delay);}
00590 
00591     int clearok(bool bf) {return ::clearok(win, bf);}
00592     int idlok(bool bf) {return ::idlok(win, bf);}
00593     void idcok(bool bf) {::idcok(win, bf);}
00594     void immedok(bool bf) {::immedok(win, bf);}
00595 #if defined(NCURSES_VERSION_MAJOR) && NCURSES_VERSION_MAJOR>=5
00596     int leaveok(bool bf) {int rval=::leaveok(win, bf); curs_set(bf?0:1); return rval;}
00597 #else
00598     int leaveok(bool bf) {return ::leaveok(win, bf);}
00599 #endif
00600     int setscrreg(int top, int bot) {return wsetscrreg(win, top, bot);}
00601     int scrollok(bool bf) {return ::scrollok(win,bf);}
00602 
00603     int printw(char *str, ...);
00604     /* You guessed it.. :) */
00605 
00606     bool enclose(int y, int x) {return wenclose(win, y, x);}
00607 
00608     WINDOW *getwin() {return win;}
00609     operator bool () {return win!=NULL;}
00610     cwindow &operator =(const cwindow &a)
00611     {
00612       cwindow_master *newmaster=a.master;
00613       newmaster->ref();
00614 
00615       master->deref();
00616       master=newmaster;
00617       win=a.win;
00618       return *this;
00619     }
00620     bool operator ==(cwindow &other) {return win==other.win;}
00621     bool operator !=(cwindow &other) {return win!=other.win;}
00622 
00623     static void remove_cruft();
00624   };
00625 
00626   extern cwindow rootwin;
00627   // This is stdscr, but calling it 'stdscr' would confuse the compiler, so I'm
00628   // confusing the programmer instead :)
00629 
00630   void init_curses();
00631   // Initializes curses and sets rootwin to the correct value
00632 
00633   void resize();
00634   // Called when a terminal resize is detected.
00635 }
00636 
00637 #endif

Generated on Mon Feb 16 01:16:31 2009 for cwidget by  doxygen 1.4.6