/* Prompt Widget Management Functions: char *PromptGetS(CDisplay *display, Prompt *p) int PromptGetI(CDisplay *display, Prompt *p) long PromptGetL(CDisplay *display, Prompt *p) double PromptGetF(CDisplay *display, Prompt *p) void PromptSetLabel(CDisplay *display, Prompt *p, char *label) void PromptSetS(CDisplay *display, Prompt *p, char *s) void PromptSetI(CDisplay *display, Prompt *p, int i) void PromptSetL(CDisplay *display, Prompt *p, long l) void PromptSetF(CDisplay *display, Prompt *p, double d, int decimals) int PromptInit( CDisplay *display, Prompt *p, Window parent, int x, int y, unsigned int width, unsigned int height, int buf_len, void *client_data, void (*func_cb)(void *, char *) ) void PromptResize( CDisplay *display, Prompt *p, unsigned int width, unsigned int height ) void PromptDraw(CDisplay *display, Prompt *p) int PromptManage(CDisplay *display, Prompt *p, CEvent *event) void PromptSetFocus(CDisplay *display, Prompt *p, int focus) void PromptMap(CDisplay *display, Prompt *p) void PromptUnmap(CDisplay *display, Prompt *p) void PromptDestroy(CDisplay *display, Prompt *) --- */ #include #include #include #include #include "../include/string.h" #include "prompt.h" /* * Checks if control key was held down. */ #define PromptCtrl(c) ((c) & 037) /* * Prompt value fetching. */ char *PromptGetS(CDisplay *display, Prompt *p) { if((display == NULL) || (p == NULL) ) return(NULL); return(p->buf); } int PromptGetI(CDisplay *display, Prompt *p) { if((display == NULL) || (p == NULL) ) return(0); return(atoi(p->buf)); } long PromptGetL(CDisplay *display, Prompt *p) { if((display == NULL) || (p == NULL) ) return(0); return(atol(p->buf)); } double PromptGetF(CDisplay *display, Prompt *p) { if((display == NULL) || (p == NULL) ) return(0); return(atof(p->buf)); } /* * Prompt value setting. */ void PromptSetLabel(CDisplay *display, Prompt *p, char *label) { if((display == NULL) || (p == NULL) ) return; free(p->label); p->label = StringCopyAlloc(label); /* Need to recalculate buf_start_pos. */ if(p->label == NULL) p->buf_start_pos = 0; else p->buf_start_pos = strlen(p->label) + 1; return; } void PromptSetS(CDisplay *display, Prompt *p, char *s) { if((display == NULL) || (p == NULL) ) return; if(p->buf == NULL) return; strncpy( p->buf, s, p->buf_len ); p->buf[p->buf_len] = '\0'; /* Move cursor position to end. */ p->buf_cursor_pos = strlen(p->buf); /* Redraw as needed. */ if(p->map_state) PromptDraw(display, p); return; } void PromptSetI(CDisplay *display, Prompt *p, int i) { char num_str[128]; if((display == NULL) || (p == NULL) ) return; if(p->buf == NULL) return; sprintf(num_str, "%i", i); PromptSetS(display, p, num_str); return; } void PromptSetL(CDisplay *display, Prompt *p, long l) { char num_str[128]; if((display == NULL) || (p == NULL) ) return; if(p->buf == NULL) return; sprintf(num_str, "%ld", l); PromptSetS(display, p, num_str); return; } void PromptSetF(CDisplay *display, Prompt *p, double d, int decimals) { char num_str[80]; char num_str2[128]; if((display == NULL) || (p == NULL) ) return; if(p->buf == NULL) return; sprintf(num_str, "%%.%ilf", decimals); sprintf(num_str2, num_str, d); PromptSetS(display, p, num_str2); return; } int PromptInit( CDisplay *display, Prompt *p, Window parent, int x, int y, unsigned int width, unsigned int height, int buf_len, char *label, void *client_data, void (*func_cb)(void *, char *) ) { if((display == NULL) || (parent == None) || (p == NULL) ) return(-1); memset(p, 0x00, sizeof(Prompt)); p->map_state = 0; p->is_in_focus = 0; p->x = x; p->y = y; p->width = width; p->height = height; p->w = parent; p->client_data = client_data; p->func_cb = func_cb; /* Allocate buffer (add one extra char). */ if(buf_len < 1) buf_len = 1; p->buf = (char *)malloc((buf_len + 1) * sizeof(char)); if(p->buf == NULL) { p->buf_len = 0; return(-1); } p->buf_len = buf_len; *p->buf = '\0'; /* Set first char null. */ p->buf[p->buf_len] = '\0'; /* Set last char null. */ p->buf_scroll_pos = 0; p->buf_cursor_pos = 0; /* Set label. */ p->label = NULL; PromptSetLabel(display, p, label); return(0); } void PromptResize( CDisplay *display, Prompt *p, unsigned int width, unsigned int height ) { if((display == NULL) || (p == NULL) ) return; if(width < 1) width = 1; if(height < 1) height = 1; p->width = width; p->height = height; return; } void PromptDraw(CDisplay *display, Prompt *p) { int x, y, x2, len; int scroll_pos, scroll_end_pos, cursor_pos; Window w; char tmp_char; if((display == NULL) || (p == NULL) ) return; /* Do not draw if not mapped. */ if(!p->map_state) return; /* Get window to draw to. */ w = p->w; /* Clear entire prompt area. */ for(x = p->x, y = p->y, x2 = p->x + (int)p->width; x < x2; x++ ) CWDrawCharacter( display, w, x, y, ' ' ); /* Get starting values. */ x = p->x; y = p->y; /* Draw label (if prompt has one) and add one extra space. */ if(p->label != NULL) { len = strlen(p->label); CWDrawStringPosition( display, w, x, y, p->label ); x += len; /* Draw a space to padd between label and text value. */ CWDrawStringPosition( display, w, x, y, " " ); x += 1; } /* Get sanitized scrolled buffer position. */ scroll_pos = p->buf_scroll_pos; if(scroll_pos >= p->buf_len) scroll_pos = p->buf_len - 1; if(scroll_pos < 0) scroll_pos = 0; /* Get sanitized cursor position. */ cursor_pos = p->buf_cursor_pos; if(cursor_pos >= p->buf_len) cursor_pos = p->buf_len - 1; if(cursor_pos < 0) cursor_pos = 0; /* Draw text value if exists. */ if((p->buf != NULL) && (p->buf_len > 0)) { /* Calculate length of characters visable. */ len = (int)p->width - p->buf_start_pos - 1; if(len < 0) len = 0; /* Calculate scroll end position (can be at buffer end). */ scroll_end_pos = scroll_pos + len; if(scroll_end_pos > p->buf_len) scroll_end_pos = p->buf_len; if(scroll_end_pos < 0) scroll_end_pos = 0; /* Playing a trick here, store character at * scroll_end_pos then set it to null. * After redrawing, set it back. */ tmp_char = p->buf[scroll_end_pos]; p->buf[scroll_end_pos] = '\0'; /* Draw text value. */ CWDrawStringPosition( display, w, x, y, &p->buf[scroll_pos] ); x += len; /* Set back tempory character at scrolled end position. */ p->buf[scroll_end_pos] = tmp_char; /* Draw a space to padd after text value. */ CWDrawStringPosition( display, w, x, y, " " ); x += 1; /* Make the character the cursor is on `stand out'. */ tmp_char = p->buf[cursor_pos]; if((tmp_char == '\0') || /* Use '_' so standout shows. */ (tmp_char == ' ') ) tmp_char = '_'; x2 = p->x + p->buf_start_pos + (cursor_pos - scroll_pos); standout(); CWDrawCharacter( display, w, x2, y, tmp_char ); standend(); } /* Move cursor back to the starting position of prompt. */ CWMoveCursor( display, w, p->x, p->y ); /* CWSync(display, 0); */ return; } int PromptManage(CDisplay *display, Prompt *p, CEvent *event) { int i, c, buf_cursor_pos, chars_visable, text_value_len; int events_handled = 0; if((display == NULL) || (p == NULL) || (event == NULL) ) return(events_handled); switch(event->type) { /* **************************************************** */ case CKeyPress: if(!p->is_in_focus || !p->map_state ) break; if((p->buf == NULL) || (p->buf_len < 1)) break; /* Get key character value. */ c = event->ckey.key; /* Get position of cursor in text value buffer. */ buf_cursor_pos = p->buf_cursor_pos; if(buf_cursor_pos >= p->buf_len) buf_cursor_pos = p->buf_len - 1; if(buf_cursor_pos < 0) buf_cursor_pos = 0; /* Calculate characters visable. */ chars_visable = (int)p->width - p->buf_start_pos - 1; if(chars_visable < 0) chars_visable = 0; /* Check what character we got. */ switch(c) { case KEY_LEFT: buf_cursor_pos--; break; case KEY_RIGHT: buf_cursor_pos++; break; case KEY_UP: /* Does nothing. */ break; case KEY_DOWN: /* Does nothing. */ break; case KEY_ENTER: /* Enter. */ case KEY_NUMPADENTER: if(p->func_cb != NULL) { p->func_cb(p->client_data, p->buf); p->buf[0] = '\0'; buf_cursor_pos = 0; } break; case PromptCtrl('l'): /* Redraw. */ break; case KEY_BACKSPACE: /* Backspace. */ if(buf_cursor_pos > 0) { buf_cursor_pos--; for(i = buf_cursor_pos; i < p->buf_len; i++) { p->buf[i] = p->buf[i + 1]; if(p->buf[i] == '\0') break; } } break; case KEY_DC: /* Delete. */ case PromptCtrl('d'): case KEY_DELETE: for(i = buf_cursor_pos; i < p->buf_len; i++) { p->buf[i] = p->buf[i + 1]; if(p->buf[i] == '\0') break; } break; case PromptCtrl('k'): /* Clear line. */ p->buf[0] = '\0'; buf_cursor_pos = 0; break; default: /* Shift characters. */ for(i = p->buf_len - 1; i > buf_cursor_pos; i--) p->buf[i] = p->buf[i - 1]; /* Null terminate, this may be needed! */ p->buf[p->buf_len] = '\0'; /* Set new character. */ p->buf[buf_cursor_pos] = (char)c; /* Increment cursor position. */ buf_cursor_pos++; break; } /* Get length of text value buffer contents. */ text_value_len = strlen(p->buf); /* Sanitize new cursor position in buffer. */ if(buf_cursor_pos > text_value_len) buf_cursor_pos = text_value_len; if(buf_cursor_pos >= p->buf_len) buf_cursor_pos = p->buf_len - 1; if(buf_cursor_pos < 0) buf_cursor_pos = 0; /* Adjust scrolled position as needed. */ if(buf_cursor_pos < p->buf_scroll_pos) { p->buf_scroll_pos = buf_cursor_pos; } else if(buf_cursor_pos >= (p->buf_scroll_pos + chars_visable)) { p->buf_scroll_pos = buf_cursor_pos - chars_visable + 1; } if(p->buf_scroll_pos >= p->buf_len) p->buf_scroll_pos = p->buf_len - 1; if(p->buf_scroll_pos < 0) p->buf_scroll_pos = 0; /* Set new cursor position. */ p->buf_cursor_pos = buf_cursor_pos; PromptDraw(display, p); events_handled++; break; /* **************************************************** */ case CKeyRelease: if(!p->is_in_focus || !p->map_state ) break; if((p->buf == NULL) || (p->buf_len < 1)) break; break; } return(events_handled); } void PromptSetFocus(CDisplay *display, Prompt *p, int focus) { if((display == NULL) || (p == NULL) ) return; p->is_in_focus = focus; return; } void PromptMap(CDisplay *display, Prompt *p) { if((display == NULL) || (p == NULL) ) return; p->map_state = 1; PromptDraw(display, p); return; } void PromptUnmap(CDisplay *display, Prompt *p) { if((display == NULL) || (p == NULL) ) return; /* If was not mapped, then clear area. */ if(p->map_state) { CWClearArea( display, p->w, p->x, p->y, p->width, p->height ); /* CWSync(display, 0); */ } /* Prompt should go out of focus when unmapped. */ PromptSetFocus(display, p, 0); p->map_state = 0; return; } void PromptDestroy(CDisplay *display, Prompt *p) { if((display == NULL) || (p == NULL) ) return; free(p->buf); free(p->label); memset(p, 0x00, sizeof(Prompt)); return; }