summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2020-02-24 08:40:45 +0100
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2020-02-24 08:40:45 +0100
commita5ea2f7e9928c651319f8133eeb0fcc9fe6df6fb (patch)
tree761528101bd2df4dffdd6504ee24a1acabeba8d2
parent291b3cebb905c3924eefa1e5a7c6ac31ca89aacd (diff)
parent875420f1c29f0d5e66b4dcacbe95d31dd5dca585 (diff)
Merge remote-tracking branch 'origin/5.14' into 5.15
-rw-r--r--src/3rdparty/md4c/md4c.c596
-rw-r--r--src/3rdparty/md4c/md4c.h19
-rw-r--r--src/3rdparty/md4c/qt_attribution.json6
-rw-r--r--src/plugins/styles/windowsvista/qwindowsvistastyle.cpp2
-rw-r--r--src/plugins/styles/windowsvista/qwindowsxpstyle.cpp4
-rw-r--r--src/widgets/dialogs/qcolordialog.cpp3
-rw-r--r--src/widgets/dialogs/qwizard.cpp7
-rw-r--r--src/widgets/graphicsview/qgraphicslayout_p.h4
-rw-r--r--src/widgets/graphicsview/qgraphicslayoutstyleinfo.cpp4
-rw-r--r--src/widgets/graphicsview/qgraphicswidget.cpp2
-rw-r--r--src/widgets/itemviews/qabstractitemview.cpp4
-rw-r--r--src/widgets/itemviews/qitemdelegate.cpp2
-rw-r--r--src/widgets/itemviews/qlistview.cpp7
-rw-r--r--src/widgets/styles/qcommonstyle.cpp42
-rw-r--r--src/widgets/styles/qfusionstyle.cpp8
-rw-r--r--src/widgets/styles/qpixmapstyle.cpp4
-rw-r--r--src/widgets/widgets/qcalendarwidget.cpp4
-rw-r--r--src/widgets/widgets/qcombobox_p.h2
-rw-r--r--src/widgets/widgets/qcommandlinkbutton.cpp8
-rw-r--r--src/widgets/widgets/qfocusframe.cpp12
-rw-r--r--src/widgets/widgets/qgroupbox.cpp6
-rw-r--r--src/widgets/widgets/qlineedit.cpp2
-rw-r--r--src/widgets/widgets/qmenu.cpp2
-rw-r--r--src/widgets/widgets/qmenubar.cpp2
-rw-r--r--src/widgets/widgets/qtoolbarextension.cpp4
-rw-r--r--src/widgets/widgets/qwidgettextcontrol.cpp2
-rw-r--r--tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp27
-rw-r--r--tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp2
28 files changed, 489 insertions, 298 deletions
diff --git a/src/3rdparty/md4c/md4c.c b/src/3rdparty/md4c/md4c.c
index 3745cf3e46..b0ef739b3c 100644
--- a/src/3rdparty/md4c/md4c.c
+++ b/src/3rdparty/md4c/md4c.c
@@ -2,7 +2,7 @@
* MD4C: Markdown parser for C
* (http://github.com/mity/md4c)
*
- * Copyright (c) 2016-2019 Martin Mitas
+ * Copyright (c) 2016-2020 Martin Mitas
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -35,14 +35,23 @@
*** Miscellaneous Stuff ***
*****************************/
-#ifdef _MSC_VER
- /* MSVC does not understand "inline" when building as pure C (not C++).
- * However it understands "__inline" */
- #ifndef __cplusplus
+#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199409L
+ /* C89/90 or old compilers in general may not understand "inline". */
+ #if defined __GNUC__
+ #define inline __inline__
+ #elif defined _MSC_VER
#define inline __inline
+ #else
+ #define inline
#endif
#endif
+/* Make the UTF-8 support the default. */
+#if !defined MD4C_USE_ASCII && !defined MD4C_USE_UTF8 && !defined MD4C_USE_UTF16
+ #define MD4C_USE_UTF8
+#endif
+
+/* Magic for making wide literals with MD4C_USE_UTF16. */
#ifdef _T
#undef _T
#endif
@@ -127,7 +136,7 @@ struct MD_CTX_tag {
#endif
/* For resolving of inline spans. */
- MD_MARKCHAIN mark_chains[12];
+ MD_MARKCHAIN mark_chains[13];
#define PTR_CHAIN ctx->mark_chains[0]
#define TABLECELLBOUNDARIES ctx->mark_chains[1]
#define ASTERISK_OPENERS_extraword_mod3_0 ctx->mark_chains[2]
@@ -137,11 +146,12 @@ struct MD_CTX_tag {
#define ASTERISK_OPENERS_intraword_mod3_1 ctx->mark_chains[6]
#define ASTERISK_OPENERS_intraword_mod3_2 ctx->mark_chains[7]
#define UNDERSCORE_OPENERS ctx->mark_chains[8]
-#define TILDE_OPENERS ctx->mark_chains[9]
-#define BRACKET_OPENERS ctx->mark_chains[10]
-#define DOLLAR_OPENERS ctx->mark_chains[11]
+#define TILDE_OPENERS_1 ctx->mark_chains[9]
+#define TILDE_OPENERS_2 ctx->mark_chains[10]
+#define BRACKET_OPENERS ctx->mark_chains[11]
+#define DOLLAR_OPENERS ctx->mark_chains[12]
#define OPENERS_CHAIN_FIRST 2
-#define OPENERS_CHAIN_LAST 11
+#define OPENERS_CHAIN_LAST 12
int n_table_cell_boundaries;
@@ -263,6 +273,9 @@ struct MD_VERBATIMLINE_tag {
#define CH(off) (ctx->text[(off)])
#define STR(off) (ctx->text + (off))
+/* Check whether the pointer points into ctx->text. */
+#define IS_INPUT_STR(ptr) (ctx->text <= (ptr) && (ptr) < (ctx->text + ctx->size))
+
/* Character classification.
* Note we assume ASCII compatibility of code points < 128 here. */
#define ISIN_(ch, ch_min, ch_max) ((ch_min) <= (unsigned)(ch) && (unsigned)(ch) <= (ch_max))
@@ -297,16 +310,14 @@ struct MD_VERBATIMLINE_tag {
#define ISDIGIT(off) ISDIGIT_(CH(off))
#define ISXDIGIT(off) ISXDIGIT_(CH(off))
#define ISALNUM(off) ISALNUM_(CH(off))
-static inline const CHAR*
-md_strchr(const CHAR* str, CHAR ch)
-{
- OFF i;
- for(i = 0; str[i] != _T('\0'); i++) {
- if(ch == str[i])
- return (str + i);
- }
- return NULL;
-}
+
+
+#if defined MD4C_USE_UTF16
+ #define md_strchr wcschr
+#else
+ #define md_strchr strchr
+#endif
+
/* Case insensitive check of string equality. */
static inline int
@@ -364,89 +375,89 @@ md_text_with_null_replacement(MD_CTX* ctx, MD_TEXTTYPE type, const CHAR* str, SZ
}
-#define MD_CHECK(func) \
- do { \
- ret = (func); \
- if(ret < 0) \
- goto abort; \
+#define MD_CHECK(func) \
+ do { \
+ ret = (func); \
+ if(ret < 0) \
+ goto abort; \
} while(0)
-#define MD_TEMP_BUFFER(sz) \
- do { \
- if(sz > ctx->alloc_buffer) { \
- CHAR* new_buffer; \
- SZ new_size = ((sz) + (sz) / 2 + 128) & ~127; \
- \
- new_buffer = realloc(ctx->buffer, new_size); \
- if(new_buffer == NULL) { \
- MD_LOG("realloc() failed."); \
- ret = -1; \
- goto abort; \
- } \
- \
- ctx->buffer = new_buffer; \
- ctx->alloc_buffer = new_size; \
- } \
+#define MD_TEMP_BUFFER(sz) \
+ do { \
+ if(sz > ctx->alloc_buffer) { \
+ CHAR* new_buffer; \
+ SZ new_size = ((sz) + (sz) / 2 + 128) & ~127; \
+ \
+ new_buffer = realloc(ctx->buffer, new_size); \
+ if(new_buffer == NULL) { \
+ MD_LOG("realloc() failed."); \
+ ret = -1; \
+ goto abort; \
+ } \
+ \
+ ctx->buffer = new_buffer; \
+ ctx->alloc_buffer = new_size; \
+ } \
} while(0)
-#define MD_ENTER_BLOCK(type, arg) \
- do { \
- ret = ctx->parser.enter_block((type), (arg), ctx->userdata); \
- if(ret != 0) { \
- MD_LOG("Aborted from enter_block() callback."); \
- goto abort; \
- } \
+#define MD_ENTER_BLOCK(type, arg) \
+ do { \
+ ret = ctx->parser.enter_block((type), (arg), ctx->userdata); \
+ if(ret != 0) { \
+ MD_LOG("Aborted from enter_block() callback."); \
+ goto abort; \
+ } \
} while(0)
-#define MD_LEAVE_BLOCK(type, arg) \
- do { \
- ret = ctx->parser.leave_block((type), (arg), ctx->userdata); \
- if(ret != 0) { \
- MD_LOG("Aborted from leave_block() callback."); \
- goto abort; \
- } \
+#define MD_LEAVE_BLOCK(type, arg) \
+ do { \
+ ret = ctx->parser.leave_block((type), (arg), ctx->userdata); \
+ if(ret != 0) { \
+ MD_LOG("Aborted from leave_block() callback."); \
+ goto abort; \
+ } \
} while(0)
-#define MD_ENTER_SPAN(type, arg) \
- do { \
- ret = ctx->parser.enter_span((type), (arg), ctx->userdata); \
- if(ret != 0) { \
- MD_LOG("Aborted from enter_span() callback."); \
- goto abort; \
- } \
+#define MD_ENTER_SPAN(type, arg) \
+ do { \
+ ret = ctx->parser.enter_span((type), (arg), ctx->userdata); \
+ if(ret != 0) { \
+ MD_LOG("Aborted from enter_span() callback."); \
+ goto abort; \
+ } \
} while(0)
-#define MD_LEAVE_SPAN(type, arg) \
- do { \
- ret = ctx->parser.leave_span((type), (arg), ctx->userdata); \
- if(ret != 0) { \
- MD_LOG("Aborted from leave_span() callback."); \
- goto abort; \
- } \
+#define MD_LEAVE_SPAN(type, arg) \
+ do { \
+ ret = ctx->parser.leave_span((type), (arg), ctx->userdata); \
+ if(ret != 0) { \
+ MD_LOG("Aborted from leave_span() callback."); \
+ goto abort; \
+ } \
} while(0)
-#define MD_TEXT(type, str, size) \
- do { \
- if(size > 0) { \
- ret = ctx->parser.text((type), (str), (size), ctx->userdata); \
- if(ret != 0) { \
- MD_LOG("Aborted from text() callback."); \
- goto abort; \
- } \
- } \
+#define MD_TEXT(type, str, size) \
+ do { \
+ if(size > 0) { \
+ ret = ctx->parser.text((type), (str), (size), ctx->userdata); \
+ if(ret != 0) { \
+ MD_LOG("Aborted from text() callback."); \
+ goto abort; \
+ } \
+ } \
} while(0)
-#define MD_TEXT_INSECURE(type, str, size) \
- do { \
- if(size > 0) { \
- ret = md_text_with_null_replacement(ctx, type, str, size); \
- if(ret != 0) { \
- MD_LOG("Aborted from text() callback."); \
- goto abort; \
- } \
- } \
+#define MD_TEXT_INSECURE(type, str, size) \
+ do { \
+ if(size > 0) { \
+ ret = md_text_with_null_replacement(ctx, type, str, size); \
+ if(ret != 0) { \
+ MD_LOG("Aborted from text() callback."); \
+ goto abort; \
+ } \
+ } \
} while(0)
@@ -1329,8 +1340,9 @@ md_build_attr_append_substr(MD_CTX* ctx, MD_ATTRIBUTE_BUILD* build,
MD_TEXTTYPE* new_substr_types;
OFF* new_substr_offsets;
- build->substr_alloc = (build->substr_alloc == 0 ? 8 : build->substr_alloc * 2);
-
+ build->substr_alloc = (build->substr_alloc > 0
+ ? build->substr_alloc + build->substr_alloc / 2
+ : 8);
new_substr_types = (MD_TEXTTYPE*) realloc(build->substr_types,
build->substr_alloc * sizeof(MD_TEXTTYPE));
if(new_substr_types == NULL) {
@@ -1456,8 +1468,8 @@ abort:
*** Dictionary of Reference Definitions ***
*********************************************/
-#define MD_FNV1A_BASE 2166136261
-#define MD_FNV1A_PRIME 16777619
+#define MD_FNV1A_BASE 2166136261U
+#define MD_FNV1A_PRIME 16777619U
static inline unsigned
md_fnv1a(unsigned base, const void* data, size_t n)
@@ -1479,9 +1491,7 @@ struct MD_REF_DEF_tag {
CHAR* label;
CHAR* title;
unsigned hash;
- SZ label_size : 24;
- unsigned label_needs_free : 1;
- unsigned title_needs_free : 1;
+ SZ label_size;
SZ title_size;
OFF dest_beg;
OFF dest_end;
@@ -1530,7 +1540,7 @@ md_link_label_cmp_load_fold_info(const CHAR* label, OFF off, SZ size,
SZ char_size;
if(off >= size) {
- /* Treat end of link label as a whitespace. */
+ /* Treat end of a link label as a whitespace. */
goto whitespace;
}
@@ -1554,7 +1564,7 @@ md_link_label_cmp_load_fold_info(const CHAR* label, OFF off, SZ size,
whitespace:
fold_info->codepoints[0] = _T(' ');
fold_info->n_codepoints = 1;
- return off;
+ return md_skip_unicode_whitespace(label, off, size);
}
static int
@@ -1572,7 +1582,7 @@ md_link_label_cmp(const CHAR* a_label, SZ a_size, const CHAR* b_label, SZ b_size
a_off = md_skip_unicode_whitespace(a_label, 0, a_size);
b_off = md_skip_unicode_whitespace(b_label, 0, b_size);
- while(!a_reached_end && !b_reached_end) {
+ while(!a_reached_end || !b_reached_end) {
/* If needed, load fold info for next char. */
if(a_fi_off >= a_fi.n_codepoints) {
a_fi_off = 0;
@@ -1618,7 +1628,7 @@ md_ref_def_cmp(const void* a, const void* b)
}
static int
-md_ref_def_cmp_stable(const void* a, const void* b)
+md_ref_def_cmp_for_sort(const void* a, const void* b)
{
int cmp;
@@ -1671,6 +1681,7 @@ md_build_ref_def_hashtable(MD_CTX* ctx)
bucket = ctx->ref_def_hashtable[def->hash % ctx->ref_def_hashtable_size];
if(bucket == NULL) {
+ /* The bucket is empty. Make it just point to the def. */
ctx->ref_def_hashtable[def->hash % ctx->ref_def_hashtable_size] = def;
continue;
}
@@ -1682,12 +1693,12 @@ md_build_ref_def_hashtable(MD_CTX* ctx)
MD_REF_DEF* old_def = (MD_REF_DEF*) bucket;
if(md_link_label_cmp(def->label, def->label_size, old_def->label, old_def->label_size) == 0) {
- /* Ignore this ref. def. */
+ /* Duplicate label: Ignore this ref. def. */
continue;
}
- /* Make the bucket capable of holding more ref. defs. */
- list = (MD_REF_DEF_LIST*) malloc(sizeof(MD_REF_DEF_LIST) + 4 * sizeof(MD_REF_DEF*));
+ /* Make the bucket complex, i.e. able to hold more ref. defs. */
+ list = (MD_REF_DEF_LIST*) malloc(sizeof(MD_REF_DEF_LIST) + 2 * sizeof(MD_REF_DEF*));
if(list == NULL) {
MD_LOG("malloc() failed.");
goto abort;
@@ -1695,22 +1706,28 @@ md_build_ref_def_hashtable(MD_CTX* ctx)
list->ref_defs[0] = old_def;
list->ref_defs[1] = def;
list->n_ref_defs = 2;
- list->alloc_ref_defs = 4;
+ list->alloc_ref_defs = 2;
ctx->ref_def_hashtable[def->hash % ctx->ref_def_hashtable_size] = list;
continue;
}
- /* Append the def to the bucket list. */
+ /* Append the def to the complex bucket list.
+ *
+ * Note in this case we ignore potential duplicates to avoid expensive
+ * iterating over the complex bucket. Below, we revisit all the complex
+ * buckets and handle it more cheaply after the complex bucket contents
+ * is sorted. */
list = (MD_REF_DEF_LIST*) bucket;
if(list->n_ref_defs >= list->alloc_ref_defs) {
+ int alloc_ref_defs = list->alloc_ref_defs + list->alloc_ref_defs / 2;
MD_REF_DEF_LIST* list_tmp = (MD_REF_DEF_LIST*) realloc(list,
- sizeof(MD_REF_DEF_LIST) + 2 * list->alloc_ref_defs * sizeof(MD_REF_DEF*));
+ sizeof(MD_REF_DEF_LIST) + alloc_ref_defs * sizeof(MD_REF_DEF*));
if(list_tmp == NULL) {
MD_LOG("realloc() failed.");
goto abort;
}
list = list_tmp;
- list->alloc_ref_defs *= 2;
+ list->alloc_ref_defs = alloc_ref_defs;
ctx->ref_def_hashtable[def->hash % ctx->ref_def_hashtable_size] = list;
}
@@ -1729,9 +1746,12 @@ md_build_ref_def_hashtable(MD_CTX* ctx)
continue;
list = (MD_REF_DEF_LIST*) bucket;
- qsort(list->ref_defs, list->n_ref_defs, sizeof(MD_REF_DEF*), md_ref_def_cmp_stable);
+ qsort(list->ref_defs, list->n_ref_defs, sizeof(MD_REF_DEF*), md_ref_def_cmp_for_sort);
- /* Disable duplicates. */
+ /* Disable all duplicates in the complex bucket by forcing all such
+ * records to point to the 1st such ref. def. I.e. no matter which
+ * record is found during the lookup, it will always point to the right
+ * ref. def. in ctx->ref_defs[]. */
for(j = 1; j < list->n_ref_defs; j++) {
if(md_ref_def_cmp(&list->ref_defs[j-1], &list->ref_defs[j]) == 0)
list->ref_defs[j] = list->ref_defs[j-1];
@@ -2055,9 +2075,8 @@ md_is_link_reference_definition(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
OFF label_contents_end;
int label_contents_line_index = -1;
int label_is_multiline;
- CHAR* label;
+ CHAR* label = NULL;
SZ label_size;
- int label_needs_free = FALSE;
OFF dest_contents_beg;
OFF dest_contents_end;
OFF title_contents_beg;
@@ -2123,23 +2142,22 @@ md_is_link_reference_definition(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
if(!label_is_multiline) {
label = (CHAR*) STR(label_contents_beg);
label_size = label_contents_end - label_contents_beg;
- label_needs_free = FALSE;
} else {
MD_CHECK(md_merge_lines_alloc(ctx, label_contents_beg, label_contents_end,
lines + label_contents_line_index, n_lines - label_contents_line_index,
_T(' '), &label, &label_size));
- label_needs_free = TRUE;
}
/* Store the reference definition. */
if(ctx->n_ref_defs >= ctx->alloc_ref_defs) {
MD_REF_DEF* new_defs;
- ctx->alloc_ref_defs = (ctx->alloc_ref_defs > 0 ? ctx->alloc_ref_defs * 2 : 16);
+ ctx->alloc_ref_defs = (ctx->alloc_ref_defs > 0
+ ? ctx->alloc_ref_defs + ctx->alloc_ref_defs / 2
+ : 16);
new_defs = (MD_REF_DEF*) realloc(ctx->ref_defs, ctx->alloc_ref_defs * sizeof(MD_REF_DEF));
if(new_defs == NULL) {
MD_LOG("realloc() failed.");
- ret = -1;
goto abort;
}
@@ -2151,7 +2169,6 @@ md_is_link_reference_definition(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
def->label = label;
def->label_size = label_size;
- def->label_needs_free = label_needs_free;
def->dest_beg = dest_contents_beg;
def->dest_end = dest_contents_end;
@@ -2166,7 +2183,6 @@ md_is_link_reference_definition(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
MD_CHECK(md_merge_lines_alloc(ctx, title_contents_beg, title_contents_end,
lines + title_contents_line_index, n_lines - title_contents_line_index,
_T('\n'), &def->title, &def->title_size));
- def->title_needs_free = TRUE;
}
/* Success. */
@@ -2175,9 +2191,9 @@ md_is_link_reference_definition(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
abort:
/* Failure. */
- if(label_needs_free)
+ if(!IS_INPUT_STR(label))
free(label);
- return -1;
+ return ret;
}
static int
@@ -2225,7 +2241,7 @@ md_is_link_reference(MD_CTX* ctx, const MD_LINE* lines, int n_lines,
attr->title_needs_free = FALSE;
}
- if(beg_line != end_line)
+ if(!IS_INPUT_STR(label))
free(label);
ret = (def != NULL);
@@ -2339,9 +2355,9 @@ md_free_ref_defs(MD_CTX* ctx)
for(i = 0; i < ctx->n_ref_defs; i++) {
MD_REF_DEF* def = &ctx->ref_defs[i];
- if(def->label_needs_free)
+ if(!IS_INPUT_STR(def->label))
free(def->label);
- if(def->title_needs_free)
+ if(!IS_INPUT_STR(def->title))
free(def->title);
}
@@ -2470,7 +2486,7 @@ md_mark_chain(MD_CTX* ctx, int mark_index)
switch(mark->ch) {
case _T('*'): return md_asterisk_chain(ctx, mark->flags);
case _T('_'): return &UNDERSCORE_OPENERS;
- case _T('~'): return &TILDE_OPENERS;
+ case _T('~'): return (mark->end - mark->beg == 1) ? &TILDE_OPENERS_1 : &TILDE_OPENERS_2;
case _T('['): return &BRACKET_OPENERS;
case _T('|'): return &TABLECELLBOUNDARIES;
default: return NULL;
@@ -2483,7 +2499,9 @@ md_push_mark(MD_CTX* ctx)
if(ctx->n_marks >= ctx->alloc_marks) {
MD_MARK* new_marks;
- ctx->alloc_marks = (ctx->alloc_marks > 0 ? ctx->alloc_marks * 2 : 64);
+ ctx->alloc_marks = (ctx->alloc_marks > 0
+ ? ctx->alloc_marks + ctx->alloc_marks / 2
+ : 64);
new_marks = realloc(ctx->marks, ctx->alloc_marks * sizeof(MD_MARK));
if(new_marks == NULL) {
MD_LOG("realloc() failed.");
@@ -2526,6 +2544,7 @@ md_mark_chain_append(MD_CTX* ctx, MD_MARKCHAIN* chain, int mark_index)
chain->head = mark_index;
ctx->marks[mark_index].prev = chain->tail;
+ ctx->marks[mark_index].next = -1;
chain->tail = mark_index;
}
@@ -2617,7 +2636,7 @@ md_rollback(MD_CTX* ctx, int opener_index, int closer_index, int how)
chain->head = -1;
}
- /* Go backwards so that un-resolved openers are re-added into their
+ /* Go backwards so that unresolved openers are re-added into their
* respective chains, in the right order. */
mark_index = closer_index - 1;
while(mark_index > opener_index) {
@@ -2696,7 +2715,7 @@ md_build_mark_char_map(MD_CTX* ctx)
if(ctx->parser.flags & MD_FLAG_PERMISSIVEWWWAUTOLINKS)
ctx->mark_char_map['.'] = 1;
- if(ctx->parser.flags & MD_FLAG_TABLES)
+ if((ctx->parser.flags & MD_FLAG_TABLES) || (ctx->parser.flags & MD_FLAG_WIKILINKS))
ctx->mark_char_map['|'] = 1;
if(ctx->parser.flags & MD_FLAG_COLLAPSEWHITESPACE) {
@@ -2896,7 +2915,7 @@ md_is_autolink_email(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end)
return FALSE;
off++;
- /* Labels delimited with '.'; each label is sequence of 1 - 62 alnum
+ /* Labels delimited with '.'; each label is sequence of 1 - 63 alnum
* characters or '-', but '-' is not allowed as first or last char. */
label_len = 0;
while(off < max_end) {
@@ -2909,7 +2928,7 @@ md_is_autolink_email(MD_CTX* ctx, OFF beg, OFF max_end, OFF* p_end)
else
break;
- if(label_len > 62)
+ if(label_len > 63)
return FALSE;
off++;
@@ -3236,8 +3255,8 @@ md_collect_marks(MD_CTX* ctx, const MD_LINE* lines, int n_lines, int table_mode)
continue;
}
- /* A potential table cell boundary. */
- if(table_mode && ch == _T('|')) {
+ /* A potential table cell boundary or wiki link label delimiter. */
+ if((table_mode || ctx->parser.flags & MD_FLAG_WIKILINKS) && ch == _T('|')) {
PUSH_MARK(ch, off, off+1, 0);
off++;
continue;
@@ -3250,7 +3269,17 @@ md_collect_marks(MD_CTX* ctx, const MD_LINE* lines, int n_lines, int table_mode)
while(tmp < line_end && CH(tmp) == _T('~'))
tmp++;
- PUSH_MARK(ch, off, tmp, MD_MARK_POTENTIAL_OPENER | MD_MARK_POTENTIAL_CLOSER);
+ if(tmp - off < 3) {
+ unsigned flags = 0;
+
+ if(tmp < line_end && !ISUNICODEWHITESPACE(tmp))
+ flags |= MD_MARK_POTENTIAL_OPENER;
+ if(off > line->beg && !ISUNICODEWHITESPACEBEFORE(off))
+ flags |= MD_MARK_POTENTIAL_CLOSER;
+ if(flags != 0)
+ PUSH_MARK(ch, off, tmp, flags);
+ }
+
off = tmp;
continue;
}
@@ -3398,6 +3427,91 @@ md_resolve_links(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
continue;
}
+ /* Recognize and resolve wiki links.
+ * Wiki-links maybe '[[destination]]' or '[[destination|label]]'.
+ */
+ if ((ctx->parser.flags & MD_FLAG_WIKILINKS) &&
+ (opener->end - opener->beg == 1) && /* not image */
+ next_opener != NULL && /* double '[' opener */
+ next_opener->ch == '[' &&
+ (next_opener->beg == opener->beg - 1) &&
+ (next_opener->end - next_opener->beg == 1) &&
+ next_closer != NULL && /* double ']' closer */
+ next_closer->ch == ']' &&
+ (next_closer->beg == closer->beg + 1) &&
+ (next_closer->end - next_closer->beg == 1))
+ {
+ MD_MARK* delim = NULL;
+ int delim_index;
+ OFF dest_beg, dest_end;
+
+ is_link = TRUE;
+
+ /* We don't allow destination to be longer then 100 characters.
+ * Lets scan to see whether there is '|'. (If not then the whole
+ * wiki-link has to be below the 100 characters.) */
+ delim_index = opener_index + 1;
+ while(delim_index < closer_index) {
+ MD_MARK* m = &ctx->marks[delim_index];
+ if(m->ch == '|') {
+ delim = m;
+ break;
+ }
+ if(m->ch != 'D' && m->beg - opener->end > 100)
+ break;
+ delim_index++;
+ }
+ dest_beg = opener->end;
+ dest_end = (delim != NULL) ? delim->beg : closer->beg;
+ if(dest_end - dest_beg == 0 || dest_end - dest_beg > 100)
+ is_link = FALSE;
+
+ /* There may not be any new line in the destination. */
+ if(is_link) {
+ OFF off;
+ for(off = dest_beg; off < dest_end; off++) {
+ if(ISNEWLINE(off)) {
+ is_link = FALSE;
+ break;
+ }
+ }
+ }
+
+ if(is_link) {
+ if(delim != NULL) {
+ if(delim->end < closer->beg) {
+ opener->end = delim->beg;
+ } else {
+ /* The pipe is just before the closer: [[foo|]] */
+ closer->beg = delim->beg;
+ delim = NULL;
+ }
+ }
+
+ opener->beg = next_opener->beg;
+ opener->next = closer_index;
+ opener->flags |= MD_MARK_OPENER | MD_MARK_RESOLVED;
+
+ closer->end = next_closer->end;
+ closer->prev = opener_index;
+ closer->flags |= MD_MARK_CLOSER | MD_MARK_RESOLVED;
+
+ last_link_beg = opener->beg;
+ last_link_end = closer->end;
+
+ if(delim != NULL) {
+ delim->flags |= MD_MARK_RESOLVED;
+ md_rollback(ctx, opener_index, delim_index, MD_ROLLBACK_ALL);
+ md_analyze_link_contents(ctx, lines, n_lines, opener_index+1, closer_index);
+ } else {
+ md_rollback(ctx, opener_index, closer_index, MD_ROLLBACK_ALL);
+ }
+
+ opener_index = next_opener->prev;
+ continue;
+ }
+ }
+
if(next_opener != NULL && next_opener->beg == closer->end) {
if(next_closer->beg > closer->end + 1) {
/* Might be full reference link. */
@@ -3436,7 +3550,7 @@ md_resolve_links(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
if((mark->flags & (MD_MARK_OPENER | MD_MARK_RESOLVED)) == (MD_MARK_OPENER | MD_MARK_RESOLVED)) {
if(ctx->marks[mark->next].beg >= inline_link_end) {
/* Cancel the link status. */
- if(attr.title_needs_free)
+ if(!IS_INPUT_STR(attr.title))
free(attr.title);
is_link = FALSE;
break;
@@ -3476,6 +3590,7 @@ md_resolve_links(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
MD_ASSERT(ctx->marks[opener_index+2].ch == 'D');
md_mark_store_ptr(ctx, opener_index+2, attr.title);
+ /* The title might or might not have been allocated for us. */
if(attr.title_needs_free)
md_mark_chain_append(ctx, &PTR_CHAIN, opener_index+2);
ctx->marks[opener_index+2].prev = attr.title_size;
@@ -3574,8 +3689,7 @@ md_analyze_emph(MD_CTX* ctx, int mark_index)
int i, n_opener_chains;
unsigned flags = mark->flags;
- /* Apply "rule of three". (This is why we break asterisk opener
- * marks into multiple chains.) */
+ /* Apply the "rule of three". */
n_opener_chains = 0;
opener_chains[n_opener_chains++] = &ASTERISK_OPENERS_intraword_mod3_0;
if((flags & MD_MARK_EMPH_MOD3_MASK) != MD_MARK_EMPH_MOD3_2)
@@ -3611,16 +3725,17 @@ md_analyze_emph(MD_CTX* ctx, int mark_index)
if(opener != NULL) {
SZ opener_size = opener->end - opener->beg;
SZ closer_size = mark->end - mark->beg;
+ MD_MARKCHAIN* opener_chain = md_mark_chain(ctx, opener_index);
if(opener_size > closer_size) {
opener_index = md_split_emph_mark(ctx, opener_index, closer_size);
- md_mark_chain_append(ctx, md_mark_chain(ctx, opener_index), opener_index);
+ md_mark_chain_append(ctx, opener_chain, opener_index);
} else if(opener_size < closer_size) {
md_split_emph_mark(ctx, mark_index, closer_size - opener_size);
}
md_rollback(ctx, opener_index, mark_index, MD_ROLLBACK_CROSSING);
- md_resolve_range(ctx, chain, opener_index, mark_index);
+ md_resolve_range(ctx, opener_chain, opener_index, mark_index);
return;
}
}
@@ -3633,20 +3748,23 @@ md_analyze_emph(MD_CTX* ctx, int mark_index)
static void
md_analyze_tilde(MD_CTX* ctx, int mark_index)
{
- /* We attempt to be Github Flavored Markdown compatible here. GFM says
- * that length of the tilde sequence is not important at all. Note that
- * implies the TILDE_OPENERS chain can have at most one item. */
+ MD_MARK* mark = &ctx->marks[mark_index];
+ MD_MARKCHAIN* chain = md_mark_chain(ctx, mark_index);
+
+ /* We attempt to be Github Flavored Markdown compatible here. GFM accepts
+ * only tildes sequences of length 1 and 2, and the length of the opener
+ * and closer has to match. */
- if(TILDE_OPENERS.head >= 0) {
- /* The chain already contains an opener, so we may resolve the span. */
- int opener_index = TILDE_OPENERS.head;
+ if((mark->flags & MD_MARK_POTENTIAL_CLOSER) && chain->head >= 0) {
+ int opener_index = chain->head;
md_rollback(ctx, opener_index, mark_index, MD_ROLLBACK_CROSSING);
- md_resolve_range(ctx, &TILDE_OPENERS, opener_index, mark_index);
- } else {
- /* We can only be opener. */
- md_mark_chain_append(ctx, &TILDE_OPENERS, mark_index);
+ md_resolve_range(ctx, chain, opener_index, mark_index);
+ return;
}
+
+ if(mark->flags & MD_MARK_POTENTIAL_OPENER)
+ md_mark_chain_append(ctx, chain, mark_index);
}
static void
@@ -3860,8 +3978,16 @@ md_analyze_inlines(MD_CTX* ctx, const MD_LINE* lines, int n_lines, int table_mod
/* (1) Entities; code spans; autolinks; raw HTML. */
md_analyze_marks(ctx, lines, n_lines, 0, ctx->n_marks, _T("&"));
+ /* (2) Links. */
+ md_analyze_marks(ctx, lines, n_lines, 0, ctx->n_marks, _T("[]!"));
+ MD_CHECK(md_resolve_links(ctx, lines, n_lines));
+ BRACKET_OPENERS.head = -1;
+ BRACKET_OPENERS.tail = -1;
+ ctx->unresolved_link_head = -1;
+ ctx->unresolved_link_tail = -1;
+
if(table_mode) {
- /* (2) Analyze table cell boundaries.
+ /* (3) Analyze table cell boundaries.
* Note we reset TABLECELLBOUNDARIES chain prior to the call md_analyze_marks(),
* not after, because caller may need it. */
MD_ASSERT(n_lines == 1);
@@ -3872,14 +3998,6 @@ md_analyze_inlines(MD_CTX* ctx, const MD_LINE* lines, int n_lines, int table_mod
return ret;
}
- /* (3) Links. */
- md_analyze_marks(ctx, lines, n_lines, 0, ctx->n_marks, _T("[]!"));
- MD_CHECK(md_resolve_links(ctx, lines, n_lines));
- BRACKET_OPENERS.head = -1;
- BRACKET_OPENERS.tail = -1;
- ctx->unresolved_link_head = -1;
- ctx->unresolved_link_tail = -1;
-
/* (4) Emphasis and strong emphasis; permissive autolinks. */
md_analyze_link_contents(ctx, lines, n_lines, 0, ctx->n_marks);
@@ -3891,25 +4009,14 @@ static void
md_analyze_link_contents(MD_CTX* ctx, const MD_LINE* lines, int n_lines,
int mark_beg, int mark_end)
{
+ int i;
+
md_analyze_marks(ctx, lines, n_lines, mark_beg, mark_end, _T("*_~$@:."));
- ASTERISK_OPENERS_extraword_mod3_0.head = -1;
- ASTERISK_OPENERS_extraword_mod3_0.tail = -1;
- ASTERISK_OPENERS_extraword_mod3_1.head = -1;
- ASTERISK_OPENERS_extraword_mod3_1.tail = -1;
- ASTERISK_OPENERS_extraword_mod3_2.head = -1;
- ASTERISK_OPENERS_extraword_mod3_2.tail = -1;
- ASTERISK_OPENERS_intraword_mod3_0.head = -1;
- ASTERISK_OPENERS_intraword_mod3_0.tail = -1;
- ASTERISK_OPENERS_intraword_mod3_1.head = -1;
- ASTERISK_OPENERS_intraword_mod3_1.tail = -1;
- ASTERISK_OPENERS_intraword_mod3_2.head = -1;
- ASTERISK_OPENERS_intraword_mod3_2.tail = -1;
- UNDERSCORE_OPENERS.head = -1;
- UNDERSCORE_OPENERS.tail = -1;
- TILDE_OPENERS.head = -1;
- TILDE_OPENERS.tail = -1;
- DOLLAR_OPENERS.head = -1;
- DOLLAR_OPENERS.tail = -1;
+
+ for(i = OPENERS_CHAIN_FIRST; i <= OPENERS_CHAIN_LAST; i++) {
+ ctx->mark_chains[i].head = -1;
+ ctx->mark_chains[i].tail = -1;
+ }
}
static int
@@ -3941,6 +4048,27 @@ abort:
return ret;
}
+static int
+md_enter_leave_span_wikilink(MD_CTX* ctx, int enter, const CHAR* target, SZ target_size)
+{
+ MD_ATTRIBUTE_BUILD target_build = { 0 };
+ MD_SPAN_WIKILINK_DETAIL det;
+ int ret = 0;
+
+ memset(&det, 0, sizeof(MD_SPAN_WIKILINK_DETAIL));
+ MD_CHECK(md_build_attribute(ctx, target, target_size, 0, &det.target, &target_build));
+
+ if (enter)
+ MD_ENTER_SPAN(MD_SPAN_WIKILINK, &det);
+ else
+ MD_LEAVE_SPAN(MD_SPAN_WIKILINK, &det);
+
+abort:
+ md_free_attribute(ctx, &target_build);
+ return ret;
+}
+
+
/* Render the output, accordingly to the analyzed ctx->marks. */
static int
md_process_inlines(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
@@ -3996,7 +4124,23 @@ md_process_inlines(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
}
break;
- case '_':
+ case '_': /* Underline (or emphasis if we fall through). */
+ if(ctx->parser.flags & MD_FLAG_UNDERLINE) {
+ if(mark->flags & MD_MARK_OPENER) {
+ while(off < mark->end) {
+ MD_ENTER_SPAN(MD_SPAN_U, NULL);
+ off++;
+ }
+ } else {
+ while(off < mark->end) {
+ MD_LEAVE_SPAN(MD_SPAN_U, NULL);
+ off++;
+ }
+ }
+ break;
+ }
+ /* Fall though. */
+
case '*': /* Emphasis, strong emphasis. */
if(mark->flags & MD_MARK_OPENER) {
if((mark->end - off) % 2) {
@@ -4036,15 +4180,37 @@ md_process_inlines(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
}
break;
- case '[': /* Link, image. */
+ case '[': /* Link, wiki link, image. */
case '!':
case ']':
{
const MD_MARK* opener = (mark->ch != ']' ? mark : &ctx->marks[mark->prev]);
- const MD_MARK* dest_mark = opener+1;
- const MD_MARK* title_mark = opener+2;
+ const MD_MARK* closer = &ctx->marks[opener->next];
+ const MD_MARK* dest_mark;
+ const MD_MARK* title_mark;
+
+ if ((opener->ch == '[' && closer->ch == ']') &&
+ opener->end - opener->beg >= 2 &&
+ closer->end - closer->beg >= 2)
+ {
+ int has_label = (opener->end - opener->beg > 2);
+ SZ target_sz;
+
+ if(has_label)
+ target_sz = opener->end - (opener->beg+2);
+ else
+ target_sz = closer->beg - opener->end;
+ MD_CHECK(md_enter_leave_span_wikilink(ctx, (mark->ch != ']'),
+ has_label ? STR(opener->beg+2) : STR(opener->end),
+ target_sz));
+
+ break;
+ }
+
+ dest_mark = opener+1;
MD_ASSERT(dest_mark->ch == 'D');
+ title_mark = opener+2;
MD_ASSERT(title_mark->ch == 'D');
MD_CHECK(md_enter_leave_span_a(ctx, (mark->ch != ']'),
@@ -4251,7 +4417,7 @@ md_process_table_row(MD_CTX* ctx, MD_BLOCKTYPE cell_type, OFF beg, OFF end,
{
MD_LINE line;
OFF* pipe_offs = NULL;
- int i, j, n;
+ int i, j, k, n;
int ret = 0;
line.beg = beg;
@@ -4263,32 +4429,32 @@ md_process_table_row(MD_CTX* ctx, MD_BLOCKTYPE cell_type, OFF beg, OFF end,
/* We have to remember the cell boundaries in local buffer because
* ctx->marks[] shall be reused during cell contents processing. */
- n = ctx->n_table_cell_boundaries;
+ n = ctx->n_table_cell_boundaries + 2;
pipe_offs = (OFF*) malloc(n * sizeof(OFF));
if(pipe_offs == NULL) {
MD_LOG("malloc() failed.");
ret = -1;
goto abort;
}
- for(i = TABLECELLBOUNDARIES.head, j = 0; i >= 0; i = ctx->marks[i].next) {
+ j = 0;
+ pipe_offs[j++] = beg;
+ for(i = TABLECELLBOUNDARIES.head; i >= 0; i = ctx->marks[i].next) {
MD_MARK* mark = &ctx->marks[i];
- pipe_offs[j++] = mark->beg;
+ pipe_offs[j++] = mark->end;
}
+ pipe_offs[j++] = end+1;
/* Process cells. */
MD_ENTER_BLOCK(MD_BLOCK_TR, NULL);
- j = 0;
- if(beg < pipe_offs[0] && j < col_count)
- MD_CHECK(md_process_table_cell(ctx, cell_type, align[j++], beg, pipe_offs[0]));
- for(i = 0; i < n-1 && j < col_count; i++)
- MD_CHECK(md_process_table_cell(ctx, cell_type, align[j++], pipe_offs[i]+1, pipe_offs[i+1]));
- if(pipe_offs[n-1] < end-1 && j < col_count)
- MD_CHECK(md_process_table_cell(ctx, cell_type, align[j++], pipe_offs[n-1]+1, end));
+ k = 0;
+ for(i = 0; i < j-1 && k < col_count; i++) {
+ if(pipe_offs[i] < pipe_offs[i+1]-1)
+ MD_CHECK(md_process_table_cell(ctx, cell_type, align[k++], pipe_offs[i], pipe_offs[i+1]-1));
+ }
/* Make sure we call enough table cells even if the current table contains
* too few of them. */
- while(j < col_count)
- MD_CHECK(md_process_table_cell(ctx, cell_type, align[j++], 0, 0));
-
+ while(k < col_count)
+ MD_CHECK(md_process_table_cell(ctx, cell_type, align[k++], 0, 0));
MD_LEAVE_BLOCK(MD_BLOCK_TR, NULL);
abort:
@@ -4340,38 +4506,6 @@ abort:
return ret;
}
-static int
-md_is_table_row(MD_CTX* ctx, OFF beg, OFF* p_end)
-{
- MD_LINE line;
- int i;
- int ret = FALSE;
-
- line.beg = beg;
- line.end = beg;
-
- /* Find end of line. */
- while(line.end < ctx->size && !ISNEWLINE(line.end))
- line.end++;
-
- MD_CHECK(md_analyze_inlines(ctx, &line, 1, TRUE));
-
- if(TABLECELLBOUNDARIES.head >= 0) {
- if(p_end != NULL)
- *p_end = line.end;
- ret = TRUE;
- }
-
-abort:
- /* Free any temporary memory blocks stored within some dummy marks. */
- for(i = PTR_CHAIN.head; i >= 0; i = ctx->marks[i].next)
- free(md_mark_get_ptr(ctx, i));
- PTR_CHAIN.head = -1;
- PTR_CHAIN.tail = -1;
-
- return ret;
-}
-
/**************************
*** Processing Block ***
@@ -4704,7 +4838,9 @@ md_push_block_bytes(MD_CTX* ctx, int n_bytes)
if(ctx->n_block_bytes + n_bytes > ctx->alloc_block_bytes) {
void* new_block_bytes;
- ctx->alloc_block_bytes = (ctx->alloc_block_bytes > 0 ? ctx->alloc_block_bytes * 2 : 512);
+ ctx->alloc_block_bytes = (ctx->alloc_block_bytes > 0
+ ? ctx->alloc_block_bytes + ctx->alloc_block_bytes / 2
+ : 512);
new_block_bytes = realloc(ctx->block_bytes, ctx->alloc_block_bytes);
if(new_block_bytes == NULL) {
MD_LOG("realloc() failed.");
@@ -5136,7 +5272,7 @@ md_is_html_block_start_condition(MD_CTX* ctx, OFF beg)
#ifdef X
#undef X
#endif
-#define X(name) { _T(name), sizeof(name)-1 }
+#define X(name) { _T(name), (sizeof(name)-1) / sizeof(CHAR) }
#define Xend { NULL, 0 }
static const TAG t1[] = { X("script"), X("pre"), X("style"), Xend };
@@ -5192,7 +5328,7 @@ md_is_html_block_start_condition(MD_CTX* ctx, OFF beg)
/* Check for type 5: <![CDATA[ */
if(off + 8 < ctx->size) {
- if(md_ascii_eq(STR(off), _T("![CDATA["), 8 * sizeof(CHAR)))
+ if(md_ascii_eq(STR(off), _T("![CDATA["), 8))
return 5;
}
}
@@ -5341,7 +5477,9 @@ md_push_container(MD_CTX* ctx, const MD_CONTAINER* container)
if(ctx->n_containers >= ctx->alloc_containers) {
MD_CONTAINER* new_containers;
- ctx->alloc_containers = (ctx->alloc_containers > 0 ? ctx->alloc_containers * 2 : 16);
+ ctx->alloc_containers = (ctx->alloc_containers > 0
+ ? ctx->alloc_containers + ctx->alloc_containers / 2
+ : 16);
new_containers = realloc(ctx->containers, ctx->alloc_containers * sizeof(MD_CONTAINER));
if(new_containers == NULL) {
MD_LOG("realloc() failed.");
@@ -5561,6 +5699,7 @@ md_analyze_line(MD_CTX* ctx, OFF beg, OFF* p_end,
line->indent--;
line->beg = off;
+
} else if(c->ch != _T('>') && line->indent >= c->contents_indent) {
/* List. */
line->indent -= c->contents_indent;
@@ -5803,9 +5942,7 @@ md_analyze_line(MD_CTX* ctx, OFF beg, OFF* p_end,
}
/* Check whether we are table continuation. */
- if(pivot_line->type == MD_LINE_TABLE && md_is_table_row(ctx, off, &off) &&
- n_parents == ctx->n_containers)
- {
+ if(pivot_line->type == MD_LINE_TABLE && n_parents == ctx->n_containers) {
line->type = MD_LINE_TABLE;
break;
}
@@ -5859,8 +5996,7 @@ md_analyze_line(MD_CTX* ctx, OFF beg, OFF* p_end,
unsigned col_count;
if(ctx->current_block != NULL && ctx->current_block->n_lines == 1 &&
- md_is_table_underline(ctx, off, &off, &col_count) &&
- md_is_table_row(ctx, pivot_line->beg, NULL))
+ md_is_table_underline(ctx, off, &off, &col_count))
{
line->data = col_count;
line->type = MD_LINE_TABLEUNDERLINE;
diff --git a/src/3rdparty/md4c/md4c.h b/src/3rdparty/md4c/md4c.h
index 6d9fce5180..c2c4311f50 100644
--- a/src/3rdparty/md4c/md4c.h
+++ b/src/3rdparty/md4c/md4c.h
@@ -2,7 +2,7 @@
* MD4C: Markdown parser for C
* (http://github.com/mity/md4c)
*
- * Copyright (c) 2016-2019 Martin Mitas
+ * Copyright (c) 2016-2020 Martin Mitas
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -135,7 +135,16 @@ typedef enum MD_SPANTYPE {
* Note: Recognized only when MD_FLAG_LATEXMATHSPANS is enabled.
*/
MD_SPAN_LATEXMATH,
- MD_SPAN_LATEXMATH_DISPLAY
+ MD_SPAN_LATEXMATH_DISPLAY,
+
+ /* Wiki links
+ * Note: Recognized only when MD_FLAG_WIKILINKS is enabled.
+ */
+ MD_SPAN_WIKILINK,
+
+ /* <u>...</u>
+ * Note: Recognized only when MD_FLAG_UNDERLINE is enabled. */
+ MD_SPAN_U
} MD_SPANTYPE;
/* Text is the actual textual contents of span. */
@@ -268,6 +277,10 @@ typedef struct MD_SPAN_IMG_DETAIL {
MD_ATTRIBUTE title;
} MD_SPAN_IMG_DETAIL;
+/* Detailed info for MD_SPAN_WIKILINK. */
+typedef struct MD_SPAN_WIKILINK {
+ MD_ATTRIBUTE target;
+} MD_SPAN_WIKILINK_DETAIL;
/* Flags specifying extensions/deviations from CommonMark specification.
*
@@ -286,6 +299,8 @@ typedef struct MD_SPAN_IMG_DETAIL {
#define MD_FLAG_PERMISSIVEWWWAUTOLINKS 0x0400 /* Enable WWW autolinks (even without any scheme prefix, if they begin with 'www.') */
#define MD_FLAG_TASKLISTS 0x0800 /* Enable task list extension. */
#define MD_FLAG_LATEXMATHSPANS 0x1000 /* Enable $ and $$ containing LaTeX equations. */
+#define MD_FLAG_WIKILINKS 0x2000 /* Enable wiki links extension. */
+#define MD_FLAG_UNDERLINE 0x4000 /* Enable underline extension (and disables '_' for normal emphasis). */
#define MD_FLAG_PERMISSIVEAUTOLINKS (MD_FLAG_PERMISSIVEEMAILAUTOLINKS | MD_FLAG_PERMISSIVEURLAUTOLINKS | MD_FLAG_PERMISSIVEWWWAUTOLINKS)
#define MD_FLAG_NOHTML (MD_FLAG_NOHTMLBLOCKS | MD_FLAG_NOHTMLSPANS)
diff --git a/src/3rdparty/md4c/qt_attribution.json b/src/3rdparty/md4c/qt_attribution.json
index 5fd77269e9..c574b97711 100644
--- a/src/3rdparty/md4c/qt_attribution.json
+++ b/src/3rdparty/md4c/qt_attribution.json
@@ -9,7 +9,7 @@
"License": "MIT License",
"LicenseId": "MIT",
"LicenseFile": "LICENSE.md",
- "Version": "0.3.4",
- "DownloadLocation": "https://github.com/mity/md4c/releases/tag/release-0.3.4",
- "Copyright": "Copyright © 2016-2019 Martin Mitáš"
+ "Version": "0.4.3",
+ "DownloadLocation": "https://github.com/mity/md4c/releases/tag/release-0.4.3",
+ "Copyright": "Copyright © 2016-2020 Martin Mitáš"
}
diff --git a/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp b/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp
index e8d74180cd..30b3786a80 100644
--- a/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp
+++ b/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp
@@ -2217,7 +2217,7 @@ QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOpt
{
const int controlTop = int(6 * factor);
const int controlHeight = int(height - controlTop - 3 * factor);
- int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
+ int iconExtent = proxy()->pixelMetric(PM_SmallIconSize, option);
QSize iconSize = tb->icon.actualSize(QSize(iconExtent, iconExtent));
if (tb->icon.isNull())
iconSize = QSize(controlHeight, controlHeight);
diff --git a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
index 9d143da169..e43746e79f 100644
--- a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
+++ b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
@@ -3453,7 +3453,7 @@ QRect QWindowsXPStyle::subControlRect(ComplexControl cc, const QStyleOptionCompl
{
const int controlTop = 6;
const int controlHeight = height - controlTop - 3;
- const int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
+ const int iconExtent = proxy()->pixelMetric(PM_SmallIconSize, option);
QSize iconSize = tb->icon.actualSize(QSize(iconExtent, iconExtent));
if (tb->icon.isNull())
iconSize = QSize(controlHeight, controlHeight);
@@ -3575,7 +3575,7 @@ QSize QWindowsXPStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt
sz.rheight() += int(borderSize.bottom() + borderSize.top() - margin
+ qreal(1) / factor - 1);
}
- const int textMargins = 2*(proxy()->pixelMetric(PM_FocusFrameHMargin) + 1);
+ const int textMargins = 2*(proxy()->pixelMetric(PM_FocusFrameHMargin, option) + 1);
sz += QSize(qMax(pixelMetric(QStyle::PM_ScrollBarExtent, option, widget)
+ textMargins, 23), 0); //arrow button
}
diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp
index 689002b589..4247731275 100644
--- a/src/widgets/dialogs/qcolordialog.cpp
+++ b/src/widgets/dialogs/qcolordialog.cpp
@@ -346,7 +346,8 @@ void QWellArray::paintCell(QPainter* p, int row, int col, const QRect &rect)
const QPalette & g = palette();
QStyleOptionFrame opt;
- int dfw = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
+ opt.initFrom(this);
+ int dfw = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt);
opt.lineWidth = dfw;
opt.midLineWidth = 1;
opt.rect = rect.adjusted(b, b, -b, -b);
diff --git a/src/widgets/dialogs/qwizard.cpp b/src/widgets/dialogs/qwizard.cpp
index 87f6875c8c..31e32bb931 100644
--- a/src/widgets/dialogs/qwizard.cpp
+++ b/src/widgets/dialogs/qwizard.cpp
@@ -64,6 +64,7 @@
# include "qshortcut.h"
#endif
#include "qstyle.h"
+#include "qstyleoption.h"
#include "qvarlengtharray.h"
#if defined(Q_OS_MACX)
#include <QtCore/QMetaMethod>
@@ -897,7 +898,9 @@ QWizardLayoutInfo QWizardPrivate::layoutInfoForCurrentPage()
QWizardLayoutInfo info;
- const int layoutHorizontalSpacing = style->pixelMetric(QStyle::PM_LayoutHorizontalSpacing);
+ QStyleOption option;
+ option.initFrom(q);
+ const int layoutHorizontalSpacing = style->pixelMetric(QStyle::PM_LayoutHorizontalSpacing, &option);
info.topLevelMarginLeft = style->pixelMetric(QStyle::PM_LayoutLeftMargin, nullptr, q);
info.topLevelMarginRight = style->pixelMetric(QStyle::PM_LayoutRightMargin, nullptr, q);
info.topLevelMarginTop = style->pixelMetric(QStyle::PM_LayoutTopMargin, nullptr, q);
@@ -909,7 +912,7 @@ QWizardLayoutInfo QWizardPrivate::layoutInfoForCurrentPage()
info.hspacing = (layoutHorizontalSpacing == -1)
? style->layoutSpacing(QSizePolicy::DefaultType, QSizePolicy::DefaultType, Qt::Horizontal)
: layoutHorizontalSpacing;
- info.vspacing = style->pixelMetric(QStyle::PM_LayoutVerticalSpacing);
+ info.vspacing = style->pixelMetric(QStyle::PM_LayoutVerticalSpacing, &option);
info.buttonSpacing = (layoutHorizontalSpacing == -1)
? style->layoutSpacing(QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal)
: layoutHorizontalSpacing;
diff --git a/src/widgets/graphicsview/qgraphicslayout_p.h b/src/widgets/graphicsview/qgraphicslayout_p.h
index 0d91151e22..9e86ae2f76 100644
--- a/src/widgets/graphicsview/qgraphicslayout_p.h
+++ b/src/widgets/graphicsview/qgraphicslayout_p.h
@@ -87,8 +87,8 @@ public:
Q_ASSERT(style);
if (widget) //###
m_styleOption.initFrom(widget);
- m_defaultSpacing[0] = style->pixelMetric(QStyle::PM_LayoutHorizontalSpacing);
- m_defaultSpacing[1] = style->pixelMetric(QStyle::PM_LayoutVerticalSpacing);
+ m_defaultSpacing[0] = style->pixelMetric(QStyle::PM_LayoutHorizontalSpacing, &m_styleOption);
+ m_defaultSpacing[1] = style->pixelMetric(QStyle::PM_LayoutVerticalSpacing, &m_styleOption);
}
inline void invalidate() { m_valid = false; m_style = nullptr; m_widget = nullptr; }
diff --git a/src/widgets/graphicsview/qgraphicslayoutstyleinfo.cpp b/src/widgets/graphicsview/qgraphicslayoutstyleinfo.cpp
index 2f1526cc78..58b9f8bb9d 100644
--- a/src/widgets/graphicsview/qgraphicslayoutstyleinfo.cpp
+++ b/src/widgets/graphicsview/qgraphicslayoutstyleinfo.cpp
@@ -80,7 +80,9 @@ qreal QGraphicsLayoutStyleInfo::perItemSpacing(QLayoutPolicy::ControlType contro
qreal QGraphicsLayoutStyleInfo::spacing(Qt::Orientation orientation) const
{
Q_ASSERT(style());
- return style()->pixelMetric(orientation == Qt::Horizontal ? QStyle::PM_LayoutHorizontalSpacing : QStyle::PM_LayoutVerticalSpacing);
+ return style()->pixelMetric(orientation == Qt::Horizontal
+ ? QStyle::PM_LayoutHorizontalSpacing : QStyle::PM_LayoutVerticalSpacing,
+ &m_styleOption);
}
qreal QGraphicsLayoutStyleInfo::windowMargin(Qt::Orientation orientation) const
diff --git a/src/widgets/graphicsview/qgraphicswidget.cpp b/src/widgets/graphicsview/qgraphicswidget.cpp
index 1035ed3575..6242314e1d 100644
--- a/src/widgets/graphicsview/qgraphicswidget.cpp
+++ b/src/widgets/graphicsview/qgraphicswidget.cpp
@@ -615,7 +615,7 @@ void QGraphicsWidget::unsetWindowFrameMargins()
QStyleOptionTitleBar bar;
d->initStyleOptionTitleBar(&bar);
QStyle *style = this->style();
- qreal margin = style->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth);
+ const qreal margin = style->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth, &bar);
qreal titleBarHeight = d->titleBarHeight(bar);
setWindowFrameMargins(margin, titleBarHeight, margin, margin);
} else {
diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp
index 5b92fc6790..ebef36d033 100644
--- a/src/widgets/itemviews/qabstractitemview.cpp
+++ b/src/widgets/itemviews/qabstractitemview.cpp
@@ -3235,8 +3235,10 @@ void QAbstractItemView::setIndexWidget(const QModelIndex &index, QWidget *widget
widget->installEventFilter(this);
widget->show();
dataChanged(index, index); // update the geometry
- if (!d->delayedPendingLayout)
+ if (!d->delayedPendingLayout) {
widget->setGeometry(visualRect(index));
+ d->doDelayedItemsLayout(); // relayout due to updated geometry
+ }
}
}
diff --git a/src/widgets/itemviews/qitemdelegate.cpp b/src/widgets/itemviews/qitemdelegate.cpp
index 4420d39b8e..40ad48c655 100644
--- a/src/widgets/itemviews/qitemdelegate.cpp
+++ b/src/widgets/itemviews/qitemdelegate.cpp
@@ -1122,7 +1122,7 @@ QRect QItemDelegate::textRectangle(QPainter * /*painter*/, const QRect &rect,
QSizeF fpSize = d->doTextLayout(rect.width());
const QSize size = QSize(qCeil(fpSize.width()), qCeil(fpSize.height()));
// ###: textRectangle should take style option as argument
- const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
+ const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin, nullptr) + 1;
return QRect(0, 0, size.width() + 2 * textMargin, size.height());
}
diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp
index ec01922746..4cb9214ff4 100644
--- a/src/widgets/itemviews/qlistview.cpp
+++ b/src/widgets/itemviews/qlistview.cpp
@@ -1728,8 +1728,11 @@ void QListViewPrivate::prepareItemsLayout()
layoutBounds = QRect(QPoint(), q->maximumViewportSize());
int frameAroundContents = 0;
- if (q->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents))
- frameAroundContents = q->style()->pixelMetric(QStyle::PM_DefaultFrameWidth) * 2;
+ if (q->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents)) {
+ QStyleOption option;
+ option.initFrom(q);
+ frameAroundContents = q->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &option) * 2;
+ }
// maximumViewportSize() already takes scrollbar into account if policy is
// Qt::ScrollBarAlwaysOn but scrollbar extent must be deduced if policy
diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp
index f4a53c9dfe..4b0094e578 100644
--- a/src/widgets/styles/qcommonstyle.cpp
+++ b/src/widgets/styles/qcommonstyle.cpp
@@ -431,7 +431,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
QIcon::Active, QIcon::Off);
}
- int size = proxy()->pixelMetric(QStyle::PM_SmallIconSize);
+ const int size = proxy()->pixelMetric(QStyle::PM_SmallIconSize, opt);
QIcon::Mode mode = opt->state & State_Enabled ?
(opt->state & State_Raised ? QIcon::Active : QIcon::Normal)
: QIcon::Disabled;
@@ -477,7 +477,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
int lw = frame->lineWidth;
if (lw <= 0)
- lw = proxy()->pixelMetric(PM_DockWidgetFrameWidth);
+ lw = proxy()->pixelMetric(PM_DockWidgetFrameWidth, opt);
qDrawShadePanel(p, frame->rect, frame->palette, false, lw);
}
@@ -563,8 +563,8 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
int bsx = 0;
int bsy = 0;
if (opt->state & State_Sunken) {
- bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal);
- bsy = proxy()->pixelMetric(PM_ButtonShiftVertical);
+ bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal, opt);
+ bsy = proxy()->pixelMetric(PM_ButtonShiftVertical, opt);
}
p->save();
p->translate(sx + bsx, sy + bsy);
@@ -994,7 +994,7 @@ QSize QCommonStylePrivate::viewItemSize(const QStyleOptionViewItem *option, int
}
if (wrapText && option->features & QStyleOptionViewItem::HasCheckIndicator)
- bounds.setWidth(bounds.width() - proxyStyle->pixelMetric(QStyle::PM_IndicatorWidth) - 2 * textMargin);
+ bounds.setWidth(bounds.width() - proxyStyle->pixelMetric(QStyle::PM_IndicatorWidth, option) - 2 * textMargin);
const int lineWidth = bounds.width();
const QSizeF size = viewItemTextLayout(textLayout, lineWidth);
@@ -1240,7 +1240,7 @@ void QCommonStylePrivate::tabLayout(const QStyleOptionTab *opt, const QWidget *w
if (!opt->icon.isNull()) {
QSize iconSize = opt->iconSize;
if (!iconSize.isValid()) {
- int iconExtent = proxyStyle->pixelMetric(QStyle::PM_SmallIconSize);
+ int iconExtent = proxyStyle->pixelMetric(QStyle::PM_SmallIconSize, opt);
iconSize = QSize(iconExtent, iconExtent);
}
QSize tabIconSize = opt->icon.actualSize(iconSize,
@@ -1490,7 +1490,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
| Qt::TextSingleLine;
if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget))
alignment |= Qt::TextHideMnemonic;
- int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
+ int iconExtent = proxy()->pixelMetric(PM_SmallIconSize, opt);
QPixmap pix = mbi->icon.pixmap(qt_getWindow(widget), QSize(iconExtent, iconExtent), (mbi->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled);
if (!pix.isNull())
proxy()->drawItemPixmap(p,mbi->rect, alignment, pix);
@@ -1646,7 +1646,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
QRect rect = header->rect;
if (!header->icon.isNull()) {
- int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
+ int iconExtent = proxy()->pixelMetric(PM_SmallIconSize, opt);
QPixmap pixmap
= header->icon.pixmap(qt_getWindow(widget), QSize(iconExtent, iconExtent), (header->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled);
int pixw = pixmap.width() / pixmap.devicePixelRatio();
@@ -3863,8 +3863,8 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
if (opt->activeSubControls & QStyle::SC_MdiCloseButton && (opt->state & State_Sunken)) {
btnOpt.state |= State_Sunken;
btnOpt.state &= ~State_Raised;
- bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal);
- bsy = proxy()->pixelMetric(PM_ButtonShiftVertical);
+ bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal, opt);
+ bsy = proxy()->pixelMetric(PM_ButtonShiftVertical, opt);
} else {
btnOpt.state |= State_Raised;
btnOpt.state &= ~State_Sunken;
@@ -3880,8 +3880,8 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
if (opt->activeSubControls & QStyle::SC_MdiNormalButton && (opt->state & State_Sunken)) {
btnOpt.state |= State_Sunken;
btnOpt.state &= ~State_Raised;
- bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal);
- bsy = proxy()->pixelMetric(PM_ButtonShiftVertical);
+ bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal, opt);
+ bsy = proxy()->pixelMetric(PM_ButtonShiftVertical, opt);
} else {
btnOpt.state |= State_Raised;
btnOpt.state &= ~State_Sunken;
@@ -3897,8 +3897,8 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
if (opt->activeSubControls & QStyle::SC_MdiMinButton && (opt->state & State_Sunken)) {
btnOpt.state |= State_Sunken;
btnOpt.state &= ~State_Raised;
- bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal);
- bsy = proxy()->pixelMetric(PM_ButtonShiftVertical);
+ bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal, opt);
+ bsy = proxy()->pixelMetric(PM_ButtonShiftVertical, opt);
} else {
btnOpt.state |= State_Raised;
btnOpt.state &= ~State_Sunken;
@@ -4781,12 +4781,12 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
} else if (widget) {
isWindow = widget->isWindow();
}
- ret = proxy()->pixelMetric(isWindow ? PM_DefaultTopLevelMargin : PM_DefaultChildMargin);
+ ret = proxy()->pixelMetric(isWindow ? PM_DefaultTopLevelMargin : PM_DefaultChildMargin, opt);
}
break;
case PM_LayoutHorizontalSpacing:
case PM_LayoutVerticalSpacing:
- ret = proxy()->pixelMetric(PM_DefaultLayoutSpacing);
+ ret = proxy()->pixelMetric(PM_DefaultLayoutSpacing, opt);
break;
case PM_DefaultTopLevelMargin:
@@ -4937,7 +4937,7 @@ QSize QCommonStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
} else {
h = mi->fontMetrics.height() + 8;
if (!mi->icon.isNull()) {
- int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
+ int iconExtent = proxy()->pixelMetric(PM_SmallIconSize, opt);
h = qMax(h, mi->icon.actualSize(QSize(iconExtent, iconExtent)).height() + 4);
}
}
@@ -4963,7 +4963,7 @@ QSize QCommonStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
case CT_ComboBox:
if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
int fw = cmb->frame ? proxy()->pixelMetric(PM_ComboBoxFrameWidth, opt, widget) * 2 : 0;
- const int textMargins = 2*(proxy()->pixelMetric(PM_FocusFrameHMargin) + 1);
+ const int textMargins = 2*(proxy()->pixelMetric(PM_FocusFrameHMargin, opt) + 1);
// QItemDelegate::sizeHint expands the textMargins two times, thus the 2*textMargins...
int other = qMax(23, 2*textMargins + proxy()->pixelMetric(QStyle::PM_ScrollBarExtent, opt, widget));
sz = QSize(sz.width() + fw + other, sz.height() + fw);
@@ -5214,8 +5214,8 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget
if (widget) {
if(QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>(hret)) {
mask->region = widget->rect();
- int vmargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin),
- hmargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin);
+ const int vmargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, opt);
+ const int hmargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, opt);
mask->region -= QRect(widget->rect().adjusted(hmargin, vmargin, -hmargin, -vmargin));
}
}
@@ -5228,7 +5228,7 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget
ret = true;
if(QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>(hret)) {
mask->region = opt->rect;
- int margin = proxy()->pixelMetric(PM_DefaultFrameWidth) * 2;
+ const int margin = proxy()->pixelMetric(PM_DefaultFrameWidth, opt) * 2;
mask->region -= opt->rect.adjusted(margin, margin, -margin, -margin);
}
}
diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp
index 45154ee647..ce5f084618 100644
--- a/src/widgets/styles/qfusionstyle.cpp
+++ b/src/widgets/styles/qfusionstyle.cpp
@@ -3349,8 +3349,8 @@ QRect QFusionStyle::subControlRect(ComplexControl control, const QStyleOptionCom
switch (subControl) {
case SC_SliderHandle: {
if (slider->orientation == Qt::Horizontal) {
- rect.setHeight(proxy()->pixelMetric(PM_SliderThickness));
- rect.setWidth(proxy()->pixelMetric(PM_SliderLength));
+ rect.setHeight(proxy()->pixelMetric(PM_SliderThickness, option));
+ rect.setWidth(proxy()->pixelMetric(PM_SliderLength, option));
int centerY = slider->rect.center().y() - rect.height() / 2;
if (slider->tickPosition & QSlider::TicksAbove)
centerY += tickSize;
@@ -3358,8 +3358,8 @@ QRect QFusionStyle::subControlRect(ComplexControl control, const QStyleOptionCom
centerY -= tickSize;
rect.moveTop(centerY);
} else {
- rect.setWidth(proxy()->pixelMetric(PM_SliderThickness));
- rect.setHeight(proxy()->pixelMetric(PM_SliderLength));
+ rect.setWidth(proxy()->pixelMetric(PM_SliderThickness, option));
+ rect.setHeight(proxy()->pixelMetric(PM_SliderLength, option));
int centerX = slider->rect.center().x() - rect.width() / 2;
if (slider->tickPosition & QSlider::TicksAbove)
centerX += tickSize;
diff --git a/src/widgets/styles/qpixmapstyle.cpp b/src/widgets/styles/qpixmapstyle.cpp
index 05e8467528..7cc32b2039 100644
--- a/src/widgets/styles/qpixmapstyle.cpp
+++ b/src/widgets/styles/qpixmapstyle.cpp
@@ -1003,13 +1003,13 @@ QSize QPixmapStyle::pushButtonSizeFromContents(const QStyleOption *option,
return d->computeSize(desc, w, h);
}
-QSize QPixmapStyle::lineEditSizeFromContents(const QStyleOption *,
+QSize QPixmapStyle::lineEditSizeFromContents(const QStyleOption *option,
const QSize &contentsSize, const QWidget *) const
{
Q_D(const QPixmapStyle);
const QPixmapStyleDescriptor &desc = d->descriptors.value(LE_Enabled);
- const int border = 2 * proxy()->pixelMetric(PM_DefaultFrameWidth);
+ const int border = 2 * proxy()->pixelMetric(PM_DefaultFrameWidth, option);
int w = contentsSize.width() + border + desc.margins.left() + desc.margins.right();
int h = contentsSize.height() + border + desc.margins.top() + desc.margins.bottom();
diff --git a/src/widgets/widgets/qcalendarwidget.cpp b/src/widgets/widgets/qcalendarwidget.cpp
index fe1133c6c7..570ec72377 100644
--- a/src/widgets/widgets/qcalendarwidget.cpp
+++ b/src/widgets/widgets/qcalendarwidget.cpp
@@ -2232,7 +2232,9 @@ QSize QCalendarWidget::minimumSizeHint() const
int rows = 7;
int cols = 8;
- const int marginH = (style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1) * 2;
+ QStyleOption option;
+ option.initFrom(this);
+ const int marginH = (style()->pixelMetric(QStyle::PM_FocusFrameHMargin, &option) + 1) * 2;
if (horizontalHeaderFormat() == QCalendarWidget::NoHorizontalHeader) {
rows = 6;
diff --git a/src/widgets/widgets/qcombobox_p.h b/src/widgets/widgets/qcombobox_p.h
index 3e78e756a6..d7b2457c49 100644
--- a/src/widgets/widgets/qcombobox_p.h
+++ b/src/widgets/widgets/qcombobox_p.h
@@ -142,7 +142,7 @@ public:
setAttribute(Qt::WA_NoMousePropagation);
}
QSize sizeHint() const override {
- return QSize(20, style()->pixelMetric(QStyle::PM_MenuScrollerHeight));
+ return QSize(20, style()->pixelMetric(QStyle::PM_MenuScrollerHeight, nullptr, this));
}
protected:
diff --git a/src/widgets/widgets/qcommandlinkbutton.cpp b/src/widgets/widgets/qcommandlinkbutton.cpp
index 2b9258fd91..e9462ed229 100644
--- a/src/widgets/widgets/qcommandlinkbutton.cpp
+++ b/src/widgets/widgets/qcommandlinkbutton.cpp
@@ -208,7 +208,7 @@ bool QCommandLinkButtonPrivate::usingVistaStyle() const
//### This is a hack to detect if we are indeed running Vista style themed and not in classic
// When we add api to query for this, we should change this implementation to use it.
return q->style()->inherits("QWindowsVistaStyle")
- && !q->style()->pixelMetric(QStyle::PM_ButtonShiftHorizontal);
+ && q->style()->pixelMetric(QStyle::PM_ButtonShiftHorizontal, nullptr) == 0;
}
void QCommandLinkButtonPrivate::init()
@@ -355,8 +355,10 @@ void QCommandLinkButton::paintEvent(QPaintEvent *)
option.icon = QIcon(); //we draw this ourselves
QSize pixmapSize = icon().actualSize(iconSize());
- int vOffset = isDown() ? style()->pixelMetric(QStyle::PM_ButtonShiftVertical) : 0;
- int hOffset = isDown() ? style()->pixelMetric(QStyle::PM_ButtonShiftHorizontal) : 0;
+ const int vOffset = isDown()
+ ? style()->pixelMetric(QStyle::PM_ButtonShiftVertical, &option) : 0;
+ const int hOffset = isDown()
+ ? style()->pixelMetric(QStyle::PM_ButtonShiftHorizontal, &option) : 0;
//Draw icon
p.drawControl(QStyle::CE_PushButton, option);
diff --git a/src/widgets/widgets/qfocusframe.cpp b/src/widgets/widgets/qfocusframe.cpp
index 4d64c24db3..4e793d7a29 100644
--- a/src/widgets/widgets/qfocusframe.cpp
+++ b/src/widgets/widgets/qfocusframe.cpp
@@ -86,8 +86,10 @@ void QFocusFramePrivate::updateSize()
if (!widget)
return;
- int vmargin = q->style()->pixelMetric(QStyle::PM_FocusFrameVMargin),
- hmargin = q->style()->pixelMetric(QStyle::PM_FocusFrameHMargin);
+ QStyleOption opt;
+ q->initStyleOption(&opt);
+ int vmargin = q->style()->pixelMetric(QStyle::PM_FocusFrameVMargin, &opt),
+ hmargin = q->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, &opt);
QPoint pos(widget->x(), widget->y());
if (q->parentWidget() != widget->parentWidget())
pos = widget->parentWidget()->mapTo(q->parentWidget(), pos);
@@ -98,8 +100,6 @@ void QFocusFramePrivate::updateSize()
q->setGeometry(geom);
QStyleHintReturnMask mask;
- QStyleOption opt;
- q->initStyleOption(&opt);
if (q->style()->styleHint(QStyle::SH_FocusFrame_Mask, &opt, q, &mask))
q->setMask(mask.region);
}
@@ -263,8 +263,8 @@ QFocusFrame::paintEvent(QPaintEvent *)
QStylePainter p(this);
QStyleOption option;
initStyleOption(&option);
- int vmargin = style()->pixelMetric(QStyle::PM_FocusFrameVMargin);
- int hmargin = style()->pixelMetric(QStyle::PM_FocusFrameHMargin);
+ const int vmargin = style()->pixelMetric(QStyle::PM_FocusFrameVMargin, &option);
+ const int hmargin = style()->pixelMetric(QStyle::PM_FocusFrameHMargin, &option);
QWidgetPrivate *wd = qt_widget_private(d->widget);
QRect rect = wd->clipRect().adjusted(0, 0, hmargin*2, vmargin*2);
p.setClipRect(rect);
diff --git a/src/widgets/widgets/qgroupbox.cpp b/src/widgets/widgets/qgroupbox.cpp
index 048fe42948..02a0bed325 100644
--- a/src/widgets/widgets/qgroupbox.cpp
+++ b/src/widgets/widgets/qgroupbox.cpp
@@ -491,9 +491,9 @@ QSize QGroupBox::minimumSizeHint() const
int baseWidth = metrics.horizontalAdvance(d->title) + metrics.horizontalAdvance(QLatin1Char(' '));
int baseHeight = metrics.height();
if (d->checkable) {
- baseWidth += style()->pixelMetric(QStyle::PM_IndicatorWidth);
- baseWidth += style()->pixelMetric(QStyle::PM_CheckBoxLabelSpacing);
- baseHeight = qMax(baseHeight, style()->pixelMetric(QStyle::PM_IndicatorHeight));
+ baseWidth += style()->pixelMetric(QStyle::PM_IndicatorWidth, &option);
+ baseWidth += style()->pixelMetric(QStyle::PM_CheckBoxLabelSpacing, &option);
+ baseHeight = qMax(baseHeight, style()->pixelMetric(QStyle::PM_IndicatorHeight, &option));
}
QSize size = style()->sizeFromContents(QStyle::CT_GroupBox, &option, QSize(baseWidth, baseHeight), this);
diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp
index 19a95be0ff..675f09d283 100644
--- a/src/widgets/widgets/qlineedit.cpp
+++ b/src/widgets/widgets/qlineedit.cpp
@@ -2073,7 +2073,7 @@ void QLineEdit::paintEvent(QPaintEvent *)
if (d->cursorVisible && !d->control->isReadOnly())
flags |= QWidgetLineControl::DrawCursor;
- d->control->setCursorWidth(style()->pixelMetric(QStyle::PM_TextCursorWidth));
+ d->control->setCursorWidth(style()->pixelMetric(QStyle::PM_TextCursorWidth, &panel));
d->control->draw(&p, topLeft, r, flags);
}
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index 701035fc32..abe4e485c0 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -2844,7 +2844,7 @@ void QMenu::paintEvent(QPaintEvent *e)
frame.rect = rect();
frame.palette = palette();
frame.state = QStyle::State_None;
- frame.lineWidth = style()->pixelMetric(QStyle::PM_MenuPanelWidth);
+ frame.lineWidth = style()->pixelMetric(QStyle::PM_MenuPanelWidth, &frame);
frame.midLineWidth = 0;
style()->drawPrimitive(QStyle::PE_FrameMenu, &frame, &p, this);
}
diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp
index ccd91ebee1..8724fa1a19 100644
--- a/src/widgets/widgets/qmenubar.cpp
+++ b/src/widgets/widgets/qmenubar.cpp
@@ -1014,7 +1014,7 @@ void QMenuBar::paintEvent(QPaintEvent *e)
frame.rect = rect();
frame.palette = palette();
frame.state = QStyle::State_None;
- frame.lineWidth = style()->pixelMetric(QStyle::PM_MenuBarPanelWidth);
+ frame.lineWidth = style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, &frame);
frame.midLineWidth = 0;
style()->drawPrimitive(QStyle::PE_PanelMenuBar, &frame, &p, this);
}
diff --git a/src/widgets/widgets/qtoolbarextension.cpp b/src/widgets/widgets/qtoolbarextension.cpp
index bbe7eddaa4..165c7f274b 100644
--- a/src/widgets/widgets/qtoolbarextension.cpp
+++ b/src/widgets/widgets/qtoolbarextension.cpp
@@ -81,7 +81,9 @@ void QToolBarExtension::paintEvent(QPaintEvent *)
QSize QToolBarExtension::sizeHint() const
{
- int ext = style()->pixelMetric(QStyle::PM_ToolBarExtensionExtent);
+ QStyleOption opt;
+ opt.initFrom(this);
+ const int ext = style()->pixelMetric(QStyle::PM_ToolBarExtensionExtent, &opt);
return QSize(ext, ext);
}
diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp
index edd4885450..45ab384036 100644
--- a/src/widgets/widgets/qwidgettextcontrol.cpp
+++ b/src/widgets/widgets/qwidgettextcontrol.cpp
@@ -2463,7 +2463,7 @@ void QWidgetTextControl::setCursorWidth(int width)
Q_UNUSED(width);
#else
if (width == -1)
- width = QApplication::style()->pixelMetric(QStyle::PM_TextCursorWidth);
+ width = QApplication::style()->pixelMetric(QStyle::PM_TextCursorWidth, nullptr);
d->doc->documentLayout()->setProperty("cursorWidth", width);
#endif
d->repaintCursor();
diff --git a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp
index b29db90da4..099aa5fb51 100644
--- a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp
+++ b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp
@@ -556,8 +556,14 @@ void tst_QTcpSocket::bind_data()
// try to bind to a privileged ports
// we should fail if we're not root (unless the ports are in use!)
+#ifdef Q_OS_DARWIN
+ // Alas, some quirk (starting from macOS 10.14): bind with port number 1
+ // fails with IPv4 (not IPv6 though, see below).
+ QTest::newRow("127.0.0.1:1") << "127.0.0.1" << 1 << false << QString();
+#else
QTest::newRow("127.0.0.1:1") << "127.0.0.1" << 1 << QtNetworkSettings::canBindToLowPorts()
<< (QtNetworkSettings::canBindToLowPorts() ? "127.0.0.1" : QString());
+#endif // Q_OS_DARWIN
if (testIpv6)
QTest::newRow("[::]:1") << "::" << 1 << QtNetworkSettings::canBindToLowPorts()
<< (QtNetworkSettings::canBindToLowPorts() ? "::" : QString());
@@ -579,7 +585,7 @@ void tst_QTcpSocket::bind()
QTcpSocket dummySocket; // used only to "use up" a file descriptor
dummySocket.bind();
- QTcpSocket *socket = newSocket();
+ std::unique_ptr<QTcpSocket> socket(newSocket());
quint16 boundPort;
qintptr fd;
@@ -645,9 +651,24 @@ void tst_QTcpSocket::bind()
QCOMPARE(acceptedSocket->peerPort(), boundPort);
QCOMPARE(socket->localAddress(), remoteAddr);
QCOMPARE(socket->socketDescriptor(), fd);
+#ifdef Q_OS_DARWIN
+ // Normally, we don't see this problem: macOS sometimes does not
+ // allow us to immediately re-use a port, thinking connection is
+ // still alive. With fixed port 1 (we testing starting from
+ // macOS 10.14), this problem shows, making the test flaky:
+ // we run this 'bind' with port 1 several times (different
+ // test cases) and the problem manifests itself as
+ // "The bound address is already in use, tried port 1".
+ QTestEventLoop cleanupHelper;
+ auto client = socket.get();
+ connect(client, &QTcpSocket::disconnected, [&cleanupHelper, client](){
+ client->close();
+ cleanupHelper.exitLoop();
+ });
+ acceptedSocket->close();
+ cleanupHelper.enterLoopMSecs(100);
+#endif // Q_OS_DARWIN
}
-
- delete socket;
}
//----------------------------------------------------------------------------------
diff --git a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
index 8396fd4ec7..7259fa1ab0 100644
--- a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
+++ b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
@@ -976,6 +976,7 @@ void tst_QTreeView::indexWidget()
QStandardItemModel treeModel;
initStandardTreeModel(&treeModel);
view.setModel(&treeModel);
+ view.resize(300, 400); // make sure the width of the view is larger than the widgets below
QModelIndex index = view.model()->index(0, 0);
@@ -1004,6 +1005,7 @@ void tst_QTreeView::indexWidget()
//now let's try to do that later when the widget is already shown
view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
index = view.model()->index(1, 0);
QVERIFY(!view.indexWidget(index));