1 /* TN5250
2  * Copyright (C) 1997-2008 Michael Madore
3  *
4  * This file is part of TN5250.
5  *
6  * TN5250 is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1, or (at your option)
9  * any later version.
10  *
11  * TN5250 is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this software; see the file COPYING.  If not, write to
18  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
19  * Boston, MA 02111-1307 USA
20  *
21  */
22 #include "tn5250-private.h"
23 
24 #ifdef NDEBUG
25 #define ASSERT_VALID(This)
26 #else
27 #define ASSERT_VALID(This) \
28    { \
29       TN5250_ASSERT ((This) != NULL); \
30       TN5250_ASSERT ((This)->cy >= 0); \
31       TN5250_ASSERT ((This)->cx >= 0); \
32       TN5250_ASSERT ((This)->cy < (This)->h); \
33       TN5250_ASSERT ((This)->cx < (This)->w); \
34    }
35 #endif
36 
37 
38 /****f* lib5250/tn5250_dbuffer_new
39  * NAME
40  *    tn5250_dbuffer_new
41  * SYNOPSIS
42  *    ret = tn5250_dbuffer_new (width, height);
43  * INPUTS
44  *    int                  width      -
45  *    int                  height     -
46  * DESCRIPTION
47  *    Allocates a new display buffer.
48  *****/
49 Tn5250DBuffer *
tn5250_dbuffer_new(int width,int height)50 tn5250_dbuffer_new (int width, int height)
51 {
52   Tn5250DBuffer *This = tn5250_new (Tn5250DBuffer, 1);
53 
54   if (This == NULL)
55     {
56       return NULL;
57     }
58 
59   This->w = width;
60   This->h = height;
61   This->cx = This->cy = 0;
62   This->tcx = This->tcy = 0;
63   This->next = This->prev = NULL;
64 
65   This->field_count = 0;
66   This->entry_field_count = 0;
67   This->window_count = 0;
68   This->scrollbar_count = 0;
69   This->menubar_count = 0;
70   This->field_list = NULL;
71   This->window_list = NULL;
72   This->scrollbar_list = NULL;
73   This->menubar_list = NULL;
74   This->master_mdt = 0;
75   This->header_data = NULL;
76   This->header_length = 0;
77 
78   This->script_slot = NULL;
79 
80   This->data = tn5250_new (unsigned char, width * height);
81   if (This->data == NULL)
82     {
83       free (This);
84       return NULL;
85     }
86 
87   tn5250_dbuffer_clear (This);
88   return This;
89 }
90 
91 
92 /****f* lib5250/tn5250_dbuffer_copy
93  * NAME
94  *    tn5250_dbuffer_copy
95  * SYNOPSIS
96  *    ret = tn5250_dbuffer_copy (dsp);
97  * INPUTS
98  *    Tn5250DBuffer *      dsp        -
99  * DESCRIPTION
100  *    Allocates a new display buffer and copies the contents of the old
101  *    one.
102  *****/
103 Tn5250DBuffer *
tn5250_dbuffer_copy(Tn5250DBuffer * dsp)104 tn5250_dbuffer_copy (Tn5250DBuffer * dsp)
105 {
106   Tn5250DBuffer *This = tn5250_new (Tn5250DBuffer, 1);
107 
108   if (This == NULL)
109     {
110       return NULL;
111     }
112 
113   ASSERT_VALID (dsp);
114 
115   This->w = dsp->w;
116   This->h = dsp->h;
117   This->cx = dsp->cx;
118   This->cy = dsp->cy;
119   This->tcx = dsp->tcx;
120   This->tcy = dsp->tcy;
121   This->data = tn5250_new (unsigned char, dsp->w * dsp->h);
122   if (This->data == NULL)
123     {
124       free (This);
125       return NULL;
126     }
127   memcpy (This->data, dsp->data, dsp->w * dsp->h);
128 
129   This->field_list = tn5250_field_list_copy (dsp->field_list);
130   This->window_list = tn5250_window_list_copy (dsp->window_list);
131   This->header_length = dsp->header_length;
132   if (dsp->header_data != NULL)
133     {
134       This->header_data = (unsigned char *) malloc (This->header_length);
135       memcpy (This->header_data, dsp->header_data, dsp->header_length);
136     }
137   else
138     {
139       This->header_data = NULL;
140     }
141 
142   ASSERT_VALID (This);
143   return This;
144 }
145 
146 
147 /****f* lib5250/tn5250_dbuffer_destroy
148  * NAME
149  *    tn5250_dbuffer_destroy
150  * SYNOPSIS
151  *    tn5250_dbuffer_destroy (This);
152  * INPUTS
153  *    Tn5250DBuffer *      This       -
154  * DESCRIPTION
155  *    Free a display buffer and destroy all sub-structures.
156  *****/
157 void
tn5250_dbuffer_destroy(Tn5250DBuffer * This)158 tn5250_dbuffer_destroy (Tn5250DBuffer * This)
159 {
160   free (This->data);
161   if (This->header_data != NULL)
162     {
163       free (This->header_data);
164     }
165   (void) tn5250_field_list_destroy (This->field_list);
166   (void) tn5250_window_list_destroy (This->window_list);
167   free (This);
168   return;
169 }
170 
171 
172 /****f* lib5250/tn5250_dbuffer_set_header_data
173  * NAME
174  *    tn5250_dbuffer_set_header_data
175  * SYNOPSIS
176  *    tn5250_dbuffer_set_header_data (This, data, len);
177  * INPUTS
178  *    Tn5250DBuffer *      This       -
179  *    unsigned char *      data       -
180  *    int                  len        -
181  * DESCRIPTION
182  *    Set the format table header data.
183  *****/
184 void
tn5250_dbuffer_set_header_data(Tn5250DBuffer * This,unsigned char * data,int len)185 tn5250_dbuffer_set_header_data (Tn5250DBuffer * This, unsigned char *data,
186 				int len)
187 {
188   if (This->header_data != NULL)
189     {
190       free (This->header_data);
191     }
192   This->header_length = len;
193   if (data != NULL)
194     {
195       TN5250_ASSERT (len > 0);
196       This->header_data = (unsigned char *) malloc (len);
197       memcpy (This->header_data, data, len);
198     }
199   return;
200 }
201 
202 
203 /****f* lib5250/tn5250_dbuffer_send_data_for_aid_key
204  * NAME
205  *    tn5250_dbuffer_send_data_for_aid_key
206  * SYNOPSIS
207  *    ret = tn5250_dbuffer_send_data_for_aid_key (This, k);
208  * INPUTS
209  *    Tn5250DBuffer *      This       -
210  *    int                  k          -
211  * DESCRIPTION
212  *    Determine, according to the format table header, if we should send
213  *    data for this aid key.
214  *****/
215 int
tn5250_dbuffer_send_data_for_aid_key(Tn5250DBuffer * This,int k)216 tn5250_dbuffer_send_data_for_aid_key (Tn5250DBuffer * This, int k)
217 {
218   int byte, bit, result;
219 
220   if (This->header_data == NULL || This->header_length <= 6)
221     {
222       result = 1;
223       TN5250_LOG (("tn5250_dbuffer_send_data_for_aid_key: no format table header or key mask.\n"));
224       goto send_data_done;
225     }
226 
227 #ifndef NDEBUG
228   TN5250_LOG (("tn5250_dbuffer_send_data_for_aid_key: format table header = \n"));
229   for (byte = 0; byte < This->header_length; byte++)
230     {
231       TN5250_LOG (("0x%02X ", This->header_data[byte]));
232     }
233   TN5250_LOG (("\n"));
234 #endif
235 
236   switch (k)
237     {
238     case TN5250_SESSION_AID_F1:
239       byte = 6;
240       bit = 7;
241       break;
242     case TN5250_SESSION_AID_F2:
243       byte = 6;
244       bit = 6;
245       break;
246     case TN5250_SESSION_AID_F3:
247       byte = 6;
248       bit = 5;
249       break;
250     case TN5250_SESSION_AID_F4:
251       byte = 6;
252       bit = 4;
253       break;
254     case TN5250_SESSION_AID_F5:
255       byte = 6;
256       bit = 3;
257       break;
258     case TN5250_SESSION_AID_F6:
259       byte = 6;
260       bit = 2;
261       break;
262     case TN5250_SESSION_AID_F7:
263       byte = 6;
264       bit = 1;
265       break;
266     case TN5250_SESSION_AID_F8:
267       byte = 6;
268       bit = 0;
269       break;
270     case TN5250_SESSION_AID_F9:
271       byte = 5;
272       bit = 7;
273       break;
274     case TN5250_SESSION_AID_F10:
275       byte = 5;
276       bit = 6;
277       break;
278     case TN5250_SESSION_AID_F11:
279       byte = 5;
280       bit = 5;
281       break;
282     case TN5250_SESSION_AID_F12:
283       byte = 5;
284       bit = 4;
285       break;
286     case TN5250_SESSION_AID_F13:
287       byte = 5;
288       bit = 3;
289       break;
290     case TN5250_SESSION_AID_F14:
291       byte = 5;
292       bit = 2;
293       break;
294     case TN5250_SESSION_AID_F15:
295       byte = 5;
296       bit = 1;
297       break;
298     case TN5250_SESSION_AID_F16:
299       byte = 5;
300       bit = 0;
301       break;
302     case TN5250_SESSION_AID_F17:
303       byte = 4;
304       bit = 7;
305       break;
306     case TN5250_SESSION_AID_F18:
307       byte = 4;
308       bit = 6;
309       break;
310     case TN5250_SESSION_AID_F19:
311       byte = 4;
312       bit = 5;
313       break;
314     case TN5250_SESSION_AID_F20:
315       byte = 4;
316       bit = 4;
317       break;
318     case TN5250_SESSION_AID_F21:
319       byte = 4;
320       bit = 3;
321       break;
322     case TN5250_SESSION_AID_F22:
323       byte = 4;
324       bit = 2;
325       break;
326     case TN5250_SESSION_AID_F23:
327       byte = 4;
328       bit = 1;
329       break;
330     case TN5250_SESSION_AID_F24:
331       byte = 4;
332       bit = 0;
333       break;
334     default:
335       result = 1;
336       goto send_data_done;
337     }
338 
339   result = ((This->header_data[byte] & (0x80 >> bit)) == 0);
340 send_data_done:
341   TN5250_LOG (("tn5250_dbuffer_send_data_for_aid_key() = %d\n", result));
342   return result;
343 }
344 
345 
346 /****f* lib5250/tn5250_dbuffer_field_data
347  * NAME
348  *    tn5250_dbuffer_field_data
349  * SYNOPSIS
350  *    ret = tn5250_dbuffer_field_data (This, field);
351  * INPUTS
352  *    Tn5250DBuffer *      This       -
353  *    Tn5250Field *        field      -
354  * DESCRIPTION
355  *    Return a pointer into the display buffer data where the specified
356  *    field begins.
357  *****/
358 unsigned char *
tn5250_dbuffer_field_data(Tn5250DBuffer * This,Tn5250Field * field)359 tn5250_dbuffer_field_data (Tn5250DBuffer * This, Tn5250Field * field)
360 {
361   return &This->data[field->start_row * This->w + field->start_col];
362 }
363 
364 
365 /****f* lib5250/tn5250_dbuffer_set_size
366  * NAME
367  *    tn5250_dbuffer_set_size
368  * SYNOPSIS
369  *    tn5250_dbuffer_set_size (This, rows, cols);
370  * INPUTS
371  *    Tn5250DBuffer *      This       -
372  *    int                  rows       -
373  *    int                  cols       -
374  * DESCRIPTION
375  *    Resize the display (say, to 132 columns ;)
376  *****/
377 void
tn5250_dbuffer_set_size(Tn5250DBuffer * This,int rows,int cols)378 tn5250_dbuffer_set_size (Tn5250DBuffer * This, int rows, int cols)
379 {
380   This->w = cols;
381   This->h = rows;
382 
383   free (This->data);
384   This->data = tn5250_new (unsigned char, rows * cols);
385   TN5250_ASSERT (This->data != NULL);
386 
387   tn5250_dbuffer_clear (This);
388   return;
389 }
390 
391 
392 /****f* lib5250/tn5250_dbuffer_cursor_set
393  * NAME
394  *    tn5250_dbuffer_cursor_set
395  * SYNOPSIS
396  *    tn5250_dbuffer_cursor_set (This, y, x);
397  * INPUTS
398  *    Tn5250DBuffer *      This       -
399  *    int                  y          -
400  *    int                  x          -
401  * DESCRIPTION
402  *    DOCUMENT ME!!!
403  *****/
404 void
tn5250_dbuffer_cursor_set(Tn5250DBuffer * This,int y,int x)405 tn5250_dbuffer_cursor_set (Tn5250DBuffer * This, int y, int x)
406 {
407   This->cy = y;
408   This->cx = x;
409 
410   TN5250_LOG (("This->cy = %d, This->cx = %d\n", This->cy, This->cx));
411 
412   ASSERT_VALID (This);
413   return;
414 }
415 
416 
417 /****f* lib5250/tn5250_dbuffer_clear
418  * NAME
419  *    tn5250_dbuffer_clear
420  * SYNOPSIS
421  *    tn5250_dbuffer_clear (This);
422  * INPUTS
423  *    Tn5250DBuffer *      This       -
424  * DESCRIPTION
425  *    DOCUMENT ME!!!
426  *****/
427 void
tn5250_dbuffer_clear(Tn5250DBuffer * This)428 tn5250_dbuffer_clear (Tn5250DBuffer * This)
429 {
430   memset (This->data, 0, This->w * This->h);
431   This->cx = This->cy = 0;
432   tn5250_dbuffer_clear_table (This);
433   return;
434 }
435 
436 
437 /****f* lib5250/tn5250_dbuffer_add_field
438  * NAME
439  *    tn5250_dbuffer_add_field
440  * SYNOPSIS
441  *    tn5250_dbuffer_add_field (This, field);
442  * INPUTS
443  *    Tn5250DBuffer *      This       -
444  *    Tn5250Field *        field      -
445  * DESCRIPTION
446  *    DOCUMENT ME!!!
447  *****/
448 void
tn5250_dbuffer_add_field(Tn5250DBuffer * This,Tn5250Field * field)449 tn5250_dbuffer_add_field (Tn5250DBuffer * This, Tn5250Field * field)
450 {
451   field->id = This->field_count++;
452   field->table = This;
453   This->field_list = tn5250_field_list_add (This->field_list, field);
454 
455   if ((!tn5250_field_is_continued_middle (field))
456       && (!tn5250_field_is_continued_last (field)))
457     {
458       This->entry_field_count++;
459     }
460   field->entry_id = This->entry_field_count;
461 
462   TN5250_LOG (("adding field: field->id: %d, field->entry_id: %d\n",
463 	       field->id, field->entry_id));
464   return;
465 }
466 
467 
468 /****f* lib5250/tn5250_dbuffer_clear_table
469  * NAME
470  *    tn5250_dbuffer_clear_table
471  * SYNOPSIS
472  *    tn5250_dbuffer_clear_table (This);
473  * INPUTS
474  *    Tn5250DBuffer *      This       -
475  * DESCRIPTION
476  *    DOCUMENT ME!!!
477  *****/
478 void
tn5250_dbuffer_clear_table(Tn5250DBuffer * This)479 tn5250_dbuffer_clear_table (Tn5250DBuffer * This)
480 {
481   TN5250_LOG (("tn5250_dbuffer_clear_table() entered.\n"));
482   This->field_list = tn5250_field_list_destroy (This->field_list);
483   /* Comment this for now since the table is cleared just after we have
484    * received a Create Window Structured Field command.  We don't really
485    * want to blow away our newly created window.
486    * FIXME
487    */
488   /*
489      This->window_list = tn5250_window_list_destroy (This->window_list);
490      This->scrollbar_list = tn5250_scrollbar_list_destroy (This->scrollbar_list);
491    */
492   This->field_count = 0;
493   This->entry_field_count = 0;
494   /*
495      This->window_count = 0;
496      This->scrollbar_count = 0;
497    */
498   This->master_mdt = 0;
499   This->header_length = 0;
500   if (This->header_data != NULL)
501     {
502       free (This->header_data);
503       This->header_data = NULL;
504     }
505   return;
506 }
507 
508 
509 /****f* lib5250/tn5250_dbuffer_field_yx
510  * NAME
511  *    tn5250_dbuffer_field_yx
512  * SYNOPSIS
513  *    ret = tn5250_dbuffer_field_yx (This, y, x);
514  * INPUTS
515  *    Tn5250DBuffer *      This       -
516  *    int                  y          -
517  *    int                  x          -
518  * DESCRIPTION
519  *    DOCUMENT ME!!!
520  *****/
521 Tn5250Field *
tn5250_dbuffer_field_yx(Tn5250DBuffer * This,int y,int x)522 tn5250_dbuffer_field_yx (Tn5250DBuffer * This, int y, int x)
523 {
524   Tn5250Field *iter;
525   if ((iter = This->field_list) != NULL)
526     {
527       do
528 	{
529 	  if (tn5250_field_hit_test (iter, y, x))
530 	    {
531 	      return iter;
532 	    }
533 	  iter = iter->next;
534 	}
535       while (iter != This->field_list);
536     }
537   return NULL;
538 }
539 
540 
541 /****f* lib5250/tn5250_dbuffer_first_non_bypass
542  * NAME
543  *    tn5250_dbuffer_first_non_bypass
544  * SYNOPSIS
545  *    field = tn5250_dbuffer_first_non_bypass (dbuffer);
546  * INPUTS
547  *    Tn5250DBuffer *      dbuffer    - The display buffer to use.
548  * DESCRIPTION
549  *    Returns a pointer to the first non-bypass field in the format table,
550  *    or NULL if there are no non-bypass fields.
551  *****/
552 Tn5250Field *
tn5250_dbuffer_first_non_bypass(Tn5250DBuffer * This)553 tn5250_dbuffer_first_non_bypass (Tn5250DBuffer * This)
554 {
555   Tn5250Field *iter;
556   if ((iter = This->field_list) != NULL)
557     {
558       do
559 	{
560 	  if (!tn5250_field_is_bypass (iter))
561 	    {
562 	      return iter;
563 	    }
564 	  iter = iter->next;
565 	}
566       while (iter != This->field_list);
567     }
568   return NULL;
569 }
570 
571 
572 /****f* lib5250/tn5250_dbuffer_right
573  * NAME
574  *    tn5250_dbuffer_right
575  * SYNOPSIS
576  *    tn5250_dbuffer_right (This, n);
577  * INPUTS
578  *    Tn5250DBuffer *      This       -
579  *    int                  n          -
580  * DESCRIPTION
581  *    DOCUMENT ME!!!
582  *****/
583 void
tn5250_dbuffer_right(Tn5250DBuffer * This,int n)584 tn5250_dbuffer_right (Tn5250DBuffer * This, int n)
585 {
586   if (This->menubar_count > 0)
587     {
588       Tn5250Menubar *menubar =
589 	tn5250_menubar_hit_test (This->menubar_list, This->cx, This->cy);
590 
591       if (menubar != NULL)
592 	{
593 	  tn5250_menubar_select_next (menubar, &This->cx, &This->cy);
594 	  ASSERT_VALID (This);
595 	  return;
596 	}
597     }
598 
599   This->cx += n;
600   This->cy += (This->cx / This->w);
601   This->cx = (This->cx % This->w);
602   This->cy = (This->cy % This->h);
603 
604   ASSERT_VALID (This);
605   return;
606 }
607 
608 
609 /****f* lib5250/tn5250_dbuffer_left
610  * NAME
611  *    tn5250_dbuffer_left
612  * SYNOPSIS
613  *    tn5250_dbuffer_left (This);
614  * INPUTS
615  *    Tn5250DBuffer *      This       -
616  * DESCRIPTION
617  *    DOCUMENT ME!!!
618  *****/
619 void
tn5250_dbuffer_left(Tn5250DBuffer * This)620 tn5250_dbuffer_left (Tn5250DBuffer * This)
621 {
622   if (This->menubar_count > 0)
623     {
624       Tn5250Menubar *menubar =
625 	tn5250_menubar_hit_test (This->menubar_list, This->cx, This->cy);
626 
627       if (menubar != NULL)
628 	{
629 	  tn5250_menubar_select_prev (menubar, &This->cx, &This->cy);
630 	  ASSERT_VALID (This);
631 	  return;
632 	}
633     }
634 
635   This->cx--;
636   if (This->cx == -1)
637     {
638       This->cx = This->w - 1;
639       This->cy--;
640       if (This->cy == -1)
641 	{
642 	  This->cy = This->h - 1;
643 	}
644     }
645 
646   ASSERT_VALID (This);
647   return;
648 }
649 
650 
651 /****f* lib5250/tn5250_dbuffer_up
652  * NAME
653  *    tn5250_dbuffer_up
654  * SYNOPSIS
655  *    tn5250_dbuffer_up (This);
656  * INPUTS
657  *    Tn5250DBuffer *      This       -
658  * DESCRIPTION
659  *    DOCUMENT ME!!!
660  *****/
661 void
tn5250_dbuffer_up(Tn5250DBuffer * This)662 tn5250_dbuffer_up (Tn5250DBuffer * This)
663 {
664   if (This->menubar_count > 0)
665     {
666       Tn5250Menubar *menubar =
667 	tn5250_menubar_hit_test (This->menubar_list, This->cx, This->cy);
668 
669       if (menubar != NULL)
670 	{
671 	  tn5250_menubar_select_prev (menubar, &This->cx, &This->cy);
672 	  ASSERT_VALID (This);
673 	  return;
674 	}
675     }
676 
677   if (--This->cy == -1)
678     This->cy = This->h - 1;
679 
680   ASSERT_VALID (This);
681   return;
682 }
683 
684 
685 /****f* lib5250/tn5250_dbuffer_down
686  * NAME
687  *    tn5250_dbuffer_down
688  * SYNOPSIS
689  *    tn5250_dbuffer_down (This);
690  * INPUTS
691  *    Tn5250DBuffer *      This       -
692  * DESCRIPTION
693  *    DOCUMENT ME!!!
694  *****/
695 void
tn5250_dbuffer_down(Tn5250DBuffer * This)696 tn5250_dbuffer_down (Tn5250DBuffer * This)
697 {
698   if (This->menubar_count > 0)
699     {
700       Tn5250Menubar *menubar =
701 	tn5250_menubar_hit_test (This->menubar_list, This->cx, This->cy);
702 
703       if (menubar != NULL)
704 	{
705 	  tn5250_menubar_select_next (menubar, &This->cx, &This->cy);
706 	  ASSERT_VALID (This);
707 	  return;
708 	}
709     }
710 
711   if (++This->cy == This->h)
712     {
713       This->cy = 0;
714     }
715 
716   ASSERT_VALID (This);
717   return;
718 }
719 
720 
721 /****f* lib5250/tn5250_dbuffer_goto_ic
722  * NAME
723  *    tn5250_dbuffer_goto_ic
724  * SYNOPSIS
725  *    tn5250_dbuffer_goto_ic (This);
726  * INPUTS
727  *    Tn5250DBuffer *      This       -
728  * DESCRIPTION
729  *    DOCUMENT ME!!!
730  *****/
731 void
tn5250_dbuffer_goto_ic(Tn5250DBuffer * This)732 tn5250_dbuffer_goto_ic (Tn5250DBuffer * This)
733 {
734   ASSERT_VALID (This);
735 
736   This->cy = This->tcy;
737   This->cx = This->tcx;
738 
739   ASSERT_VALID (This);
740   return;
741 }
742 
743 /****f* lib5250/tn5250_dbuffer_addch
744  * NAME
745  *    tn5250_dbuffer_addch
746  * SYNOPSIS
747  *    tn5250_dbuffer_addch (This, c);
748  * INPUTS
749  *    Tn5250DBuffer *      This       -
750  *    unsigned char        c          -
751  * DESCRIPTION
752  *    DOCUMENT ME!!!
753  *****/
754 void
tn5250_dbuffer_addch(Tn5250DBuffer * This,unsigned char c)755 tn5250_dbuffer_addch (Tn5250DBuffer * This, unsigned char c)
756 {
757   ASSERT_VALID (This);
758 
759   This->data[(This->cy * This->w) + This->cx] = c;
760   tn5250_dbuffer_right (This, 1);
761 
762   ASSERT_VALID (This);
763   return;
764 }
765 
766 
767 /****f* lib5250/tn5250_dbuffer_del
768  * NAME
769  *    tn5250_dbuffer_del
770  * SYNOPSIS
771  *    tn5250_dbuffer_del (This, fieldid, shiftcount);
772  * INPUTS
773  *    Tn5250DBuffer *      This       -
774  *    int                  shiftcount -
775  * DESCRIPTION
776  *    DOCUMENT ME!!!
777  *****/
778 void
tn5250_dbuffer_del(Tn5250DBuffer * This,int fieldid,int shiftcount)779 tn5250_dbuffer_del (Tn5250DBuffer * This, int fieldid, int shiftcount)
780 {
781   Tn5250Field *iter, *field;
782   int x = This->cx, y = This->cy, fwdx, fwdy, i;
783 
784   field = tn5250_field_list_find_by_id (This->field_list, fieldid);
785   iter = field;
786 
787   while (tn5250_field_is_continued (iter))
788     {
789       if (tn5250_field_is_continued_last (iter))
790 	{
791 	  break;
792 	}
793       iter = iter->next;
794       shiftcount =
795 	shiftcount + tn5250_field_count_right (iter,
796 					       tn5250_field_start_row (iter),
797 					       tn5250_field_start_col (iter));
798     }
799 
800   iter = field;
801 
802   for (i = 0; i < shiftcount; i++)
803     {
804       fwdx = x + 1;
805       fwdy = y;
806       if (fwdx == This->w)
807 	{
808 	  fwdx = 0;
809 	  fwdy++;
810 	}
811 
812       if (tn5250_field_is_continued (iter)
813 	  && (!tn5250_field_is_continued_last (iter))
814 	  && (fwdx > tn5250_field_end_col (iter)))
815 	{
816 	  iter = iter->next;
817 	  fwdx = tn5250_field_start_col (iter);
818 	  fwdy = tn5250_field_start_row (iter);
819 	  i--;
820 	}
821 
822       This->data[y * This->w + x] = This->data[fwdy * This->w + fwdx];
823       x = fwdx;
824       y = fwdy;
825     }
826   This->data[y * This->w + x] = 0x00;
827 
828   ASSERT_VALID (This);
829   return;
830 }
831 
832 
833 /****f* lib5250/tn5250_dbuffer_del_this_field_only
834  * NAME
835  *    tn5250_dbuffer_del_this_field_only
836  * SYNOPSIS
837  *    tn5250_dbuffer_del_this_field_only (This, shiftcount);
838  * INPUTS
839  *    Tn5250DBuffer *      This       -
840  *    int                  shiftcount -
841  * DESCRIPTION
842  *    DOCUMENT ME!!!
843  *****/
844 void
tn5250_dbuffer_del_this_field_only(Tn5250DBuffer * This,int shiftcount)845 tn5250_dbuffer_del_this_field_only (Tn5250DBuffer * This, int shiftcount)
846 {
847   /* This function is actually the original tn5250_dbuffer_del() function
848    * without the continuous field support.  Generally, tn5250_dbuffer_del()
849    * should be used and not this function.  This function should only be
850    * when you need to delete a character from a single field within a
851    * continuous field group.  The only this should ever be necessary is
852    * when deleting a character from a wordwrap field.
853    */
854   int x = This->cx, y = This->cy, fwdx, fwdy, i;
855 
856   for (i = 0; i < shiftcount; i++)
857     {
858       fwdx = x + 1;
859       fwdy = y;
860       if (fwdx == This->w)
861 	{
862 	  fwdx = 0;
863 	  fwdy++;
864 	}
865       This->data[y * This->w + x] = This->data[fwdy * This->w + fwdx];
866       x = fwdx;
867       y = fwdy;
868     }
869   This->data[y * This->w + x] = TN5250_DISPLAY_WORD_WRAP_SPACE;
870 
871   ASSERT_VALID (This);
872   return;
873 }
874 
875 
876 /****f* lib5250/tn5250_dbuffer_ins
877  * NAME
878  *    tn5250_dbuffer_ins
879  * SYNOPSIS
880  *    tn5250_dbuffer_ins (This, fieldid, c, shiftcount);
881  * INPUTS
882  *    Tn5250DBuffer *      This       -
883  *    int                  fieldid    -
884  *    unsigned char        c          -
885  *    int                  shiftcount -
886  * DESCRIPTION
887  *    DOCUMENT ME!!!
888  *****/
889 void
tn5250_dbuffer_ins(Tn5250DBuffer * This,int fieldid,unsigned char c,int shiftcount)890 tn5250_dbuffer_ins (Tn5250DBuffer * This, int fieldid,
891 		    unsigned char c, int shiftcount)
892 {
893   Tn5250Field *iter, *field;
894   int x = This->cx, y = This->cy, i;
895   unsigned char c2;
896 
897   field = tn5250_field_list_find_by_id (This->field_list, fieldid);
898   iter = field;
899 
900   while (tn5250_field_is_continued (iter))
901     {
902       if (tn5250_field_is_continued_last (iter))
903 	{
904 	  break;
905 	}
906       iter = iter->next;
907       shiftcount =
908 	shiftcount + tn5250_field_count_right (iter,
909 					       tn5250_field_start_row (iter),
910 					       tn5250_field_start_col (iter));
911     }
912 
913   iter = field;
914 
915   for (i = 0; i <= shiftcount; i++)
916     {
917       c2 = This->data[y * This->w + x];
918       This->data[y * This->w + x] = c;
919       c = c2;
920       if (++x == This->w)
921 	{
922 	  x = 0;
923 	  y++;
924 	}
925 
926       if (tn5250_field_is_continued (iter)
927 	  && (!tn5250_field_is_continued_last (iter))
928 	  && (x > tn5250_field_end_col (iter)))
929 	{
930 	  iter = iter->next;
931 	  x = tn5250_field_start_col (iter);
932 	  y = tn5250_field_start_row (iter);
933 	  i--;
934 	}
935     }
936 
937   tn5250_dbuffer_right (This, 1);
938 
939   ASSERT_VALID (This);
940   return;
941 }
942 
943 
944 /****f* lib5250/tn5250_dbuffer_set_ic
945  * NAME
946  *    tn5250_dbuffer_set_ic
947  * SYNOPSIS
948  *    tn5250_dbuffer_set_ic (This, y, x);
949  * INPUTS
950  *    Tn5250DBuffer *      This       -
951  *    int                  y          -
952  *    int                  x          -
953  * DESCRIPTION
954  *    DOCUMENT ME!!!
955  *****/
956 void
tn5250_dbuffer_set_ic(Tn5250DBuffer * This,int y,int x)957 tn5250_dbuffer_set_ic (Tn5250DBuffer * This, int y, int x)
958 {
959   This->tcx = x;
960   This->tcy = y;
961 
962   ASSERT_VALID (This);
963   return;
964 }
965 
966 
967 /****f* lib5250/tn5250_dbuffer_roll
968  * NAME
969  *    tn5250_dbuffer_roll
970  * SYNOPSIS
971  *    tn5250_dbuffer_roll (This, top, bot, lines);
972  * INPUTS
973  *    Tn5250DBuffer *      This       -
974  *    int                  top        -
975  *    int                  bot        -
976  *    int                  lines      -
977  * DESCRIPTION
978  *    DOCUMENT ME!!!
979  *****/
980 void
tn5250_dbuffer_roll(Tn5250DBuffer * This,int top,int bot,int lines)981 tn5250_dbuffer_roll (Tn5250DBuffer * This, int top, int bot, int lines)
982 {
983   int n, c;
984 
985   ASSERT_VALID (This);
986 
987   if (lines == 0)
988     {
989       return;
990     }
991 
992   if (lines < 0)
993     {
994       /* Move text up */
995       for (n = top; n <= bot; n++)
996 	{
997 	  if (n + lines >= top)
998 	    {
999 	      for (c = 0; c < This->w; c++)
1000 		{
1001 		  This->data[(n + lines) * This->w + c] =
1002 		    This->data[n * This->w + c];
1003 		}
1004 	    }
1005 	}
1006     }
1007   else
1008     {
1009       for (n = bot; n >= top; n--)
1010 	{
1011 	  if (n + lines <= bot)
1012 	    {
1013 	      for (c = 0; c < This->w; c++)
1014 		{
1015 		  This->data[(n + lines) * This->w + c] =
1016 		    This->data[n * This->w + c];
1017 		}
1018 	    }
1019 	}
1020     }
1021   ASSERT_VALID (This);
1022   return;
1023 }
1024 
1025 
1026 /****f* lib5250/tn5250_dbuffer_char_at
1027  * NAME
1028  *    tn5250_dbuffer_char_at
1029  * SYNOPSIS
1030  *    ret = tn5250_dbuffer_char_at (This, y, x);
1031  * INPUTS
1032  *    Tn5250DBuffer *      This       -
1033  *    int                  y          -
1034  *    int                  x          -
1035  * DESCRIPTION
1036  *    DOCUMENT ME!!!
1037  *****/
1038 unsigned char
tn5250_dbuffer_char_at(Tn5250DBuffer * This,int y,int x)1039 tn5250_dbuffer_char_at (Tn5250DBuffer * This, int y, int x)
1040 {
1041   ASSERT_VALID (This);
1042   TN5250_ASSERT (y >= 0);
1043   TN5250_ASSERT (x >= 0);
1044   TN5250_ASSERT (y < This->h);
1045   TN5250_ASSERT (x < This->w);
1046   return This->data[y * This->w + x];
1047 }
1048 
1049 
1050 /****f* lib5250/tn5250_dbuffer_msg_line
1051  * NAME
1052  *    tn5250_dbuffer_msg_line
1053  * SYNOPSIS
1054  *    ret = tn5250_dbuffer_msg_line (This);
1055  * INPUTS
1056  *    Tn5250DBuffer *      This       -
1057  * DESCRIPTION
1058  *    Determine which line we should use as the operator error line.
1059  *****/
1060 int
tn5250_dbuffer_msg_line(Tn5250DBuffer * This)1061 tn5250_dbuffer_msg_line (Tn5250DBuffer * This)
1062 {
1063   int l;
1064   l = 1000;
1065   if (This->header_data && (This->header_length >= 4))
1066     {
1067       l = This->header_data[3] - 1;
1068     }
1069   if ((l > tn5250_dbuffer_height (This) - 1) || (l < 0))
1070     {
1071       l = tn5250_dbuffer_height (This) - 1;
1072     }
1073   return l;
1074 }
1075 
1076 
1077 /****f* lib5250/tn5250_dbuffer_prevword
1078  * NAME
1079  *    tn5250_dbuffer_prevword
1080  * SYNOPSIS
1081  *    tn5250_dbuffer_prevword (This);
1082  * INPUTS
1083  *    Tn5250DBuffer *      This       -
1084  * DESCRIPTION
1085  *    DOCUMENT ME!!!
1086  *****/
1087 void
tn5250_dbuffer_prevword(Tn5250DBuffer * This)1088 tn5250_dbuffer_prevword (Tn5250DBuffer * This)
1089 {
1090   int state = 0;
1091   int maxiter;
1092 
1093   TN5250_LOG (("dbuffer_prevword: entered.\n"));
1094 
1095   maxiter = (This->w * This->h);
1096   TN5250_ASSERT (maxiter > 0);
1097 
1098   while (--maxiter)
1099     {
1100       tn5250_dbuffer_left (This);
1101       switch (state)
1102 	{
1103 	case 0:
1104 	  if (This->data[This->cy * This->w + This->cx] <= 0x40)
1105 	    {
1106 	      state++;
1107 	    }
1108 	  break;
1109 	case 1:
1110 	  if (This->data[This->cy * This->w + This->cx] > 0x40)
1111 	    {
1112 	      state++;
1113 	    }
1114 	  break;
1115 	case 2:
1116 	  if (This->data[This->cy * This->w + This->cx] <= 0x40)
1117 	    {
1118 	      tn5250_dbuffer_right (This, 1);
1119 	      return;
1120 	    }
1121 	  break;
1122 	}
1123     }
1124   return;
1125 }
1126 
1127 
1128 /****f* lib5250/tn5250_dbuffer_nextword
1129  * NAME
1130  *    tn5250_dbuffer_nextword
1131  * SYNOPSIS
1132  *    tn5250_dbuffer_nextword (This);
1133  * INPUTS
1134  *    Tn5250DBuffer *      This       -
1135  * DESCRIPTION
1136  *    DOCUMENT ME!!!
1137  *****/
1138 void
tn5250_dbuffer_nextword(Tn5250DBuffer * This)1139 tn5250_dbuffer_nextword (Tn5250DBuffer * This)
1140 {
1141   int foundblank = 0;
1142   int maxiter;
1143 
1144   TN5250_LOG (("dbuffer_nextword: entered.\n"));
1145 
1146   maxiter = (This->w * This->h);
1147   TN5250_ASSERT (maxiter > 0);
1148 
1149   while (--maxiter)
1150     {
1151       tn5250_dbuffer_right (This, 1);
1152       if (This->data[This->cy * This->w + This->cx] <= 0x40)
1153 	{
1154 	  foundblank++;
1155 	}
1156       if ((foundblank) && (This->data[This->cy * This->w + This->cx] > 0x40))
1157 	{
1158 	  break;
1159 	}
1160     }
1161 
1162   ASSERT_VALID (This);
1163   return;
1164 }
1165 
1166 
1167 /***** lib5250/tn5250_dbuffer_add_window
1168  * NAME
1169  *    tn5250_dbuffer_add_window
1170  * SYNOPSIS
1171  *    tn5250_dbuffer_add_window (This, window);
1172  * INPUTS
1173  *    Tn5250DBuffer *      This       -
1174  *    Tn5250Window *       window     -
1175  * DESCRIPTION
1176  *    DOCUMENT ME!!!
1177  *****/
1178 void
tn5250_dbuffer_add_window(Tn5250DBuffer * This,Tn5250Window * window)1179 tn5250_dbuffer_add_window (Tn5250DBuffer * This, Tn5250Window * window)
1180 {
1181   window->id = This->window_count++;
1182   window->table = This;
1183   This->window_list = tn5250_window_list_add (This->window_list, window);
1184 
1185   TN5250_LOG (("adding window: window->id: %d\n", window->id));
1186   return;
1187 }
1188 
1189 
1190 /***** lib5250/tn5250_dbuffer_add_scrollbar
1191  * NAME
1192  *    tn5250_dbuffer_add_scrollbar
1193  * SYNOPSIS
1194  *    tn5250_dbuffer_add_scrollbar (This, scrollbar);
1195  * INPUTS
1196  *    Tn5250DBuffer *      This       -
1197  *    Tn5250Scrollbar *    scrollbar     -
1198  * DESCRIPTION
1199  *    DOCUMENT ME!!!
1200  *****/
1201 void
tn5250_dbuffer_add_scrollbar(Tn5250DBuffer * This,Tn5250Scrollbar * scrollbar)1202 tn5250_dbuffer_add_scrollbar (Tn5250DBuffer * This,
1203 			      Tn5250Scrollbar * scrollbar)
1204 {
1205   scrollbar->id = This->scrollbar_count++;
1206   scrollbar->table = This;
1207   This->scrollbar_list =
1208     tn5250_scrollbar_list_add (This->scrollbar_list, scrollbar);
1209 
1210   TN5250_LOG (("adding scrollbar: scrollbar->id: %d\n", scrollbar->id));
1211   return;
1212 }
1213 
1214 
1215 /***** lib5250/tn5250_dbuffer_add_menubar
1216  * NAME
1217  *    tn5250_dbuffer_add_menubar
1218  * SYNOPSIS
1219  *    tn5250_dbuffer_add_menubar (This, menubar);
1220  * INPUTS
1221  *    Tn5250DBuffer *      This       -
1222  *    Tn5250Menubar *      menubar    -
1223  * DESCRIPTION
1224  *    DOCUMENT ME!!!
1225  *****/
1226 void
tn5250_dbuffer_add_menubar(Tn5250DBuffer * This,Tn5250Menubar * menubar)1227 tn5250_dbuffer_add_menubar (Tn5250DBuffer * This, Tn5250Menubar * menubar)
1228 {
1229   menubar->id = This->menubar_count++;
1230   menubar->table = This;
1231   This->menubar_list = tn5250_menubar_list_add (This->menubar_list, menubar);
1232 
1233   TN5250_LOG (("adding selection field: menubar->id: %d\n", menubar->id));
1234   return;
1235 }
1236