more bug fixes for NIM 1.2 (KFW 3.2)
authorJeffrey Altman <jaltman@secure-endpoints.com>
Thu, 29 Mar 2007 21:19:43 +0000 (21:19 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Thu, 29 Mar 2007 21:19:43 +0000 (21:19 +0000)
netidmgr.exe

- Credentials display :

  - If an outline is marked as KHUI_CW_O_STICKY | KHUI_CW_O_RELIDENT,
    release the identity when deleting the outline node.

  - Correctly determine the location of UI widgets using the column
    specifier of the outline node instead of the column specifier of
    the row.

  - Do not recompute the extents of a row.

  - If there is a default identity and it has no credentials and it is
    not pinned, display it anyway.

krb5common.obj

- Import profile_rename_section()

krb5cred.dll

- In the realm editor:

  - When writing realm data, keep track of whether any updates were
    performed.

  - Reset the dirty bits for each element whose changes were written
    to the profile.

  - Use profile_rename_section() correctly to delete sections.

  - Check if any changes were applied before setting the 'applied' bit
    for the configuration node.

  - Don't assume that the Kerberos 5 General configuration panel has
    received WMCFG_APPLY before the realm editor.  It will not receive
    the notification if it hasn't indicated that there are changes to
    be applied.

- New credentials :

  - If there is no "ExpiresOn" value for a cached prompt set, assume
    that it has already expired.

  - Set the lifetime for a new prompt set to be 7 days longer than
    then maximum renewable lifetime.

ticket: new
component: windows
tags: pullup

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@19307 dc483132-0cff-0310-8789-dd5450dbe970

src/windows/identity/plugins/common/dynimport.c
src/windows/identity/plugins/common/dynimport.h
src/windows/identity/plugins/krb5/krb5configdlg.c
src/windows/identity/plugins/krb5/krb5newcreds.c
src/windows/identity/ui/credwnd.c
src/windows/identity/ui/credwnd.h

index d891af12240138534e90f78b1bc2df92fd672907..f49987ca733bc2bf7a3c4d954c21a52d6f0f44c2 100644 (file)
@@ -168,6 +168,7 @@ DECL_FUNC_PTR(profile_clear_relation);
 DECL_FUNC_PTR(profile_add_relation);\r
 DECL_FUNC_PTR(profile_update_relation);\r
 DECL_FUNC_PTR(profile_release_string);\r
+DECL_FUNC_PTR(profile_rename_section);\r
 \r
 // Service functions\r
 DECL_FUNC_PTR(OpenSCManagerA);\r
@@ -315,6 +316,7 @@ FUNC_INFO profile_fi[] = {
     MAKE_FUNC_INFO(profile_add_relation),\r
     MAKE_FUNC_INFO(profile_update_relation),\r
     MAKE_FUNC_INFO(profile_release_string),\r
+    MAKE_FUNC_INFO(profile_rename_section),\r
     END_FUNC_INFO\r
 };\r
 \r
index 0f2cc237d9fa5aae3f1962853f102df65ad5e206..7f3f598b066d9a150c29e474ffb01c46703a249e 100644 (file)
@@ -291,6 +291,7 @@ extern DECL_FUNC_PTR(profile_clear_relation);
 extern DECL_FUNC_PTR(profile_add_relation);\r
 extern DECL_FUNC_PTR(profile_update_relation);\r
 extern DECL_FUNC_PTR(profile_release_string);\r
+extern DECL_FUNC_PTR(profile_rename_section);\r
 \r
 // Service functions\r
 extern DECL_FUNC_PTR(OpenSCManagerA);\r
index 2d1e3259cb065431252cad2e6d87eb061e029352..36936cdea038bdcef4ee1fe5805605614c402b1b 100644 (file)
@@ -234,6 +234,7 @@ k5_is_profile_loaded(void) {
     assert(pprofile_add_relation);
     assert(pprofile_update_relation);
     assert(pprofile_flush);
+    assert(pprofile_rename_section);
 #endif
 
     if (!pprofile_init ||
@@ -247,7 +248,8 @@ k5_is_profile_loaded(void) {
         !pprofile_clear_relation ||
         !pprofile_add_relation ||
         !pprofile_update_relation ||
-        !pprofile_flush)
+        !pprofile_flush ||
+        !pprofile_rename_section)
 
         return FALSE;
 
@@ -529,7 +531,7 @@ k5_read_config_data(k5_config_data * d) {
     d->flags = 0;
 }
 
-void
+int
 k5_write_config_data(k5_config_data * d) {
     char astr[MAX_PATH * 2];
     char config_file[MAX_PATH];
@@ -537,22 +539,25 @@ k5_write_config_data(k5_config_data * d) {
     const char *filenames[2];
     long rv;
     khm_size s;
+    int applied = FALSE;
 
     if (d->flags == 0)
-        return;
+        return FALSE;
 
     if (!k5_is_profile_loaded())
-        return;
+        return FALSE;
 
     /* write the MSLSA import setting */
     if (d->flags & K5_CDFLAG_MOD_LSA_IMPORT) {
         khc_write_int32(csp_params, L"MsLsaImport", d->lsa_import);
         d->flags &= ~K5_CDFLAG_MOD_LSA_IMPORT;
+        applied = TRUE;
     }
 
     if (d->flags & K5_CDFLAG_MOD_INC_REALMS) {
         khc_write_int32(csp_params, L"UseFullRealmList", d->inc_realms);
         d->flags &= ~K5_CDFLAG_MOD_INC_REALMS;
+        applied = TRUE;
     }
 
     if (!(d->flags & 
@@ -566,7 +571,7 @@ k5_write_config_data(k5_config_data * d) {
            K5_CDFLAG_MOD_REALMS))) {
 
         d->flags = 0;
-        return;
+        return applied;
     }
 
     khm_krb5_get_profile_file(config_file, ARRAYLENGTH(config_file));
@@ -620,6 +625,7 @@ k5_write_config_data(k5_config_data * d) {
 
                 rv = pprofile_add_relation(profile, sec_libdefaults,
                                            defrealm);
+                applied = TRUE;
             }
             d->flags &= ~K5_CDFLAG_MOD_DEF_REALM;
         }
@@ -635,6 +641,7 @@ k5_write_config_data(k5_config_data * d) {
                                        KRB5_CONF_YES:
                                        KRB5_CONF_NO);
             d->flags &= ~K5_CDFLAG_MOD_DNS_LOOKUP_KDC;
+            applied = TRUE;
         }
 
         if (d->flags & K5_CDFLAG_MOD_DNS_LOOKUP_RLM) {
@@ -649,6 +656,7 @@ k5_write_config_data(k5_config_data * d) {
                                        KRB5_CONF_NO);
 
             d->flags &= ~K5_CDFLAG_MOD_DNS_LOOKUP_RLM;
+            applied = TRUE;
         }
 
         if (d->flags & K5_CDFLAG_MOD_DNS_FALLBACK) {
@@ -663,6 +671,7 @@ k5_write_config_data(k5_config_data * d) {
                                        KRB5_CONF_NO);
 
             d->flags &= ~K5_CDFLAG_MOD_DNS_FALLBACK;
+            applied = TRUE;
         }
 
         if (d->flags & K5_CDFLAG_MOD_NOADDRESSES) {
@@ -677,6 +686,7 @@ k5_write_config_data(k5_config_data * d) {
                                        KRB5_CONF_NO);
 
             d->flags &= ~K5_CDFLAG_MOD_NOADDRESSES;
+            applied = TRUE;
         }
 
         /* now we look at the [realms] section */
@@ -726,7 +736,10 @@ k5_write_config_data(k5_config_data * d) {
                             pprofile_add_relation(profile, sec_admin,
                                                   host);
 
-                        d->realms[r].kdcs[k].flags &= ~K5_RKFLAG_NEW;
+                        d->realms[r].kdcs[k].flags &= ~ (K5_RKFLAG_NEW |
+                                                         K5_RKFLAG_MOD_MASTER |
+                                                         K5_RKFLAG_MOD_ADMIN);
+                        applied = TRUE;
                     }
                 }
 
@@ -745,6 +758,7 @@ k5_write_config_data(k5_config_data * d) {
                            is deleted and not in the profile file
                            anymore. */
                         d->realms[r].domain_maps[m].flags |= K5_DMFLAG_NEW;
+                        applied = TRUE;
                     } else if (!(d->realms[r].domain_maps[m].flags &
                                K5_DMFLAG_DELETED) &&
                              (d->realms[r].domain_maps[m].flags &
@@ -753,10 +767,12 @@ k5_write_config_data(k5_config_data * d) {
                                               realm);
 
                         d->realms[r].domain_maps[m].flags &= ~K5_DMFLAG_NEW;
+                        applied = TRUE;
                     }
                 }
 
-                d->realms[r].flags &= ~K5_RDFLAG_NEW;
+                d->realms[r].flags &= ~(K5_RDFLAG_NEW |
+                                        K5_RDFLAG_MODIFED);
 
             } else if ((d->realms[r].flags & K5_RDFLAG_DELETED) &&
                        !(d->realms[r].flags & K5_RDFLAG_NEW)) {
@@ -774,7 +790,10 @@ k5_write_config_data(k5_config_data * d) {
                         sec_all[2] = values[v];
                         pprofile_clear_relation(profile, sec_all);
                     }
+                    sec_all[2] = NULL;
+                    pprofile_rename_section(profile, sec_all, NULL);
                     pprofile_free_list(values);
+                    applied = TRUE;
                 }
 
                 rv = pprofile_get_relation_names(profile, sec_domain_realm,
@@ -794,6 +813,7 @@ k5_write_config_data(k5_config_data * d) {
                                               values[v]);
                                 pprofile_clear_relation(profile, 
                                                         sec_domain_map);
+                                applied = TRUE;
                             }
                             pprofile_release_string(maprealm);
                         }
@@ -806,7 +826,8 @@ k5_write_config_data(k5_config_data * d) {
                    deleted and is not in the profile file. */
                 d->realms[r].flags |= K5_RDFLAG_NEW;
 
-            } else if (!(d->realms[r].flags & K5_RDFLAG_DELETED)) {
+            } else if (!(d->realms[r].flags & K5_RDFLAG_DELETED) &&
+                       (d->realms[r].flags & K5_RDFLAG_MODIFED)) {
                 khm_size k;
                 khm_size m;
 
@@ -830,6 +851,8 @@ k5_write_config_data(k5_config_data * d) {
                         pprofile_update_relation(profile, sec_master,
                                                  host, NULL);
 
+                        applied = TRUE;
+
                         /* as above, setting 'new' flag to indicate
                            that the item does not exist in the profile
                            file. */
@@ -849,7 +872,10 @@ k5_write_config_data(k5_config_data * d) {
                             pprofile_add_relation(profile, sec_admin,
                                                   host);
 
-                        d->realms[r].kdcs[k].flags &= ~K5_RKFLAG_NEW;
+                        d->realms[r].kdcs[k].flags &= ~(K5_RKFLAG_NEW |
+                                                        K5_RKFLAG_MOD_ADMIN |
+                                                        K5_RKFLAG_MOD_MASTER);
+                        applied = TRUE;
                         continue;
                     }
 
@@ -864,6 +890,7 @@ k5_write_config_data(k5_config_data * d) {
                                                   host);
                         }
 
+                        applied = TRUE;
                         d->realms[r].kdcs[k].flags &= ~K5_RKFLAG_MOD_MASTER;
                     }
 
@@ -878,6 +905,7 @@ k5_write_config_data(k5_config_data * d) {
                                                      host, NULL);
                         }
 
+                        applied = TRUE;
                         d->realms[r].kdcs[k].flags &= ~K5_RKFLAG_MOD_ADMIN;
                     }
                 }
@@ -895,6 +923,7 @@ k5_write_config_data(k5_config_data * d) {
 
                         pprofile_clear_relation(profile, sec_domain_map);
                         d->realms[r].domain_maps[m].flags |= K5_DMFLAG_NEW;
+                        applied = TRUE;
 
                     } else if (!(d->realms[r].domain_maps[m].flags &
                                K5_DMFLAG_DELETED) &&
@@ -905,6 +934,8 @@ k5_write_config_data(k5_config_data * d) {
                         pprofile_add_relation(profile, sec_domain_map,
                                               realm);
                         d->realms[r].domain_maps[m].flags &= ~K5_DMFLAG_NEW;
+                        applied = TRUE;
+
                     }
                 }
 
@@ -945,6 +976,8 @@ k5_write_config_data(k5_config_data * d) {
     }
 
     d->flags = 0;
+
+    return applied;
 }
 
 /* actual dialog stuff */
@@ -1199,13 +1232,14 @@ k5_config_dlgproc(HWND hwnd,
 
             if (HIWORD(wParam) == WMCFG_APPLY) {
                 khm_int32 oflags;
+                int applied;
 
                 oflags = d->flags;
-                k5_write_config_data(d);
+                applied = k5_write_config_data(d);
 
                 if (d->flags != oflags) {
                     khui_cfg_set_flags(d->node_main,
-                                       KHUI_CNFLAG_APPLIED,
+                                       (applied ? KHUI_CNFLAG_APPLIED : 0),
                                        KHUI_CNFLAG_APPLIED |
                                        KHUI_CNFLAG_MODIFIED);
                 }
@@ -2664,12 +2698,11 @@ k5_realms_dlgproc(HWND hwnd,
 
     case KHUI_WM_CFG_NOTIFY:
         /* the realms dialog receives this notification after the top
-           level krb5 configuration panel has received it.  Therefore,
-           we assume that any changes have already been applied.  When
-           applying changes, we switch the mod bits off to indicate
-           that the changes have been written.  We just have to
-           repaint the screen at this point. */
+           level krb5 configuration panel has received it. */
         if (HIWORD(wParam) == WMCFG_APPLY) {
+            int applied;
+
+            applied = k5_write_config_data(d);
             k5_purge_config_data(d, TRUE, TRUE, TRUE);
             k5_update_realms_display(GetDlgItem(hwnd, IDC_CFG_REALMS), d);
             if (d->c_realm != -1) {
@@ -2679,6 +2712,10 @@ k5_realms_dlgproc(HWND hwnd,
                 k5_update_kdcs_display(GetDlgItem(hwnd, IDC_CFG_KDC), NULL, 0);
                 k5_update_dmap_display(GetDlgItem(hwnd, IDC_CFG_DMAP), NULL, 0);
             }
+            khui_cfg_set_flags(d->node_realm,
+                               (applied ? KHUI_CNFLAG_APPLIED : 0),
+                               KHUI_CNFLAG_APPLIED);
+
         }
         break;
     }
index d52e934cc6e74a1564b60189810ca60d55b4b257..b9f0c075e31dce2b223791783e375994c295a271 100644 (file)
@@ -775,19 +775,9 @@ k5_cached_kinit_prompter(void) {
             /* already expired */\r
             goto _cleanup;\r
     } else {\r
-        FILETIME lifetime;\r
-        khm_int32 t;\r
-\r
-        /* make the cache expire at some point */\r
-        GetSystemTimeAsFileTime(&current);\r
-        khc_read_int32(csp_params, L"PromptCacheLifetime", &t);\r
-        if (t == 0)\r
-            t = 172800;         /* 48 hours */\r
-        TimetToFileTimeInterval(t, &lifetime);\r
-        expiry = FtAdd(&current, &lifetime);\r
-        iexpiry = FtToInt(&expiry);\r
-\r
-        khc_write_int64(csp_prcache, L"ExpiresOn", iexpiry);\r
+        /* if there is no value for ExpiresOn, we assume the prompts\r
+           have already expired. */\r
+        goto _cleanup;\r
     }\r
 \r
     /* we found a prompt cache.  We take this to imply that the\r
@@ -1167,9 +1157,16 @@ k5_kinit_prompter(krb5_context context,
                             (khm_int32) num_prompts);\r
 \r
             GetSystemTimeAsFileTime(&current);\r
+#ifdef USE_PROMPT_CACHE_LIFETIME\r
             khc_read_int32(csp_params, L"PromptCacheLifetime", &t);\r
             if (t == 0)\r
                 t = 172800;         /* 48 hours */\r
+#else\r
+            khc_read_int32(csp_params, L"MaxRenewLifetime", &t);\r
+            if (t == 0)\r
+                t = 2592000;    /* 30 days */\r
+            t += 604800;        /* + 7 days */\r
+#endif\r
             TimetToFileTimeInterval(t, &lifetime);\r
             expiry = FtAdd(&current, &lifetime);\r
             iexpiry = FtToInt(&expiry);\r
index b4982218ecd7c6a0226688d70f0ed52a0f1147f8..4ed45e6d91775ea50a364e33552e292e6d675ac0 100644 (file)
@@ -1037,7 +1037,8 @@ cw_del_outline(khui_credwnd_outline *o) {
         o->data)\r
         PFREE(o->data);\r
 \r
-    if ((o->flags & KHUI_CW_O_STICKY) &&\r
+    if (((o->flags & KHUI_CW_O_STICKY) ||\r
+         (o->flags & KHUI_CW_O_RELIDENT)) &&\r
         o->data)\r
         kcdb_identity_release((khm_handle) o->data);\r
 \r
@@ -1666,7 +1667,8 @@ cw_update_outline(khui_credwnd_tbl * tbl)
         prevcred = NULL;\r
     }\r
 \r
-    /* Add any sticky identities that we haven't seen yet */\r
+    /* Add any default identities with no credentials and sticky\r
+       identities that we haven't seen yet */\r
     if (n_grouping > 0 && \r
         tbl->cols[grouping[0]].attr_id == KCDB_ATTR_ID_NAME) {\r
 \r
@@ -1678,6 +1680,56 @@ cw_update_outline(khui_credwnd_tbl * tbl)
         wchar_t ** idarray = NULL;\r
         int i;\r
 \r
+        /* see if the defualt identity is in the list */\r
+        {\r
+            khm_handle id_def = NULL;\r
+            wchar_t idname[KCDB_IDENT_MAXCCH_NAME];\r
+            khm_size cb;\r
+            khm_int32 flags;\r
+\r
+            if (KHM_FAILED(kcdb_identity_get_default(&id_def))) {\r
+                goto done_with_defident;\r
+            }\r
+\r
+            kcdb_identity_get_flags(id_def, &flags);\r
+            cb = sizeof(idname);\r
+            kcdb_identity_get_name(id_def, idname, &cb);\r
+\r
+            for (o = tbl->outline; o; o = LNEXT(o)) {\r
+                if (!wcscmp(idname, o->header))\r
+                    break;\r
+            }\r
+\r
+            if (o == NULL) {\r
+                o = cw_new_outline_node(idname);\r
+                LPUSH(&tbl->outline, o);\r
+                o->flags = KHUI_CW_O_VISIBLE | KHUI_CW_O_RELIDENT;\r
+                o->level = 0;\r
+                o->col = grouping[0];\r
+                o->data = id_def;\r
+                o->attr_id = KCDB_ATTR_ID;\r
+\r
+                if (flags & KCDB_IDENT_FLAG_STICKY)\r
+                    o->flags |= KHUI_CW_O_STICKY;\r
+\r
+                o->start = n_rows;\r
+                o->length = 1;\r
+                o->idx_start = -1;\r
+\r
+                if (grouping[0] == tbl->n_cols - 1)\r
+                    o->flags |= KHUI_CW_O_NOOUTLINE;\r
+\r
+                cw_set_tbl_row_header(tbl, n_rows, grouping[0], o);\r
+\r
+                n_rows ++;\r
+            } else {\r
+                kcdb_identity_release(id_def);\r
+            }\r
+\r
+        done_with_defident:\r
+            ;\r
+        }\r
+\r
         if (kcdb_identity_enum(KCDB_IDENT_FLAG_STICKY,\r
                                KCDB_IDENT_FLAG_STICKY,\r
                                NULL,\r
@@ -1728,10 +1780,15 @@ cw_update_outline(khui_credwnd_tbl * tbl)
             } else {\r
                 /* not found.  create */\r
                 o = cw_new_outline_node(idarray[i]);\r
+                LPUSH(&tbl->outline, o);\r
                 o->flags = KHUI_CW_O_VISIBLE;\r
                 o->level = 0;\r
                 o->col = grouping[0];\r
                 o->data = (void *) h;\r
+                o->attr_id = KCDB_ATTR_ID;\r
+\r
+                if (grouping[0] == tbl->n_cols - 1)\r
+                    o->flags |= KHUI_CW_O_NOOUTLINE;\r
             }\r
 \r
             if (o->flags & KHUI_CW_O_STICKY)\r
@@ -3963,22 +4020,14 @@ cw_wm_mouse(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
     x += tbl->scr_left;\r
     y += tbl->scr_top - tbl->header_height;\r
 \r
-    if (tbl->flags & KHUI_CW_TBL_EXPIDENT) {\r
-        int ty = 0;\r
-\r
-        for (i=0; i < tbl->n_rows; i++) {\r
-            if (tbl->rows[i].flags & KHUI_CW_ROW_EXPVIEW)\r
-                ty += tbl->cell_height * CW_EXP_ROW_MULT;\r
-            else\r
-                ty += tbl->cell_height;\r
+    row = -1;\r
 \r
-            if (ty > y)\r
-                break;\r
+    for (i=0; i < tbl->n_rows; i++) {\r
+        if (y >= tbl->rows[i].r_ext.top &&\r
+            y < tbl->rows[i].r_ext.bottom) {\r
+            row = i;\r
+            break;\r
         }\r
-\r
-        row = i;\r
-    } else {\r
-        row = y / tbl->cell_height;\r
     }\r
 \r
     col = -1;\r
@@ -4006,7 +4055,7 @@ cw_wm_mouse(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
             o = (khui_credwnd_outline *) tbl->rows[row].data;\r
 \r
             /* are we on a widget then? */\r
-            x -= tbl->cols[tbl->rows[row].col].x;\r
+            x -= tbl->cols[o->col].x;\r
 \r
             if (!(o->flags & KHUI_CW_O_NOOUTLINE)) {\r
                 if(x >= 0 && x < KHUI_SMICON_CX) /* hit */ {\r
@@ -4116,41 +4165,14 @@ cw_wm_mouse(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
         }\r
         if(tbl->mouse_state & CW_MOUSE_WSTICKY) {\r
             if (tbl->flags & KHUI_CW_TBL_EXPIDENT) {\r
-                int ty = 0;\r
 \r
-                for (i=0; i < tbl->n_rows && i < tbl->mouse_row; i++) {\r
-                    if (tbl->rows[i].flags & KHUI_CW_ROW_EXPVIEW)\r
-                        ty += tbl->cell_height * CW_EXP_ROW_MULT;\r
-                    else\r
-                        ty += tbl->cell_height;\r
-                }\r
-\r
-                r.top = ty;\r
-\r
-                if (tbl->mouse_row < tbl->n_rows &&\r
-                    (tbl->rows[tbl->mouse_row].flags & KHUI_CW_ROW_EXPVIEW)) {\r
-                    r.bottom = r.top + tbl->cell_height * CW_EXP_ROW_MULT;\r
-                } else {\r
-                    r.bottom = r.top + tbl->cell_height;\r
-                }\r
-\r
-                if (tbl->mouse_row < tbl->n_rows &&\r
-                    (tbl->rows[tbl->mouse_row].flags & KHUI_CW_ROW_HEADER)) {\r
-                    khui_credwnd_outline * o;\r
-\r
-                    o = (khui_credwnd_outline *) tbl->rows[tbl->mouse_row].data;\r
-\r
-                    if (o->flags & KHUI_CW_O_NOOUTLINE) {\r
-                        r.left = tbl->cols[tbl->mouse_col].x - tbl->scr_left;\r
-                    } else {\r
-                        r.left = KHUI_SMICON_CX * 3 / 2 + tbl->cols[tbl->mouse_col].x - tbl->scr_left;\r
-                    }\r
+                if (tbl->mouse_row >= 0 && tbl->mouse_row < tbl->n_rows) {\r
+                    r = tbl->rows[tbl->mouse_row].r_ext;\r
+                    OffsetRect(&r, -tbl->scr_left, tbl->header_height - tbl->scr_top);\r
                     r.right = r.left + KHUI_SMICON_CX;\r
-                } else {\r
-#ifdef DEBUG\r
-                    assert(FALSE);\r
-#endif\r
+                    InvalidateRect(tbl->hwnd, &r, TRUE);\r
                 }\r
+\r
             } else {\r
                 r.left = KHUI_SMICON_CX * 3 / 2 + \r
                     tbl->cols[tbl->mouse_col].x - tbl->scr_left;\r
@@ -4182,41 +4204,14 @@ cw_wm_mouse(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
         }\r
         if(tbl->mouse_state & CW_MOUSE_WSTICKY) {\r
             if (tbl->flags & KHUI_CW_TBL_EXPIDENT) {\r
-                int ty = 0;\r
-\r
-                for (i=0; i < tbl->n_rows && i < tbl->mouse_row; i++) {\r
-                    if (tbl->rows[i].flags & KHUI_CW_ROW_EXPVIEW)\r
-                        ty += tbl->cell_height * CW_EXP_ROW_MULT;\r
-                    else\r
-                        ty += tbl->cell_height;\r
-                }\r
-\r
-                r.top = ty;\r
-\r
-                if (tbl->mouse_row < tbl->n_rows &&\r
-                    (tbl->rows[tbl->mouse_row].flags & KHUI_CW_ROW_EXPVIEW)) {\r
-                    r.bottom = r.top + tbl->cell_height * CW_EXP_ROW_MULT;\r
-                } else {\r
-                    r.bottom = r.top + tbl->cell_height;\r
-                }\r
 \r
-                if (tbl->mouse_row < tbl->n_rows &&\r
-                    (tbl->rows[tbl->mouse_row].flags & KHUI_CW_ROW_HEADER)) {\r
-                    khui_credwnd_outline * o;\r
-\r
-                    o = (khui_credwnd_outline *) tbl->rows[tbl->mouse_row].data;\r
-\r
-                    if (o->flags & KHUI_CW_O_NOOUTLINE) {\r
-                        r.left = tbl->cols[tbl->mouse_col].x - tbl->scr_left;\r
-                    } else {\r
-                        r.left = KHUI_SMICON_CX * 3 / 2 + tbl->cols[tbl->mouse_col].x - tbl->scr_left;\r
-                    }\r
+                if (tbl->mouse_row >= 0 && tbl->mouse_row < tbl->n_rows) {\r
+                    r = tbl->rows[tbl->mouse_row].r_ext;\r
+                    OffsetRect(&r, -tbl->scr_left, tbl->header_height - tbl->scr_top);\r
                     r.right = r.left + KHUI_SMICON_CX;\r
-                } else {\r
-#ifdef DEBUG\r
-                    assert(FALSE);\r
-#endif\r
+                    InvalidateRect(tbl->hwnd, &r, TRUE);\r
                 }\r
+\r
             } else {\r
                 r.left = KHUI_SMICON_CX * 3 / 2 + \r
                     tbl->cols[tbl->mouse_col].x - tbl->scr_left;\r
index 42edf2842b5f8678a43c26b2ad74e465c348fbac..7e7e63cba79c9d15d5df2022e0040a5a8b4c8420 100644 (file)
@@ -68,6 +68,7 @@ typedef struct khui_credwnd_outline_t {
 #define KHUI_CW_O_SELECTED      0x00000010\r
 #define KHUI_CW_O_DATAALLOC     0x00000020\r
 #define KHUI_CW_O_NOOUTLINE     0x00000040\r
+#define KHUI_CW_O_RELIDENT      0x00000080\r
 \r
 typedef struct khui_credwnd_row_t {\r
     khm_int32   flags;\r