1 /* AbiWord
2 * Copyright (C) 1998,1999 AbiSource, Inc.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301 USA.
18 */
19
20 #include <windows.h>
21 #include <commctrl.h>
22
23 #include "ut_string.h"
24 #include "ut_assert.h"
25 #include "ut_debugmsg.h"
26 #include "ut_Win32OS.h"
27
28 #include "xap_App.h"
29 #include "xap_Win32App.h"
30 #include "xap_Win32FrameImpl.h"
31
32 #include "ap_Dialog_Id.h"
33 #include "ap_Strings.h"
34 #include "ap_Preview_Paragraph.h"
35 #include "ap_Win32Dialog_Paragraph.h"
36 #include "xap_Win32PreviewWidget.h"
37 #include "xap_Win32LabelledSeparator.h"
38
39 #include "gr_Win32Graphics.h"
40 #include "xap_Win32DialogHelper.h"
41 #include "ap_Win32Resources.rc2"
42
43 /*****************************************************************/
44
45 #define GWL(hwnd) (AP_Win32Dialog_Paragraph*)GetWindowLongPtrW((hwnd), DWLP_USER)
46 #define SWL(hwnd, d) SetWindowLongPtrW((hwnd), DWLP_USER,(LONG_PTR)(d))
47
48 /*****************************************************************/
49
static_constructor(XAP_DialogFactory * pFactory,XAP_Dialog_Id id)50 XAP_Dialog * AP_Win32Dialog_Paragraph::static_constructor(XAP_DialogFactory * pFactory,
51 XAP_Dialog_Id id)
52 {
53 AP_Win32Dialog_Paragraph * p = new AP_Win32Dialog_Paragraph(pFactory,id);
54 return p;
55 }
56
AP_Win32Dialog_Paragraph(XAP_DialogFactory * pDlgFactory,XAP_Dialog_Id id)57 AP_Win32Dialog_Paragraph::AP_Win32Dialog_Paragraph(XAP_DialogFactory * pDlgFactory,
58 XAP_Dialog_Id id)
59 : AP_Dialog_Paragraph(pDlgFactory,id)
60 {
61 m_pPreviewWidget = NULL;
62 m_bEditChanged = false;
63 }
64
~AP_Win32Dialog_Paragraph(void)65 AP_Win32Dialog_Paragraph::~AP_Win32Dialog_Paragraph(void)
66 {
67 DELETEP(m_pPreviewWidget);
68 }
69
70 /*****************************************************************/
71
runModal(XAP_Frame * pFrame)72 void AP_Win32Dialog_Paragraph::runModal(XAP_Frame * pFrame)
73 {
74 /*
75 This dialog is non-persistent.
76
77 This dialog should do the following:
78
79 - Construct itself to represent the paragraph properties
80 in the base class (AP_Dialog_Paragraph).
81
82 The Unix one looks just like Microsoft Word 97's Paragraph
83 dialog.
84
85 - The base class stores all the paragraph parameters in
86 m_paragraphData.
87
88 On "OK" (or during user-interaction) the dialog should:
89
90 - Save all the data to the m_paragraphData struct so it
91 can be queried by the caller (edit methods routines).
92
93 On "Cancel" the dialog should:
94
95 - Just quit, the data items will be ignored by the caller.
96
97 On "Tabs..." the dialog should (?):
98
99 - Just quit, discarding changed data, and let the caller (edit methods)
100 invoke the Tabs dialog.
101
102 */
103
104 // store frame for later use
105 m_pFrame = pFrame;
106
107 // raise the dialog
108 XAP_Win32App * pWin32App = static_cast<XAP_Win32App *>(m_pApp);
109
110 XAP_Win32LabelledSeparator_RegisterClass(pWin32App);
111
112 // createModal(pFrame, MAKEINTRESOURCEW(AP_RID_DIALOG_PARAGRAPH));
113
114 LPCWSTR lpTemplate = NULL;
115
116 UT_ASSERT(m_id == AP_DIALOG_ID_PARAGRAPH);
117
118 lpTemplate = MAKEINTRESOURCEW(AP_RID_DIALOG_PARAGRAPH);
119
120 XAP_Win32FrameImpl* pWin32FrameImpl = static_cast<XAP_Win32FrameImpl*>(pFrame->getFrameImpl());
121
122 HWND hFrameWnd = pWin32FrameImpl->getTopLevelWindow();
123
124 UT_DebugOnly<int> result = DialogBoxParamW(pWin32App->getInstance(),lpTemplate,
125 hFrameWnd,
126 (DLGPROC)s_dlgProc,(LPARAM)this);
127 UT_ASSERT((result != -1));
128 }
129
130 /**/ //was commented out from here
s_dlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)131 BOOL CALLBACK AP_Win32Dialog_Paragraph::s_dlgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
132 {
133 // This is a static function.
134
135 AP_Win32Dialog_Paragraph * pThis;
136
137 switch (msg)
138 {
139 case WM_INITDIALOG:
140 pThis = (AP_Win32Dialog_Paragraph *)lParam;
141 SWL(hWnd,lParam);
142 pThis->setHandle(hWnd);
143 return pThis->_onInitDialog(hWnd,wParam,lParam);
144
145 case WM_COMMAND:
146 pThis = GWL(hWnd);
147 return pThis->_onCommand(hWnd,wParam,lParam);
148
149 case WM_NOTIFY:
150 {
151 pThis = GWL(hWnd);
152
153 switch (((LPNMHDR) lParam)->code)
154 {
155 case TCN_SELCHANGING:
156 {
157 // TODO: validate data before leaving page
158 }
159 break;
160
161 case TCN_SELCHANGE:
162 {
163 int iTo = TabCtrl_GetCurSel(pThis->m_hwndTab);
164
165 // a more general solution would be better here
166 ShowWindow(pThis->m_hwndSpacing, (iTo ? SW_HIDE : SW_SHOW));
167 ShowWindow(pThis->m_hwndBreaks, (!iTo ? SW_HIDE : SW_SHOW));
168 }
169 break;
170
171 // Process other notifications here
172 default:
173 break;
174 }
175 }
176 return 0;
177
178 default:
179 return 0;
180 }
181 }
182 /**/ // and to here
183 // this little struct gets passed into s_tabProc
184 typedef struct _tabParam
185 {
186 AP_Win32Dialog_Paragraph * pThis;
187 WORD which;
188 } TabParam;
189
s_tabProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)190 BOOL CALLBACK AP_Win32Dialog_Paragraph::s_tabProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
191 {
192 // This is a static function.
193
194 AP_Win32Dialog_Paragraph * pThis;
195
196 switch (msg)
197 {
198 case WM_INITDIALOG:
199 {
200 TabParam * pTP = (TabParam *) lParam;
201
202 // from now on, we can just remember pThis
203 pThis = pTP->pThis;
204 SWL(hWnd,pThis);
205 return pThis->_onInitTab(hWnd,wParam,lParam);
206 }
207
208 case WM_COMMAND:
209 pThis = GWL(hWnd);
210 return pThis->_onCommand(hWnd,wParam,lParam);
211
212 case WM_NOTIFY:
213 pThis = GWL(hWnd);
214 switch (((LPNMHDR)lParam)->code)
215 {
216 case UDN_DELTAPOS: return pThis->_onDeltaPos((NM_UPDOWN *)lParam);
217 default: return 0;
218 }
219
220 default:
221 return 0;
222 }
223 }
224
225 /*****************************************************************/
226
227 #define _DS(c,s) setDlgItemText(hWnd, AP_RID_DIALOG_##c,pSS->getValue(AP_STRING_ID_##s))
228 #define _DSX(c,s) setDlgItemText(hWnd, AP_RID_DIALOG_##c,pSS->getValue(XAP_STRING_ID_##s))
229 #define _GV(s) (pSS->getValue(AP_STRING_ID_##s))
230
_onInitDialog(HWND hWnd,WPARAM,LPARAM)231 BOOL AP_Win32Dialog_Paragraph::_onInitDialog(HWND hWnd, WPARAM /*wParam*/, LPARAM /*lParam*/)
232 {
233 const XAP_StringSet * pSS = m_pApp->getStringSet();
234
235 setDialogTitle (pSS->getValue(AP_STRING_ID_DLG_Para_ParaTitle));
236
237 // localize controls
238 _DSX(PARA_BTN_OK, DLG_OK);
239 _DSX(PARA_BTN_CANCEL, DLG_Cancel);
240
241 _DS(PARA_BTN_TABS, DLG_Para_ButtonTabs);
242
243 // setup the tabs
244 {
245 TabParam tp;
246 TCITEMW tie;
247
248 XAP_Win32App * pWin32App = static_cast<XAP_Win32App *>(m_pApp);
249 HINSTANCE hinst = pWin32App->getInstance();
250 DLGTEMPLATE * pTemplate = NULL;
251 UT_DebugOnly<HWND> w;
252
253 tp.pThis = this;
254
255 // remember the windows we're using
256
257 m_hwndDlg = hWnd;
258 m_hwndTab = GetDlgItem(hWnd, AP_RID_DIALOG_PARA_TAB);
259
260 // add a tab for each of the child dialog boxes
261
262 UT_Win32LocaleString str;
263
264 tie.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_PARAM;
265 tie.iImage = -1;
266 str.fromUTF8(_GV(DLG_Para_TabLabelIndentsAndSpacing));
267 tie.pszText = (LPWSTR)str.c_str();
268 tie.lParam = AP_RID_DIALOG_PARA_TAB1;
269 SendMessageW(m_hwndTab, TCM_INSERTITEMW, 0, (LPARAM)&tie);
270 str.fromUTF8(_GV(DLG_Para_TabLabelLineAndPageBreaks));
271 tie.pszText = (LPWSTR)str.c_str();
272 tie.lParam = AP_RID_DIALOG_PARA_TAB2;
273 SendMessageW(m_hwndTab, TCM_INSERTITEMW, 1, (LPARAM)&tie);
274
275 // finally, create the (modeless) child dialogs
276
277 tp.which = AP_RID_DIALOG_PARA_TAB1;
278 pTemplate = UT_LockDlgRes(hinst, MAKEINTRESOURCEW(tp.which));
279 w = CreateDialogIndirectParamW(hinst, pTemplate, m_hwndTab,
280 (DLGPROC)s_tabProc, (LPARAM)&tp);
281 UT_ASSERT_HARMLESS((w && (w == m_hwndSpacing)));
282
283 tp.which = AP_RID_DIALOG_PARA_TAB2;
284 pTemplate = UT_LockDlgRes(hinst, MAKEINTRESOURCEW(tp.which));
285 w = CreateDialogIndirectParamW(hinst, pTemplate, m_hwndTab,
286 (DLGPROC)s_tabProc, (LPARAM)&tp);
287 UT_ASSERT_HARMLESS((w && (w == m_hwndBreaks)));
288 }
289
290 // HACK: make sure the first tab is visible
291 // TODO: trigger selchange logic instead
292 ShowWindow(m_hwndSpacing, SW_SHOW);
293
294 // sync all controls once to get started
295 // HACK: the first arg gets ignored
296 _syncControls(id_MENU_ALIGNMENT, true);
297 centerDialog();
298 return 1; // 1 == we did not call SetFocus()
299 }
300
301 /*****************************************************************/
302
303 #define _CAS(w,s) str.fromUTF8(_GV(s));\
304 SendMessageW(w, CB_ADDSTRING, 0, (LPARAM)str.c_str())
305 #define _SST(c,i) setDlgItemText(hWnd,AP_RID_DIALOG_##c,_getSpinItemValue(i))
306 #define _CDB(c,i) CheckDlgButton(hWnd,AP_RID_DIALOG_##c,_getCheckItemValue(i))
307
_onInitTab(HWND hWnd,WPARAM,LPARAM lParam)308 BOOL AP_Win32Dialog_Paragraph::_onInitTab(HWND hWnd, WPARAM /*wParam*/, LPARAM lParam)
309 {
310 const XAP_StringSet * pSS = m_pApp->getStringSet();
311
312 UT_Win32LocaleString str;
313
314 // position ourselves w.r.t. containing tab
315
316 RECT r;
317 GetClientRect(m_hwndTab, &r);
318 TabCtrl_AdjustRect(m_hwndTab, FALSE, &r);
319 SetWindowPos(hWnd, HWND_TOP, r.left, r.top, 0, 0, SWP_NOSIZE);
320
321 // remember which window is which tab
322
323 TabParam * pTP = (TabParam *) lParam;
324 switch (pTP->which)
325 {
326 case AP_RID_DIALOG_PARA_TAB1: // first tab
327 {
328 m_hwndSpacing = hWnd;
329
330 // Hide Bidi Check Box unless required
331 {
332 HWND hwndBidi = GetDlgItem(hWnd, AP_RID_DIALOG_PARA_CHECK_BIDI);
333 ShowWindow(hwndBidi,SW_HIDE);
334 ShowWindow(hwndBidi,SW_SHOW);
335 }
336
337 // localize controls
338 _DS(PARA_TEXT_ALIGN, DLG_Para_LabelAlignment);
339 _DS(PARA_TEXT_INDENT, DLG_Para_LabelIndentation);
340 _DS(PARA_TEXT_LEFT, DLG_Para_LabelLeft);
341 _DS(PARA_TEXT_RIGHT, DLG_Para_LabelRight);
342 _DS(PARA_TEXT_HANG, DLG_Para_LabelSpecial);
343 _DS(PARA_TEXT_BY, DLG_Para_LabelBy);
344 _DS(PARA_TEXT_SPACING, DLG_Para_LabelSpacing);
345 _DS(PARA_TEXT_BEFORE, DLG_Para_LabelBefore);
346 _DS(PARA_TEXT_AFTER, DLG_Para_LabelAfter);
347 _DS(PARA_TEXT_LEAD, DLG_Para_LabelLineSpacing);
348 _DS(PARA_TEXT_AT, DLG_Para_LabelAt);
349 _DS(PARA_CHECK_BIDI, DLG_Para_DomDirection);
350
351 // populate fixed choices
352 {
353 HWND hwndAlign = GetDlgItem(hWnd, AP_RID_DIALOG_PARA_COMBO_ALIGN);
354 // insert the empty value (for multi-para selections with different state)
355 SendMessageW(hwndAlign, CB_ADDSTRING, 0, (LPARAM) L"");
356 _CAS(hwndAlign, DLG_Para_AlignLeft);
357 _CAS(hwndAlign, DLG_Para_AlignCentered);
358 _CAS(hwndAlign, DLG_Para_AlignRight);
359 _CAS(hwndAlign, DLG_Para_AlignJustified);
360 SendMessageW(hwndAlign, CB_SETCURSEL, (WPARAM) _getMenuItemValue(id_MENU_ALIGNMENT), 0);
361
362 HWND hwndHang = GetDlgItem(hWnd, AP_RID_DIALOG_PARA_COMBO_HANG);
363 SendMessageW(hwndHang, CB_ADDSTRING, 0, (LPARAM) L"");
364 _CAS(hwndHang, DLG_Para_SpecialNone);
365 _CAS(hwndHang, DLG_Para_SpecialFirstLine);
366 _CAS(hwndHang, DLG_Para_SpecialHanging);
367 SendMessageW(hwndHang, CB_SETCURSEL, (WPARAM) _getMenuItemValue(id_MENU_SPECIAL_INDENT), 0);
368
369 HWND hwndLead = GetDlgItem(hWnd, AP_RID_DIALOG_PARA_COMBO_LEAD);
370 SendMessageW(hwndLead, CB_ADDSTRING, 0, (LPARAM) L"");
371 _CAS(hwndLead, DLG_Para_SpacingSingle);
372 _CAS(hwndLead, DLG_Para_SpacingHalf);
373 _CAS(hwndLead, DLG_Para_SpacingDouble);
374 _CAS(hwndLead, DLG_Para_SpacingAtLeast);
375 _CAS(hwndLead, DLG_Para_SpacingExactly);
376 _CAS(hwndLead, DLG_Para_SpacingMultiple);
377 SendMessageW(hwndLead, CB_SETCURSEL, (WPARAM) _getMenuItemValue(id_MENU_SPECIAL_SPACING), 0);
378 }
379
380 // set initial state
381 _SST(PARA_EDIT_LEFT, id_SPIN_LEFT_INDENT);
382 _SST(PARA_EDIT_RIGHT, id_SPIN_RIGHT_INDENT);
383 _SST(PARA_EDIT_BY, id_SPIN_SPECIAL_INDENT);
384 _SST(PARA_EDIT_BEFORE, id_SPIN_BEFORE_SPACING);
385 _SST(PARA_EDIT_AFTER, id_SPIN_AFTER_SPACING);
386 _SST(PARA_EDIT_AT, id_SPIN_SPECIAL_SPACING);
387 _CDB(PARA_CHECK_BIDI, id_CHECK_DOMDIRECTION);
388 }
389 break;
390
391 case AP_RID_DIALOG_PARA_TAB2: // second tab
392 {
393 m_hwndBreaks = hWnd;
394
395 // localize controls
396 _DS(PARA_TEXT_PAGE, DLG_Para_LabelPagination);
397 _DS(PARA_CHECK_WIDOW, DLG_Para_PushWidowOrphanControl);
398 _DS(PARA_CHECK_NEXT, DLG_Para_PushKeepWithNext);
399 _DS(PARA_CHECK_TOGETHER, DLG_Para_PushKeepLinesTogether);
400 _DS(PARA_CHECK_BREAK, DLG_Para_PushPageBreakBefore);
401 _DS(PARA_CHECK_SUPPRESS, DLG_Para_PushSuppressLineNumbers);
402 _DS(PARA_CHECK_NOHYPHEN, DLG_Para_PushNoHyphenate);
403
404 // set initial state
405 _CDB(PARA_CHECK_WIDOW, id_CHECK_WIDOW_ORPHAN);
406 _CDB(PARA_CHECK_NEXT, id_CHECK_KEEP_NEXT);
407 _CDB(PARA_CHECK_TOGETHER, id_CHECK_KEEP_LINES);
408 _CDB(PARA_CHECK_BREAK, id_CHECK_PAGE_BREAK);
409 _CDB(PARA_CHECK_SUPPRESS, id_CHECK_SUPPRESS);
410 _CDB(PARA_CHECK_NOHYPHEN, id_CHECK_NO_HYPHENATE);
411 }
412 break;
413
414 default:
415 UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
416 break;
417 }
418
419 // the following are common to each tab
420
421 _DS(PARA_TEXT_PREVIEW, DLG_Para_LabelPreview);
422
423 if (!m_pPreviewWidget)
424 {
425 // for XP purposes, life is simplest if we only have one preview
426 // widget which "floats" above both tabs. to get the window
427 // parentage right, we use the dimensions and location of the
428 // owner-draw control on the tab to position *another* dummy
429 // window which is parented by the main dialog instead.
430
431 HWND hwndChild = GetDlgItem(hWnd, AP_RID_DIALOG_PARA_PREVIEW);
432 HWND hwndFloater = GetDlgItem(m_hwndDlg, AP_RID_DIALOG_PARA_PREVIEW);
433
434 RECT r2;
435 GetWindowRect(hwndChild, &r2);
436
437 POINT pt;
438 pt.x = r2.left;
439 pt.y = r2.top;
440 ScreenToClient(m_hwndDlg, &pt);
441
442 SetWindowPos(hwndFloater, HWND_TOP, pt.x, pt.y,
443 r2.right - r2.left, r2.bottom - r2.top, SWP_NOREDRAW);
444
445 // use this floater window as a parent to the widget that we create
446 // here and thus have complete control of.
447
448 m_pPreviewWidget = new XAP_Win32PreviewWidget(static_cast<XAP_Win32App *>(m_pApp),
449 hwndFloater,
450 0);
451
452 // instantiate the XP preview object using the win32 preview widget (window)
453 // we just created. we seem to have a mish-mash of terms here, sorry.
454
455 UT_uint32 w,h;
456 m_pPreviewWidget->getWindowSize(&w,&h);
457
458 _createPreviewFromGC(m_pPreviewWidget->getGraphics(),w,h);
459 m_pPreviewWidget->setPreview(m_paragraphPreview); // we need this to call draw() on WM_PAINTs
460 // _updatePreview();
461 }
462
463 return 1; // 1 == we did not call SetFocus()
464 }
465
466 /*****************************************************************/
467
468 #define _COMBO(c,i) \
469 case AP_RID_DIALOG_##c: \
470 switch (HIWORD(wParam)) \
471 { \
472 case CBN_SELCHANGE: \
473 _setMenuItemValue(i,SendMessageW(hWndCtrl,CB_GETCURSEL,0,0)); \
474 return 1; \
475 \
476 default: \
477 return 0; \
478 } \
479 break; \
480
481 // to ensure the accurate value is displayed to the user
482 // we call "_syncControls(i)" after we set the variable, to
483 // catch any changes the _setSpinItemValue() call might
484 // have done to validate data
485 #define _EDIT(c,i) \
486 case AP_RID_DIALOG_##c: \
487 switch (wNotifyCode) \
488 { \
489 case EN_CHANGE: \
490 m_bEditChanged = true; \
491 return 1; \
492 \
493 case EN_KILLFOCUS: \
494 char buf[SPIN_BUF_TEXT_SIZE]; \
495 GetWindowText(hWndCtrl,buf,SPIN_BUF_TEXT_SIZE); \
496 _setSpinItemValue(i,buf); \
497 _syncControls(i); \
498 m_bEditChanged = false; \
499 return 1; \
500 \
501 default: \
502 return 0; \
503 } \
504 break; \
505
506 #define _CHECK(c,i) \
507 case AP_RID_DIALOG_##c: \
508 _setCheckItemValue(i,(tCheckState) IsDlgButtonChecked(hWnd,AP_RID_DIALOG_##c)); \
509 return 1; \
510
511 /*****************************************************************/
512
_onCommand(HWND hWnd,WPARAM wParam,LPARAM lParam)513 BOOL AP_Win32Dialog_Paragraph::_onCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
514 {
515 WORD wNotifyCode = HIWORD(wParam);
516 WORD wId = LOWORD(wParam);
517 HWND hWndCtrl = (HWND)lParam;
518
519 switch (wId)
520 {
521 _COMBO(PARA_COMBO_ALIGN, id_MENU_ALIGNMENT);
522 _COMBO(PARA_COMBO_HANG, id_MENU_SPECIAL_INDENT);
523 _COMBO(PARA_COMBO_LEAD, id_MENU_SPECIAL_SPACING);
524
525 _EDIT(PARA_EDIT_LEFT, id_SPIN_LEFT_INDENT);
526 _EDIT(PARA_EDIT_RIGHT, id_SPIN_RIGHT_INDENT);
527 _EDIT(PARA_EDIT_BY, id_SPIN_SPECIAL_INDENT);
528 _EDIT(PARA_EDIT_BEFORE, id_SPIN_BEFORE_SPACING);
529 _EDIT(PARA_EDIT_AFTER, id_SPIN_AFTER_SPACING);
530 _EDIT(PARA_EDIT_AT, id_SPIN_SPECIAL_SPACING);
531
532 _CHECK(PARA_CHECK_WIDOW, id_CHECK_WIDOW_ORPHAN);
533 _CHECK(PARA_CHECK_NEXT, id_CHECK_KEEP_NEXT);
534 _CHECK(PARA_CHECK_TOGETHER, id_CHECK_KEEP_LINES);
535 _CHECK(PARA_CHECK_BREAK, id_CHECK_PAGE_BREAK);
536 _CHECK(PARA_CHECK_SUPPRESS, id_CHECK_SUPPRESS);
537 _CHECK(PARA_CHECK_NOHYPHEN, id_CHECK_NO_HYPHENATE);
538 _CHECK(PARA_CHECK_BIDI, id_CHECK_DOMDIRECTION);
539
540 case IDCANCEL: // also AP_RID_DIALOG_PARA_BTN_CANCEL
541 m_answer = a_CANCEL;
542 EndDialog(hWnd,0);
543 return 1;
544
545 case IDOK: // also AP_RID_DIALOG_PARA_BTN_OK
546 m_answer = a_OK;
547 EndDialog(hWnd,0);
548 return 1;
549
550 case AP_RID_DIALOG_PARA_BTN_TABS:
551 m_answer = a_TABS;
552 EndDialog(hWnd,0);
553 return 1;
554
555 default: // we did not handle this notification
556 UT_DEBUGMSG(("WM_Command for id %ld\n",wId));
557 return 0; // return zero to let windows take care of it.
558 }
559 }
560
561 /*****************************************************************/
562
563 #define _SPIN(w,c,i) \
564 case AP_RID_DIALOG_PARA_SPIN_##c: \
565 if (m_bEditChanged) \
566 { \
567 GetDlgItemText(w,AP_RID_DIALOG_PARA_EDIT_##c,buf,SPIN_BUF_TEXT_SIZE); \
568 _setSpinItemValue(i,buf); \
569 m_bEditChanged = false; \
570 } \
571 _doSpin(i, (0 - (UT_sint32) pnmud->iDelta)); \
572 break; \
573
_onDeltaPos(NM_UPDOWN * pnmud)574 BOOL AP_Win32Dialog_Paragraph::_onDeltaPos(NM_UPDOWN * pnmud)
575 {
576 // respond to WM_NOTIFY/UDN_DELTAPOS message
577 // return TRUE to prevent the change from happening
578 // return FALSE to allow it to occur
579 // we may alter the change by changing the fields in pnmud.
580
581 UT_DEBUGMSG(("onDeltaPos: [idFrom %d][iPos %d][iDelta %d]\n",
582 pnmud->hdr.idFrom,pnmud->iPos,pnmud->iDelta));
583
584 char buf[SPIN_BUF_TEXT_SIZE];
585
586 switch(pnmud->hdr.idFrom)
587 {
588 _SPIN(m_hwndSpacing, LEFT, id_SPIN_LEFT_INDENT);
589 _SPIN(m_hwndSpacing, RIGHT, id_SPIN_RIGHT_INDENT);
590 _SPIN(m_hwndSpacing, BY, id_SPIN_SPECIAL_INDENT);
591 _SPIN(m_hwndSpacing, BEFORE, id_SPIN_BEFORE_SPACING);
592 _SPIN(m_hwndSpacing, AFTER, id_SPIN_AFTER_SPACING);
593 _SPIN(m_hwndSpacing, AT, id_SPIN_SPECIAL_SPACING);
594
595 default:
596 UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN);
597 break;
598 }
599
600 return FALSE;
601 }
602
603 /*****************************************************************/
604
605 #define _syncSPIN(w,c,i) \
606 case i: \
607 SetDlgItemText(w,AP_RID_DIALOG_##c,_getSpinItemValue(i)); \
608 break; \
609
_syncControls(tControl changed,bool bAll)610 void AP_Win32Dialog_Paragraph::_syncControls(tControl changed, bool bAll /* = false */)
611 {
612 // let parent sync any member variables first
613
614 AP_Dialog_Paragraph::_syncControls(changed, bAll);
615
616 // sync the display
617
618 // 1. link the "hanging indent by" combo and spinner
619
620 if (bAll || (changed == id_SPIN_SPECIAL_INDENT))
621 {
622 // typing in the control can change the associated combo
623 if (_getMenuItemValue(id_MENU_SPECIAL_INDENT) == indent_FIRSTLINE)
624 {
625 HWND h = GetDlgItem(m_hwndSpacing, AP_RID_DIALOG_PARA_COMBO_HANG);
626 SendMessageW(h, CB_SETCURSEL, (WPARAM) _getMenuItemValue(id_MENU_SPECIAL_INDENT), 0);
627 }
628 }
629 if (bAll || (changed == id_MENU_SPECIAL_INDENT))
630 {
631 switch(_getMenuItemValue(id_MENU_SPECIAL_INDENT))
632 {
633 case indent_NONE:
634 // clear the spin control
635 SetDlgItemText(m_hwndSpacing, AP_RID_DIALOG_PARA_EDIT_BY, NULL);
636 break;
637
638 default:
639 // set the spin control
640 SetDlgItemText(m_hwndSpacing, AP_RID_DIALOG_PARA_EDIT_BY, _getSpinItemValue(id_SPIN_SPECIAL_INDENT));
641 break;
642 }
643 }
644
645 // 2. link the "line spacing at" combo and spinner
646
647 if (bAll || (changed == id_SPIN_SPECIAL_SPACING))
648 {
649 // typing in the control can change the associated combo
650 if (_getMenuItemValue(id_MENU_SPECIAL_SPACING) == spacing_MULTIPLE)
651 {
652 HWND h = GetDlgItem(m_hwndSpacing, AP_RID_DIALOG_PARA_COMBO_LEAD);
653 SendMessageW(h, CB_SETCURSEL, (WPARAM) _getMenuItemValue(id_MENU_SPECIAL_SPACING), 0);
654 }
655 }
656 if (bAll || (changed == id_MENU_SPECIAL_SPACING))
657 {
658 switch(_getMenuItemValue(id_MENU_SPECIAL_SPACING))
659 {
660 case spacing_SINGLE:
661 case spacing_ONEANDHALF:
662 case spacing_DOUBLE:
663 // clear the spin control
664 SetDlgItemText(m_hwndSpacing, AP_RID_DIALOG_PARA_EDIT_AT, NULL);
665 break;
666
667 default:
668 // set the spin control
669 SetDlgItemText(m_hwndSpacing, AP_RID_DIALOG_PARA_EDIT_AT, _getSpinItemValue(id_SPIN_SPECIAL_SPACING));
670 break;
671 }
672 }
673
674 // 3. move results of _doSpin() back to screen
675
676 if (!bAll)
677 {
678 // spin controls only sync when spun
679 switch (changed)
680 {
681 _syncSPIN(m_hwndSpacing, PARA_EDIT_LEFT, id_SPIN_LEFT_INDENT)
682 _syncSPIN(m_hwndSpacing, PARA_EDIT_RIGHT, id_SPIN_RIGHT_INDENT)
683 _syncSPIN(m_hwndSpacing, PARA_EDIT_BY, id_SPIN_SPECIAL_INDENT)
684 _syncSPIN(m_hwndSpacing, PARA_EDIT_BEFORE, id_SPIN_BEFORE_SPACING)
685 _syncSPIN(m_hwndSpacing, PARA_EDIT_AFTER, id_SPIN_AFTER_SPACING)
686 _syncSPIN(m_hwndSpacing, PARA_EDIT_AT, id_SPIN_SPECIAL_SPACING)
687 default:
688 break;
689 }
690 }
691 }
692