Package list dillo / bfc6d84
Imported Upstream version 3.0.2~rc1 Axel Beckert 9 years ago
76 changed file(s) with 2862 addition(s) and 1367 deletion(s). Raw diff Collapse all Expand all
7373
7474 Contributions are always welcome!
7575
76
77
78 ---------------
79 Non-Dillo code:
80 ---------------
81
82 * dw/fltkcomplexbutton.(cc|hh) contain code from the FLTK project whose
83 copyright is held by Bill Spitzak and others.
84 * src/binaryconst.h contains code by Tom Torfs that the author placed in the
85 public domain.
86 * src/md5.[ch] contain code by L. Peter Deutsch whose copyright is held by
87 Aladdin Enterprises.
00 =============================================================================
11 Dillo project
22 =============================================================================
3
4 Here we list changes that are relatively significant and/or visible to the
5 user. For a history of changes in full detail, see our Mercurial repository
6 at http://hg.dillo.org/dillo
7
8
9 dillo-3.0.2 [December 05, 2011]
10
11 +- Digest authentication
12 Patch: Justus Winter, corvid
13 +- text-transform property
14 - If not following redirection, show body of redirecting page.
15 - Middle click on stylesheet menu item opens in new tab/window.
16 - Improve handling of combining characters.
17 - Locale-independent ASCII character case handling (fixes Turkic locales).
18 Patches: corvid
19 +- Rework line breaking and fix white-space:nowrap handling.
20 Patch: Johannes Hofmann
21 +- Bind Ctrl-{PageUp,PageDown} to tab-{previous,next}.
22 Patch: Jeremy Henty
23
24 -----------------------------------------------------------------------------
325
426 dillo-3.0.1 [September 21, 2011]
527
5173 Patch: Johannes Hofmann
5274 +- Default binding for left-tab changed to Shift-Ctrl-Tab.
5375 Patch: Jeremy Henty
54
55 Note: these are user-visible changes. The full Changelog is kept
56 in our Mercurial repository at http://hg.dillo.org/dillo
57
5876
5977 -----------------------------------------------------------------------------
6078
11 Dillo web browser
22 ===================
33
4 Dillo-3.0 is the first release of the newest branch, which is
5 based on the already released fltk-1.3 toolkit. This is big news
6 because it clears the way for Dillo to return to those
7 distributions which had excluded Dillo2 due to FLTK2 never
8 being officially released.
4 Dillo is a multi-platform graphical web browser, known for its
5 speed and small footprint, that is developed with a focus on
6 personal security and privacy.
97
10 The development effort shifted to the dillo-3.x branch long ago,
11 and it became the active one; dillo-2.x received less and less
12 attention, and dillo-2.2.1 became the last of its series.
8 The dillo3 series uses version 1.3.x of the FLTK GUI toolkit
9 (http://fltk.org).
1310
14 The core team will focus on implementing the CSS feature of
15 floating elements. This will greatly improve dillo's web page
16 rendering since many sites have adopted floats instead of tables.
17
18 The new dillo3 has shown excellent stability.
11 The core team currently plans to focus on implementing the CSS
12 feature of floating elements. This will greatly improve
13 dillo's web page rendering since many sites have adopted floats
14 instead of tables.
1915
2016 The core team welcomes developers willing to join our workforce.
2117
2218
2319 NOTE: With FLTK-1.3, when running on X with Xft enabled (the
24 default), font naming is more restricted than it was with FLTK2.
25 If your font_* preferences are no longer working well, please try
26 the fc-list command as given in dillorc.
20 default), font naming is more restricted than it was with FLTK2
21 as used by dillo2. If your font_* preferences are no longer
22 working well, please try the fc-list command as it is shown in
23 dillorc.
2724
2825
2926 Here's a list of some old well-known problems of dillo:
3330
3431
3532 -------
36 FLTK1.3
33 FLTK-1.3
3734 -------
3835
3936 You can get FLTK-1.3 here:
5855
5956 2.- Then dillo3:
6057
61 tar jxvf dillo-3.0.1.tar.bz2
62 cd dillo-3.0.1
58 tar jxvf dillo-3.0.2.tar.bz2
59 cd dillo-3.0.2
6360 ./configure; make
6461 sudo make install-strip
6562
00 #! /bin/sh
11 # Attempt to guess a canonical system name.
22 # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3 # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
3 # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
44 # Free Software Foundation, Inc.
55
6 timestamp='2009-12-30'
6 timestamp='2009-11-20'
77
88 # This file is free software; you can redistribute it and/or modify it
99 # under the terms of the GNU General Public License as published by
5555 GNU config.guess ($timestamp)
5656
5757 Originally written by Per Bothner.
58 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
59 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free
60 Software Foundation, Inc.
58 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
59 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
6160
6261 This is free software; see the source for copying conditions. There is NO
6362 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
00 #! /bin/sh
11 # Configuration validation subroutine script.
22 # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3 # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
3 # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
44 # Free Software Foundation, Inc.
55
6 timestamp='2009-12-31'
6 timestamp='2009-11-20'
77
88 # This file is (in principle) common to ALL GNU software.
99 # The presence of a machine in this file suggests that SOME GNU software
7474 version="\
7575 GNU config.sub ($timestamp)
7676
77 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
78 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free
79 Software Foundation, Inc.
77 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
78 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
8079
8180 This is free software; see the source for copying conditions. There is NO
8281 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
14351434 -dicos*)
14361435 os=-dicos
14371436 ;;
1438 -nacl*)
1439 ;;
14401437 -none)
14411438 ;;
14421439 *)
00 #! /bin/sh
11 # Guess values for system-dependent variables and create Makefiles.
2 # Generated by GNU Autoconf 2.68 for dillo 3.0.1.
2 # Generated by GNU Autoconf 2.68 for dillo 3.0.2.
33 #
44 #
55 # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
556556 # Identity of this package.
557557 PACKAGE_NAME='dillo'
558558 PACKAGE_TARNAME='dillo'
559 PACKAGE_VERSION='3.0.1'
560 PACKAGE_STRING='dillo 3.0.1'
559 PACKAGE_VERSION='3.0.2'
560 PACKAGE_STRING='dillo 3.0.2'
561561 PACKAGE_BUGREPORT=''
562562 PACKAGE_URL=''
563563
12861286 # Omit some internal or obsolete options to make the list less imposing.
12871287 # This message is too long to be a string in the A/UX 3.1 sh.
12881288 cat <<_ACEOF
1289 \`configure' configures dillo 3.0.1 to adapt to many kinds of systems.
1289 \`configure' configures dillo 3.0.2 to adapt to many kinds of systems.
12901290
12911291 Usage: $0 [OPTION]... [VAR=VALUE]...
12921292
13571357
13581358 if test -n "$ac_init_help"; then
13591359 case $ac_init_help in
1360 short | recursive ) echo "Configuration of dillo 3.0.1:";;
1360 short | recursive ) echo "Configuration of dillo 3.0.2:";;
13611361 esac
13621362 cat <<\_ACEOF
13631363
14631463 test -n "$ac_init_help" && exit $ac_status
14641464 if $ac_init_version; then
14651465 cat <<\_ACEOF
1466 dillo configure 3.0.1
1466 dillo configure 3.0.2
14671467 generated by GNU Autoconf 2.68
14681468
14691469 Copyright (C) 2010 Free Software Foundation, Inc.
21712171 This file contains any messages produced by compilers while
21722172 running configure, to aid debugging if configure makes a mistake.
21732173
2174 It was created by dillo $as_me 3.0.1, which was
2174 It was created by dillo $as_me 3.0.2, which was
21752175 generated by GNU Autoconf 2.68. Invocation command line was
21762176
21772177 $ $0 $@
30983098
30993099 # Define the identity of the package.
31003100 PACKAGE='dillo'
3101 VERSION='3.0.1'
3101 VERSION='3.0.2'
31023102
31033103
31043104 cat >>confdefs.h <<_ACEOF
69836983 # report actual input values of CONFIG_FILES etc. instead of their
69846984 # values after options handling.
69856985 ac_log="
6986 This file was extended by dillo $as_me 3.0.1, which was
6986 This file was extended by dillo $as_me 3.0.2, which was
69876987 generated by GNU Autoconf 2.68. Invocation command line was
69886988
69896989 CONFIG_FILES = $CONFIG_FILES
70497049 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
70507050 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
70517051 ac_cs_version="\\
7052 dillo config.status 3.0.1
7052 dillo config.status 3.0.2
70537053 configured by $0, generated by GNU Autoconf 2.68,
70547054 with options \\"\$ac_cs_config\\"
70557055
00 dnl Process this file with aclocal, autoconf and automake.
11
2 AC_INIT([dillo], [3.0.1])
2 AC_INIT([dillo], [3.0.2])
33
44 dnl Detect the canonical target build environment
55 AC_CANONICAL_TARGET
4646 dnl
4747 AC_CHECK_SIZEOF(char)
4848 AC_CHECK_SIZEOF(short)
49 AC_CHECK_SIZEOF(long)
50 AC_CHECK_SIZEOF(int)
49 AC_CHECK_SIZEOF(long)
50 AC_CHECK_SIZEOF(int)
5151 AC_CHECK_SIZEOF(void *)
5252
5353 AC_TYPE_INT16_T
303303
304304 dnl ----------------------
305305 dnl Check if we need to
306 dnl support the old
306 dnl support the old
307307 dnl iconv interface
308308 dnl ----------------------
309309 if test "x$iconv_ok" = "xyes"; then
369369 else
370370 AC_MSG_RESULT(no. Now we will try some libraries.)
371371
372 AC_SEARCH_LIBS(pthread_create, pthread,
373 LIBPTHREADS_LIBS="-lpthread",
374 AC_SEARCH_LIBS(pthread_create, pthreads,
372 AC_SEARCH_LIBS(pthread_create, pthread,
373 LIBPTHREADS_LIBS="-lpthread",
374 AC_SEARCH_LIBS(pthread_create, pthreads,
375375 LIBPTHREADS_LIBS="-lpthreads",
376376 AC_SEARCH_LIBS(pthread_create, c_r,
377377 LIBPTHREADS_LIBS="-lc_r", thread_ok=no)))
164164 #
165165 # See http://zytrax.com/tech/web/browser_ids.htm for a compilation of strings.
166166 #
167 # http_user_agent="Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6"
168 # http_user_agent="Wget/1.11.4"
169 #The default is Dillo/(current version number)
167 # http_user_agent="Mozilla/5.0 (Windows NT 5.1; rv:7.0.1) Gecko/20100101 Firefox/7.0.1"
168 # http_user_agent="Wget/1.12 (linux-gnu)"
169 #The default is "Dillo/"+current_version_number
170170
171171 #-------------------------------------------------------------------------
172172 # COLORS SECTION
239239
240240 # A mouse's middle click over a tab closes the Tab.
241241 # With mousewheel mouses, right click feels way better (set to YES).
242 #right_click_closes_tab=NO
242 #right_click_closes_tab=NO
243243
244244 # Mouse middle click by default drives drag-scrolling.
245245 # To paste an URL into the window instead of scrolling, set it to NO.
133133 }
134134
135135 /*
136 * Clear the contents of the string
137 */
138 void dStrshred(char *s)
139 {
140 if (s)
141 memset(s, 0, strlen(s));
142 }
143
144 /*
136145 * Return a new string of length 'len' filled with 'c' characters
137146 */
138147 char *dStrnfill(size_t len, char c)
163172 }
164173
165174 /*
175 * ASCII functions to avoid the case difficulties introduced by I/i in
176 * Turkic locales.
177 */
178
179 /*
166180 * Case insensitive strstr
167181 */
168 char *dStristr(const char *haystack, const char *needle)
182 char *dStriAsciiStr(const char *haystack, const char *needle)
169183 {
170184 int i, j;
171185 char *ret = NULL;
172186
173187 if (haystack && needle) {
174188 for (i = 0, j = 0; haystack[i] && needle[j]; ++i)
175 if (tolower(haystack[i]) == tolower(needle[j])) {
189 if (D_ASCII_TOLOWER(haystack[i]) == D_ASCII_TOLOWER(needle[j])) {
176190 ++j;
177191 } else if (j) {
178192 i -= j;
184198 return ret;
185199 }
186200
201 int dStrAsciiCasecmp(const char *s1, const char *s2)
202 {
203 int ret = 0;
204
205 while ((*s1 || *s2) &&
206 !(ret = D_ASCII_TOLOWER(*s1) - D_ASCII_TOLOWER(*s2))) {
207 s1++;
208 s2++;
209 }
210 return ret;
211 }
212
213 int dStrnAsciiCasecmp(const char *s1, const char *s2, size_t n)
214 {
215 int ret = 0;
216
217 while (n-- && (*s1 || *s2) &&
218 !(ret = D_ASCII_TOLOWER(*s1) - D_ASCII_TOLOWER(*s2))) {
219 s1++;
220 s2++;
221 }
222 return ret;
223 }
187224
188225 /*
189226 *- dStr ----------------------------------------------------------------------
332369 ds->str[len] = 0;
333370 ds->len = len;
334371 }
372 }
373
374 /*
375 * Clear a Dstr.
376 */
377 void dStr_shred (Dstr *ds)
378 {
379 if (ds && ds->sz > 0)
380 memset(ds->str, '\0', ds->sz);
335381 }
336382
337383 /*
44 #include <stddef.h> /* for size_t */
55 #include <stdarg.h> /* for va_list */
66 #include <string.h> /* for strerror */
7 #include <strings.h> /* for strcasecmp, strncasecmp (POSIX 2001) */
87
98 #include "d_size.h"
109
3332 #define dIsspace(c) isspace((uchar_t)(c))
3433 #define dIsalnum(c) isalnum((uchar_t)(c))
3534
35 #define D_ASCII_TOUPPER(c) (((c) >= 'a' && (c) <= 'z') ? (c) - 0x20 : (c))
36 #define D_ASCII_TOLOWER(c) (((c) >= 'A' && (c) <= 'Z') ? (c) + 0x20 : (c))
3637 /*
3738 *-- Casts -------------------------------------------------------------------
3839 */
8586 char *dStrstrip(char *s);
8687 char *dStrnfill(size_t len, char c);
8788 char *dStrsep(char **orig, const char *delim);
88 char *dStristr(const char *haystack, const char *needle);
89 void dStrshred(char *s);
90 char *dStriAsciiStr(const char *haystack, const char *needle);
91 int dStrAsciiCasecmp(const char *s1, const char *s2);
92 int dStrnAsciiCasecmp(const char *s1, const char *s2, size_t n);
8993
90 /* these are in POSIX 2001. Could be implemented if a port requires it */
91 #define dStrcasecmp strcasecmp
92 #define dStrncasecmp strncasecmp
9394 #define dStrerror strerror
9495
9596 /*
113114 void dStr_insert (Dstr *ds, int pos_0, const char *s);
114115 void dStr_insert_l (Dstr *ds, int pos_0, const char *s, int l);
115116 void dStr_truncate (Dstr *ds, int len);
117 void dStr_shred (Dstr *ds);
116118 void dStr_erase (Dstr *ds, int pos_0, int len);
117119 void dStr_vsprintfa (Dstr *ds, const char *format, va_list argp);
118120 void dStr_vsprintf (Dstr *ds, const char *format, va_list argp);
0 .TH dillo 1 "August 5, 2010" "version 2.2" "USER COMMANDS"
0 .TH dillo 1 "October 13, 2011" "" "USER COMMANDS"
11 .SH NAME
22 dillo \- web browser
33 .SH SYNOPSIS
1616 downloader.
1717 .PP
1818 Dillo displays HTML, text, PNG, JPEG, and GIF files.
19 It handles cookies, basic authentication, proxying, and some CSS.
19 It handles cookies, HTTP authentication (basic and digest), proxying (basic),
20 and some CSS.
2021 .PP
2122 Framesets are displayed as links to frames, and there is currently
2223 no support for javascript or video.
22
33 <head>
44 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
5 <title> Dillo Web Browser ::
5 <title> Dillo Web Browser ::
66
77 Help for New Users
88
5353 </ul>
5454 </td></tr>
5555 </table>
56
56
5757 <table WIDTH="100%" BORDER=1 CELLSPACING=0 CELLPADDING=3>
5858 <tr ALIGN=LEFT VALIGN=TOP><td bgcolor="wheat">
5959 <h4><font color="green">Usage:</font></h4>
7676 <li> <b>Configuration:</b> If you want to change Dillo's
7777 appearance or behaviour, look at the options in your
7878 <b><font color="#5040a0">dillorc</font></b>
79 file (if you don't have a copy in your ~/.dillo/ directory, get it
80 <a href='http://www.dillo.org/dillorc'>here</a>).
79 file (if you don't have a copy in your ~/.dillo/ directory, get it
80 <a href='http://www.dillo.org/dillorc'>here</a>).
8181
8282 <li> Clicking the "Reload" button always requests an end-to-end reload
8383 of the page currently viewed, but it will *not* reload embedded
194194 That is, if you just compile and use dillo, it will reject
195195 every single cookie sent to it!
196196 <p>
197 If you want to enable cookies in dillo, please read
197 If you want to enable cookies in dillo, please read
198198 <a href="Cookies.txt">Cookies.txt</a>. It's very easy --
199199 just a matter of setting up a <code>cookiesrc</code> file).
200200 </td></tr>
251251 (<a href='http://www.dillo.org/dpi1.html'>dpi</a>) framework.
252252 This should be transparent to the end user. Please note that:
253253 <ul>
254 <li>It is a good idea to keep a backup of your
254 <li>It is a good idea to keep a backup of your
255255 <code>~/.dillo/bm.txt</code>
256256 <li>The server will stay alive after closing dillo.
257257 <li>You can stop the server by sending it a KILL signal. Dillo
307307 <tr><td>Back or "<b>,</b>" <td>< <td>previous page
308308 <tr><td>Shift-Back or "<b>.</b>" <td>> <td>next page
309309 <tr><td>Alt-F <td>File <td>file menu
310 <tr><td>Ctrl-TabKey <td>TabKey <td>Next tab
311 <tr><td>Ctrl-Shift-TabKey <td>TabKey <td>Previous tab
310 <tr><td>Ctrl-TabKey or
311 Ctrl-PageDown <td>TabKey <td>Next tab
312 <tr><td>Ctrl-Shift-TabKey or
313 Ctrl-PageUp <td>TabKey <td>Previous tab
312314 <tr><td>Esc <td>escape <td>close dialog,
313315 close findbar,<br>
314316 Hide/show control panels
441441 if (*e == '+') {
442442 *p = ' ';
443443 } else if (*e == '%') {
444 if (dStrncasecmp(e, "%0D%0A", 6) == 0) {
444 if (dStrnAsciiCasecmp(e, "%0D%0A", 6) == 0) {
445445 *p = '\n';
446446 e += 5;
447447 } else {
16251625 dFree(cmd);
16261626 url = a_Dpip_get_attr_l(Buf, BufSize, "url");
16271627
1628 if (strcmp(url, "dpi:/bm/modify") == 0) {
1629 st = Bmsrv_send_modify_answer(sh, url);
1630 dFree(url);
1631 return st;
1632
1633 } else if (strncmp(url, "dpi:/bm/modify?", 15) == 0) {
1634 /* process request */
1635 st = Bmsrv_process_modify_request(sh, url);
1636 dFree(url);
1637 return st;
1628 if (dStrnAsciiCasecmp(url, "dpi:", 4) == 0) {
1629 if (strcmp(url+4, "/bm/modify") == 0) {
1630 st = Bmsrv_send_modify_answer(sh, url);
1631 dFree(url);
1632 return st;
1633 } else if (strncmp(url+4, "/bm/modify?", 11) == 0) {
1634 /* process request */
1635 st = Bmsrv_process_modify_request(sh, url);
1636 dFree(url);
1637 return st;
1638 }
16381639 }
16391640
16401641
157157 {
158158 const DomainNode *n1 = v1, *n2 = v2;
159159
160 return dStrcasecmp(n1->domain, n2->domain);
160 return dStrAsciiCasecmp(n1->domain, n2->domain);
161161 }
162162
163163 /*
168168 const DomainNode *node = v1;
169169 const char *domain = v2;
170170
171 return dStrcasecmp(node->domain, domain);
171 return dStrAsciiCasecmp(node->domain, domain);
172172 }
173173
174174 /*
467467 int i;
468468
469469 for (i = 0; i < 12; i++) {
470 if (!dStrncasecmp(months[i], month_name, 3))
470 if (!dStrnAsciiCasecmp(months[i], month_name, 3))
471471 return i;
472472 }
473473 return -1;
820820 cookie->expires_at = mktime(tm);
821821 if (cookie->expires_at == (time_t) -1)
822822 cookie->expires_at = cookies_future_time;
823 } else if (dStrcasecmp(attr, "Path") == 0) {
823 } else if (dStrAsciiCasecmp(attr, "Path") == 0) {
824824 value = Cookies_parse_value(&str);
825825 dFree(cookie->path);
826826 cookie->path = value;
827 } else if (dStrcasecmp(attr, "Domain") == 0) {
827 } else if (dStrAsciiCasecmp(attr, "Domain") == 0) {
828828 value = Cookies_parse_value(&str);
829829 dFree(cookie->domain);
830830 cookie->domain = value;
831 } else if (dStrcasecmp(attr, "Max-Age") == 0) {
831 } else if (dStrAsciiCasecmp(attr, "Max-Age") == 0) {
832832 value = Cookies_parse_value(&str);
833833 if (isdigit(*value) || *value == '-') {
834834 time_t now = time(NULL);
844844 expires = max_age = TRUE;
845845 }
846846 dFree(value);
847 } else if (dStrcasecmp(attr, "Expires") == 0) {
847 } else if (dStrAsciiCasecmp(attr, "Expires") == 0) {
848848 if (!max_age) {
849849 value = Cookies_parse_value(&str);
850850 Cookies_unquote_string(value);
869869 } else {
870870 Cookies_eat_value(&str);
871871 }
872 } else if (dStrcasecmp(attr, "Secure") == 0) {
872 } else if (dStrAsciiCasecmp(attr, "Secure") == 0) {
873873 cookie->secure = TRUE;
874874 Cookies_eat_value(&str);
875 } else if (dStrcasecmp(attr, "HttpOnly") == 0) {
875 } else if (dStrAsciiCasecmp(attr, "HttpOnly") == 0) {
876876 Cookies_eat_value(&str);
877877 } else {
878878 MSG("Cookie contains unknown attribute: '%s'\n", attr);
919919 _MSG("an IPv4 address\n");
920920 return TRUE;
921921 }
922 if (*domain == '[' &&
923 (len == strspn(domain, "0123456789abcdefABCDEF:.[]"))) {
922 if (strchr(domain, ':') &&
923 (len == strspn(domain, "0123456789abcdefABCDEF:."))) {
924924 /* The precise format is shown in section 3.2.2 of rfc 3986 */
925 _MSG("an IPv6 address\n");
925 MSG("an IPv6 address\n");
926926 return TRUE;
927927 }
928928 return FALSE;
991991 * don't, so: No.
992992 */
993993
994 if (!dStrcasecmp(A, B))
994 if (!dStrAsciiCasecmp(A, B))
995995 return TRUE;
996996
997997 if (Cookies_domain_is_ip(B))
10011001
10021002 if (diff > 0) {
10031003 /* B is the tail of A, and the match is preceded by a '.' */
1004 return (dStrcasecmp(A + diff, B) == 0 && A[diff - 1] == '.');
1004 return (dStrAsciiCasecmp(A + diff, B) == 0 && A[diff - 1] == '.');
10051005 } else {
10061006 return FALSE;
10071007 }
10491049
10501050 for (i = 0; i < tld_num; i++) {
10511051 if (strlen(tlds[i]) == (uint_t) tld_len &&
1052 !dStrncasecmp(tlds[i], host + start, tld_len)) {
1052 !dStrnAsciiCasecmp(tlds[i], host + start, tld_len)) {
10531053 _MSG("TLD code matched %s\n", tlds[i]);
10541054 ret++;
10551055 break;
12201220 matching_cookies = dList_new(8);
12211221
12221222 /* Check if the protocol is secure or not */
1223 is_ssl = (!dStrcasecmp(url_scheme, "https"));
1223 is_ssl = (!dStrAsciiCasecmp(url_scheme, "https"));
12241224
12251225 is_ip_addr = Cookies_domain_is_ip(url_host);
12261226
13491349 rule[j++] = line[i++];
13501350 rule[j] = '\0';
13511351
1352 if (dStrcasecmp(rule, "ACCEPT") == 0)
1352 if (dStrAsciiCasecmp(rule, "ACCEPT") == 0)
13531353 cc.action = COOKIE_ACCEPT;
1354 else if (dStrcasecmp(rule, "ACCEPT_SESSION") == 0)
1354 else if (dStrAsciiCasecmp(rule, "ACCEPT_SESSION") == 0)
13551355 cc.action = COOKIE_ACCEPT_SESSION;
1356 else if (dStrcasecmp(rule, "DENY") == 0)
1356 else if (dStrAsciiCasecmp(rule, "DENY") == 0)
13571357 cc.action = COOKIE_DENY;
13581358 else {
13591359 MSG("Cookies: rule '%s' for domain '%s' is not recognised.\n",
13621362 }
13631363
13641364 cc.domain = dStrdup(domain);
1365 if (dStrcasecmp(cc.domain, "DEFAULT") == 0) {
1365 if (dStrAsciiCasecmp(cc.domain, "DEFAULT") == 0) {
13661366 /* Set the default action */
13671367 default_action = cc.action;
13681368 dFree(cc.domain);
14031403 if (ccontrol[i].domain[0] == '.') {
14041404 diff = strlen(domain) - strlen(ccontrol[i].domain);
14051405 if (diff >= 0) {
1406 if (dStrcasecmp(domain + diff, ccontrol[i].domain) != 0)
1406 if (dStrAsciiCasecmp(domain + diff, ccontrol[i].domain) != 0)
14071407 continue;
14081408 } else {
14091409 continue;
14101410 }
14111411 } else {
1412 if (dStrcasecmp(domain, ccontrol[i].domain) != 0)
1412 if (dStrAsciiCasecmp(domain, ccontrol[i].domain) != 0)
14131413 continue;
14141414 }
14151415
4343 MSG("len=%d{%s}\n", strlen((char*)str), str);
4444
4545 for (p = s; (*p = *s); ++s) {
46 if (isalnum(*p) || strchr("+/=", *p))
46 if (isascii(*p) && (isalnum(*p) || strchr("+/=", *p)))
4747 ++p;
4848 }
4949
225225 char *mime_type = NULL, *p;
226226 size_t len = 0;
227227
228 if (dStrncasecmp(url, "data:", 5) == 0) {
228 if (dStrnAsciiCasecmp(url, "data:", 5) == 0) {
229229 if ((p = strchr(url, ',')) && p - url < 256) {
230230 url += 5;
231231 len = p - url;
232232 strncpy(buf, url, len);
233233 buf[len] = 0;
234234 /* strip ";base64" */
235 if (len >= 7 && dStrcasecmp(buf + len - 7, ";base64") == 0) {
235 if (len >= 7 && dStrAsciiCasecmp(buf + len - 7, ";base64") == 0) {
236236 len -= 7;
237237 buf[len] = 0;
238238 }
241241 /* that's it, now handle omitted types */
242242 if (len == 0) {
243243 mime_type = dStrdup("text/plain;charset=US-ASCII");
244 } else if (!dStrncasecmp(buf, "charset", 7)) {
244 } else if (!dStrnAsciiCasecmp(buf, "charset", 7)) {
245245 mime_type = dStrconcat("text/plain", buf, NULL);
246246 } else {
247247 mime_type = dStrdup(buf);
261261 unsigned char *data = NULL;
262262
263263 if ((p = strchr(url, ',')) && p - url >= 12 && /* "data:;base64" */
264 dStrncasecmp(p - 7, ";base64", 7) == 0) {
264 dStrnAsciiCasecmp(p - 7, ";base64", 7) == 0) {
265265 is_base64 = 1;
266266 }
267267
326326 /* escape "'" character for the shell. Is it necessary? */
327327 esc_url = Escape_uri_str(url, "'");
328328 /* avoid malicious SMTP relaying with FTP urls */
329 if (dStrncasecmp(esc_url, "ftp:/", 5) == 0)
329 if (dStrnAsciiCasecmp(esc_url, "ftp:/", 5) == 0)
330330 Filter_smtp_hack(esc_url);
331331 dl_argv = new char*[8];
332332 int i = 0;
353353 gw = 400, gh = 70;
354354 group = new Fl_Group(0,0,gw,gh);
355355 group->begin();
356 prTitle = new Fl_Box(24, 7, 290, 23);
357 prTitle->box(FL_RSHADOW_BOX);
358 prTitle->color(FL_WHITE);
359 prTitle->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_CLIP);
360 prTitle->copy_label(shortname);
361 // Attach this 'log_text' to the tooltip
362 log_text_add("Target File: ", 13);
363 log_text_add(fullname, strlen(fullname));
364 log_text_add("\n\n", 2);
365
366 prBar = new ProgressBar(24, 40, 92, 20);
367 prBar->box(FL_THIN_UP_BOX);
368 prBar->tooltip("Progress Status");
369
370 int ix = 122, iy = 37, iw = 50, ih = 14;
371 Fl_Widget *o = new Fl_Box(ix,iy,iw,ih, "Got");
372 o->box(FL_RFLAT_BOX);
373 o->color(FL_DARK2);
374 o->labelsize(12);
375 o->tooltip("Downloaded Size");
376 prGot = new Fl_Box(ix,iy+14,iw,ih, "0KB");
377 prGot->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
378 prGot->labelcolor(FL_BLUE);
379 prGot->labelsize(12);
380 prGot->box(FL_NO_BOX);
381
382 ix += iw;
383 o = new Fl_Box(ix,iy,iw,ih, "Size");
384 o->box(FL_RFLAT_BOX);
385 o->color(FL_DARK2);
386 o->labelsize(12);
387 o->tooltip("Total Size");
388 prSize = new Fl_Box(ix,iy+14,iw,ih, "??");
389 prSize->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
390 prSize->labelsize(12);
391 prSize->box(FL_NO_BOX);
392
393 ix += iw;
394 o = new Fl_Box(ix,iy,iw,ih, "Rate");
395 o->box(FL_RFLAT_BOX);
396 o->color(FL_DARK2);
397 o->labelsize(12);
398 o->tooltip("Current transfer Rate (KBytes/sec)");
399 prRate = new Fl_Box(ix,iy+14,iw,ih, "??");
400 prRate->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
401 prRate->labelsize(12);
402 prRate->box(FL_NO_BOX);
403
404 ix += iw;
405 o = new Fl_Box(ix,iy,iw,ih, "~Rate");
406 o->box(FL_RFLAT_BOX);
407 o->color(FL_DARK2);
408 o->labelsize(12);
409 o->tooltip("Average transfer Rate (KBytes/sec)");
410 pr_Rate = new Fl_Box(ix,iy+14,iw,ih, "??");
411 pr_Rate->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
412 pr_Rate->labelsize(12);
413 pr_Rate->box(FL_NO_BOX);
414
415 ix += iw;
416 prETAt = o = new Fl_Box(ix,iy,iw,ih, "ETA");
417 o->box(FL_RFLAT_BOX);
418 o->color(FL_DARK2);
419 o->labelsize(12);
420 o->tooltip("Estimated Time of Arrival");
421 prETA = new Fl_Box(ix,iy+14,iw,ih, "??");
422 prETA->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
423 prETA->labelsize(12);
424 prETA->box(FL_NO_BOX);
425
426 prButton = new Fl_Button(326, 9, 44, 19, "Stop");
427 prButton->tooltip("Stop this transfer");
428 prButton->box(FL_UP_BOX);
429 prButton->clear_visible_focus();
430 prButton->callback(prButton_scb, this);
356 prTitle = new Fl_Box(24, 7, 290, 23);
357 prTitle->box(FL_RSHADOW_BOX);
358 prTitle->color(FL_WHITE);
359 prTitle->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_CLIP);
360 prTitle->copy_label(shortname);
361 // Attach this 'log_text' to the tooltip
362 log_text_add("Target File: ", 13);
363 log_text_add(fullname, strlen(fullname));
364 log_text_add("\n\n", 2);
365
366 prBar = new ProgressBar(24, 40, 92, 20);
367 prBar->box(FL_THIN_UP_BOX);
368 prBar->tooltip("Progress Status");
369
370 int ix = 122, iy = 37, iw = 50, ih = 14;
371 Fl_Widget *o = new Fl_Box(ix,iy,iw,ih, "Got");
372 o->box(FL_RFLAT_BOX);
373 o->color(FL_DARK2);
374 o->labelsize(12);
375 o->tooltip("Downloaded Size");
376 prGot = new Fl_Box(ix,iy+14,iw,ih, "0KB");
377 prGot->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
378 prGot->labelcolor(FL_BLUE);
379 prGot->labelsize(12);
380 prGot->box(FL_NO_BOX);
381
382 ix += iw;
383 o = new Fl_Box(ix,iy,iw,ih, "Size");
384 o->box(FL_RFLAT_BOX);
385 o->color(FL_DARK2);
386 o->labelsize(12);
387 o->tooltip("Total Size");
388 prSize = new Fl_Box(ix,iy+14,iw,ih, "??");
389 prSize->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
390 prSize->labelsize(12);
391 prSize->box(FL_NO_BOX);
392
393 ix += iw;
394 o = new Fl_Box(ix,iy,iw,ih, "Rate");
395 o->box(FL_RFLAT_BOX);
396 o->color(FL_DARK2);
397 o->labelsize(12);
398 o->tooltip("Current transfer Rate (KBytes/sec)");
399 prRate = new Fl_Box(ix,iy+14,iw,ih, "??");
400 prRate->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
401 prRate->labelsize(12);
402 prRate->box(FL_NO_BOX);
403
404 ix += iw;
405 o = new Fl_Box(ix,iy,iw,ih, "~Rate");
406 o->box(FL_RFLAT_BOX);
407 o->color(FL_DARK2);
408 o->labelsize(12);
409 o->tooltip("Average transfer Rate (KBytes/sec)");
410 pr_Rate = new Fl_Box(ix,iy+14,iw,ih, "??");
411 pr_Rate->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
412 pr_Rate->labelsize(12);
413 pr_Rate->box(FL_NO_BOX);
414
415 ix += iw;
416 prETAt = o = new Fl_Box(ix,iy,iw,ih, "ETA");
417 o->box(FL_RFLAT_BOX);
418 o->color(FL_DARK2);
419 o->labelsize(12);
420 o->tooltip("Estimated Time of Arrival");
421 prETA = new Fl_Box(ix,iy+14,iw,ih, "??");
422 prETA->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
423 prETA->labelsize(12);
424 prETA->box(FL_NO_BOX);
425
426 prButton = new Fl_Button(326, 9, 44, 19, "Stop");
427 prButton->tooltip("Stop this transfer");
428 prButton->box(FL_UP_BOX);
429 prButton->clear_visible_focus();
430 prButton->callback(prButton_scb, this);
431431
432432 group->box(FL_ROUNDED_BOX);
433433 group->end();
10861086 }
10871087
10881088 /*
1089 * A Scroll class that resizes its resizable widget to its width.
1090 * see http://seriss.com/people/erco/fltk/#ScrollableWidgetBrowser
1091 */
1092 class DlScroll : public Fl_Scroll
1093 {
1094 public:
1095 void resize(int x_, int y_, int w_, int h_)
1096 {
1097 Fl_Widget *resizable_ = resizable();
1098 if (resizable_)
1099 resizable_->resize(resizable_->x(),
1100 resizable_->y(),
1101 w() - scrollbar_size(),
1102 resizable_->h());
1103 Fl_Scroll::resize(x_, y_, w_, h_);
1104 }
1105 DlScroll(int x, int y, int w, int h, const char *l = 0)
1106 : Fl_Scroll(x, y, w, h, l)
1107 {
1108 }
1109 };
1110
1111 /*
10891112 * Create the main window and an empty list of requests.
10901113 */
10911114 DLWin::DLWin(int ww, int wh) {
10961119 // Create the empty main window
10971120 mWin = new Fl_Window(ww, wh, "Downloads:");
10981121 mWin->begin();
1099 mScroll = new Fl_Scroll(0,0,ww,wh);
1100 mScroll->begin();
1101 mPG = new Fl_Pack(0,0,ww-18,wh);
1102 mPG->end();
1103 mScroll->end();
1104 mScroll->type(Fl_Scroll::VERTICAL);
1122 mScroll = new DlScroll(0,0,ww,wh);
1123 mScroll->begin();
1124 mPG = new Fl_Pack(0,0,ww-18,wh);
1125 mPG->end();
1126 mScroll->end();
1127 mScroll->type(Fl_Scroll::VERTICAL);
1128 mScroll->resizable(mPG);
11051129 mWin->end();
11061130 mWin->resizable(mScroll);
11071131 mWin->callback(dlwin_esc_cb, NULL);
6767 if (strchr(s, '%')) {
6868 for (p = buf; (*p = *s); ++s, ++p) {
6969 if (*p == '%' && isxdigit(s[1]) && isxdigit(s[2])) {
70 *p = (isdigit(s[1]) ? (s[1] - '0') : toupper(s[1]) - 'A' + 10)*16;
71 *p += isdigit(s[2]) ? (s[2] - '0') : toupper(s[2]) - 'A' + 10;
70 *p = (isdigit(s[1]) ? (s[1] - '0')
71 : D_ASCII_TOUPPER(s[1]) - 'A' + 10) * 16;
72 *p += isdigit(s[2]) ? (s[2] - '0')
73 : D_ASCII_TOUPPER(s[2]) - 'A' + 10;
7274 s += 2;
7375 }
7476 }
120122 for (i = 0, j = 0; str[i]; ++i) {
121123 if (str[i] == '&') {
122124 for (k = 0; k < 5; ++k) {
123 if (!dStrncasecmp(str + i, unsafe_rep[k], unsafe_rep_len[k])) {
125 if (!dStrnAsciiCasecmp(str + i, unsafe_rep[k], unsafe_rep_len[k])) {
124126 i += unsafe_rep_len[k] - 1;
125127 break;
126128 }
153155 memmove(url + i, url + i + 1, strlen(url + i));
154156 --i;
155157 } else if (c == '%' && url[i+1] == '0' &&
156 (tolower(url[i+2]) == 'a' || tolower(url[i+2]) == 'd')) {
158 (D_ASCII_TOLOWER(url[i+2]) == 'a' ||
159 D_ASCII_TOLOWER(url[i+2]) == 'd')) {
157160 memmove(url + i, url + i + 3, strlen(url + i + 2));
158161 --i;
159162 }
1414 * With new HTML layout.
1515 */
1616
17 #include <ctype.h> /* for tolower */
17 #include <ctype.h> /* for isspace */
1818 #include <errno.h> /* for errno */
1919 #include <stdio.h>
2020 #include <stdlib.h>
141141
142142 /* HTML try */
143143 for (i = 0; i < Size && dIsspace(p[i]); ++i);
144 if ((Size - i >= 5 && !dStrncasecmp(p+i, "<html", 5)) ||
145 (Size - i >= 5 && !dStrncasecmp(p+i, "<head", 5)) ||
146 (Size - i >= 6 && !dStrncasecmp(p+i, "<title", 6)) ||
147 (Size - i >= 14 && !dStrncasecmp(p+i, "<!doctype html", 14)) ||
144 if ((Size - i >= 5 && !dStrnAsciiCasecmp(p+i, "<html", 5)) ||
145 (Size - i >= 5 && !dStrnAsciiCasecmp(p+i, "<head", 5)) ||
146 (Size - i >= 6 && !dStrnAsciiCasecmp(p+i, "<title", 6)) ||
147 (Size - i >= 14 && !dStrnAsciiCasecmp(p+i, "<!doctype html", 14)) ||
148148 /* this line is workaround for FTP through the Squid proxy */
149 (Size - i >= 17 && !dStrncasecmp(p+i, "<!-- HTML listing", 17))) {
149 (Size - i >= 17 && !dStrnAsciiCasecmp(p+i, "<!-- HTML listing", 17))) {
150150
151151 Type = 1;
152152
153153 /* Images */
154 } else if (Size >= 4 && !dStrncasecmp(p, "GIF8", 4)) {
154 } else if (Size >= 4 && !strncmp(p, "GIF8", 4)) {
155155 Type = 3;
156 } else if (Size >= 4 && !dStrncasecmp(p, "\x89PNG", 4)) {
156 } else if (Size >= 4 && !strncmp(p, "\x89PNG", 4)) {
157157 Type = 4;
158 } else if (Size >= 2 && !dStrncasecmp(p, "\xff\xd8", 2)) {
158 } else if (Size >= 2 && !strncmp(p, "\xff\xd8", 2)) {
159159 /* JPEG has the first 2 bytes set to 0xffd8 in BigEndian - looking
160160 * at the character representation should be machine independent. */
161161 Type = 5;
501501
502502 e++;
503503
504 if (!dStrcasecmp(e, "gif")) {
504 if (!dStrAsciiCasecmp(e, "gif")) {
505505 return "image/gif";
506 } else if (!dStrcasecmp(e, "jpg") ||
507 !dStrcasecmp(e, "jpeg")) {
506 } else if (!dStrAsciiCasecmp(e, "jpg") ||
507 !dStrAsciiCasecmp(e, "jpeg")) {
508508 return "image/jpeg";
509 } else if (!dStrcasecmp(e, "png")) {
509 } else if (!dStrAsciiCasecmp(e, "png")) {
510510 return "image/png";
511 } else if (!dStrcasecmp(e, "html") ||
512 !dStrcasecmp(e, "htm") ||
513 !dStrcasecmp(e, "shtml")) {
511 } else if (!dStrAsciiCasecmp(e, "html") ||
512 !dStrAsciiCasecmp(e, "htm") ||
513 !dStrAsciiCasecmp(e, "shtml")) {
514514 return "text/html";
515 } else if (!dStrcasecmp(e, "txt")) {
515 } else if (!dStrAsciiCasecmp(e, "txt")) {
516516 return "text/plain";
517517 } else {
518518 return NULL;
711711
712712 /* Check for gzipped file */
713713 namelen = strlen(client->filename);
714 if (namelen > 3 && !dStrcasecmp(client->filename + namelen - 3, ".gz")) {
714 if (namelen > 3 &&
715 !dStrAsciiCasecmp(client->filename + namelen - 3, ".gz")) {
715716 gzipped = TRUE;
716717 namelen -= 3;
717718 }
798799 dReturn_val_if (orig == NULL, ret);
799800
800801 /* Make sure the string starts with "file:/" */
801 if (strncmp(str, "file:/", 5) != 0)
802 if (dStrnAsciiCasecmp(str, "file:/", 5) != 0)
802803 return ret;
803804 str += 5;
804805
805806 /* Skip "localhost" */
806 if (dStrncasecmp(str, "//localhost/", 12) == 0)
807 if (dStrnAsciiCasecmp(str, "//localhost/", 12) == 0)
807808 str += 11;
808809
809810 /* Skip packed slashes, and leave just one */
940941 DPIBYE = 1;
941942 MSG("(pid %d): Got DpiBye.\n", (int)getpid());
942943 client->flags |= FILE_DONE;
943 } else if (url && strcmp(url, "dpi:/file/toggle") == 0) {
944 } else if (url && dStrnAsciiCasecmp(url, "dpi:", 4) == 0 &&
945 strcmp(url+4, "/file/toggle") == 0) {
944946 File_toggle_html_style(client);
945947 } else if (path) {
946948 File_get(client, path, url);
9797
9898 /* HTML try */
9999 for (i = 0; i < Size && dIsspace(p[i]); ++i);
100 if ((Size - i >= 5 && !dStrncasecmp(p+i, "<html", 5)) ||
101 (Size - i >= 5 && !dStrncasecmp(p+i, "<head", 5)) ||
102 (Size - i >= 6 && !dStrncasecmp(p+i, "<title", 6)) ||
103 (Size - i >= 14 && !dStrncasecmp(p+i, "<!doctype html", 14)) ||
100 if ((Size - i >= 5 && !dStrnAsciiCasecmp(p+i, "<html", 5)) ||
101 (Size - i >= 5 && !dStrnAsciiCasecmp(p+i, "<head", 5)) ||
102 (Size - i >= 6 && !dStrnAsciiCasecmp(p+i, "<title", 6)) ||
103 (Size - i >= 14 && !dStrnAsciiCasecmp(p+i, "<!doctype html", 14)) ||
104104 /* this line is workaround for FTP through the Squid proxy */
105 (Size - i >= 17 && !dStrncasecmp(p+i, "<!-- HTML listing", 17))) {
105 (Size - i >= 17 && !dStrnAsciiCasecmp(p+i, "<!-- HTML listing", 17))) {
106106
107107 Type = 1;
108108 st = 0;
109109 /* Images */
110 } else if (Size >= 4 && !dStrncasecmp(p, "GIF8", 4)) {
110 } else if (Size >= 4 && !strncmp(p, "GIF8", 4)) {
111111 Type = 3;
112112 st = 0;
113 } else if (Size >= 4 && !dStrncasecmp(p, "\x89PNG", 4)) {
113 } else if (Size >= 4 && !strncmp(p, "\x89PNG", 4)) {
114114 Type = 4;
115115 st = 0;
116 } else if (Size >= 2 && !dStrncasecmp(p, "\xff\xd8", 2)) {
116 } else if (Size >= 2 && !strncmp(p, "\xff\xd8", 2)) {
117117 /* JPEG has the first 2 bytes set to 0xffd8 in BigEndian - looking
118118 * at the character representation should be machine independent. */
119119 Type = 5;
359359 char * url_look_up = NULL;
360360
361361 /*Determine how much of url we chop off as unneeded*/
362 if (dStrncasecmp(url, "https://", 8) == 0){
362 if (dStrnAsciiCasecmp(url, "https://", 8) == 0){
363363 url_offset = 8;
364 } else if (dStrncasecmp(url, "http://", 7) == 0) {
364 } else if (dStrnAsciiCasecmp(url, "http://", 7) == 0) {
365365 url_offset = 7;
366366 portnum = 80;
367367 }
100100 int bytes_read = 0, old_line = 0, line = 1;
101101 char *p, *q, *src_str, line_str[128];
102102
103 if (strncmp(url, "dpi:/vsource/:", 14) == 0)
103 if (dStrnAsciiCasecmp(url, "dpi:", 4) == 0 &&
104 strncmp(url+4, "/vsource/:", 10) == 0)
104105 url += 14;
105106
106107 /* Send HTTP header for plain text MIME type */
844844 if (A->name[A_len - 1] == '*')
845845 len = A_len - 1;
846846
847 return(dStrncasecmp(A->name, B, len));
847 return(dStrnAsciiCasecmp(A->name, B, len));
848848 }
849849
850850 /*!
0 // fltkcomplexbutton.cc contains code from FLTK 1.3's src/Fl_Button.cxx
1 // that is Copyright 1998-2010 by Bill Spitzak and others.
0 // fltkcomplexbutton.cc is derived from src/Fl_Button.cxx from FLTK's 1.3
1 // branch at http://fltk.org in early 2011.
2 // src/Fl_Button.cxx is Copyright 1998-2010 by Bill Spitzak and others.
23
34 /*
45 * This program is free software; you can redistribute it and/or modify
107108 return 1;
108109 } else return 0;
109110 case FL_KEYBOARD :
110 if (Fl::focus() == this && Fl::event_key() == ' ' &&
111 if (Fl::focus() == this &&
112 (Fl::event_key() == ' ' || Fl::event_key() == FL_Enter) &&
111113 !(Fl::event_state() & (FL_SHIFT | FL_CTRL | FL_ALT | FL_META))) {
112114 set_changed();
113115 Fl_Widget_Tracker wp(this);
00
1 // fltkcomplexbutton.hh contains code from FLTK 1.3's FL/Fl_Button.H
2 // that is Copyright 1998-2010 by Bill Spitzak and others.
1 // fltkcomplexbutton.hh is derived from FL/Fl_Button.H from FLTK's 1.3 branch
2 // at http://fltk.org in early 2011.
3 // FL/Fl_Button.H is Copyright 1998-2010 by Bill Spitzak and others.
34
45 /*
56 * This program is free software; you can redistribute it and/or modify
140140 static void strstrip(char *big, const char *little)
141141 {
142142 if (strlen(big) >= strlen(little) &&
143 strcasecmp(big + strlen(big) - strlen(little), little) == 0)
143 misc::AsciiStrcasecmp(big + strlen(big) - strlen(little), little) == 0)
144144 *(big + strlen(big) - strlen(little)) = '\0';
145145 }
146146
524524 if ((cu = fl_toupper(c)) == c) {
525525 /* already uppercase, just draw the character */
526526 fl_font(ff->font, ff->size);
527 width += font->letterSpacing;
528 width += (int)fl_width(text + curr, next - curr);
527 if (fl_nonspacing(cu) == 0) {
528 width += font->letterSpacing;
529 width += (int)fl_width(text + curr, next - curr);
530 }
529531 } else {
530532 /* make utf8 string for converted char */
531533 nb = fl_utf8encode(cu, chbuf);
532534 fl_font(ff->font, sc_fontsize);
533 width += font->letterSpacing;
534 width += (int)fl_width(chbuf, nb);
535 if (fl_nonspacing(cu) == 0) {
536 width += font->letterSpacing;
537 width += (int)fl_width(chbuf, nb);
538 }
535539 }
536540 }
537541 } else {
543547
544548 while (next < len) {
545549 next = nextGlyph(text, curr);
546 width += font->letterSpacing;
550 c = fl_utf8decode(text + curr, text + next, &nb);
551 if (fl_nonspacing(c) == 0)
552 width += font->letterSpacing;
547553 curr = next;
548554 }
549555 }
550556 }
551557
552558 return width;
559 }
560
561 char *FltkPlatform::textToUpper (const char *text, int len)
562 {
563 char *newstr = NULL;
564
565 if (len > 0) {
566 int newlen;
567
568 newstr = (char*) malloc(3 * len + 1);
569 newlen = fl_utf_toupper((const unsigned char*)text, len, newstr);
570 assert(newlen <= 3 * len);
571 newstr[newlen] = '\0';
572 }
573 return newstr;
574 }
575
576 char *FltkPlatform::textToLower (const char *text, int len)
577 {
578 char *newstr = NULL;
579
580 if (len > 0) {
581 int newlen;
582
583 newstr = (char*) malloc(3 * len + 1);
584 newlen = fl_utf_tolower((const unsigned char*)text, len, newstr);
585 assert(newlen <= 3 * len);
586 newstr[newlen] = '\0';
587 }
588 return newstr;
553589 }
554590
555591 int FltkPlatform::nextGlyph (const char *text, int idx)
152152 void detachView (core::View *view);
153153
154154 int textWidth (core::style::Font *font, const char *text, int len);
155 char *textToUpper (const char *text, int len);
156 char *textToLower (const char *text, int len);
155157 int nextGlyph (const char *text, int idx);
156158 int prevGlyph (const char *text, int idx);
157159 float dpiX ();
265265
266266 // ----------------------------------------------------------------------
267267
268 class EnterButton : public Fl_Button {
269 public:
270 EnterButton (int x,int y,int w,int h, const char* label = 0) :
271 Fl_Button (x,y,w,h,label) {};
272 int handle(int e);
273 };
274
275 int EnterButton::handle(int e)
276 {
277 if (e == FL_KEYBOARD && Fl::focus() == this && Fl::event_key() == FL_Enter){
278 set_changed();
279 simulate_key_action();
280 do_callback();
281 return 1;
282 }
283 return Fl_Button::handle(e);
284 }
285
268286 FltkLabelButtonResource::FltkLabelButtonResource (FltkPlatform *platform,
269287 const char *label):
270288 FltkSpecificResource <dw::core::ui::LabelButtonResource> (platform)
282300 *allocation)
283301 {
284302 Fl_Button *button =
285 new Fl_Button (allocation->x, allocation->y, allocation->width,
286 allocation->ascent + allocation->descent, label);
303 new EnterButton (allocation->x, allocation->y, allocation->width,
304 allocation->ascent + allocation->descent, label);
287305 button->callback (widgetCallback, this);
288306 button->when (FL_WHEN_RELEASE);
289307 return button;
547547 viewY = translateCanvasYToViewY (Y);
548548 int curr = 0, next = 0, nb;
549549 char chbuf[4];
550 int c, cu;
550 int c, cu, width;
551551
552552 if (font->fontVariant == core::style::FONT_VARIANT_SMALL_CAPS) {
553553 int sc_fontsize = lout::misc::roundInt(ff->size * 0.78);
557557 if ((cu = fl_toupper(c)) == c) {
558558 /* already uppercase, just draw the character */
559559 fl_font(ff->font, ff->size);
560 width = (int)fl_width(text + curr, next - curr);
561 if (curr && width)
562 viewX += font->letterSpacing;
560563 fl_draw(text + curr, next - curr, viewX, viewY);
561 viewX += font->letterSpacing;
562 viewX += (int)fl_width(text + curr, next - curr);
564 viewX += width;
563565 } else {
564566 /* make utf8 string for converted char */
565567 nb = fl_utf8encode(cu, chbuf);
566568 fl_font(ff->font, sc_fontsize);
569 width = (int)fl_width(chbuf, nb);
570 if (curr && width)
571 viewX += font->letterSpacing;
567572 fl_draw(chbuf, nb, viewX, viewY);
568 viewX += font->letterSpacing;
569 viewX += (int)fl_width(chbuf, nb);
573 viewX += width;
570574 }
571575 }
572576 } else {
573577 while (next < len) {
574578 next = theLayout->nextGlyph(text, curr);
579 width = (int)fl_width(text + curr, next - curr);
580 if (curr && width)
581 viewX += font->letterSpacing;
575582 fl_draw(text + curr, next - curr, viewX, viewY);
576 viewX += font->letterSpacing +
577 (int)fl_width(text + curr,next - curr);
583 viewX += width;
578584 curr = next;
579585 }
580586 }
296296 return platform->textWidth (font, text, len);
297297 }
298298
299 inline char *textToUpper (const char *text, int len)
300 {
301 return platform->textToUpper (text, len);
302 }
303
304 inline char *textToLower (const char *text, int len)
305 {
306 return platform->textToLower (text, len);
307 }
308
299309 inline int nextGlyph (const char *text, int idx)
300310 {
301311 return platform->nextGlyph (text, idx);
5555 * \brief Return the width of a text, with a given length and font.
5656 */
5757 virtual int textWidth (style::Font *font, const char *text, int len) = 0;
58
59 /**
60 * \brief Return the string resulting from transforming text to uppercase.
61 */
62 virtual char *textToUpper (const char *text, int len) = 0;
63
64 /**
65 * \brief Return the string resulting from transforming text to lowercase.
66 */
67 virtual char *textToLower (const char *text, int len) = 0;
5868
5969 /**
6070 * \brief Return the index of the next glyph in string text.
4141 textDecoration = TEXT_DECORATION_NONE;
4242 textAlign = TEXT_ALIGN_LEFT;
4343 textAlignChar = '.';
44 textTransform = TEXT_TRANSFORM_NONE;
4445 listStylePosition = LIST_STYLE_POSITION_OUTSIDE;
4546 listStyleType = LIST_STYLE_TYPE_DISC;
4647 valign = VALIGN_BASELINE;
116117 textAlign == otherAttrs->textAlign &&
117118 valign == otherAttrs->valign &&
118119 textAlignChar == otherAttrs->textAlignChar &&
120 textTransform == otherAttrs->textTransform &&
119121 hBorderSpacing == otherAttrs->hBorderSpacing &&
120122 vBorderSpacing == otherAttrs->vBorderSpacing &&
121123 wordSpacing == otherAttrs->wordSpacing &&
153155 textAlign +
154156 valign +
155157 textAlignChar +
158 textTransform +
156159 hBorderSpacing +
157160 vBorderSpacing +
158161 wordSpacing +
243246 textAlign = attrs->textAlign;
244247 valign = attrs->valign;
245248 textAlignChar = attrs->textAlignChar;
249 textTransform = attrs->textTransform;
246250 hBorderSpacing = attrs->hBorderSpacing;
247251 vBorderSpacing = attrs->vBorderSpacing;
248252 wordSpacing = attrs->wordSpacing;
884888 *const roman_I2[] = { "","C","CC","CCC","CD","D","DC","DCC","DCCC","CM" },
885889 *const roman_I3[] = { "","M","MM","MMM","MMMM" };
886890
887 static void strtolower (char *s)
891 static void strAsciiTolower (char *s)
888892 {
889893 for ( ; *s; s++)
890 *s = tolower (*s);
894 *s = misc::AsciiTolower (*s);
891895 }
892896
893897 /**
942946 buf[buflen - 1] = '\0';
943947
944948 if (low)
945 strtolower(buf);
949 strAsciiTolower(buf);
946950
947951 }
948952
244244 VALIGN_SUPER,
245245 VALIGN_TEXT_TOP,
246246 VALIGN_TEXT_BOTTOM,
247 };
248
249 enum TextTransform {
250 TEXT_TRANSFORM_NONE,
251 TEXT_TRANSFORM_CAPITALIZE,
252 TEXT_TRANSFORM_UPPERCASE,
253 TEXT_TRANSFORM_LOWERCASE,
247254 };
248255
249256 /**
440447 TextAlignType textAlign;
441448 VAlignType valign;
442449 char textAlignChar; /* In future, strings will be supported. */
450 TextTransform textTransform;
443451
444452 int hBorderSpacing, vBorderSpacing, wordSpacing;
445453 Length width, height, lineHeight, textIndent;
269269
270270 void Table::addCell (Widget *widget, int colspan, int rowspan)
271271 {
272 const int maxspan = 100;
272273 Child *child;
273274 int colspanEff;
274275
275 // We limit the values for colspan and rowspan to 50, to avoid
276 // We limit the values for colspan and rowspan to avoid
276277 // attacks by malicious web pages.
277 if (colspan > 50 || colspan < 0) {
278 MSG_WARN("colspan = %d is set to 50.\n", colspan);
279 colspan = 50;
280 }
281 if (rowspan > 50 || rowspan <= 0) {
282 MSG_WARN("rowspan = %d is set to 50.\n", rowspan);
283 rowspan = 50;
278 if (colspan > maxspan || colspan < 0) {
279 MSG_WARN("colspan = %d is set to %d.\n", colspan, maxspan);
280 colspan = maxspan;
281 }
282 if (rowspan > maxspan || rowspan <= 0) {
283 MSG_WARN("rowspan = %d is set to %d.\n", rowspan, maxspan);
284 rowspan = maxspan;
284285 }
285286
286287 if (numRows == 0) {
6969 words = new misc::SimpleVector <Word> (1);
7070 anchors = new misc::SimpleVector <Anchor> (1);
7171
72 //DBG_OBJ_SET_NUM(page, "num_lines", num_lines);
72 //DBG_OBJ_SET_NUM(this, "num_lines", num_lines);
7373
7474 lastLineWidth = 0;
75 lastLineParMin = 0;
7675 lastLineParMax = 0;
7776 wrapRef = -1;
7877
79 //DBG_OBJ_SET_NUM(page, "last_line_width", last_line_width);
80 //DBG_OBJ_SET_NUM(page, "last_line_par_min", last_line_par_min);
81 //DBG_OBJ_SET_NUM(page, "last_line_par_max", last_line_par_max);
82 //DBG_OBJ_SET_NUM(page, "wrap_ref", wrap_ref);
78 //DBG_OBJ_SET_NUM(this, "last_line_width", last_line_width);
79 //DBG_OBJ_SET_NUM(this, "last_line_par_min", last_line_par_min);
80 //DBG_OBJ_SET_NUM(this, "last_line_par_max", last_line_par_max);
81 //DBG_OBJ_SET_NUM(this, "wrap_ref", wrap_ref);
8382
8483 hoverLink = -1;
8584
128127 parent class destructor. (???) */
129128 words = NULL;
130129
131 //DBG_OBJ_SET_NUM(page, "num_lines", page->num_lines);
130 //DBG_OBJ_SET_NUM(this, "num_lines", lines->size ());
132131 }
133132
134133 /**
201200 {
202201 core::Extremes wordExtremes;
203202 Line *line;
204 Word *word;
203 Word *word, *prevWord = NULL;
205204 int wordIndex, lineIndex;
206 int parMin, parMax;
207 bool nowrap;
208
209 //DBG_MSG (widget, "extremes", 0, "Dw_page_get_extremes");
205 int parMax;
206
207 //DBG_MSG (widget, "extremes", 0, "getExtremesImpl");
210208 //DBG_MSG_START (widget);
211209
212210 if (lines->size () == 0) {
216214 } else if (wrapRef == -1) {
217215 /* no rewrap necessary -> values in lines are up to date */
218216 line = lines->getRef (lines->size () - 1);
219 /* Historical note: The former distinction between lines with and without
220 * words[first_word]->nowrap set is no longer necessary, since
221 * Dw_page_real_word_wrap sets max_word_min to the correct value in any
222 * case. */
223 extremes->minWidth = line->maxWordMin;
217 extremes->minWidth = line->maxParMin;
224218 extremes->maxWidth = misc::max (line->maxParMax, lastLineParMax);
225219 //DBG_MSG (widget, "extremes", 0, "simple case");
226220 } else {
231225 if (wrapRef == 0) {
232226 extremes->minWidth = 0;
233227 extremes->maxWidth = 0;
234 parMin = 0;
235228 parMax = 0;
236229 } else {
237230 line = lines->getRef (wrapRef);
238 extremes->minWidth = line->maxWordMin;
231 extremes->minWidth = line->maxParMin;
239232 extremes->maxWidth = line->maxParMax;
240 parMin = line->parMin;
241233 parMax = line->parMax;
242234
243235 //DBG_MSGF (widget, "extremes", 0, "parMin = %d", parMin);
249241 for (lineIndex = wrapRef; lineIndex < lines->size (); lineIndex++) {
250242 //DBG_MSGF (widget, "extremes", 0, "line %d", lineIndex);
251243 //DBG_MSG_START (widget);
252 core::style::WhiteSpace ws;
244 int parMin = 0;
253245
254246 line = lines->getRef (lineIndex);
255 ws = words->getRef(line->firstWord)->style->whiteSpace;
256 nowrap = ws == core::style::WHITE_SPACE_PRE ||
257 ws == core::style::WHITE_SPACE_NOWRAP;
258
259 //DEBUG_MSG (DEBUG_SIZE_LEVEL, " line %d (of %d), nowrap = %d\n",
260 // lineIndex, page->num_lines, nowrap);
261247
262248 for (wordIndex = line->firstWord; wordIndex <= line->lastWord;
263249 wordIndex++) {
268254 wordExtremes.minWidth += line1OffsetEff;
269255 wordExtremes.maxWidth += line1OffsetEff;
270256 //DEBUG_MSG (DEBUG_SIZE_LEVEL + 1,
271 // " (next plus %d)\n", page->line1_offset);
257 // " (next plus %d)\n", line1OffsetEff);
272258 }
273259
274 if (nowrap) {
275 parMin += prevWordSpace + wordExtremes.minWidth;
276 //DBG_MSGF (widget, "extremes", 0, "parMin = %d", parMin);
277 } else {
278 if (extremes->minWidth < wordExtremes.minWidth)
279 extremes->minWidth = wordExtremes.minWidth;
280 }
260
261 if (extremes->minWidth < wordExtremes.minWidth)
262 extremes->minWidth = wordExtremes.minWidth;
281263
282264 _MSG("parMax = %d, wordMaxWidth=%d, prevWordSpace=%d\n",
283265 parMax, wordExtremes.maxWidth, prevWordSpace);
284266 if (word->content.type != core::Content::BREAK)
285267 parMax += prevWordSpace;
286268 parMax += wordExtremes.maxWidth;
269
270 if (prevWord && !canBreakAfter(prevWord)) {
271 parMin += prevWordSpace + wordExtremes.minWidth;
272 } else {
273 parMin = wordExtremes.minWidth;
274 }
275
276 if (extremes->minWidth < parMin) {
277 extremes->minWidth = parMin;
278 }
279
287280 prevWordSpace = word->origSpace;
281 prevWord = word;
288282
289283 //DEBUG_MSG (DEBUG_SIZE_LEVEL + 1,
290284 // " word %s: maxWidth = %d\n",
291 // a_Dw_content_text (&word->content),
285 // word->content.text,
292286 // word_extremes.maxWidth);
293287 }
294288
299293 //DEBUG_MSG (DEBUG_SIZE_LEVEL + 2,
300294 // " parMax = %d, after word %d (%s)\n",
301295 // parMax, line->last_word - 1,
302 // a_Dw_content_text (&word->content));
296 // word->content.text);
303297
304298 if (extremes->maxWidth < parMax)
305299 extremes->maxWidth = parMax;
306300
307 if (nowrap) {
308 //DBG_MSGF (widget, "extremes", 0, "parMin = %d", parMin);
309 if (extremes->minWidth < parMin)
310 extremes->minWidth = parMin;
311
312 //DEBUG_MSG (DEBUG_SIZE_LEVEL + 2,
313 // " parMin = %d, after word %d (%s)\n",
314 // parMin, line->last_word - 1,
315 // a_Dw_content_text (&word->content));
316 }
317
318301 prevWordSpace = 0;
319 parMin = 0;
320302 parMax = 0;
321303 }
322304
328310 }
329311
330312 //DBG_MSGF (widget, "extremes", 0, "width difference: %d + %d",
331 // page->inner_padding, p_Dw_style_box_diff_width (widget->style));
313 // innerPadding, getStyle()->boxDiffWidth ());
332314
333315 int diff = innerPadding + getStyle()->boxDiffWidth ();
334316 extremes->minWidth += diff;
479461 void Textblock::markChange (int ref)
480462 {
481463 if (ref != -1) {
482 //DBG_MSGF (page, "wrap", 0, "Dw_page_mark_size_change (ref = %d)", ref);
464 //DBG_MSGF (page, "wrap", 0, "markChange (ref = %d)", ref);
483465
484466 if (wrapRef == -1)
485467 wrapRef = ref;
486468 else
487469 wrapRef = misc::min (wrapRef, ref);
488470
489 //DBG_OBJ_SET_NUM (page, "wrap_ref", page->wrap_ref);
471 //DBG_OBJ_SET_NUM (this, "wrap_ref", wrapRef);
490472 }
491473 }
492474
493475 void Textblock::setWidth (int width)
494476 {
495 /* If limitTextWidth is set to YES, a queue_resize may also be
477 /* If limitTextWidth is set to YES, a queueResize() may also be
496478 * necessary. */
497479 if (availWidth != width || limitTextWidth) {
498480 //DEBUG_MSG(DEBUG_REWRAP_LEVEL,
499 // "Dw_page_set_width: Calling p_Dw_widget_queue_resize, "
481 // "setWidth: Calling queueResize, "
500482 // "in page with %d word(s)\n",
501 // page->num_words);
483 // words->size());
502484
503485 availWidth = width;
504486 queueResize (0, false);
511493 {
512494 if (availAscent != ascent) {
513495 //DEBUG_MSG(DEBUG_REWRAP_LEVEL,
514 // "Dw_page_set_ascent: Calling p_Dw_widget_queue_resize, "
496 // "setAscent: Calling queueResize, "
515497 // "in page with %d word(s)\n",
516 // page->num_words);
498 // words->size());
517499
518500 availAscent = ascent;
519501 queueResize (0, false);
525507 {
526508 if (availDescent != descent) {
527509 //DEBUG_MSG(DEBUG_REWRAP_LEVEL,
528 // "Dw_page_set_descent: Calling p_Dw_widget_queue_resize, "
510 // "setDescent: Calling queueResize, "
529511 // "in page with %d word(s)\n",
530 // page->num_words);
512 // words->size());
531513
532514 availDescent = descent;
533515 queueResize (0, false);
620602 core::MousePositionEvent *event)
621603 {
622604 core::Iterator *it;
623 Line *line, *lastLine;
624 int nextWordStartX, wordStartX, wordX, nextWordX, yFirst, yLast;
625 int charPos = 0, link = -1, prevPos, wordIndex, lineIndex;
626 Word *word;
627 bool found, r;
605 int wordIndex;
606 int charPos = 0, link = -1;
607 bool r;
628608
629609 if (words->size () == 0) {
630610 wordIndex = -1;
631611 } else {
632 lastLine = lines->getRef (lines->size () - 1);
633 yFirst = lineYOffsetCanvasI (0);
634 yLast = lineYOffsetCanvas (lastLine) + lastLine->boxAscent +
635 lastLine->boxDescent;
612 Line *lastLine = lines->getRef (lines->size () - 1);
613 int yFirst = lineYOffsetCanvasI (0);
614 int yLast = lineYOffsetCanvas (lastLine) + lastLine->boxAscent +
615 lastLine->boxDescent;
636616 if (event->yCanvas < yFirst) {
637617 // Above the first line: take the first word.
638618 wordIndex = 0;
639 charPos = 0;
640619 } else if (event->yCanvas >= yLast) {
641620 // Below the last line: take the last word.
642621 wordIndex = words->size () - 1;
643 word = words->getRef (wordIndex);
644 charPos = word->content.type == core::Content::TEXT ?
645 strlen (word->content.text) : 0;
622 charPos = core::SelectionState::END_OF_WORD;
646623 } else {
647 lineIndex = findLineIndex (event->yWidget);
648 line = lines->getRef (lineIndex);
624 Line *line = lines->getRef (findLineIndex (event->yWidget));
649625
650626 // Pointer within the break space?
651627 if (event->yWidget >
652628 (lineYOffsetWidget (line) + line->boxAscent + line->boxDescent)) {
653629 // Choose this break.
654630 wordIndex = line->lastWord;
655 charPos = 0;
631 charPos = core::SelectionState::END_OF_WORD;
656632 } else if (event->xWidget < lineXOffsetWidget (line)) {
657633 // Left of the first word in the line.
658634 wordIndex = line->firstWord;
659 charPos = 0;
660635 } else {
661 nextWordStartX = lineXOffsetWidget (line);
662 found = false;
636 int nextWordStartX = lineXOffsetWidget (line);
637
663638 for (wordIndex = line->firstWord;
664 !found && wordIndex <= line->lastWord;
639 wordIndex <= line->lastWord;
665640 wordIndex++) {
666 word = words->getRef (wordIndex);
667 wordStartX = nextWordStartX;
641 Word *word = words->getRef (wordIndex);
642 int wordStartX = nextWordStartX;
643
668644 nextWordStartX += word->size.width + word->effSpace;
669645
670646 if (event->xWidget >= wordStartX &&
671647 event->xWidget < nextWordStartX) {
672648 // We have found the word.
673 if (word->content.type == core::Content::TEXT) {
674 // Search the character the mouse pointer is in.
675 // nextWordX is the right side of this character.
676 charPos = 0;
677 while ((nextWordX = wordStartX +
678 layout->textWidth (word->style->font,
679 word->content.text, charPos))
680 <= event->xWidget)
681 charPos = layout->nextGlyph (word->content.text,
682 charPos);
683 // The left side of this character.
684 prevPos = layout->prevGlyph (word->content.text, charPos);
685 wordX = wordStartX + layout->textWidth (word->style->font,
686 word->content.text,
687 prevPos);
688
689 // If the mouse pointer is left from the middle, use the
690 // left position, otherwise, use the right one.
691 if (event->xWidget <= (wordX + nextWordX) / 2)
692 charPos = prevPos;
649 int yWidgetBase = lineYOffsetWidget (line) + line->boxAscent;
650
651 if (event->xWidget >= nextWordStartX - word->effSpace) {
652 charPos = core::SelectionState::END_OF_WORD;
653 if (wordIndex < line->lastWord &&
654 (words->getRef(wordIndex + 1)->content.type !=
655 core::Content::BREAK) &&
656 (event->yWidget <=
657 yWidgetBase + word->spaceStyle->font->descent) &&
658 (event->yWidget >
659 yWidgetBase - word->spaceStyle->font->ascent)) {
660 link = word->spaceStyle->x_link;
661 }
693662 } else {
694 // Depends on whether the pointer is within the left or
695 // right half of the (non-text) word.
696 if (event->xWidget >=
697 (wordStartX + nextWordStartX) / 2)
698 charPos = core::SelectionState::END_OF_WORD;
699 else
700 charPos = 0;
663 if (event->yWidget <= yWidgetBase + word->size.descent &&
664 event->yWidget > yWidgetBase - word->size.ascent) {
665 link = word->style->x_link;
666 }
667 if (word->content.type == core::Content::TEXT) {
668 int glyphX = wordStartX;
669
670 while (1) {
671 int nextCharPos =
672 layout->nextGlyph (word->content.text, charPos);
673 int glyphWidth =
674 textWidth (word->content.text, charPos,
675 nextCharPos - charPos, word->style);
676 if (event->xWidget > glyphX + glyphWidth) {
677 glyphX += glyphWidth;
678 charPos = nextCharPos;
679 continue;
680 } else if (event->xWidget >= glyphX + glyphWidth/2){
681 // On the right half of a character;
682 // now just look for combining chars
683 charPos = nextCharPos;
684 while (word->content.text[charPos]) {
685 nextCharPos =
686 layout->nextGlyph (word->content.text,
687 charPos);
688 if (textWidth (word->content.text, charPos,
689 nextCharPos - charPos,
690 word->style))
691 break;
692 charPos = nextCharPos;
693 }
694 }
695 break;
696 }
697 } else {
698 // Depends on whether the pointer is within the left or
699 // right half of the (non-text) word.
700 if (event->xWidget >= (wordStartX + nextWordStartX) /2)
701 charPos = core::SelectionState::END_OF_WORD;
702 }
701703 }
702
703 found = true;
704 link = word->style ? word->style->x_link : -1;
705704 break;
706705 }
707706 }
708
709 if (!found) {
707 if (wordIndex > line->lastWord) {
710708 // No word found in this line (i.e. we are on the right side),
711709 // take the last of this line.
712710 wordIndex = line->lastWord;
713 if (wordIndex >= words->size ())
714 wordIndex--;
715 word = words->getRef (wordIndex);
716 charPos = word->content.type == core::Content::TEXT ?
717 strlen (word->content.text) :
718 (int)core::SelectionState::END_OF_WORD;
711 charPos = core::SelectionState::END_OF_WORD;
719712 }
720713 }
721714 }
769762
770763 words->getRef(i)->effSpace = words->getRef(i)->origSpace +
771764 (effSpaceDiffCum - lastEffSpaceDiffCum);
772 //DBG_OBJ_ARRSET_NUM (page, "words.%d.eff_space", i,
773 // page->words[i].eff_space);
765 //DBG_OBJ_ARRSET_NUM (this, "words.%d.effSpace", i,
766 // words->getRef(i)->effSpace);
774767
775768 lastEffSpaceDiffCum = effSpaceDiffCum;
776769 }
782775 {
783776 Line *lastLine;
784777
785 //DBG_MSG (page, "wrap", 0, "Dw_page_add_line");
778 //DBG_MSG (page, "wrap", 0, "addLine");
786779 //DBG_MSG_START (page);
787780
788781 lines->increase ();
789 //DBG_OBJ_SET_NUM(page, "num_lines", page->num_lines);
782 //DBG_OBJ_SET_NUM(this, "num_lines", lines->size ());
790783
791784 //DEBUG_MSG (DEBUG_REWRAP_LEVEL, "--- new line %d in %p, with word %d of %d"
792 // "\n", page->num_lines - 1, page, word_ind, page->num_words);
785 // "\n", lines->size () - 1, page, word_ind, words->size());
793786
794787 lastLine = lines->getRef (lines->size () - 1);
795788
796789 if (lines->size () == 1) {
797790 lastLine->top = 0;
798791 lastLine->maxLineWidth = line1OffsetEff;
799 lastLine->maxWordMin = 0;
792 lastLine->maxParMin = 0;
800793 lastLine->maxParMax = 0;
801794 } else {
802795 Line *prevLine = lines->getRef (lines->size () - 2);
804797 lastLine->top = prevLine->top + prevLine->boxAscent +
805798 prevLine->boxDescent + prevLine->breakSpace;
806799 lastLine->maxLineWidth = prevLine->maxLineWidth;
807 lastLine->maxWordMin = prevLine->maxWordMin;
800 lastLine->maxParMin = prevLine->maxParMin;
808801 lastLine->maxParMax = prevLine->maxParMax;
809802 }
810803
811 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.top", page->num_lines - 1,
804 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.top", lines->size () - 1,
812805 // lastLine->top);
813 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.maxLineWidth", page->num_lines - 1,
806 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.maxLineWidth", lines->size () - 1,
814807 // lastLine->maxLineWidth);
815 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.maxWordMin", page->num_lines - 1,
816 // lastLine->maxWordMin);
817 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.maxParMax", page->num_lines - 1,
808 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.maxParMin", lines->size () - 1,
809 // lastLine->maxParMin);
810 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.maxParMax", lines->size () - 1,
818811 // lastLine->maxParMax);
819 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.parMin", page->num_lines - 1,
812 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.parMin", lines->size () - 1,
820813 // lastLine->parMin);
821 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.parMax", page->num_lines - 1,
814 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.parMax", lines->size () - 1,
822815 // lastLine->parMax);
823816
824817 lastLine->firstWord = wordIndex;
828821 lastLine->breakSpace = 0;
829822 lastLine->leftOffset = 0;
830823
831 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.ascent", page->num_lines - 1,
824 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.ascent", lines->size () - 1,
832825 // lastLine->boxAscent);
833 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.descent", page->num_lines - 1,
826 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.descent", lines->size () - 1,
834827 // lastLine->boxDescent);
835828
836829 /* update values in line */
843836
844837 if (newPar) {
845838 lastLine->maxParMax = misc::max (lastLine->maxParMax, lastLineParMax);
846 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.maxParMax", page->num_lines - 1,
839 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.maxParMax", lines->size () - 1,
847840 // lastLine->maxParMax);
848841
849 /* The following code looks questionable (especially since the values
850 * will be overwritten). In any case, line1OffsetEff is probably
851 * supposed to go into lastLinePar*, not lastLine->par*.
852 */
853842 if (lines->size () > 1) {
854 lastLine->parMin = 0;
855 lastLine->parMax = 0;
843 lastLineParMax = 0;
856844 } else {
857 lastLine->parMin = line1OffsetEff;
858 lastLine->parMax = line1OffsetEff;
859 }
860 lastLineParMin = 0;
861 lastLineParMax = 0;
862
863 //DBG_OBJ_SET_NUM(page, "lastLineParMin", page->lastLineParMin);
864 //DBG_OBJ_SET_NUM(page, "lastLineParMax", page->lastLineParMax);
865 }
866
867 lastLine->parMin = lastLineParMin;
845 lastLineParMax = line1OffsetEff;
846 }
847
848 //DBG_OBJ_SET_NUM(this, "lastLineParMax", lastLineParMax);
849 }
850
868851 lastLine->parMax = lastLineParMax;
869852
870 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.parMin", page->num_lines - 1,
853 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.parMin", lines->size () - 1,
871854 // lastLine->parMin);
872 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.parMax", page->num_lines - 1,
855 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.parMax", lines->size () - 1,
873856 // lastLine->parMax);
874857
875858 //DBG_MSG_END (page);
886869 Line *lastLine;
887870 Word *word;
888871 int availWidth, lastSpace, leftOffset, len;
889 bool newLine = false, newPar = false;
872 bool newLine = false, newPar = false, canBreakBefore = true;
890873 core::Extremes wordExtremes;
891874
892 //DBG_MSGF (page, "wrap", 0, "Dw_page_real_word_wrap (%d): %s, width = %d",
893 // word_ind, a_Dw_content_html (&page->words[word_ind].content),
894 // page->words[word_ind].size.width);
875 //DBG_MSGF (page, "wrap", 0, "wordWrap (%d): %s, width = %d",
876 // wordIndex, words->getRef(wordIndex)->content.text),
877 // words->getRef(wordIndex)->size.width);
895878 //DBG_MSG_START (page);
896879
897880 availWidth = this->availWidth - getStyle()->boxDiffWidth() - innerPadding;
941924 /* previous word is a break */
942925 newLine = true;
943926 newPar = true;
944 } else if (word->style->whiteSpace == core::style::WHITE_SPACE_NOWRAP ||
945 word->style->whiteSpace == core::style::WHITE_SPACE_PRE) {
946 //DBG_MSGF (page, "wrap", 0, "no wrap (white_space = %d)",
947 // word->style->white_space);
927 } else if (!canBreakAfter (prevWord)) {
928 canBreakBefore = false;
929 // no break within nowrap
948930 newLine = false;
949931 newPar = false;
932 if (lastLineWidth + prevWord->origSpace + word->size.width >
933 availWidth)
934 markChange (lines->size () - 1);
950935 } else if (lastLine->firstWord != wordIndex) {
951 /* Does new word fit into the last line? */
952 //DBG_MSGF (page, "wrap", 0,
953 // "word %d (%s) fits? (%d + %d + %d &lt;= %d)...",
954 // word_ind, a_Dw_content_html (&word->content),
955 // page->lastLine_width, prevWord->orig_space,
956 // word->size.width, availWidth);
957 newLine = lastLineWidth + prevWord->origSpace + word->size.width >
958 availWidth;
959 //DBG_MSGF (page, "wrap", 0, "... %s.",
960 // newLine ? "No" : "Yes");
936 // check if we need to break because nowrap sequence is following
937 newLine = false;
938 int lineWidthNeeded = lastLineWidth + prevWord->origSpace;
939 for (int i = wordIndex; i < words->size (); i++) {
940 Word *w = words->getRef (i);
941
942 if (w->content.type == core::Content::BREAK ||
943 (word->content.type == core::Content::WIDGET &&
944 word->content.widget->blockLevel()))
945 break;
946
947 lineWidthNeeded += w->size.width;
948
949 if (lineWidthNeeded > availWidth) {
950 newLine = true;
951 break;
952 } else if (canBreakAfter (w)) {
953 break;
954 }
955
956 lineWidthNeeded += w->origSpace;
957 }
961958 }
962959 }
963960
983980 len += word->style->font->ascent / 3;
984981 lastLine->contentDescent = misc::max (lastLine->contentDescent, len);
985982
986 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.ascent", page->num_lines - 1,
983 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.ascent", lines->size () - 1,
987984 // lastLine->boxAscent);
988 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.descent", page->num_lines - 1,
985 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.descent", lines->size () - 1,
989986 // lastLine->boxDescent);
990987
991988 if (word->content.type == core::Content::WIDGET) {
1000997 word->content.widget->blockLevel () &&
1001998 getStyle ()->borderWidth.top == 0 &&
1002999 getStyle ()->padding.top == 0) {
1003 // collapse top margin of parent element with top margin of first child
1000 // collapse top margins of parent element and its first child
10041001 // see: http://www.w3.org/TR/CSS21/box.html#collapsing-margins
10051002 collapseMarginTop = getStyle ()->margin.top;
10061003 }
10281025 if (!newLine)
10291026 lastLineWidth += lastSpace;
10301027 if (!newPar) {
1031 lastLineParMin += lastSpace;
10321028 lastLineParMax += lastSpace;
10331029 }
10341030
10351031 lastLineWidth += word->size.width;
10361032
10371033 getWordExtremes (word, &wordExtremes);
1038 lastLineParMin += wordExtremes.maxWidth; /* Why maxWidth? */
10391034 lastLineParMax += wordExtremes.maxWidth;
10401035
1041 if (word->style->whiteSpace == core::style::WHITE_SPACE_NOWRAP ||
1042 word->style->whiteSpace == core::style::WHITE_SPACE_PRE) {
1043 lastLine->parMin += wordExtremes.minWidth + lastSpace;
1036 if (!canBreakBefore) {
1037 lastLineParMin += wordExtremes.minWidth + lastSpace;
10441038 /* This may also increase the accumulated minimum word width. */
1045 lastLine->maxWordMin =
1046 misc::max (lastLine->maxWordMin, lastLine->parMin);
1047 /* NOTE: Most code relies on that all values of nowrap are equal for all
1048 * words within one line. */
1039 lastLine->maxParMin = misc::max (lastLine->maxParMin, lastLineParMin);
10491040 } else {
1050 lastLine->maxWordMin =
1051 misc::max (lastLine->maxWordMin, wordExtremes.minWidth);
1052 }
1053
1054 //DBG_OBJ_SET_NUM(page, "lastLine_par_min", page->lastLine_par_min);
1055 //DBG_OBJ_SET_NUM(page, "lastLine_par_max", page->lastLine_par_max);
1056 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.par_min", page->num_lines - 1,
1041 lastLineParMin = wordExtremes.minWidth;
1042 lastLine->maxParMin =
1043 misc::max (lastLine->maxParMin, wordExtremes.minWidth);
1044 }
1045
1046 //DBG_OBJ_SET_NUM(this, "lastLine_par_min", lastLineParMin);
1047 //DBG_OBJ_SET_NUM(this, "lastLine_par_max", lastLineParMax);
1048 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.par_min", lines->size () - 1,
10571049 // lastLine->par_min);
1058 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.par_max", page->num_lines - 1,
1050 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.par_max", lines->size () - 1,
10591051 // lastLine->par_max);
1060 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.max_word_min", page->num_lines - 1,
1052 //DBG_OBJ_ARRSET_NUM (this, "lines.%d.max_word_min", lines->size () - 1,
10611053 // lastLine->max_word_min);
10621054
10631055 /* Align the line.
10861078 if (leftOffset < 0)
10871079 leftOffset = 0;
10881080
1089 if (hasListitemValue && lastLine == lines->getRef (0)) {
1090 /* List item markers are always on the left. */
1091 lastLine->leftOffset = 0;
1092 words->getRef(0)->effSpace = words->getRef(0)->origSpace + leftOffset;
1093 //DBG_OBJ_ARRSET_NUM (page, "words.%d.eff_space", 0,
1094 // page->words[0].eff_space);
1095 } else {
1096 lastLine->leftOffset = leftOffset;
1097 }
1081 lastLine->leftOffset = leftOffset;
10981082 }
10991083 mustQueueResize = true;
11001084
11761160 return;
11771161
11781162 //DBG_MSGF (page, "wrap", 0,
1179 // "Dw_page_rewrap: page->wrap_ref = %d, in page with %d word(s)",
1180 // page->wrap_ref, page->num_words);
1163 // "rewrap: wrapRef = %d, in page with %d word(s)",
1164 // wrapRef, words->size());
11811165 //DBG_MSG_START (page);
11821166
1183 /* All lines up from page->wrap_ref will be rebuild from the word list,
1167 /* All lines up from wrapRef will be rebuild from the word list,
11841168 * the line list up from this position is rebuild. */
11851169 lines->setSize (wrapRef);
11861170 lastLineWidth = 0;
1187 //DBG_OBJ_SET_NUM(page, "num_lines", page->num_lines);
1188 //DBG_OBJ_SET_NUM(page, "lastLine_width", page->lastLine_width);
1171 lastLineParMin = 0;
1172 //DBG_OBJ_SET_NUM(this, "num_lines", lines->size ());
1173 //DBG_OBJ_SET_NUM(this, "lastLine_width", lastLineWidth);
11891174
11901175 /* In the word list, start at the last word plus one in the line before. */
11911176 if (wrapRef > 0) {
1192 /* Note: In this case, Dw_page_real_word_wrap will immediately find
1193 * the need to rewrap the line, since we start with the last one (plus
1194 * one). This is also the reason, why page->lastLine_width is set
1177 /* Note: In this case, wordWrap() will immediately find the need
1178 * to rewrap the line, since we start with the last one (plus one).
1179 * This is also the reason, why lastLineWidth is set
11951180 * to the length of the line. */
11961181 lastLine = lines->getRef (lines->size () - 1);
11971182
1198 lastLineParMin = lastLine->parMin;
11991183 lastLineParMax = lastLine->parMax;
12001184
12011185 wordIndex = lastLine->lastWord + 1;
12041188 words->getRef(i)->origSpace);
12051189 lastLineWidth += words->getRef(lastLine->lastWord)->size.width;
12061190 } else {
1207 lastLineParMin = 0;
12081191 lastLineParMax = 0;
12091192
12101193 wordIndex = 0;
12261209 //DEBUG_MSG(DEBUG_REWRAP_LEVEL,
12271210 // "Assigning parent_ref = %d to rewrapped word %d, "
12281211 // "in page with %d word(s)\n",
1229 // page->num_lines - 1, wordIndex, page->num_words);
1212 // lines->size () - 1, wordIndex, words->size());
12301213
12311214 /* todo_refactoring:
12321215 if (word->content.type == DW_CONTENT_ANCHOR)
12331216 p_Dw_gtk_viewport_change_anchor
12341217 (widget, word->content.anchor,
12351218 Dw_page_line_total_y_offset (page,
1236 &page->lines[page->num_lines - 1]));
1219 &page->lines[lines->size () - 1]));
12371220 */
12381221 }
12391222
12691252 }
12701253
12711254 /*
1255 * Draw a string of text
1256 */
1257 void Textblock::drawText(core::View *view, core::style::Style *style,
1258 core::style::Color::Shading shading, int x, int y,
1259 const char *text, int start, int len)
1260 {
1261 if (len > 0) {
1262 char *str = NULL;
1263
1264 switch (style->textTransform) {
1265 case core::style::TEXT_TRANSFORM_NONE:
1266 default:
1267 break;
1268 case core::style::TEXT_TRANSFORM_UPPERCASE:
1269 str = layout->textToUpper(text + start, len);
1270 break;
1271 case core::style::TEXT_TRANSFORM_LOWERCASE:
1272 str = layout->textToLower(text + start, len);
1273 break;
1274 case core::style::TEXT_TRANSFORM_CAPITALIZE:
1275 {
1276 /* \bug No way to know about non-ASCII punctuation. */
1277 bool initial_seen = false;
1278
1279 for (int i = 0; i < start; i++)
1280 if (!ispunct(text[i]))
1281 initial_seen = true;
1282 if (initial_seen)
1283 break;
1284
1285 int after = 0;
1286 text += start;
1287 while (ispunct(text[after]))
1288 after++;
1289 if (text[after])
1290 after = layout->nextGlyph(text, after);
1291 if (after > len)
1292 after = len;
1293
1294 char *initial = layout->textToUpper(text, after);
1295 int newlen = strlen(initial) + len-after;
1296 str = (char *)malloc(newlen + 1);
1297 strcpy(str, initial);
1298 strncpy(str + strlen(str), text+after, len-after);
1299 str[newlen] = '\0';
1300 free(initial);
1301 break;
1302 }
1303 }
1304 view->drawText(style->font, style->color, shading, x, y,
1305 str ? str : text + start, str ? strlen(str) : len);
1306 if (str)
1307 free(str);
1308 }
1309 }
1310
1311 /*
12721312 * Draw a word of text.
12731313 */
1274 void Textblock::drawText(int wordIndex, core::View *view,core::Rectangle *area,
1314 void Textblock::drawWord(int wordIndex, core::View *view,core::Rectangle *area,
12751315 int xWidget, int yWidgetBase)
12761316 {
12771317 Word *word = words->getRef(wordIndex);
12871327 }
12881328 yWorldBase = yWidgetBase + allocation.y;
12891329
1290 view->drawText (style->font, style->color,
1291 core::style::Color::SHADING_NORMAL, xWorld, yWorldBase,
1292 word->content.text, strlen (word->content.text));
1330 drawText (view, style, core::style::Color::SHADING_NORMAL, xWorld,
1331 yWorldBase, word->content.text, 0, strlen (word->content.text));
12931332
12941333 if (style->textDecoration)
12951334 decorateText(view, style, core::style::Color::SHADING_NORMAL, xWorld,
13111350
13121351 xStart = xWorld;
13131352 if (firstCharIdx)
1314 xStart += layout->textWidth (style->font, word->content.text,
1315 firstCharIdx);
1353 xStart += textWidth (word->content.text, 0, firstCharIdx, style);
13161354 if (firstCharIdx == 0 && lastCharIdx == wordLen)
13171355 width = word->size.width;
13181356 else
1319 width = layout->textWidth (style->font,
1320 word->content.text + firstCharIdx,
1321 lastCharIdx - firstCharIdx);
1357 width = textWidth (word->content.text, firstCharIdx,
1358 lastCharIdx - firstCharIdx, style);
13221359 if (width > 0) {
13231360 /* Highlight text */
13241361 core::style::Color *wordBgColor;
13331370 style->font->ascent + style->font->descent);
13341371
13351372 /* Highlight the text. */
1336 view->drawText (style->font, style->color,
1337 core::style::Color::SHADING_INVERSE, xStart,
1338 yWorldBase, word->content.text + firstCharIdx,
1339 lastCharIdx - firstCharIdx);
1373 drawText (view, style, core::style::Color::SHADING_INVERSE, xStart,
1374 yWorldBase, word->content.text, firstCharIdx,
1375 lastCharIdx - firstCharIdx);
13401376
13411377 if (style->textDecoration)
13421378 decorateText(view, style, core::style::Color::SHADING_INVERSE,
14341470 yWidgetBase - line->boxAscent, word->size.width,
14351471 line->boxAscent + line->boxDescent, false);
14361472 }
1437 drawText(wordIndex, view, area, xWidget, yWidgetBase);
1473 drawWord(wordIndex, view, area, xWidget, yWidgetBase);
14381474 }
14391475 }
14401476 if (word->effSpace > 0 && wordIndex < line->lastWord &&
15341570 word = words->getRef (wordIndex);
15351571 lastXCursor = xCursor;
15361572 xCursor += word->size.width + word->effSpace;
1537 if (lastXCursor <= x && xCursor > x &&
1538 y > yWidgetBase - word->size.ascent &&
1539 y <= yWidgetBase + word->size.descent) {
1540 *inSpace = x >= xCursor - word->effSpace;
1541 return word;
1573 if (lastXCursor <= x && xCursor > x) {
1574 if (x >= xCursor - word->effSpace) {
1575 if (wordIndex < line->lastWord &&
1576 (words->getRef(wordIndex + 1)->content.type !=
1577 core::Content::BREAK) &&
1578 y > yWidgetBase - word->spaceStyle->font->ascent &&
1579 y <= yWidgetBase + word->spaceStyle->font->descent) {
1580 *inSpace = true;
1581 return word;
1582 }
1583 } else {
1584 if (y > yWidgetBase - word->size.ascent &&
1585 y <= yWidgetBase + word->size.descent)
1586 return word;
1587 }
1588 break;
15421589 }
15431590 }
15441591
15801627 word->origSpace = 0;
15811628 word->effSpace = 0;
15821629 word->content.space = false;
1583
1584 //DBG_OBJ_ARRSET_NUM (page, "words.%d.size.width", page->num_words - 1,
1630 word->content.breakType = core::Content::BREAK_NO;
1631
1632 //DBG_OBJ_ARRSET_NUM (this, "words.%d.size.width", words->size() - 1,
15851633 // word->size.width);
1586 //DBG_OBJ_ARRSET_NUM (page, "words.%d.size.descent", page->num_words - 1,
1634 //DBG_OBJ_ARRSET_NUM (this, "words.%d.size.descent", words->size() - 1,
15871635 // word->size.descent);
1588 //DBG_OBJ_ARRSET_NUM (page, "words.%d.size.ascent", page->num_words - 1,
1636 //DBG_OBJ_ARRSET_NUM (this, "words.%d.size.ascent", words->size() - 1,
15891637 // word->size.ascent);
1590 //DBG_OBJ_ARRSET_NUM (page, "words.%d.orig_space", page->num_words - 1,
1638 //DBG_OBJ_ARRSET_NUM (this, "words.%d.orig_space", words->size() - 1,
15911639 // word->orig_space);
1592 //DBG_OBJ_ARRSET_NUM (page, "words.%d.eff_space", page->num_words - 1,
1640 //DBG_OBJ_ARRSET_NUM (this, "words.%d.effSpace", words->size() - 1,
15931641 // word->eff_space);
1594 //DBG_OBJ_ARRSET_NUM (page, "words.%d.content.space", page->num_words - 1,
1642 //DBG_OBJ_ARRSET_NUM (this, "words.%d.content.space", words->size() - 1,
15951643 // word->content.space);
15961644
15971645 word->style = style;
16021650 return word;
16031651 }
16041652
1653 /*
1654 * Get the width of a string of text.
1655 */
1656 int Textblock::textWidth(const char *text, int start, int len,
1657 core::style::Style *style)
1658 {
1659 int ret = 0;
1660
1661 if (len > 0) {
1662 char *str = NULL;
1663
1664 switch (style->textTransform) {
1665 case core::style::TEXT_TRANSFORM_NONE:
1666 default:
1667 ret = layout->textWidth(style->font, text+start, len);
1668 break;
1669 case core::style::TEXT_TRANSFORM_UPPERCASE:
1670 str = layout->textToUpper(text+start, len);
1671 ret = layout->textWidth(style->font, str, strlen(str));
1672 break;
1673 case core::style::TEXT_TRANSFORM_LOWERCASE:
1674 str = layout->textToLower(text+start, len);
1675 ret = layout->textWidth(style->font, str, strlen(str));
1676 break;
1677 case core::style::TEXT_TRANSFORM_CAPITALIZE:
1678 {
1679 /* \bug No way to know about non-ASCII punctuation. */
1680 bool initial_seen = false;
1681
1682 for (int i = 0; i < start; i++)
1683 if (!ispunct(text[i]))
1684 initial_seen = true;
1685 if (initial_seen) {
1686 ret = layout->textWidth(style->font, text+start, len);
1687 } else {
1688 int after = 0;
1689
1690 text += start;
1691 while (ispunct(text[after]))
1692 after++;
1693 if (text[after])
1694 after = layout->nextGlyph(text, after);
1695 if (after > len)
1696 after = len;
1697 str = layout->textToUpper(text, after);
1698 ret = layout->textWidth(style->font, str, strlen(str)) +
1699 layout->textWidth(style->font, text+after, len-after);
1700 }
1701 break;
1702 }
1703 }
1704 if (str)
1705 free(str);
1706 }
1707 return ret;
1708 }
1709
16051710 /**
16061711 * Calculate the size of a text word.
16071712 */
16091714 core::style::Style *style,
16101715 core::Requisition *size)
16111716 {
1612 size->width = layout->textWidth (style->font, text, len);
1717 size->width = textWidth (text, 0, len, style);
16131718 size->ascent = style->font->ascent;
16141719 size->descent = style->font->descent;
16151720
16681773 word->content.type = core::Content::TEXT;
16691774 word->content.text = layout->textZone->strndup(text, len);
16701775
1671 //DBG_OBJ_ARRSET_STR (page, "words.%d.content.text", page->num_words - 1,
1776 //DBG_OBJ_ARRSET_STR (page, "words.%d.content.text", words->size() - 1,
16721777 // word->content.text);
16731778
16741779 wordWrap (words->size () - 1);
16971802 word->content.type = core::Content::WIDGET;
16981803 word->content.widget = widget;
16991804
1700 //DBG_OBJ_ARRSET_PTR (page, "words.%d.content.widget", page->num_words - 1,
1805 //DBG_OBJ_ARRSET_PTR (page, "words.%d.content.widget", words->size() - 1,
17011806 // word->content.widget);
17021807
17031808 wordWrap (words->size () - 1);
17081813 //DEBUG_MSG(DEBUG_REWRAP_LEVEL,
17091814 // "Assigning parent_ref = %d to added word %d, "
17101815 // "in page with %d word(s)\n",
1711 // page->num_lines - 1, page->num_words - 1, page->num_words);
1712 }
1713
1816 // lines->size () - 1, words->size() - 1, words->size());
1817 }
17141818
17151819 /**
17161820 * Add an anchor to the page. "name" is copied, so no strdup is necessary for
17631867 if (wordIndex >= 0) {
17641868 Word *word = words->getRef(wordIndex);
17651869
1870 // According to http://www.w3.org/TR/CSS2/text.html#white-space-model:
1871 // "line breaking opportunities are determined based on the text prior
1872 // to the white space collapsing steps".
1873 // So we call addBreakOption () for each Textblock::addSpace () call.
1874 // This is important e.g. to be able to break between foo and bar in:
1875 // <span style="white-space:nowrap">foo </span> bar
1876 addBreakOption (style);
1877
17661878 if (!word->content.space) {
17671879 word->content.space = true;
17681880 word->effSpace = word->origSpace = style->font->spaceWidth +
17691881 style->wordSpacing;
17701882
1771 //DBG_OBJ_ARRSET_NUM (page, "words.%d.orig_space", nw,
1772 // page->words[nw].orig_space);
1773 //DBG_OBJ_ARRSET_NUM (page, "words.%d.eff_space", nw,
1774 // page->words[nw].eff_space);
1775 //DBG_OBJ_ARRSET_NUM (page, "words.%d.content.space", nw,
1776 // page->words[nw].content.space);
1883 //DBG_OBJ_ARRSET_NUM (this, "words.%d.origSpace", wordIndex,
1884 // word->origSpace);
1885 //DBG_OBJ_ARRSET_NUM (this, "words.%d.effSpace", wordIndex,
1886 // word->effSpace);
1887 //DBG_OBJ_ARRSET_NUM (this, "words.%d.content.space", wordIndex,
1888 // word->content.space);
17771889 word->spaceStyle->unref ();
17781890 word->spaceStyle = style;
17791891 style->ref ();
17801892 }
17811893 }
17821894 }
1783
17841895
17851896 /**
17861897 * Cause a paragraph break
19412052 }
19422053
19432054 /*
1944 * Any words added by a_Dw_page_add_... are not immediately (queued to
2055 * Any words added by addWord() are not immediately (queued to
19452056 * be) drawn, instead, this function must be called. This saves some
1946 * calls to p_Dw_widget_queue_resize.
2057 * calls to queueResize().
19472058 *
19482059 */
19492060 void Textblock::flush ()
21842295 allocation->x += w->size.width + w->effSpace;
21852296 }
21862297 if (start > 0 && word->content.type == core::Content::TEXT) {
2187 allocation->x += textblock->layout->textWidth (word->style->font,
2188 word->content.text,
2189 start);
2298 allocation->x += textblock->textWidth (word->content.text, 0, start,
2299 word->style);
21902300 }
21912301 allocation->y = textblock->lineYOffsetCanvas (line) + line->boxAscent -
21922302 word->size.ascent;
21982308 if (start > 0 || end < wordEnd) {
21992309 end = misc::min(end, wordEnd); /* end could be INT_MAX */
22002310 allocation->width =
2201 textblock->layout->textWidth (word->style->font,
2202 word->content.text + start,
2203 end - start);
2311 textblock->textWidth (word->content.text, start, end - start,
2312 word->style);
22042313 }
22052314 }
22062315 allocation->ascent = word->size.ascent;
147147 /* The following members contain accumulated values, from the top
148148 * down to the line before. */
149149 int maxLineWidth; /* maximum of all line widths */
150 int maxWordMin; /* maximum of all word minima */
150 int maxParMin; /* maximum of all paragraph minima */
151151 int maxParMax; /* maximum of all paragraph maxima */
152 int parMin; /* the minimal total width down from the last
153 * paragraph start, to the *beginning* of the
154 * line */
155152 int parMax; /* the maximal total width down from the last
156153 * paragraph start, to the *beginning* of the
157154 * line */
239236 int availWidth, availAscent, availDescent;
240237
241238 int lastLineWidth;
242 int lastLineParMin;
239 int lastLineParMin; /* width of the current non-breakable word sequence
240 * used by wordWrap () */
243241 int lastLineParMax;
244242 int wrapRef; /* [0 based] */
245243
255253
256254 void queueDrawRange (int index1, int index2);
257255 void getWordExtremes (Word *word, core::Extremes *extremes);
256 inline bool canBreakAfter (Word *word)
257 {
258 return word->content.breakType == core::Content::BREAK_OK;
259 }
258260 void markChange (int ref);
259261 void justifyLine (Line *line, int availWidth);
260262 Line *addLine (int wordInd, bool newPar);
263265 void decorateText(core::View *view, core::style::Style *style,
264266 core::style::Color::Shading shading,
265267 int x, int yBase, int width);
266 void drawText(int wordIndex, core::View *view, core::Rectangle *area,
268 void drawText(core::View *view, core::style::Style *style,
269 core::style::Color::Shading shading, int x, int y,
270 const char *text, int start, int len);
271 void drawWord(int wordIndex, core::View *view, core::Rectangle *area,
267272 int xWidget, int yWidgetBase);
268273 void drawSpace(int wordIndex, core::View *view, core::Rectangle *area,
269274 int xWidget, int yWidgetBase);
274279
275280 Word *addWord (int width, int ascent, int descent,
276281 core::style::Style *style);
282 int textWidth (const char *text, int start, int len,
283 core::style::Style *style);
277284 void calcTextSize (const char *text, size_t len, core::style::Style *style,
278285 core::Requisition *size);
279
280286
281287 /**
282288 * \brief Returns the x offset (the indentation plus any offset needed for
381387 void addWidget (core::Widget *widget, core::style::Style *style);
382388 bool addAnchor (const char *name, core::style::Style *style);
383389 void addSpace(core::style::Style *style);
390 inline void addBreakOption (core::style::Style *style)
391 {
392 int wordIndex = words->size () - 1;
393 if (wordIndex >= 0 &&
394 style->whiteSpace != core::style::WHITE_SPACE_NOWRAP &&
395 style->whiteSpace != core::style::WHITE_SPACE_PRE)
396 words->getRef(wordIndex)->content.breakType = core::Content::BREAK_OK;
397 }
384398 void addParbreak (int space, core::style::Style *style);
385399 void addLinebreak (core::style::Style *style);
386400
193193 REAL_CONTENT = 0xff ^ (START | END),
194194 SELECTION_CONTENT = TEXT | WIDGET | BREAK
195195 };
196 enum BreakType {
197 BREAK_NO,
198 BREAK_OK
199 };
196200 /* Content is embedded in struct Word therefore we
197201 * try to be space efficient.
198202 */
199203 short type;
200204 bool space;
205 unsigned char breakType;
201206 union {
202207 const char *text;
203208 Widget *widget;
00 #!/bin/sh
1 #
2 # $NetBSD: install-sh.in,v 1.5 2010/10/08 19:57:05 tez Exp $
3 # This script now also installs multiple files, but might choke on installing
4 # multiple files with spaces in the file names.
5 #
61 # install - install a program, script, or datafile
7 # This comes from X11R5 (mit/util/scripts/install.sh).
8 #
9 # Copyright 1991 by the Massachusetts Institute of Technology
10 #
11 # Permission to use, copy, modify, distribute, and sell this software and its
12 # documentation for any purpose is hereby granted without fee, provided that
13 # the above copyright notice appear in all copies and that both that
14 # copyright notice and this permission notice appear in supporting
15 # documentation, and that the name of M.I.T. not be used in advertising or
16 # publicity pertaining to distribution of the software without specific,
17 # written prior permission. M.I.T. makes no representations about the
18 # suitability of this software for any purpose. It is provided "as is"
19 # without express or implied warranty.
2
3 scriptversion=2009-04-28.21; # UTC
4
5 # This originates from X11R5 (mit/util/scripts/install.sh), which was
6 # later released in X11R6 (xc/config/util/install.sh) with the
7 # following copyright and license.
8 #
9 # Copyright (C) 1994 X Consortium
10 #
11 # Permission is hereby granted, free of charge, to any person obtaining a copy
12 # of this software and associated documentation files (the "Software"), to
13 # deal in the Software without restriction, including without limitation the
14 # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
15 # sell copies of the Software, and to permit persons to whom the Software is
16 # furnished to do so, subject to the following conditions:
17 #
18 # The above copyright notice and this permission notice shall be included in
19 # all copies or substantial portions of the Software.
20 #
21 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
25 # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
26 # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 #
28 # Except as contained in this notice, the name of the X Consortium shall not
29 # be used in advertising or otherwise to promote the sale, use or other deal-
30 # ings in this Software without prior written authorization from the X Consor-
31 # tium.
32 #
33 #
34 # FSF changes to this file are in the public domain.
2035 #
2136 # Calling this script install-sh is preferred over install.sh, to prevent
2237 # `make' implicit rules from creating a file called install from it
2540 # This script is compatible with the BSD install script, but was written
2641 # from scratch.
2742
43 nl='
44 '
45 IFS=" "" $nl"
46
2847 # set DOITPROG to echo to test this script
2948
3049 # Don't use :- since 4.3BSD and earlier shells don't like it.
31 doit="${DOITPROG-}"
32
33
34 # put in absolute paths if you don't have them in your path; or use env. vars.
35
36 awkprog="${AWKPROG-awk}"
37 mvprog="${MVPROG-mv}"
38 cpprog="${CPPROG-cp}"
39 chmodprog="${CHMODPROG-chmod}"
40 chownprog="${CHOWNPROG-chown}"
41 chgrpprog="${CHGRPPROG-chgrp}"
42 stripprog="${STRIPPROG-strip}"
43 rmprog="${RMPROG-rm}"
44 mkdirprog="${MKDIRPROG-mkdir}"
45
46 instcmd="$cpprog"
47 pathcompchmodcmd="$chmodprog 755"
48 chmodcmd="$chmodprog 755"
49 chowncmd=""
50 chgrpcmd=""
51 stripcmd=""
52 stripflags=""
50 doit=${DOITPROG-}
51 if test -z "$doit"; then
52 doit_exec=exec
53 else
54 doit_exec=$doit
55 fi
56
57 # Put in absolute file names if you don't have them in your path;
58 # or use environment vars.
59
60 chgrpprog=${CHGRPPROG-chgrp}
61 chmodprog=${CHMODPROG-chmod}
62 chownprog=${CHOWNPROG-chown}
63 cmpprog=${CMPPROG-cmp}
64 cpprog=${CPPROG-cp}
65 mkdirprog=${MKDIRPROG-mkdir}
66 mvprog=${MVPROG-mv}
67 rmprog=${RMPROG-rm}
68 stripprog=${STRIPPROG-strip}
69
70 posix_glob='?'
71 initialize_posix_glob='
72 test "$posix_glob" != "?" || {
73 if (set -f) 2>/dev/null; then
74 posix_glob=
75 else
76 posix_glob=:
77 fi
78 }
79 '
80
81 posix_mkdir=
82
83 # Desired mode of installed file.
84 mode=0755
85
86 chgrpcmd=
87 chmodcmd=$chmodprog
88 chowncmd=
89 mvcmd=$mvprog
5390 rmcmd="$rmprog -f"
54 mvcmd="$mvprog"
55 src=""
56 msrc=""
57 dst=""
58 dir_arg=""
59 suffix=""
60 suffixfmt=""
61
62 while [ x"$1" != x ]; do
63 case $1 in
64 -b) suffix=".old"
65 shift
66 continue;;
67
68 -B) suffixfmt="$2"
69 shift
70 shift
71 continue;;
72
73 -c) instcmd="$cpprog"
74 shift
75 continue;;
76
77 -d) dir_arg=true
78 shift
79 continue;;
80
81 -m) chmodcmd="$chmodprog $2"
82 shift
83 shift
84 continue;;
85
86 -o) chowncmd="$chownprog $2"
87 shift
88 shift
89 continue;;
90
91 -g) chgrpcmd="$chgrpprog $2"
92 shift
93 shift
94 continue;;
95
96 -s) stripcmd="$stripprog"
97 shift
98 continue;;
99
100 -S) stripcmd="$stripprog"
101 stripflags="-S $2 $stripflags"
102 shift
103 shift
104 continue;;
105
106 *) if [ x"$msrc" = x ]
91 stripcmd=
92
93 src=
94 dst=
95 dir_arg=
96 dst_arg=
97
98 copy_on_change=false
99 no_target_directory=
100
101 usage="\
102 Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
103 or: $0 [OPTION]... SRCFILES... DIRECTORY
104 or: $0 [OPTION]... -t DIRECTORY SRCFILES...
105 or: $0 [OPTION]... -d DIRECTORIES...
106
107 In the 1st form, copy SRCFILE to DSTFILE.
108 In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
109 In the 4th, create DIRECTORIES.
110
111 Options:
112 --help display this help and exit.
113 --version display version info and exit.
114
115 -c (ignored)
116 -C install only if different (preserve the last data modification time)
117 -d create directories instead of installing files.
118 -g GROUP $chgrpprog installed files to GROUP.
119 -m MODE $chmodprog installed files to MODE.
120 -o USER $chownprog installed files to USER.
121 -s $stripprog installed files.
122 -t DIRECTORY install into DIRECTORY.
123 -T report an error if DSTFILE is a directory.
124
125 Environment variables override the default commands:
126 CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
127 RMPROG STRIPPROG
128 "
129
130 while test $# -ne 0; do
131 case $1 in
132 -c) ;;
133
134 -C) copy_on_change=true;;
135
136 -d) dir_arg=true;;
137
138 -g) chgrpcmd="$chgrpprog $2"
139 shift;;
140
141 --help) echo "$usage"; exit $?;;
142
143 -m) mode=$2
144 case $mode in
145 *' '* | *' '* | *'
146 '* | *'*'* | *'?'* | *'['*)
147 echo "$0: invalid mode: $mode" >&2
148 exit 1;;
149 esac
150 shift;;
151
152 -o) chowncmd="$chownprog $2"
153 shift;;
154
155 -s) stripcmd=$stripprog;;
156
157 -t) dst_arg=$2
158 shift;;
159
160 -T) no_target_directory=true;;
161
162 --version) echo "$0 $scriptversion"; exit $?;;
163
164 --) shift
165 break;;
166
167 -*) echo "$0: invalid option: $1" >&2
168 exit 1;;
169
170 *) break;;
171 esac
172 shift
173 done
174
175 if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
176 # When -d is used, all remaining arguments are directories to create.
177 # When -t is used, the destination is already specified.
178 # Otherwise, the last argument is the destination. Remove it from $@.
179 for arg
180 do
181 if test -n "$dst_arg"; then
182 # $@ is not empty: it contains at least $arg.
183 set fnord "$@" "$dst_arg"
184 shift # fnord
185 fi
186 shift # arg
187 dst_arg=$arg
188 done
189 fi
190
191 if test $# -eq 0; then
192 if test -z "$dir_arg"; then
193 echo "$0: no input file specified." >&2
194 exit 1
195 fi
196 # It's OK to call `install-sh -d' without argument.
197 # This can happen when creating conditional directories.
198 exit 0
199 fi
200
201 if test -z "$dir_arg"; then
202 trap '(exit $?); exit' 1 2 13 15
203
204 # Set umask so as not to create temps with too-generous modes.
205 # However, 'strip' requires both read and write access to temps.
206 case $mode in
207 # Optimize common cases.
208 *644) cp_umask=133;;
209 *755) cp_umask=22;;
210
211 *[0-7])
212 if test -z "$stripcmd"; then
213 u_plus_rw=
214 else
215 u_plus_rw='% 200'
216 fi
217 cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
218 *)
219 if test -z "$stripcmd"; then
220 u_plus_rw=
221 else
222 u_plus_rw=,u+rw
223 fi
224 cp_umask=$mode$u_plus_rw;;
225 esac
226 fi
227
228 for src
229 do
230 # Protect names starting with `-'.
231 case $src in
232 -*) src=./$src;;
233 esac
234
235 if test -n "$dir_arg"; then
236 dst=$src
237 dstdir=$dst
238 test -d "$dstdir"
239 dstdir_status=$?
240 else
241
242 # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
243 # might cause directories to be created, which would be especially bad
244 # if $src (and thus $dsttmp) contains '*'.
245 if test ! -f "$src" && test ! -d "$src"; then
246 echo "$0: $src does not exist." >&2
247 exit 1
248 fi
249
250 if test -z "$dst_arg"; then
251 echo "$0: no destination specified." >&2
252 exit 1
253 fi
254
255 dst=$dst_arg
256 # Protect names starting with `-'.
257 case $dst in
258 -*) dst=./$dst;;
259 esac
260
261 # If destination is a directory, append the input filename; won't work
262 # if double slashes aren't ignored.
263 if test -d "$dst"; then
264 if test -n "$no_target_directory"; then
265 echo "$0: $dst_arg: Is a directory" >&2
266 exit 1
267 fi
268 dstdir=$dst
269 dst=$dstdir/`basename "$src"`
270 dstdir_status=0
271 else
272 # Prefer dirname, but fall back on a substitute if dirname fails.
273 dstdir=`
274 (dirname "$dst") 2>/dev/null ||
275 expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
276 X"$dst" : 'X\(//\)[^/]' \| \
277 X"$dst" : 'X\(//\)$' \| \
278 X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
279 echo X"$dst" |
280 sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
281 s//\1/
282 q
283 }
284 /^X\(\/\/\)[^/].*/{
285 s//\1/
286 q
287 }
288 /^X\(\/\/\)$/{
289 s//\1/
290 q
291 }
292 /^X\(\/\).*/{
293 s//\1/
294 q
295 }
296 s/.*/./; q'
297 `
298
299 test -d "$dstdir"
300 dstdir_status=$?
301 fi
302 fi
303
304 obsolete_mkdir_used=false
305
306 if test $dstdir_status != 0; then
307 case $posix_mkdir in
308 '')
309 # Create intermediate dirs using mode 755 as modified by the umask.
310 # This is like FreeBSD 'install' as of 1997-10-28.
311 umask=`umask`
312 case $stripcmd.$umask in
313 # Optimize common cases.
314 *[2367][2367]) mkdir_umask=$umask;;
315 .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
316
317 *[0-7])
318 mkdir_umask=`expr $umask + 22 \
319 - $umask % 100 % 40 + $umask % 20 \
320 - $umask % 10 % 4 + $umask % 2
321 `;;
322 *) mkdir_umask=$umask,go-w;;
323 esac
324
325 # With -d, create the new directory with the user-specified mode.
326 # Otherwise, rely on $mkdir_umask.
327 if test -n "$dir_arg"; then
328 mkdir_mode=-m$mode
329 else
330 mkdir_mode=
331 fi
332
333 posix_mkdir=false
334 case $umask in
335 *[123567][0-7][0-7])
336 # POSIX mkdir -p sets u+wx bits regardless of umask, which
337 # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
338 ;;
339 *)
340 tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
341 trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
342
343 if (umask $mkdir_umask &&
344 exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
107345 then
108 msrc="$dst"
346 if test -z "$dir_arg" || {
347 # Check for POSIX incompatibilities with -m.
348 # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
349 # other-writeable bit of parent directory when it shouldn't.
350 # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
351 ls_ld_tmpdir=`ls -ld "$tmpdir"`
352 case $ls_ld_tmpdir in
353 d????-?r-*) different_mode=700;;
354 d????-?--*) different_mode=755;;
355 *) false;;
356 esac &&
357 $mkdirprog -m$different_mode -p -- "$tmpdir" && {
358 ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
359 test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
360 }
361 }
362 then posix_mkdir=:
363 fi
364 rmdir "$tmpdir/d" "$tmpdir"
109365 else
110 msrc="$msrc $dst"
366 # Remove any dirs left behind by ancient mkdir implementations.
367 rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
111368 fi
112 src="$dst"
113 dst="$1"
114 shift
115 continue;;
369 trap '' 0;;
370 esac;;
116371 esac
372
373 if
374 $posix_mkdir && (
375 umask $mkdir_umask &&
376 $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
377 )
378 then :
379 else
380
381 # The umask is ridiculous, or mkdir does not conform to POSIX,
382 # or it failed possibly due to a race condition. Create the
383 # directory the slow way, step by step, checking for races as we go.
384
385 case $dstdir in
386 /*) prefix='/';;
387 -*) prefix='./';;
388 *) prefix='';;
389 esac
390
391 eval "$initialize_posix_glob"
392
393 oIFS=$IFS
394 IFS=/
395 $posix_glob set -f
396 set fnord $dstdir
397 shift
398 $posix_glob set +f
399 IFS=$oIFS
400
401 prefixes=
402
403 for d
404 do
405 test -z "$d" && continue
406
407 prefix=$prefix$d
408 if test -d "$prefix"; then
409 prefixes=
410 else
411 if $posix_mkdir; then
412 (umask=$mkdir_umask &&
413 $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
414 # Don't fail if two instances are running concurrently.
415 test -d "$prefix" || exit 1
416 else
417 case $prefix in
418 *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
419 *) qprefix=$prefix;;
420 esac
421 prefixes="$prefixes '$qprefix'"
422 fi
423 fi
424 prefix=$prefix/
425 done
426
427 if test -n "$prefixes"; then
428 # Don't fail if two instances are running concurrently.
429 (umask $mkdir_umask &&
430 eval "\$doit_exec \$mkdirprog $prefixes") ||
431 test -d "$dstdir" || exit 1
432 obsolete_mkdir_used=true
433 fi
434 fi
435 fi
436
437 if test -n "$dir_arg"; then
438 { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
439 { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
440 { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
441 test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
442 else
443
444 # Make a couple of temp file names in the proper directory.
445 dsttmp=$dstdir/_inst.$$_
446 rmtmp=$dstdir/_rm.$$_
447
448 # Trap to clean up those temp files at exit.
449 trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
450
451 # Copy the file name to the temp name.
452 (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
453
454 # and set any options; do chmod last to preserve setuid bits.
455 #
456 # If any of these fail, we abort the whole thing. If we want to
457 # ignore errors from any of these, just make sure not to ignore
458 # errors from the above "$doit $cpprog $src $dsttmp" command.
459 #
460 { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
461 { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
462 { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
463 { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
464
465 # If -C, don't bother to copy if it wouldn't change the file.
466 if $copy_on_change &&
467 old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
468 new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
469
470 eval "$initialize_posix_glob" &&
471 $posix_glob set -f &&
472 set X $old && old=:$2:$4:$5:$6 &&
473 set X $new && new=:$2:$4:$5:$6 &&
474 $posix_glob set +f &&
475
476 test "$old" = "$new" &&
477 $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
478 then
479 rm -f "$dsttmp"
480 else
481 # Rename the file to the real destination.
482 $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
483