home *** CD-ROM | disk | FTP | other *** search
/ TOS Silver 2000 / TOS Silver 2000.iso / programm / GNU_C++ / LIB / CFLIB-11.LZH / src / mdial.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-08-09  |  10.6 KB  |  455 lines

  1. #include "intern.h"
  2.  
  3. #ifdef __MTAES__
  4. #define wind_create_grect(a,b)    wind_create(a,b)
  5. #define wind_calc_grect(a,b,c,d)    wind_calc(a,b,c,d)
  6. #define wind_open_grect(a,b)        wind_open(a,b)
  7. #define wind_set_str(a,b,c)        wind_set_string(a,b,c)
  8. #endif
  9.  
  10. /* --------------------------------------------------------------------------- */
  11. /* app-modaler Fensterdialog                                                                     */
  12. /* --------------------------------------------------------------------------- */
  13.  
  14. #define KIND    (NAME|MOVER|BACKDROP)
  15.  
  16. static MDIAL_WCB    win_cb = NULL;
  17. static MDIAL        *md_list = NULL;
  18.  
  19. static int handle_msg(int *msg);
  20.  
  21.  
  22. void set_mdial_wincb(MDIAL_WCB cb)
  23. {
  24.     win_cb = cb;
  25.     cf_msg_cb = (win_cb != NULL);
  26. }
  27.  
  28. void handle_mdial_msg(int *msg)
  29. {
  30.     if (!handle_msg(msg) && win_cb)
  31.     {
  32.         switch (msg[0])
  33.         {
  34.             case WM_REDRAW :
  35.             case WM_MOVED :
  36.             case WM_SIZED :
  37.                 win_cb(msg);
  38.                 break;
  39.             default:
  40.                 ;
  41.         }
  42.     }
  43. }
  44.  
  45. static void redraw_dial(MDIAL *dial, int start, int depth, int x, int y, int w, int h)
  46. {
  47.     GRECT        r, r1;
  48.     
  49.     r.g_x = x; r.g_y = y; r.g_w = w; r.g_h = h;
  50.     wind_update(BEG_UPDATE);
  51.     hide_mouse_if_needed(&r);
  52.     wind_get_grect(dial->win_handle, WF_FIRSTXYWH, &r1);
  53.     while (r1.g_w != 0 && r1.g_h != 0)
  54.     {
  55.         if (rc_intersect(&r, &r1))
  56. #ifdef __MTAES__
  57.             objc_draw(dial->tree, start, depth, &r1);
  58. #else
  59.             objc_draw(dial->tree, start, depth, r1.g_x, r1.g_y, r1.g_w, r1.g_h);
  60. #endif
  61.         wind_get_grect(dial->win_handle, WF_NEXTXYWH, &r1);
  62.     }
  63.     show_mouse();
  64.     wind_update(END_UPDATE);
  65. }
  66.  
  67. static void redraw_cursor(MDIAL *dial)
  68. {
  69.     if (dial->edit_obj > 0)
  70.     {
  71.         GRECT    r;
  72.     
  73.         objc_edit(dial->tree, dial->edit_obj, 0, &dial->edit_idx, ED_INIT);
  74.         get_objframe(dial->tree, dial->edit_obj, &r);
  75.         redraw_dial(dial, ROOT, MAX_DEPTH, r.g_x, r.g_y - 3, r.g_w + 1, r.g_h + 6);
  76.         objc_edit(dial->tree, dial->edit_obj, 0, &dial->edit_idx, ED_INIT);
  77.     }
  78. }
  79.  
  80. static void move_dial(MDIAL *dial, int x, int y)
  81. {
  82.     GRECT    r;
  83.  
  84.     wind_get_grect(dial->win_handle, WF_CURRXYWH, &r);
  85.     r.g_x = x;
  86.     r.g_y = y;
  87.     wind_set_grect(dial->win_handle, WF_CURRXYWH, &r);
  88.     wind_get_grect(dial->win_handle, WF_WORKXYWH, &r);
  89.     dial->tree[0].ob_x = r.g_x;
  90.     dial->tree[0].ob_y = r.g_y - dial->delta_y;
  91. }
  92.  
  93. static int handle_msg(int *msg)
  94. {
  95.     MDIAL    *md;
  96.     int    ret = FALSE;
  97.     
  98.     md = md_list;
  99.     while (md)
  100.     {
  101.         if (msg[3] == md->win_handle)
  102.             break;
  103.         md = md->next;
  104.     }
  105.     if (md)
  106.     {
  107.         switch (msg[0])
  108.         {
  109.             case WM_REDRAW :
  110.                     redraw_dial(md, ROOT, MAX_DEPTH, msg[4], msg[5], msg[6], msg[7]);
  111.                     redraw_cursor(md);
  112.                     ret = TRUE;
  113.                     break;
  114.                     
  115.             case WM_MOVED :
  116.                     move_dial(md, msg[4], msg[5]);
  117.                     ret = TRUE;
  118.                     break;
  119.         }
  120.     }
  121.     return ret;
  122. }
  123.  
  124. /* --------------------------------------------------------------------------- */
  125. MDIAL *open_mdial(OBJECT *tree, int edit_start)
  126. {
  127.     GRECT    r1, r2;
  128.     MDIAL    *dial;
  129.     int    center = FALSE;
  130.     
  131.     dial = (MDIAL *)cf_malloc(sizeof(MDIAL), "open_mdial", FALSE);
  132.     if (dial != NULL)
  133.     {    
  134.         memset(dial, 0, sizeof(MDIAL));
  135.         dial->tree = tree;
  136.     
  137.         dial->next = md_list;
  138.         md_list = dial;
  139.         
  140.         /* Rahmen abschalten */
  141.         dial->save_frame = tree[0].ob_spec.obspec.framesize;
  142.         tree[0].ob_spec.obspec.framesize = 0;
  143.     
  144.         /* Zentrieren, nur beim ersten Mal */
  145.         if (tree[0].ob_x == 0 && tree[0].ob_y == 0)
  146.         {
  147. #ifdef __MTAES__
  148.             form_center(tree, &r1);    
  149. #else
  150.             form_center(tree, &r1.g_x, &r1.g_y, &r1.g_w, &r1.g_h);    
  151. #endif
  152.             center = TRUE;
  153.         }
  154.         
  155.         /* Fenstertitel holen und ausblenden */
  156.         if (get_magx_obj(tree, 1) == MX_UNDERLINE)
  157.         {
  158.             dial->win_name = (char *)get_obspec(tree, 1);
  159.             dial->delta_y = (tree[1].ob_y + tree[1].ob_height);
  160.             dial->tree[0].ob_y -= dial->delta_y;
  161.             set_flag(tree, 1, HIDETREE, TRUE);
  162.         }
  163.         else
  164.             dial->win_name = NULL;
  165.     
  166.         /* Editfeld */
  167.         if ((edit_start <= 0) || !edit_valid(dial->tree, edit_start))
  168.             dial->edit_obj = find_edit(dial->tree, 0, FMD_FORWARD);
  169.         else
  170.             dial->edit_obj = edit_start;
  171.  
  172.         r1.g_x = tree[0].ob_x;
  173.         r1.g_y = tree[0].ob_y + dial->delta_y;
  174.         r1.g_w = tree[0].ob_width;
  175.         r1.g_h = tree[0].ob_height - dial->delta_y;
  176.         wind_calc_grect(WC_BORDER, KIND, &r1, &r2);
  177.  
  178.         /* Fenster neu zentrieren */
  179.         if (center)
  180.         {
  181.             int    d;
  182.         
  183.             d = (r2.g_h - r1.g_h) / 2 + dial->delta_y / 2;
  184.             r2.g_y += d ;
  185.             tree[0].ob_y += d;
  186.             /* herausragen ins Menü verhindern */
  187.             if (r2.g_y < gl_desk.g_y)
  188.             {
  189.                 tree[0].ob_y += (gl_desk.g_y - r2.g_y);
  190.                 r2.g_y = gl_desk.g_y;
  191.             }
  192.         }
  193.  
  194.         dial->win_handle = wind_create_grect(KIND, &r2);
  195.         if (dial->win_handle > 0)
  196.         {
  197.             int msg[8];
  198.  
  199.             /* Menü abschalten */
  200.             disable_menu();
  201.     
  202.             if (dial->win_name)
  203.                 wind_set_str(dial->win_handle, WF_NAME, dial->win_name);
  204.             wind_open_grect(dial->win_handle, &r2);
  205.  
  206.             /* den REDRAW noch abholen */
  207.             while (TRUE)
  208.             {
  209.                 evnt_mesag(msg);
  210.                 handle_mdial_msg(msg);
  211.                 if ((msg[0] == WM_REDRAW) && (msg[3] == dial->win_handle))
  212.                     break;
  213.             }
  214.         }
  215.         else
  216.         {
  217.             close_mdial(dial);
  218.             dial = NULL;
  219.         }
  220.     }
  221.     return dial;
  222. }
  223.  
  224. int do_mdial(MDIAL *dial)
  225. {
  226.     int    msg[8], mx, my, mbutton, kstate, kreturn, breturn, event, ret;
  227.     int    cont, b, doppel = FALSE;
  228.     
  229.     ret = -1;
  230.     if (dial != NULL)
  231.     {
  232.         cont = TRUE;
  233.         while (cont)
  234.         {
  235. #ifdef __MTAES__
  236.             GRECT        n = {0,0,0,0};
  237.             EVNTDATA    ev;
  238.             
  239.             event = evnt_multi(MU_MESAG|MU_BUTTON|MU_KEYBD,
  240.                                         2, 1, 1, 0, &n, 0, &n,
  241.                                         msg, 0, &ev,
  242.                                         &kreturn, &breturn);
  243.             mx = ev.x;
  244.             my = ev.y;
  245.             mbutton = ev.bstate;
  246.             kstate = ev.kstate;
  247. #else
  248.             event = evnt_multi(MU_MESAG|MU_BUTTON|MU_KEYBD,
  249.                                         2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  250.                                         msg, 0, &mx, &my, &mbutton, &kstate,
  251.                                         &kreturn, &breturn);
  252. #endif
  253.  
  254.             if (event & MU_MESAG)
  255.             {
  256.                 switch (msg[0])
  257.                 {
  258.                     case WM_REDRAW :
  259.                     case WM_MOVED :
  260.                     case WM_SIZED:
  261.                         handle_mdial_msg(msg);
  262.                         break;
  263.  
  264.                     case WM_TOPPED :
  265. /*
  266.                         if (msg[3] != dial->win_handle)
  267.                             Bconout(2, 7);
  268. */
  269.                         /* kein break! */
  270.                     case WM_NEWTOP :
  271.                     case WM_ONTOP :        
  272.                         /* immer den Dialog toppen! */
  273.                         wind_set(dial->win_handle, WF_TOP, 0, 0, 0, 0);
  274.                         break;
  275.  
  276.                     case WM_BOTTOMED:
  277.                     case 100:                    /* WM_M_BACKDROPED MagiC 2.x */
  278.                         Bconout(2, 7);
  279.                         break;
  280.  
  281.                     case WM_SHADED :
  282.                     case WM_UNSHADED :
  283.                         dial->is_shaded = !dial->is_shaded;
  284.                         break;
  285.  
  286.                     case AP_TERM :            /* sofort verlassen */
  287.                         event = 0;
  288.                         cont = FALSE;
  289.                         dial->next_obj = -1;
  290.                         break;
  291.                 }
  292.             }
  293.  
  294.             if ((event & MU_KEYBD) && (!dial->is_shaded))
  295.             {
  296.                 cont = cf_form_keybd(dial->tree, dial->edit_obj, kstate, &kreturn, &dial->next_obj);
  297.                 if (cont)        /* kein Exit-Obj ausgelöst */
  298.                 {
  299.                     if (kreturn)
  300.                         cf_objc_edit(dial->tree, dial->edit_obj, kreturn, &dial->edit_idx, ED_CHAR, kstate, &b);
  301.                     else if (cont && (dial->tree[dial->next_obj].ob_flags & EDITABLE))
  302.                     {    
  303.                         /* kein Exit-Obj aber neues Edit-Obj */
  304.                       objc_edit(dial->tree, dial->edit_obj, 0, &dial->edit_idx, ED_END);
  305.                       dial->edit_obj = dial->next_obj;
  306.                       objc_edit(dial->tree, dial->edit_obj, 0, &dial->edit_idx, ED_INIT);
  307.                     }
  308.                 }
  309.             }
  310.             if (event & MU_BUTTON)
  311.             {
  312.                 dial->next_obj = cf_objc_find(dial->tree, ROOT, MAX_DEPTH, mx, my);
  313.                 if (dial->next_obj == -1)
  314.                 {
  315.                     Bconout(2, 7);
  316.                     dial->next_obj = 0;
  317.                 }
  318.                 else
  319.                 {
  320.                     doppel = (breturn == 2);
  321.                     cont = form_button(dial->tree, dial->next_obj, mbutton, &dial->next_obj);
  322.                     if (cont && (dial->tree[dial->next_obj].ob_flags & EDITABLE))
  323.                     {
  324.                         /* kein Exit-Obj aber neues Edit-Obj */
  325.                         objc_edit(dial->tree, dial->edit_obj, 0, &dial->edit_idx, ED_END);
  326.                       dial->edit_obj = dial->next_obj;
  327.                         if (gl_magx)
  328.                           objc_edit(dial->tree, dial->edit_obj, mx, &dial->edit_idx, ED_CRSR);
  329.                         else
  330.                           objc_edit(dial->tree, dial->edit_obj, 0, &dial->edit_idx, ED_INIT);
  331.  
  332.                     }
  333.                 }
  334.             }
  335.         }
  336.         ret = dial->next_obj;
  337.     }
  338.     if (doppel)
  339.         ret |= 0x8000;            /* bit 15 für Doppelklick */
  340.     return ret;
  341. }
  342.  
  343. void close_mdial(MDIAL *dial)
  344. {
  345.     if (dial != NULL)
  346.     {
  347.         if (dial->win_handle > 0)
  348.         {
  349.             int    msg[8], d, event = 0;
  350.  
  351.             wind_close(dial->win_handle);
  352.             wind_delete(dial->win_handle);
  353.  
  354.             /*
  355.              * Alle auflaufenden Redraw-Messages abarbeiten, damit
  356.              * alle Fenster sauber sind, wenn der Dialog beendet ist.
  357.             */
  358.             while (event != MU_TIMER)
  359.             {
  360. #ifdef __MTAES__
  361.                 GRECT        n = {0,0,0,0};
  362.                 EVNTDATA    ev;
  363.             
  364.                 event = evnt_multi(MU_MESAG|MU_TIMER, 1, 1, 1, 
  365.                                         0, &n, 0, &n,
  366.                                         msg, 1, &ev, &d, &d);
  367. #else
  368.                 event = evnt_multi(MU_MESAG|MU_TIMER, 1, 1, 1, 
  369.                                         0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  370.                                         msg, 1, &d, &d, &d, &d, &d, &d);
  371. #endif
  372.                 if ((event & MU_MESAG) && (msg[0] == WM_REDRAW))
  373.                     handle_mdial_msg(msg);
  374.             }
  375.  
  376.             /* Menü wieder an */
  377.             enable_menu();
  378.         }
  379.         
  380.         /* Dialog wieder herstellen */
  381.         dial->tree[0].ob_spec.obspec.framesize = dial->save_frame;
  382.         set_flag(dial->tree, 1, HIDETREE, FALSE);
  383.         dial->tree[0].ob_y += dial->delta_y;
  384.     
  385.         md_list = dial->next;
  386.         Mfree(dial);
  387.     }
  388. }
  389.  
  390. int simple_mdial(OBJECT *tree, int edit_start)
  391. {
  392.     MDIAL    *dial;
  393.     int    ret = -1;
  394.     
  395.     graf_mouse(ARROW, NULL);
  396.     dial = open_mdial(tree, edit_start);
  397.     if (dial)
  398.     {
  399.         ret = do_mdial(dial) & 0x7FFF;
  400.         set_state(tree, ret, SELECTED, FALSE);
  401.         close_mdial(dial);
  402.     }
  403.     return ret;
  404. }
  405.  
  406. void redraw_mdobj(MDIAL *dial, int obj)
  407. {
  408.     GRECT    r;
  409.     
  410.     if (dial != NULL)
  411.     {
  412.         get_objframe(dial->tree, obj, &r);
  413.         redraw_dial(dial, ROOT, MAX_DEPTH, r.g_x, r.g_y - 3, r.g_w + 1, r.g_h + 6);
  414.         
  415.         /* neu zeichnen, wenn obj das Editfeld bzw. ein Child von obj ist */
  416.         if ((obj == dial->edit_obj) ||
  417.              (dial->edit_obj >= dial->tree[obj].ob_head && dial->edit_obj <= dial->tree[obj].ob_tail))
  418.             redraw_cursor(dial);
  419.     }
  420. }
  421.  
  422. void change_mdedit(MDIAL *md, int new)
  423. {
  424.     int    last = 0;
  425.     
  426.     if (md != NULL)
  427.     {
  428.         /* 1. prüfen, ob aktuelles nicht mehr gültig ist */
  429.         if (md->edit_obj > 0)
  430.         {
  431.             last = -1;
  432.             if (!edit_valid(md->tree, md->edit_obj))
  433.             {
  434.                 objc_edit(md->tree, md->edit_obj, 0, &md->edit_idx, ED_END);
  435.                 last = md->edit_obj;
  436.             }
  437.         }
  438.         
  439.         /*
  440.          * last = -1    -> aktuelles Editfeld weiterhin gültig, nix weiteres tun
  441.          * last = 0        -> bisher kein Editfeld, erstes suchen
  442.          * last > 0        -> aktuelles Editfeld ungültig geworden, nächstes suchen
  443.         */
  444.         if (last != -1)
  445.         {
  446.             if (new > 0 && edit_valid(md->tree, new))
  447.                 md->edit_obj = new;            /* 2a. ein gültiges neues übergeben? */
  448.             else                                    /* 2b. neues suchen */
  449.                 md->edit_obj = find_edit(md->tree, last, FMD_FORWARD);
  450.             if (md->edit_obj > 0)
  451.               objc_edit(md->tree, md->edit_obj, 0, &md->edit_idx, ED_INIT);
  452.         }
  453.     }
  454. }
  455.