home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / fed0217s.zip / source / dialog.cpp < prev    next >
C/C++ Source or Header  |  2001-02-20  |  15KB  |  711 lines

  1. /*
  2. ** Module   :DIALOG.CPP
  3. ** Abstract :Simple Text UI
  4. **
  5. ** Copyright (C) Sergey I. Yevtushenko
  6. **
  7. ** Log: Fri  07/11/1997       Created
  8. */
  9.  
  10. #include <string.h>
  11.  
  12. #include <dialog.h>
  13. #include <keynames.h>
  14. #include <version.h>
  15.  
  16. //----------------------------------------------------------------------
  17. //
  18. //----------------------------------------------------------------------
  19. Control::Control(int r, int c, int nr, int nc)
  20. {
  21.     row = r;
  22.     col = c;
  23.     rows = nr;
  24.     cols = nc;
  25.     active = hotkey = 0;
  26. }
  27.  
  28. //----------------------------------------------------------------------
  29. //
  30. //----------------------------------------------------------------------
  31.  
  32. Dialog::Dialog(int r, int c, int nr, int nc)
  33.     :Control(r, c, nr, nc),
  34.     savebuff(0),
  35.     current(-1)
  36. {
  37. }
  38.  
  39. void Dialog::draw()
  40. {
  41.     int i;
  42.  
  43.     vio_cursor_type(NoCursor);
  44.  
  45.     if(!savebuff)
  46.         savebuff = vio_save_box(row, col, rows + 1, cols + 1);
  47.  
  48.     vio_box(row, col, rows, cols, 0, mk_clr(CL_DEFAULT));
  49.  
  50.     for(i = 1; i < rows - 1; i++)
  51.         vio_hdraw(row + i, col + 1, ' ', cols - 2, mk_clr(CL_BORDER));
  52.  
  53.     for(i = 0; i < Count(); i++)
  54.     {
  55.         Control* ctrl = (Control*)Get(i);
  56.  
  57.         if(ctrl)
  58.             ctrl->draw();
  59.     }
  60.  
  61.     for(i = 0; i < rows; i++)
  62.         vio_show_str(row + i, col, cols);
  63. }
  64.  
  65. Dialog::~Dialog()
  66. {
  67.     if(savebuff)
  68.         vio_restore_box(savebuff);
  69.  
  70.     RemoveAll();
  71. }
  72.  
  73. void Dialog::Free(Ptr p)
  74. {
  75.     delete (Control *)p;
  76. }
  77.  
  78. void Dialog::do_key(KeyInfo& k)
  79. {
  80.     switch(k.skey & 0x00FF)
  81.     {
  82.         case kbTab:
  83.             if(k.skey & shShift)
  84.                 prev();
  85.             else
  86.                 next();
  87.             return;
  88.  
  89.         case kbEnter:
  90.             next();
  91.             return;
  92.     }
  93.  
  94.     PControl ctl = in_focus();
  95.  
  96.     if(ctl)
  97.         ctl->do_key(k);
  98. }
  99.  
  100. void Dialog::next()
  101. {
  102.     int i;
  103.  
  104.     //1: from current to end
  105.     for(i = current+1; i < Count(); i++)
  106.     {
  107.         if(control(i)->select(1))
  108.         {
  109.             control(current)->select(0);
  110.             current = i;
  111.             return;
  112.         }
  113.     }
  114.  
  115.     //2: from start to current
  116.     for(i = 0; i < current; i++)
  117.     {
  118.         if(control(i)->select(1))
  119.         {
  120.             control(current)->select(0);
  121.             current = i;
  122.             return;
  123.         }
  124.     }
  125. }
  126.  
  127. void Dialog::prev()
  128. {
  129.     int i;
  130.  
  131.     //1: from current to start
  132.     for(i = current-1; i >= 0; i--)
  133.     {
  134.         if(control(i)->select(1))
  135.         {
  136.             control(current)->select(0);
  137.             current = i;
  138.             return;
  139.         }
  140.     }
  141.  
  142.     //2: from end to current
  143.     for(i = Count()- 1; i > current ; i--)
  144.     {
  145.         if(control(i)->select(1))
  146.         {
  147.             control(current)->select(0);
  148.             current = i;
  149.             return;
  150.         }
  151.     }
  152. }
  153.  
  154. void Dialog::Ins(Control* ctrl)
  155. {
  156.     ctrl->move(ctrl->row + row, ctrl->col + col);
  157.  
  158.     Collection::Add(ctrl);
  159.  
  160.     if(current < 0 && ctrl->select(1))
  161.         current = Count()-1;
  162. }
  163.  
  164. void Dialog::move(int r, int c)
  165. {
  166.     int off_r = r - row;
  167.     int off_c = c - col;
  168.  
  169.     for(int i = 0; i < Count(); i++)
  170.     {
  171.         Control* ctrl = (Control*)Get(i);
  172.  
  173.         if(ctrl)
  174.             ctrl->move(ctrl->row + off_r, ctrl->col + off_c);
  175.     }
  176.     Control::move(r,c);
  177. }
  178.  
  179. //----------------------------------------------------------------------
  180. //
  181. //----------------------------------------------------------------------
  182.  
  183. StaticText::StaticText(int r, int c, int nr, int nc, char *aText)
  184.     :Control(r,c,nr,nc)
  185. {
  186.     text = 0;
  187.     set_text(aText);
  188. }
  189.  
  190. void StaticText::draw()
  191. {
  192.     vio_printh(row, col, text, cols, mk_clr(CL_DEFAULT), mk_clr(CL_HILITE));
  193. }
  194.  
  195. StaticText::~StaticText()
  196. {
  197.     delete text;
  198. }
  199.  
  200. void StaticText::set_text(char *aText)
  201. {
  202.     delete text;
  203.     text = new char[strlen(aText)+1];
  204.     strcpy(text, aText);
  205. }
  206.  
  207. //----------------------------------------------------------------------
  208. //
  209. //----------------------------------------------------------------------
  210. void ListBoxItem::set_text(char *aText)
  211. {
  212.     if(text)
  213.     {
  214.         delete text;
  215.         text = 0;
  216.         len = 0;
  217.     }
  218.     if(aText)
  219.     {
  220.         len = strlen(aText);
  221.         text = new char[len + 1];
  222.         strcpy(text, aText);
  223.     }
  224. }
  225.  
  226. ListBoxItem::~ListBoxItem()
  227. {
  228.     set_text(0);
  229. }
  230.  
  231. //----------------------------------------------------------------------
  232. //
  233. //----------------------------------------------------------------------
  234. ListBox::ListBox(int r, int c, int nr, int nc, int opt)
  235.     :Control(r,c,nr,nc),Collection(128,128),flags(opt)
  236. {
  237.     start_row = cur_row = 0;
  238.     start_x   = 0;
  239.     index_ptr = -1;
  240.     last_sel_was_key = 0;
  241.  
  242.     if(opt & lbMultiSel)
  243.         flags &= ~lbWrap;
  244. }
  245.  
  246. void ListBox::draw()
  247. {
  248.     if(flags & lbHilite)
  249.     {
  250.         for(int i = 0; i < rows; i++)
  251.         {
  252.             int color1 = (cur_row == i) ? CL_CURRENT:CL_DEFAULT;
  253.             int color2 = (cur_row == i) ? CL_CURRSEL:CL_SELECTION;
  254.  
  255.             char *txt = get_item_text(start_row + i);
  256.  
  257.             if(!txt)
  258.                 txt = "";
  259.  
  260.             if(start_x > cstrlen(txt))
  261.                 txt = "";
  262.             else
  263.                 txt = &txt[start_x];
  264.  
  265.             vio_printh(row+i, col, txt, cols, mk_clr(color1), mk_clr(color2));
  266.         }
  267.     }
  268.     else
  269.     {
  270.         for(int i = 0; i < rows; i++)
  271.         {
  272.             int color = (cur_row == i) ? CL_CURRENT:CL_DEFAULT;
  273.             if(item(start_row + i))
  274.                 if(item(start_row + i)->flags & ListBoxItem::lbiSelected)
  275.                     color = (cur_row == i) ? CL_CURRSEL:CL_SELECTION;
  276.  
  277.             char *txt = get_item_text(start_row + i);
  278.  
  279.             if(!txt)
  280.                 txt = "";
  281.  
  282.             if(start_x > strlen(txt))
  283.                 txt = "";
  284.             else
  285.                 txt = &txt[start_x];
  286.  
  287.             vio_print(row+i, col, txt, cols, mk_clr(color));
  288.         }
  289.     }
  290. }
  291.  
  292. int ListBox::first_selected()
  293. {
  294.     if(!(flags & lbMultiSel))
  295.         return abs_row();
  296.     for(index_ptr = 0; index_ptr < Count(); index_ptr++)
  297.     {
  298.         if(item(index_ptr)->flags & ListBoxItem::lbiSelected)
  299.             return index_ptr;
  300.     }
  301.     return (index_ptr = -1);
  302. }
  303.  
  304. int ListBox::next_selected()
  305. {
  306.     if(index_ptr < 0)
  307.         return -1;
  308.  
  309.     for(++index_ptr; index_ptr < Count(); index_ptr++)
  310.     {
  311.         if(item(index_ptr)->flags & ListBoxItem::lbiSelected)
  312.             return index_ptr;
  313.     }
  314.     return (index_ptr = -1);
  315. }
  316.  
  317. char* ListBox::get_item_text(int ndx)
  318. {
  319.     PListBoxItem p = item(ndx);
  320.  
  321.     if(p)
  322.         return p->get_text();
  323.     return 0;
  324. }
  325.  
  326. void ListBox::set_item_text(int ndx, char* text)
  327. {
  328.     PListBoxItem p = item(ndx);
  329.  
  330.     if(p)
  331.         p->set_text(text);
  332. }
  333.  
  334. unsigned ListBox::get_item_key(int ndx)
  335. {
  336.     PListBoxItem p = item(ndx);
  337.  
  338.     if(p)
  339.         return p->userdata;
  340.     return 0;
  341. }
  342.  
  343. void ListBox::set_item_key(int ndx, unsigned int key)
  344. {
  345.     PListBoxItem p = item(ndx);
  346.  
  347.     if(p)
  348.         p->userdata = key;
  349. }
  350.  
  351. void ListBox::add_item(char *text, int pos)
  352. {
  353.     if(pos < 0 || pos > Count())
  354.         return;
  355.  
  356.     At(new ListBoxItem(text), pos);
  357. }
  358.  
  359. void ListBox::del_item(int index)
  360. {
  361.     Free(Remove(index));
  362. }
  363.  
  364. void ListBox::go_item(int index)
  365. {
  366.     if(index < 0 || index > Count())
  367.         return;
  368.     while(index < abs_row())
  369.         prev();
  370.     while(index > abs_row())
  371.         next();
  372. }
  373.  
  374.  
  375. void ListBox::Free(Ptr p)
  376. {
  377.     delete PListBoxItem(p);
  378. }
  379. void ListBox::prev()
  380. {
  381.  
  382.     if((flags & lbWrap) && abs_row() == 0)
  383.     {
  384.         while(abs_row() < Count() - 1)
  385.         {
  386.             cur_row++;
  387.             if(cur_row + start_row >= Count())
  388.                 cur_row = Count() - start_row - 1;
  389.  
  390.             if(cur_row >= rows)
  391.             {
  392.                 start_row += cur_row - rows + 1;
  393.                 cur_row    = rows-1;
  394.             }
  395.         }
  396.         return;
  397.     }
  398.  
  399.  
  400.     if(!(flags & lbMultiSel))
  401.         item(abs_row())->flags &= ~ListBoxItem::lbiSelected;
  402.  
  403.  
  404.     cur_row--;
  405.     if(cur_row < 0)
  406.     {
  407.         start_row += cur_row;
  408.         cur_row    = 0;
  409.     }
  410.     if(start_row <0)
  411.         start_row = 0;
  412.  
  413.     if(!(flags & lbMultiSel))
  414.         item(abs_row())->flags |= ListBoxItem::lbiSelected;
  415. }
  416.  
  417. void ListBox::next()
  418. {
  419.  
  420.     if((flags & lbWrap) && abs_row() == (Count() - 1))
  421.     {
  422.         cur_row = start_row = 0;
  423.         return;
  424.     }
  425.  
  426.  
  427.     if(!(flags & lbMultiSel))
  428.         item(abs_row())->flags &= ~ListBoxItem::lbiSelected;
  429.  
  430.     cur_row++;
  431.  
  432.     if(cur_row + start_row >= Count())
  433.         cur_row = Count() - start_row - 1;
  434.  
  435.     if(cur_row >= rows)
  436.     {
  437.         if(flags & lbCanScroll)
  438.         {
  439.             start_row += cur_row - rows + 1;
  440.             cur_row    = rows-1;
  441.         }
  442.         else
  443.             cur_row = rows-1;
  444.     }
  445.  
  446.     if(!(flags & lbMultiSel))
  447.         item(abs_row())->flags |= ListBoxItem::lbiSelected;
  448. }
  449.  
  450. void ListBox::sel(KeyInfo& k)
  451. {
  452.     if(flags & lbMultiSel)
  453.     {
  454.         if((k.skey & shCtrl) == shCtrl)
  455.             item(abs_row())->flags |= ListBoxItem::lbiSelected;
  456.         if((k.skey & shShift) == shShift)
  457.             item(abs_row())->flags &= ~ListBoxItem::lbiSelected;
  458.         if((k.skey & shAlt) == shAlt)
  459.             item(abs_row())->flags ^= ListBoxItem::lbiSelected;
  460.     }
  461. }
  462.  
  463. void ListBox::do_key(KeyInfo& k)
  464. {
  465.     int i;
  466.  
  467.     last_sel_was_key = 0;
  468.  
  469.     switch(k.skey & 0x00FF)
  470.     {
  471.         case kbLeft:
  472.             if(flags & lbXScroll)
  473.             {
  474.                 if(start_x > 0)
  475.                     start_x--;
  476.             }
  477.             break;
  478.  
  479.         case kbRight:
  480.             if(flags & lbXScroll)
  481.             {
  482.                 start_x++;
  483.             }
  484.             break;
  485.  
  486.         case kbUp:
  487.             sel(k);
  488.             prev();
  489.             break;
  490.  
  491.         case kbDown:
  492.             sel(k);
  493.             next();
  494.             break;
  495.  
  496.         case kbPgUp:
  497.  
  498.             for(i = 0; i < rows; i++)
  499.             {
  500.                 sel(k);
  501.                 prev();
  502.             }
  503.             break;
  504.  
  505.         case kbPgDown:
  506.  
  507.             for(i = 0; i < rows; i++)
  508.             {
  509.                 sel(k);
  510.                 next();
  511.             }
  512.             break;
  513.  
  514.         case kbEnd:
  515.  
  516.             if(!(k.skey & shCtrl) || !(flags & lbXScroll))
  517.             {
  518.                 while(abs_row() < (Count() - 1))
  519.                 {
  520.                     sel(k);
  521.                     next();
  522.                 }
  523.             }
  524.             else
  525.             {
  526.                 if(flags & lbXScroll)
  527.                 {
  528.                     //start_x = ;
  529.                     char *s = item(abs_row())->text;
  530.                     int  i  = cstrlen(s);
  531.  
  532.                     while(start_x < (i - cols))
  533.                         start_x++;
  534.                 }
  535.             }
  536.  
  537.             break;
  538.  
  539.         case kbHome:
  540.  
  541.             if(!(k.skey & shCtrl) || !(flags & lbXScroll))
  542.             {
  543.                 while(abs_row())
  544.                 {
  545.                     //i = abs_row();
  546.                     sel(k);
  547.                     prev();
  548.                 }
  549.  
  550.             }
  551.             else
  552.                 if(flags & lbXScroll)
  553.                     start_x = 0;
  554.  
  555.             break;
  556.  
  557.         case kbSpace:
  558.             if(flags & lbMultiSel)
  559.                 item(abs_row())->flags ^= ListBoxItem::lbiSelected;
  560.             break;
  561.  
  562.         default:
  563.             if(!(k.skey & shIsCtrl)) //Usual key
  564.             {
  565.                 //Search forward
  566.                 int i;
  567.  
  568.                 for(i = abs_row() + 1; i < Count(); i++)
  569.                 {
  570.                     if(item_char(i) == __to_upper((char)k.key))
  571.                         break;
  572.                 }
  573.  
  574.                 if(i < Count())
  575.                 {
  576.                     go_item(i);
  577.                     last_sel_was_key = 1;
  578.                     break;
  579.                 }
  580.  
  581.                 for(i = 0; i < abs_row(); i++)
  582.                 {
  583.                     if(item_char(i) == __to_upper((char)k.key))
  584.                         break;
  585.                 }
  586.  
  587.                 if(i < abs_row())
  588.                 {
  589.                     last_sel_was_key = 1;
  590.                     go_item(i);
  591.                     break;
  592.                 }
  593.  
  594.                 if(item_char(abs_row()) == __to_upper((char)k.key))
  595.                     last_sel_was_key = 1;
  596.  
  597.                 break;
  598.             }
  599.     }
  600. }
  601.  
  602. char ListBox::item_char(int ndx)
  603. {
  604.     if(ndx < 0 || ndx >= Count())
  605.         return 0;
  606.  
  607.     char* s = item(ndx)->text;
  608.  
  609.     if(flags & lbHilite)
  610.     {
  611.         while(*s && *s != SWITCH_CHAR)
  612.             s++;
  613.  
  614.         if(*s)
  615.             s++;
  616.     }
  617.     else
  618.     {
  619.         while(*s && __issp(*s))
  620.             s++;
  621.     }
  622.  
  623.     return __to_upper(*s);
  624. }
  625.  
  626. char ListBox::mk_clr(int index)
  627. {
  628.     return app_pal[(active ? CL_LISTBOX_ACTIVE:CL_LISTBOX_INACTIVE) + index];
  629. }
  630.  
  631. ListBox::~ListBox()
  632. {
  633.     RemoveAll();
  634. }
  635.  
  636. //----------------------------------------------------------------------
  637. //
  638. //----------------------------------------------------------------------
  639.  
  640. Menu::Menu(int r, int c, char **itemlist)
  641.     :ListBox(r,c,0,1,ListBox::lbHilite | ListBox::lbWrap)
  642. {
  643.     int i;
  644.  
  645.     if(itemlist)
  646.         for(i = 0; itemlist[i]; i++)
  647.             add_menu(itemlist[i]);
  648. }
  649.  
  650. void Menu::add_menu(char* item)
  651. {
  652.     int len = cstrlen(item);
  653.  
  654.     if(len > cols)
  655.         cols = len;
  656.  
  657.     add_at_end(item);
  658.     rows++;
  659. }
  660.  
  661. char Menu::mk_clr(int index)
  662. {
  663.     return app_pal[CL_MENU+index];
  664. }
  665.  
  666. //----------------------------------------------------------------------
  667. //
  668. //----------------------------------------------------------------------
  669.  
  670. JumpEntryHolder::JumpEntryHolder(int arow, int acol, char *name, char *file):
  671.                 row(arow), col(acol)
  672. {
  673.     if(name)
  674.     {
  675.         hdr = new char[strlen(name)+1];
  676.         strcpy(hdr, name);
  677.     }
  678.     else
  679.     {
  680.         hdr = new char[1];
  681.         hdr[0] = 0;
  682.     }
  683.  
  684.     if(file)
  685.     {
  686.         text = new char[strlen(file)+1];
  687.         strcpy(text, file);
  688.     }
  689.     else
  690.     {
  691.         text = new char[1];
  692.         text[0] = 0;
  693.     }
  694. }
  695.  
  696. JumpEntryHolder::~JumpEntryHolder()
  697. {
  698.     delete text;
  699.     delete hdr;
  700. }
  701.  
  702. JumpList::~JumpList()
  703. {
  704.     RemoveAll();
  705. }
  706.  
  707. void JumpList::add_entry(int row, int col, char *name, char *file)
  708. {
  709.     Add(new JumpEntryHolder(row, col, name, file));
  710. }
  711.