Fix release build of dflat32, initalizing some vars and fixing one typo.
[reactos.git] / rosapps / dflat32 / textbox.c
1 /* ------------- textbox.c ------------ */
2
3 #include "dflat.h"
4
5 static void ComputeWindowTop(DFWINDOW);
6 static void ComputeWindowLeft(DFWINDOW);
7 static int ComputeVScrollBox(DFWINDOW);
8 static int ComputeHScrollBox(DFWINDOW);
9 static void MoveScrollBox(DFWINDOW, int);
10 static char *GetTextLine(DFWINDOW, int);
11
12 BOOL DfVSliding;
13 BOOL DfHSliding;
14
15 /* ------------ DFM_ADDTEXT Message -------------- */
16 static BOOL AddTextMsg(DFWINDOW wnd, char *txt)
17 {
18 /* --- append text to the textbox's buffer --- */
19 unsigned adln = strlen(txt);
20 if (adln > (unsigned)0xfff0)
21 return FALSE;
22 if (wnd->text != NULL) {
23 /* ---- appending to existing text ---- */
24 unsigned txln = strlen(wnd->text);
25 if ((long)txln+adln > (unsigned) 0xfff0)
26 return FALSE;
27 if (txln+adln > wnd->textlen) {
28 wnd->text = DfRealloc(wnd->text, txln+adln+3);
29 wnd->textlen = txln+adln+1;
30 }
31 }
32 else {
33 /* ------ 1st text appended ------ */
34 wnd->text = DfCalloc(1, adln+3);
35 wnd->textlen = adln+1;
36 }
37 if (wnd->text != NULL) {
38 /* ---- append the text ---- */
39 strcat(wnd->text, txt);
40 strcat(wnd->text, "\n");
41 DfBuildTextPointers(wnd);
42 return TRUE;
43 }
44 return FALSE;
45 }
46
47 /* ------------ DFM_DELETETEXT Message -------------- */
48 static void DeleteTextMsg(DFWINDOW wnd, int lno)
49 {
50 char *cp1 = DfTextLine(wnd, lno);
51 --wnd->wlines;
52 if (lno == wnd->wlines)
53 *cp1 = '\0';
54 else {
55 char *cp2 = DfTextLine(wnd, lno+1);
56 memmove(cp1, cp2, strlen(cp2)+1);
57 }
58 DfBuildTextPointers(wnd);
59 }
60
61 /* ------------ DFM_INSERTTEXT Message -------------- */
62 static void InsertTextMsg(DFWINDOW wnd, char *txt, int lno)
63 {
64 if (AddTextMsg(wnd, txt)) {
65 int len = strlen(txt);
66 char *cp2 = DfTextLine(wnd, lno);
67 char *cp1 = cp2+len+1;
68 memmove(cp1, cp2, strlen(cp2)-len);
69 strcpy(cp2, txt);
70 *(cp2+len) = '\n';
71 DfBuildTextPointers(wnd);
72 }
73 }
74
75 /* ------------ DFM_SETTEXT Message -------------- */
76 static void SetTextMsg(DFWINDOW wnd, char *txt)
77 {
78 /* -- assign new text value to textbox buffer -- */
79 unsigned int len = strlen(txt)+1;
80 DfSendMessage(wnd, DFM_CLEARTEXT, 0, 0);
81 wnd->textlen = len;
82 wnd->text=DfRealloc(wnd->text, len+1);
83 wnd->text[len] = '\0';
84 strcpy(wnd->text, txt);
85 DfBuildTextPointers(wnd);
86 }
87
88 /* ------------ DFM_CLEARTEXT Message -------------- */
89 static void ClearTextMsg(DFWINDOW wnd)
90 {
91 /* ----- clear text from textbox ----- */
92 if (wnd->text != NULL)
93 free(wnd->text);
94 wnd->text = NULL;
95 wnd->textlen = 0;
96 wnd->wlines = 0;
97 wnd->textwidth = 0;
98 wnd->wtop = wnd->wleft = 0;
99 DfClearTextBlock(wnd);
100 DfClearTextPointers(wnd);
101 }
102
103 /* ------------ DFM_KEYBOARD Message -------------- */
104 static int KeyboardMsg(DFWINDOW wnd, DF_PARAM p1)
105 {
106 switch ((int) p1) {
107 case DF_UP:
108 return DfSendMessage(wnd,DFM_SCROLL,FALSE,0);
109 case DF_DN:
110 return DfSendMessage(wnd,DFM_SCROLL,TRUE,0);
111 case DF_FWD:
112 return DfSendMessage(wnd,DFM_HORIZSCROLL,TRUE,0);
113 case DF_BS:
114 return DfSendMessage(wnd,DFM_HORIZSCROLL,FALSE,0);
115 case DF_PGUP:
116 return DfSendMessage(wnd,DFM_SCROLLPAGE,FALSE,0);
117 case DF_PGDN:
118 return DfSendMessage(wnd,DFM_SCROLLPAGE,TRUE,0);
119 case DF_CTRL_PGUP:
120 return DfSendMessage(wnd,DFM_HORIZPAGE,FALSE,0);
121 case DF_CTRL_PGDN:
122 return DfSendMessage(wnd,DFM_HORIZPAGE,TRUE,0);
123 case DF_HOME:
124 return DfSendMessage(wnd,DFM_SCROLLDOC,TRUE,0);
125 case DF_END:
126 return DfSendMessage(wnd,DFM_SCROLLDOC,FALSE,0);
127 default:
128 break;
129 }
130 return FALSE;
131 }
132
133 /* ------------ DFM_LEFT_BUTTON Message -------------- */
134 static int LeftButtonMsg(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
135 {
136 int mx = (int) p1 - DfGetLeft(wnd);
137 int my = (int) p2 - DfGetTop(wnd);
138 if (DfTestAttribute(wnd, DF_VSCROLLBAR) &&
139 mx == DfWindowWidth(wnd)-1) {
140 /* -------- in the right border ------- */
141 if (my == 0 || my == DfClientHeight(wnd)+1)
142 /* --- above or below the scroll bar --- */
143 return FALSE;
144 if (my == 1)
145 /* -------- top scroll button --------- */
146 return DfSendMessage(wnd, DFM_SCROLL, FALSE, 0);
147 if (my == DfClientHeight(wnd))
148 /* -------- bottom scroll button --------- */
149 return DfSendMessage(wnd, DFM_SCROLL, TRUE, 0);
150 /* ---------- in the scroll bar ----------- */
151 if (!DfVSliding && my-1 == wnd->VScrollBox) {
152 DFRECT rc;
153 DfVSliding = TRUE;
154 rc.lf = rc.rt = DfGetRight(wnd);
155 rc.tp = DfGetTop(wnd)+2;
156 rc.bt = DfGetBottom(wnd)-2;
157 return DfSendMessage(NULL, DFM_MOUSE_TRAVEL,
158 (DF_PARAM) &rc, 0);
159 }
160 if (my-1 < wnd->VScrollBox)
161 return DfSendMessage(wnd,DFM_SCROLLPAGE,FALSE,0);
162 if (my-1 > wnd->VScrollBox)
163 return DfSendMessage(wnd,DFM_SCROLLPAGE,TRUE,0);
164 }
165 if (DfTestAttribute(wnd, DF_HSCROLLBAR) &&
166 my == DfWindowHeight(wnd)-1) {
167 /* -------- in the bottom border ------- */
168 if (mx == 0 || my == DfClientWidth(wnd)+1)
169 /* ------ outside the scroll bar ---- */
170 return FALSE;
171 if (mx == 1)
172 return DfSendMessage(wnd, DFM_HORIZSCROLL,FALSE,0);
173 if (mx == DfWindowWidth(wnd)-2)
174 return DfSendMessage(wnd, DFM_HORIZSCROLL,TRUE,0);
175 if (!DfHSliding && mx-1 == wnd->HScrollBox) {
176 /* --- hit the scroll box --- */
177 DFRECT rc;
178 rc.lf = DfGetLeft(wnd)+2;
179 rc.rt = DfGetRight(wnd)-2;
180 rc.tp = rc.bt = DfGetBottom(wnd);
181 /* - keep the mouse in the scroll bar - */
182 DfSendMessage(NULL,DFM_MOUSE_TRAVEL,(DF_PARAM)&rc,0);
183 DfHSliding = TRUE;
184 return TRUE;
185 }
186 if (mx-1 < wnd->HScrollBox)
187 return DfSendMessage(wnd,DFM_HORIZPAGE,FALSE,0);
188 if (mx-1 > wnd->HScrollBox)
189 return DfSendMessage(wnd,DFM_HORIZPAGE,TRUE,0);
190 }
191 return FALSE;
192 }
193
194 /* ------------ MOUSE_MOVED Message -------------- */
195 static BOOL MouseMovedMsg(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
196 {
197 int mx = (int) p1 - DfGetLeft(wnd);
198 int my = (int) p2 - DfGetTop(wnd);
199 if (DfVSliding) {
200 /* ---- dragging the vertical scroll box --- */
201 if (my-1 != wnd->VScrollBox) {
202 DfForeground = DfFrameForeground(wnd);
203 DfBackground = DfFrameBackground(wnd);
204 DfWPutch(wnd, DF_SCROLLBARCHAR, DfWindowWidth(wnd)-1,
205 wnd->VScrollBox+1);
206 wnd->VScrollBox = my-1;
207 DfWPutch(wnd, DF_SCROLLBOXCHAR, DfWindowWidth(wnd)-1,
208 my);
209 }
210 return TRUE;
211 }
212 if (DfHSliding) {
213 /* --- dragging the horizontal scroll box --- */
214 if (mx-1 != wnd->HScrollBox) {
215 DfForeground = DfFrameForeground(wnd);
216 DfBackground = DfFrameBackground(wnd);
217 DfWPutch(wnd, DF_SCROLLBARCHAR, wnd->HScrollBox+1,
218 DfWindowHeight(wnd)-1);
219 wnd->HScrollBox = mx-1;
220 DfWPutch(wnd, DF_SCROLLBOXCHAR, mx, DfWindowHeight(wnd)-1);
221 }
222 return TRUE;
223 }
224 return FALSE;
225 }
226
227 /* ------------ BUTTON_RELEASED Message -------------- */
228 static void ButtonReleasedMsg(DFWINDOW wnd)
229 {
230 if (DfHSliding || DfVSliding) {
231 /* release the mouse ouside the scroll bar */
232 DfSendMessage(NULL, DFM_MOUSE_TRAVEL, 0, 0);
233 DfVSliding ? ComputeWindowTop(wnd):ComputeWindowLeft(wnd);
234 DfSendMessage(wnd, DFM_PAINT, 0, 0);
235 DfSendMessage(wnd, DFM_KEYBOARD_CURSOR, 0, 0);
236 DfVSliding = DfHSliding = FALSE;
237 }
238 }
239
240 /* ------------ DFM_SCROLL Message -------------- */
241 static BOOL ScrollMsg(DFWINDOW wnd, DF_PARAM p1)
242 {
243 /* ---- vertical scroll one line ---- */
244 if (p1) {
245 /* ----- scroll one line up ----- */
246 if (wnd->wtop+DfClientHeight(wnd) >= wnd->wlines)
247 return FALSE;
248 wnd->wtop++;
249 }
250 else {
251 /* ----- scroll one line down ----- */
252 if (wnd->wtop == 0)
253 return FALSE;
254 --wnd->wtop;
255 }
256 if (DfIsVisible(wnd)) {
257 DFRECT rc;
258 rc = DfClipRectangle(wnd, DfClientRect(wnd));
259 if (DfValidRect(rc)) {
260 /* ---- scroll the window ----- */
261 if (wnd != DfInFocus)
262 DfSendMessage(wnd, DFM_PAINT, 0, 0);
263 else {
264 DfScrollWindow(wnd, rc, (int)p1);
265 if (!(int)p1)
266 /* -- write top line (down) -- */
267 DfWriteTextLine(wnd,NULL,wnd->wtop,FALSE);
268 else {
269 /* -- write bottom line (up) -- */
270 int y=DfRectBottom(rc)-DfGetClientTop(wnd);
271 DfWriteTextLine(wnd, NULL,
272 wnd->wtop+y, FALSE);
273 }
274 }
275 }
276 /* ---- reset the scroll box ---- */
277 if (DfTestAttribute(wnd, DF_VSCROLLBAR)) {
278 int vscrollbox = ComputeVScrollBox(wnd);
279 if (vscrollbox != wnd->VScrollBox)
280 MoveScrollBox(wnd, vscrollbox);
281 }
282 }
283 return TRUE;
284 }
285
286 /* ------------ DFM_HORIZSCROLL Message -------------- */
287 static BOOL HorizScrollMsg(DFWINDOW wnd, DF_PARAM p1)
288 {
289 /* --- horizontal scroll one column --- */
290 if (p1) {
291 /* --- scroll left --- */
292 if (wnd->wleft + DfClientWidth(wnd)-1 >= wnd->textwidth)
293 return FALSE;
294 wnd->wleft++;
295 }
296 else {
297 /* --- scroll right --- */
298 if (wnd->wleft == 0)
299 return FALSE;
300 --wnd->wleft;
301 }
302 DfSendMessage(wnd, DFM_PAINT, 0, 0);
303 return TRUE;
304 }
305
306 /* ------------ DFM_SCROLLPAGE Message -------------- */
307 static void ScrollPageMsg(DFWINDOW wnd, DF_PARAM p1)
308 {
309 /* --- vertical scroll one page --- */
310 if ((int) p1 == FALSE) {
311 /* ---- page up ---- */
312 if (wnd->wtop)
313 wnd->wtop -= DfClientHeight(wnd);
314 }
315 else {
316 /* ---- page down ---- */
317 if (wnd->wtop+DfClientHeight(wnd) < wnd->wlines) {
318 wnd->wtop += DfClientHeight(wnd);
319 if (wnd->wtop>wnd->wlines-DfClientHeight(wnd))
320 wnd->wtop=wnd->wlines-DfClientHeight(wnd);
321 }
322 }
323 if (wnd->wtop < 0)
324 wnd->wtop = 0;
325 DfSendMessage(wnd, DFM_PAINT, 0, 0);
326 }
327
328 /* ------------ HORIZSCROLLPAGE Message -------------- */
329 static void HorizScrollPageMsg(DFWINDOW wnd, DF_PARAM p1)
330 {
331 /* --- horizontal scroll one page --- */
332 if ((int) p1 == FALSE)
333 /* ---- page left ----- */
334 wnd->wleft -= DfClientWidth(wnd);
335 else {
336 /* ---- page right ----- */
337 wnd->wleft += DfClientWidth(wnd);
338 if (wnd->wleft > wnd->textwidth-DfClientWidth(wnd))
339 wnd->wleft = wnd->textwidth-DfClientWidth(wnd);
340 }
341 if (wnd->wleft < 0)
342 wnd->wleft = 0;
343 DfSendMessage(wnd, DFM_PAINT, 0, 0);
344 }
345
346 /* ------------ DFM_SCROLLDOC Message -------------- */
347 static void ScrollDocMsg(DFWINDOW wnd, DF_PARAM p1)
348 {
349 /* --- scroll to beginning or end of document --- */
350 if ((int) p1)
351 wnd->wtop = wnd->wleft = 0;
352 else if (wnd->wtop+DfClientHeight(wnd) < wnd->wlines){
353 wnd->wtop = wnd->wlines-DfClientHeight(wnd);
354 wnd->wleft = 0;
355 }
356 DfSendMessage(wnd, DFM_PAINT, 0, 0);
357 }
358
359 /* ------------ DFM_PAINT Message -------------- */
360 static void PaintMsg(DFWINDOW wnd, DF_PARAM p1, DF_PARAM p2)
361 {
362 /* ------ paint the client area ----- */
363 DFRECT rc, rcc;
364 int y;
365 char blankline[201];
366
367 /* ----- build the rectangle to paint ----- */
368 if ((DFRECT *)p1 == NULL)
369 rc=DfRelativeWindowRect(wnd, DfWindowRect(wnd));
370 else
371 rc= *(DFRECT *)p1;
372 if (DfTestAttribute(wnd, DF_HASBORDER) &&
373 DfRectRight(rc) >= DfWindowWidth(wnd)-1) {
374 if (DfRectLeft(rc) >= DfWindowWidth(wnd)-1)
375 return;
376 DfRectRight(rc) = DfWindowWidth(wnd)-2;
377 }
378 rcc = DfAdjustRectangle(wnd, rc);
379
380 if (!p2 && wnd != DfInFocus)
381 DfClipString++;
382
383 /* ----- blank line for padding ----- */
384 memset(blankline, ' ', DfGetScreenWidth());
385 blankline[DfRectRight(rcc)+1] = '\0';
386
387 /* ------- each line DfWithin rectangle ------ */
388 for (y = DfRectTop(rc); y <= DfRectBottom(rc); y++){
389 int yy;
390 /* ---- test outside of Client area ---- */
391 if (DfTestAttribute(wnd,
392 DF_HASBORDER | DF_HASTITLEBAR)) {
393 if (y < DfTopBorderAdj(wnd))
394 continue;
395 if (y > DfWindowHeight(wnd)-2)
396 continue;
397 }
398 yy = y-DfTopBorderAdj(wnd);
399 if (yy < wnd->wlines-wnd->wtop)
400 /* ---- paint a text line ---- */
401 DfWriteTextLine(wnd, &rc,
402 yy+wnd->wtop, FALSE);
403 else {
404 /* ---- paint a blank line ---- */
405 DfSetStandardColor(wnd);
406 DfWriteLine(wnd, blankline+DfRectLeft(rcc),
407 DfRectLeft(rcc)+DfBorderAdj(wnd), y, FALSE);
408 }
409 }
410 /* ------- position the scroll box ------- */
411 if (DfTestAttribute(wnd, DF_VSCROLLBAR|DF_HSCROLLBAR)) {
412 int hscrollbox = ComputeHScrollBox(wnd);
413 int vscrollbox = ComputeVScrollBox(wnd);
414 if (hscrollbox != wnd->HScrollBox ||
415 vscrollbox != wnd->VScrollBox) {
416 wnd->HScrollBox = hscrollbox;
417 wnd->VScrollBox = vscrollbox;
418 DfSendMessage(wnd, DFM_BORDER, p1, 0);
419 }
420 }
421 if (!p2 && wnd != DfInFocus)
422 --DfClipString;
423 }
424
425 /* ------------ DFM_CLOSE_WINDOW Message -------------- */
426 static void CloseWindowMsg(DFWINDOW wnd)
427 {
428 DfSendMessage(wnd, DFM_CLEARTEXT, 0, 0);
429 if (wnd->TextPointers != NULL) {
430 free(wnd->TextPointers);
431 wnd->TextPointers = NULL;
432 }
433 }
434
435 /* ----------- DF_TEXTBOX Message-processing Module ----------- */
436 int DfTextBoxProc(DFWINDOW wnd, DFMESSAGE msg, DF_PARAM p1, DF_PARAM p2)
437 {
438 switch (msg) {
439 case DFM_CREATE_WINDOW:
440 wnd->HScrollBox = wnd->VScrollBox = 1;
441 DfClearTextPointers(wnd);
442 break;
443 case DFM_ADDTEXT:
444 return AddTextMsg(wnd, (char *) p1);
445 case DFM_DELETETEXT:
446 DeleteTextMsg(wnd, (int) p1);
447 return TRUE;
448 case DFM_INSERTTEXT:
449 InsertTextMsg(wnd, (char *) p1, (int) p2);
450 return TRUE;
451 case DFM_SETTEXT:
452 SetTextMsg(wnd, (char *) p1);
453 return TRUE;
454 case DFM_CLEARTEXT:
455 ClearTextMsg(wnd);
456 break;
457 case DFM_KEYBOARD:
458 if (DfWindowMoving || DfWindowSizing)
459 break;
460 if (KeyboardMsg(wnd, p1))
461 return TRUE;
462 break;
463 case DFM_LEFT_BUTTON:
464 if (DfWindowSizing || DfWindowMoving)
465 return FALSE;
466 if (LeftButtonMsg(wnd, p1, p2))
467 return TRUE;
468 break;
469 case MOUSE_MOVED:
470 if (MouseMovedMsg(wnd, p1, p2))
471 return TRUE;
472 break;
473 case DFM_BUTTON_RELEASED:
474 ButtonReleasedMsg(wnd);
475 break;
476 case DFM_SCROLL:
477 return ScrollMsg(wnd, p1);
478 case DFM_HORIZSCROLL:
479 return HorizScrollMsg(wnd, p1);
480 case DFM_SCROLLPAGE:
481 ScrollPageMsg(wnd, p1);
482 return TRUE;
483 case DFM_HORIZPAGE:
484 HorizScrollPageMsg(wnd, p1);
485 return TRUE;
486 case DFM_SCROLLDOC:
487 ScrollDocMsg(wnd, p1);
488 return TRUE;
489 case DFM_PAINT:
490 if (DfIsVisible(wnd))
491 {
492 PaintMsg(wnd, p1, p2);
493 return FALSE;
494 }
495 break;
496 case DFM_CLOSE_WINDOW:
497 CloseWindowMsg(wnd);
498 break;
499 default:
500 break;
501 }
502 return DfBaseWndProc(DF_TEXTBOX, wnd, msg, p1, p2);
503 }
504
505 /* ------ compute the vertical scroll box position from
506 the text pointers --------- */
507 static int ComputeVScrollBox(DFWINDOW wnd)
508 {
509 int pagelen = wnd->wlines - DfClientHeight(wnd);
510 int barlen = DfClientHeight(wnd)-2;
511 int lines_tick;
512 int vscrollbox;
513
514 if (pagelen < 1 || barlen < 1)
515 vscrollbox = 1;
516 else {
517 if (pagelen > barlen)
518 lines_tick = pagelen / barlen;
519 else
520 lines_tick = barlen / pagelen;
521 vscrollbox = 1 + (wnd->wtop / lines_tick);
522 if (vscrollbox > DfClientHeight(wnd)-2 ||
523 wnd->wtop + DfClientHeight(wnd) >= wnd->wlines)
524 vscrollbox = DfClientHeight(wnd)-2;
525 }
526 return vscrollbox;
527 }
528
529 /* ---- compute top text line from scroll box position ---- */
530 static void ComputeWindowTop(DFWINDOW wnd)
531 {
532 int pagelen = wnd->wlines - DfClientHeight(wnd);
533 if (wnd->VScrollBox == 0)
534 wnd->wtop = 0;
535 else if (wnd->VScrollBox == DfClientHeight(wnd)-2)
536 wnd->wtop = pagelen;
537 else {
538 int barlen = DfClientHeight(wnd)-2;
539 int lines_tick;
540
541 if (pagelen > barlen)
542 lines_tick = barlen ? (pagelen / barlen) : 0;
543 else
544 lines_tick = pagelen ? (barlen / pagelen) : 0;
545 wnd->wtop = (wnd->VScrollBox-1) * lines_tick;
546 if (wnd->wtop + DfClientHeight(wnd) > wnd->wlines)
547 wnd->wtop = pagelen;
548 }
549 if (wnd->wtop < 0)
550 wnd->wtop = 0;
551 }
552
553 /* ------ compute the horizontal scroll box position from
554 the text pointers --------- */
555 static int ComputeHScrollBox(DFWINDOW wnd)
556 {
557 int pagewidth = wnd->textwidth - DfClientWidth(wnd);
558 int barlen = DfClientWidth(wnd)-2;
559 int chars_tick;
560 int hscrollbox;
561
562 if (pagewidth < 1 || barlen < 1)
563 hscrollbox = 1;
564 else {
565 if (pagewidth > barlen)
566 chars_tick = barlen ? (pagewidth / barlen) : 0;
567 else
568 chars_tick = pagewidth ? (barlen / pagewidth) : 0;
569 hscrollbox = 1 + (chars_tick ? (wnd->wleft / chars_tick) : 0);
570 if (hscrollbox > DfClientWidth(wnd)-2 ||
571 wnd->wleft + DfClientWidth(wnd) >= wnd->textwidth)
572 hscrollbox = DfClientWidth(wnd)-2;
573 }
574 return hscrollbox;
575 }
576
577 /* ---- compute left column from scroll box position ---- */
578 static void ComputeWindowLeft(DFWINDOW wnd)
579 {
580 int pagewidth = wnd->textwidth - DfClientWidth(wnd);
581
582 if (wnd->HScrollBox == 0)
583 wnd->wleft = 0;
584 else if (wnd->HScrollBox == DfClientWidth(wnd)-2)
585 wnd->wleft = pagewidth;
586 else {
587 int barlen = DfClientWidth(wnd)-2;
588 int chars_tick;
589
590 if (pagewidth > barlen)
591 chars_tick = pagewidth / barlen;
592 else
593 chars_tick = barlen / pagewidth;
594 wnd->wleft = (wnd->HScrollBox-1) * chars_tick;
595 if (wnd->wleft + DfClientWidth(wnd) > wnd->textwidth)
596 wnd->wleft = pagewidth;
597 }
598 if (wnd->wleft < 0)
599 wnd->wleft = 0;
600 }
601
602 /* ----- get the text to a specified line ----- */
603 static char *GetTextLine(DFWINDOW wnd, int selection)
604 {
605 char *line;
606 int len = 0;
607 char *cp, *cp1;
608 cp = cp1 = DfTextLine(wnd, selection);
609 while (*cp && *cp != '\n') {
610 len++;
611 cp++;
612 }
613 line = DfMalloc(len+7);
614 memmove(line, cp1, len);
615 line[len] = '\0';
616 return line;
617 }
618
619 /* ------- write a line of text to a textbox window ------- */
620 void DfWriteTextLine(DFWINDOW wnd, DFRECT *rcc, int y, BOOL reverse)
621 {
622 int len = 0;
623 int dif = 0;
624 char line[200];
625 DFRECT rc;
626 char *lp, *svlp;
627 int lnlen;
628 int i;
629 BOOL trunc = FALSE;
630
631 /* ------ make sure y is inside the window ----- */
632 if (y < wnd->wtop || y >= wnd->wtop+DfClientHeight(wnd))
633 return;
634
635 /* ---- build the retangle DfWithin which can write ---- */
636 if (rcc == NULL) {
637 rc = DfRelativeWindowRect(wnd, DfWindowRect(wnd));
638 if (DfTestAttribute(wnd, DF_HASBORDER) &&
639 DfRectRight(rc) >= DfWindowWidth(wnd)-1)
640 DfRectRight(rc) = DfWindowWidth(wnd)-2;
641 }
642 else
643 rc = *rcc;
644
645 /* ----- make sure rectangle is DfWithin window ------ */
646 if (DfRectLeft(rc) >= DfWindowWidth(wnd)-1)
647 return;
648 if (DfRectRight(rc) == 0)
649 return;
650 rc = DfAdjustRectangle(wnd, rc);
651 if (y-wnd->wtop<DfRectTop(rc) || y-wnd->wtop>DfRectBottom(rc))
652 return;
653
654 /* --- get the text and length of the text line --- */
655 lp = svlp = GetTextLine(wnd, y);
656 if (svlp == NULL)
657 return;
658 lnlen = DfLineLength(lp);
659
660 /* -------- insert block DfColor change controls ------- */
661 if (DfTextBlockMarked(wnd)) {
662 int bbl = wnd->BlkBegLine;
663 int bel = wnd->BlkEndLine;
664 int bbc = wnd->BlkBegCol;
665 int bec = wnd->BlkEndCol;
666 int by = y;
667
668 /* ----- put lowest marker first ----- */
669 if (bbl > bel) {
670 swap(bbl, bel);
671 swap(bbc, bec);
672 }
673 if (bbl == bel && bbc > bec)
674 swap(bbc, bec);
675
676 if (by >= bbl && by <= bel) {
677 /* ------ the block includes this line ----- */
678 int blkbeg = 0;
679 int blkend = lnlen;
680 if (!(by > bbl && by < bel)) {
681 /* --- the entire line is not in the block -- */
682 if (by == bbl)
683 /* ---- the block begins on this line --- */
684 blkbeg = bbc;
685 if (by == bel)
686 /* ---- the block ends on this line ---- */
687 blkend = bec;
688 }
689 if (blkend == 0 && lnlen == 0) {
690 strcpy(lp, " ");
691 blkend++;
692 }
693 /* ----- insert the reset DfColor token ----- */
694 memmove(lp+blkend+1,lp+blkend,strlen(lp+blkend)+1);
695 lp[blkend] = DF_RESETCOLOR;
696 /* ----- insert the change DfColor token ----- */
697 memmove(lp+blkbeg+3,lp+blkbeg,strlen(lp+blkbeg)+1);
698 lp[blkbeg] = DF_CHANGECOLOR;
699 /* ----- insert the DfColor tokens ----- */
700 DfSetReverseColor(wnd);
701 lp[blkbeg+1] = DfForeground | 0x80;
702 lp[blkbeg+2] = DfBackground | 0x80;
703 lnlen += 4;
704 }
705 }
706 /* - make sure left margin doesn't overlap DfColor change - */
707 for (i = 0; i < wnd->wleft+3; i++) {
708 if (*(lp+i) == '\0')
709 break;
710 if (*(lp + i) == DF_RESETCOLOR)
711 break;
712 }
713 if (*(lp+i) && i < wnd->wleft+3) {
714 if (wnd->wleft+4 > lnlen)
715 trunc = TRUE;
716 else
717 lp += 4;
718 }
719 else {
720 /* --- it does, shift the DfColor change over --- */
721 for (i = 0; i < wnd->wleft; i++) {
722 if (*(lp+i) == '\0')
723 break;
724 if (*(lp + i) == DF_CHANGECOLOR) {
725 *(lp+wnd->wleft+2) = *(lp+i+2);
726 *(lp+wnd->wleft+1) = *(lp+i+1);
727 *(lp+wnd->wleft) = *(lp+i);
728 break;
729 }
730 }
731 }
732 /* ------ build the line to display -------- */
733 if (!trunc) {
734 if (lnlen < wnd->wleft)
735 lnlen = 0;
736 else
737 lp += wnd->wleft;
738 if (lnlen > DfRectLeft(rc)) {
739 /* ---- the line exceeds the rectangle ---- */
740 int ct = DfRectLeft(rc);
741 char *initlp = lp;
742 /* --- point to end of clipped line --- */
743 while (ct) {
744 if (*lp == DF_CHANGECOLOR)
745 lp += 3;
746 else if (*lp == DF_RESETCOLOR)
747 lp++;
748 else
749 lp++, --ct;
750 }
751 if (DfRectLeft(rc)) {
752 char *lpp = lp;
753 while (*lpp) {
754 if (*lpp==DF_CHANGECOLOR)
755 break;
756 if (*lpp==DF_RESETCOLOR) {
757 lpp = lp;
758 while (lpp >= initlp) {
759 if (*lpp == DF_CHANGECOLOR) {
760 lp -= 3;
761 memmove(lp,lpp,3);
762 break;
763 }
764 --lpp;
765 }
766 break;
767 }
768 lpp++;
769 }
770 }
771 lnlen = DfLineLength(lp);
772 len = min(lnlen, DfRectWidth(rc));
773 dif = strlen(lp) - lnlen;
774 len += dif;
775 if (len > 0)
776 strncpy(line, lp, len);
777 }
778 }
779 /* -------- pad the line --------- */
780 while (len < DfRectWidth(rc)+dif)
781 line[len++] = ' ';
782 line[len] = '\0';
783 dif = 0;
784 /* ------ establish the line's main DfColor ----- */
785 if (reverse) {
786 char *cp = line;
787 DfSetReverseColor(wnd);
788 while ((cp = strchr(cp, DF_CHANGECOLOR)) != NULL) {
789 cp += 2;
790 *cp++ = DfBackground | 0x80;
791 }
792 if (*line == DF_CHANGECOLOR)
793 dif = 3;
794 }
795 else
796 DfSetStandardColor(wnd);
797 /* ------- display the line -------- */
798 DfWriteLine(wnd, line+dif,
799 DfRectLeft(rc)+DfBorderAdj(wnd),
800 y-wnd->wtop+DfTopBorderAdj(wnd), FALSE);
801 free(svlp);
802 }
803
804 void DfMarkTextBlock(DFWINDOW wnd, int BegLine, int BegCol,
805 int EndLine, int EndCol)
806 {
807 wnd->BlkBegLine = BegLine;
808 wnd->BlkEndLine = EndLine;
809 wnd->BlkBegCol = BegCol;
810 wnd->BlkEndCol = EndCol;
811 }
812
813 /* ----- clear and initialize text line pointer array ----- */
814 void DfClearTextPointers(DFWINDOW wnd)
815 {
816 wnd->TextPointers = DfRealloc(wnd->TextPointers, sizeof(int));
817 *(wnd->TextPointers) = 0;
818 }
819
820 #define INITLINES 100
821
822 /* ---- build array of pointers to text lines ---- */
823 void DfBuildTextPointers(DFWINDOW wnd)
824 {
825 char *cp = wnd->text, *cp1;
826 int incrs = INITLINES;
827 unsigned int off;
828 wnd->textwidth = wnd->wlines = 0;
829 while (*cp) {
830 if (incrs == INITLINES) {
831 incrs = 0;
832 wnd->TextPointers = DfRealloc(wnd->TextPointers,
833 (wnd->wlines + INITLINES) * sizeof(int));
834 }
835 off = (unsigned int) ((unsigned int)cp - (unsigned int)wnd->text);
836 *((wnd->TextPointers) + wnd->wlines) = off;
837 wnd->wlines++;
838 incrs++;
839 cp1 = cp;
840 while (*cp && *cp != '\n')
841 cp++;
842 wnd->textwidth = max(wnd->textwidth, (int)(cp - cp1));
843 if (*cp)
844 cp++;
845 }
846 }
847
848 static void MoveScrollBox(DFWINDOW wnd, int vscrollbox)
849 {
850 DfForeground = DfFrameForeground(wnd);
851 DfBackground = DfFrameBackground(wnd);
852 DfWPutch(wnd, DF_SCROLLBARCHAR, DfWindowWidth(wnd)-1,
853 wnd->VScrollBox+1);
854 DfWPutch(wnd, DF_SCROLLBOXCHAR, DfWindowWidth(wnd)-1,
855 vscrollbox+1);
856 wnd->VScrollBox = vscrollbox;
857 }
858
859 int DfTextLineNumber(DFWINDOW wnd, char *lp)
860 {
861 int lineno;
862 char *cp;
863 for (lineno = 0; lineno < wnd->wlines; lineno++) {
864 cp = wnd->text + *((wnd->TextPointers) + lineno);
865 if (cp == lp)
866 return lineno;
867 if (cp > lp)
868 break;
869 }
870 return lineno-1;
871 }
872
873 /* EOF */